1/* passwd.c - Program to update user password. 2 * 3 * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com> 4 * Modified 2012 Jason Kyungwan Han <asura321@gmail.com> 5 * 6 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html 7 8USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN)) 9 10config PASSWD 11 bool "passwd" 12 default y 13 depends on TOYBOX_SHADOW 14 help 15 usage: passwd [-a ALGO] [-dlu] <account name> 16 17 update user's authentication tokens. Default : current user 18 19 -a ALGO Encryption method (des, md5, sha256, sha512) default: des 20 -d Set password to '' 21 -l Lock (disable) account 22 -u Unlock (enable) account 23 24config PASSWD_SAD 25 bool "Add sad password checking heuristics" 26 default n 27 depends on PASSWD 28 help 29 Password changes are checked to make sure they don't include the entire 30 username (but not a subset of it), and the entire previous password 31 (but changing password1, password2, password3 is fine). This heuristic 32 accepts "aaaaaa" as a password. 33*/ 34 35#define FOR_passwd 36#include "toys.h" 37 38GLOBALS( 39 char *algo; 40) 41 42static int str_check(char *s, char *p) 43{ 44 if (strnstr(s, p) || strnstr(p, s)) return 1; 45 return 0; 46} 47 48// Insane heuristic won't find password1 password2 password3...? 49static void strength_check(char *newp, char *oldp, char *user) 50{ 51 char *msg = NULL; 52 53 if (strlen(newp) < 6) { //Min passwd len 54 msg = "too short"; 55 xprintf("BAD PASSWORD: %s\n",msg); 56 } 57 if (!newp[0]) return; //passwd is empty 58 59 if (str_check(newp, user)) { 60 msg = "user based password"; 61 xprintf("BAD PASSWORD: %s\n",msg); 62 } 63 64 if (oldp[0] && str_check(newp, oldp)) { 65 msg = "based on old passwd"; 66 xprintf("BAD PASSWORD: %s\n",msg); 67 } 68} 69 70static int verify_passwd(char * pwd) 71{ 72 char * pass; 73 74 if (!pwd) return 1; 75 if (pwd[0] == '!' || pwd[0] == '*') return 1; 76 77 pass = crypt(toybuf, pwd); 78 if (pass && !strcmp(pass, pwd)) return 0; 79 80 return 1; 81} 82 83static char *new_password(char *oldp, char *user) 84{ 85 char *newp = NULL; 86 87 if (read_password(toybuf, sizeof(toybuf), "New password:")) 88 return NULL; //may be due to Ctrl-C 89 90 newp = xstrdup(toybuf); 91 if (CFG_PASSWD_SAD) strength_check(newp, oldp, user); 92 if (read_password(toybuf, sizeof(toybuf), "Retype password:")) { 93 free(newp); 94 return NULL; //may be due to Ctrl-C 95 } 96 97 if (!strcmp(newp, toybuf)) return newp; 98 else error_msg("Passwords do not match.\n"); 99 // Failure Case 100 free(newp); 101 return NULL; 102} 103 104void passwd_main(void) 105{ 106 uid_t myuid; 107 struct passwd *pw; 108 struct spwd *sp; 109 char *name = NULL, *pass = NULL, *encrypted = NULL, *newp = NULL, 110 *orig = (char *)"", salt[MAX_SALT_LEN]; 111 int ret = -1; 112 113 myuid = getuid(); 114 if (myuid && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) 115 error_exit("Not root"); 116 117 pw = xgetpwuid(myuid); 118 119 if (*toys.optargs) name = toys.optargs[0]; 120 else name = xstrdup(pw->pw_name); 121 122 pw = xgetpwnam(name); 123 124 if (myuid && (myuid != pw->pw_uid)) error_exit("Not root"); 125 126 pass = pw->pw_passwd; 127 if (pw->pw_passwd[0] == 'x') { 128 //get shadow passwd 129 sp = getspnam(name); 130 if (sp) pass = sp->sp_pwdp; 131 } 132 133 134 if (!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { 135 136 if (!(toys.optflags & FLAG_a)) TT.algo = "des"; 137 if (get_salt(salt, TT.algo) == -1) 138 error_exit("Error: Unkown encryption algorithm\n"); 139 140 printf("Changing password for %s\n",name); 141 if (myuid && pass[0] == '!') 142 error_exit("Can't change, password is locked for %s",name); 143 if (myuid) { 144 //Validate user 145 146 if (read_password(toybuf, sizeof(toybuf), "Origial password:")) { 147 if (!toys.optargs[0]) free(name); 148 return; 149 } 150 orig = toybuf; 151 if (verify_passwd(pass)) error_exit("Authentication failed\n"); 152 } 153 154 orig = xstrdup(orig); 155 156 // Get new password 157 newp = new_password(orig, name); 158 if (!newp) { 159 free(orig); 160 if (!toys.optargs[0]) free(name); 161 return; //new password is not set well. 162 } 163 164 encrypted = crypt(newp, salt); 165 free(newp); 166 free(orig); 167 } else if (toys.optflags & FLAG_l) { 168 if (pass[0] == '!') error_exit("password is already locked for %s",name); 169 printf("Locking password for %s\n",name); 170 encrypted = xmprintf("!%s",pass); 171 } else if (toys.optflags & FLAG_u) { 172 if (pass[0] != '!') error_exit("password is already unlocked for %s",name); 173 174 printf("Unlocking password for %s\n",name); 175 encrypted = xstrdup(&pass[1]); 176 } else if (toys.optflags & FLAG_d) { 177 printf("Deleting password for %s\n",name); 178 encrypted = xstrdup(""); //1 = "", 2 = '\0' 179 } 180 181 // Update the passwd 182 if (pw->pw_passwd[0] == 'x') 183 ret = update_password("/etc/shadow", name, encrypted); 184 else ret = update_password("/etc/passwd", name, encrypted); 185 186 if ((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) free(encrypted); 187 188 if (!toys.optargs[0]) free(name); 189 if (!ret) error_msg("Success"); 190 else error_msg("Failure"); 191} 192