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] [USER] 16 17 Update user's authentication tokens. Defaults to 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're at least 6 chars long, 30 don't include the entire username (but not a subset of it), or the entire 31 previous password (but changing password1, password2, password3 is fine). 32 This heuristic accepts "aaaaaa" and "123456". 33*/ 34 35#define FOR_passwd 36#include "toys.h" 37 38GLOBALS( 39 char *a; 40) 41 42// Sad advisory heuristic, won't find password1 password2 password3... 43static void weak_check(char *new, char *old, char *user) 44{ 45 char *msg = 0; 46 47 if (strlen(new) < 6) msg = "too short"; 48 if (*new) { 49 if (strcasestr(new, user) || strcasestr(user, new)) msg = "user"; 50 if (*old && (strcasestr(new, old) || strcasestr(old, new))) msg = "old"; 51 } 52 if (msg) xprintf("BAD PASSWORD: %s\n",msg); 53} 54 55void passwd_main(void) 56{ 57 uid_t myuid; 58 struct passwd *pw = 0; 59 struct spwd *sp; 60 char *pass, *name, *encrypted = 0, salt[MAX_SALT_LEN]; 61 int ret = -1; 62 63 // If we're root or not -lud, load specified user. Exit if not allowed. 64 if (!(myuid = getuid()) || !(toys.optflags&(FLAG_l|FLAG_u|FLAG_d))) { 65 if (*toys.optargs) pw = xgetpwnam(*toys.optargs); 66 else pw = xgetpwuid(myuid); 67 } 68 if (!pw || (myuid && (myuid != pw->pw_uid))) error_exit("Not root"); 69 70 // Get password from /etc/passwd or /etc/shadow 71 // TODO: why still support non-shadow passwords...? 72 name = pw->pw_name; 73 if (*(pass = pw->pw_passwd)=='x' && (sp = getspnam(name))) pass = sp->sp_pwdp; 74 75 if (toys.optflags & FLAG_l) { 76 if (*pass=='!') error_exit("already locked"); 77 printf("Locking '%s'\n", name); 78 encrypted = xmprintf("!%s", pass); 79 } else if (toys.optflags & FLAG_u) { 80 if (*pass!='!') error_exit("already unlocked"); 81 printf("Unlocking '%s'\n", name); 82 encrypted = pass+1; 83 } else if (toys.optflags & FLAG_d) { 84 printf("Deleting password for '%s'\n", name); 85 encrypted = ""; 86 } else { 87 if (get_salt(salt, TT.a ? TT.a : "des")<0) error_exit("bad -a '%s'", TT.a); 88 89 printf("Changing password for %s\n", name); 90 if (myuid) { 91 if (*pass=='!') error_exit("'%s' locked", name); 92 93 if (read_password(toybuf+2048, 2048, "Old password:")) return; 94 pass = crypt(toybuf+2048, pw->pw_passwd); 95 if (!pass || strcmp(pass, pw->pw_passwd)) error_exit("No"); 96 } 97 98 if (read_password(toybuf, 2048, "New password:")) return; 99 100 if (CFG_PASSWD_SAD) weak_check(toybuf, toybuf+2048, name); 101 if (read_password(toybuf+2048, 2048, "Retype password:")) return; 102 if (strcmp(toybuf, toybuf+2048)) error_exit("Passwords do not match."); 103 104 encrypted = crypt(toybuf, salt); 105 } 106 107 // Update the passwd 108 ret = update_password(*pw->pw_passwd=='x' ? "/etc/shadow" : "/etc/passwd", 109 name, encrypted); 110 111 if (ret) error_msg("Failure"); 112 else fprintf(stderr, "Success\n"); 113 114 if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_l)) free(encrypted); 115} 116