1 /* passwd.c - Program to update user password. 2 * 3 * Copyright 2012 Ashwini Kumar <ak.ashwini (at) gmail.com> 4 * Modified 2012 Jason Kyungwan Han <asura321 (at) gmail.com> 5 * 6 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html 7 8 USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN)) 9 10 config 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 */ 24 25 #define FOR_passwd 26 #include "toys.h" 27 28 GLOBALS( 29 char *algo; 30 ) 31 32 #ifndef _GNU_SOURCE 33 char *strcasestr(const char *haystack, const char *needle); 34 #endif 35 36 static int str_check(char *s, char *p) 37 { 38 if (strcasestr(s, p) || strcasestr(p, s)) return 1; 39 return 0; 40 } 41 42 static void strength_check(char *newp, char *oldp, char *user) 43 { 44 char *msg = NULL; 45 46 if (strlen(newp) < 6) { //Min passwd len 47 msg = "too short"; 48 xprintf("BAD PASSWORD: %s\n",msg); 49 } 50 if (!newp[0]) return; //passwd is empty 51 52 if (str_check(newp, user)) { 53 msg = "user based password"; 54 xprintf("BAD PASSWORD: %s\n",msg); 55 } 56 57 if (oldp[0] && str_check(newp, oldp)) { 58 msg = "based on old passwd"; 59 xprintf("BAD PASSWORD: %s\n",msg); 60 } 61 } 62 63 static int verify_passwd(char * pwd) 64 { 65 char * pass; 66 67 if (!pwd) return 1; 68 if (pwd[0] == '!' || pwd[0] == '*') return 1; 69 70 pass = crypt(toybuf, pwd); 71 if (pass && !strcmp(pass, pwd)) return 0; 72 73 return 1; 74 } 75 76 static char *new_password(char *oldp, char *user) 77 { 78 char *newp = NULL; 79 80 if (read_password(toybuf, sizeof(toybuf), "New password:")) 81 return NULL; //may be due to Ctrl-C 82 83 newp = xstrdup(toybuf); 84 strength_check(newp, oldp, user); 85 if (read_password(toybuf, sizeof(toybuf), "Retype password:")) { 86 free(newp); 87 return NULL; //may be due to Ctrl-C 88 } 89 90 if (!strcmp(newp, toybuf)) return newp; 91 else error_msg("Passwords do not match.\n"); 92 // Failure Case 93 free(newp); 94 return NULL; 95 } 96 97 void passwd_main(void) 98 { 99 uid_t myuid; 100 struct passwd *pw; 101 struct spwd *sp; 102 char *name = NULL, *pass = NULL, *encrypted = NULL, *newp = NULL, 103 *orig = (char *)"", salt[MAX_SALT_LEN]; 104 int ret = -1; 105 106 myuid = getuid(); 107 if (myuid && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) 108 error_exit("Not root"); 109 110 pw = xgetpwuid(myuid); 111 112 if (*toys.optargs) name = toys.optargs[0]; 113 else name = xstrdup(pw->pw_name); 114 115 pw = xgetpwnam(name); 116 117 if (myuid && (myuid != pw->pw_uid)) 118 error_exit("You need to be root to change '%s' password\n", name); 119 120 pass = pw->pw_passwd; 121 if (pw->pw_passwd[0] == 'x') { 122 //get shadow passwd 123 sp = getspnam(name); 124 if (sp) pass = sp->sp_pwdp; 125 } 126 127 128 if (!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { 129 130 if (!(toys.optflags & FLAG_a)) TT.algo = "des"; 131 if (get_salt(salt, TT.algo) == -1) 132 error_exit("Error: Unkown encryption algorithm\n"); 133 134 printf("Changing password for %s\n",name); 135 if (myuid && pass[0] == '!') 136 error_exit("Can't change, password is locked for %s",name); 137 if (myuid) { 138 //Validate user 139 140 if (read_password(toybuf, sizeof(toybuf), "Origial password:")) { 141 if (!toys.optargs[0]) free(name); 142 return; 143 } 144 orig = toybuf; 145 if (verify_passwd(pass)) error_exit("Authentication failed\n"); 146 } 147 148 orig = xstrdup(orig); 149 150 // Get new password 151 newp = new_password(orig, name); 152 if (!newp) { 153 free(orig); 154 if (!toys.optargs[0]) free(name); 155 return; //new password is not set well. 156 } 157 158 encrypted = crypt(newp, salt); 159 free(newp); 160 free(orig); 161 } else if (toys.optflags & FLAG_l) { 162 if (pass[0] == '!') error_exit("password is already locked for %s",name); 163 printf("Locking password for %s\n",name); 164 encrypted = xmprintf("!%s",pass); 165 } else if (toys.optflags & FLAG_u) { 166 if (pass[0] != '!') error_exit("password is already unlocked for %s",name); 167 168 printf("Unlocking password for %s\n",name); 169 encrypted = xstrdup(&pass[1]); 170 } else if (toys.optflags & FLAG_d) { 171 printf("Deleting password for %s\n",name); 172 encrypted = xstrdup(""); //1 = "", 2 = '\0' 173 } 174 175 // Update the passwd 176 if (pw->pw_passwd[0] == 'x') 177 ret = update_password("/etc/shadow", name, encrypted); 178 else ret = update_password("/etc/passwd", name, encrypted); 179 180 if ((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) free(encrypted); 181 182 if (!toys.optargs[0]) free(name); 183 if (!ret) error_msg("Success"); 184 else error_msg("Failure"); 185 } 186