From de365c8a091ac758f83de68d8986a54959063067 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 29 Jun 2018 18:27:59 -0500 Subject: Cleanup pass on passwd, needs more testing. --- toys/lsb/passwd.c | 181 ++++++++++++++++-------------------------------------- 1 file changed, 53 insertions(+), 128 deletions(-) (limited to 'toys/lsb') diff --git a/toys/lsb/passwd.c b/toys/lsb/passwd.c index 687d4c09..e23de1c6 100644 --- a/toys/lsb/passwd.c +++ b/toys/lsb/passwd.c @@ -26,10 +26,10 @@ config PASSWD_SAD default n depends on PASSWD help - Password changes are checked to make sure they don't include the entire - username (but not a subset of it), and the entire previous password - (but changing password1, password2, password3 is fine). This heuristic - accepts "aaaaaa" as a password. + Password changes are checked to make sure they're at least 6 chars long, + don't include the entire username (but not a subset of it), or the entire + previous password (but changing password1, password2, password3 is fine). + This heuristic accepts "aaaaaa" and "123456". */ #define FOR_passwd @@ -39,153 +39,78 @@ GLOBALS( char *algo; ) -static int str_check(char *s, char *p) +// Sad advisory heuristic, won't find password1 password2 password3... +static void weak_check(char *new, char *old, char *user) { - if (strnstr(s, p) || strnstr(p, s)) return 1; - return 0; -} - -// Insane heuristic won't find password1 password2 password3...? -static void strength_check(char *newp, char *oldp, char *user) -{ - char *msg = NULL; - - if (strlen(newp) < 6) { //Min passwd len - msg = "too short"; - xprintf("BAD PASSWORD: %s\n",msg); - } - if (!newp[0]) return; //passwd is empty - - if (str_check(newp, user)) { - msg = "user based password"; - xprintf("BAD PASSWORD: %s\n",msg); - } - - if (oldp[0] && str_check(newp, oldp)) { - msg = "based on old passwd"; - xprintf("BAD PASSWORD: %s\n",msg); - } -} - -static int verify_passwd(char * pwd) -{ - char * pass; - - if (!pwd) return 1; - if (pwd[0] == '!' || pwd[0] == '*') return 1; - - pass = crypt(toybuf, pwd); - if (pass && !strcmp(pass, pwd)) return 0; - - return 1; -} + char *msg = 0; -static char *new_password(char *oldp, char *user) -{ - char *newp = NULL; - - if (read_password(toybuf, sizeof(toybuf), "New password:")) - return NULL; //may be due to Ctrl-C - - newp = xstrdup(toybuf); - if (CFG_PASSWD_SAD) strength_check(newp, oldp, user); - if (read_password(toybuf, sizeof(toybuf), "Retype password:")) { - free(newp); - return NULL; //may be due to Ctrl-C + if (strlen(new) < 6) msg = "too short"; + if (*new) { + if (strnstr(new, user) || strnstr(user, new)) msg = "user"; + if (*old && (strnstr(new, old) || strnstr(old, new))) msg = "old"; } - - if (!strcmp(newp, toybuf)) return newp; - else error_msg("Passwords do not match.\n"); - // Failure Case - free(newp); - return NULL; + if (msg) xprintf("BAD PASSWORD: %s\n",msg); } void passwd_main(void) { uid_t myuid; - struct passwd *pw; + struct passwd *pw = 0; struct spwd *sp; - char *name = NULL, *pass = NULL, *encrypted = NULL, *newp = NULL, - *orig = (char *)"", salt[MAX_SALT_LEN]; + char *pass, *name, *encrypted = 0, salt[MAX_SALT_LEN]; int ret = -1; - myuid = getuid(); - if (myuid && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) - error_exit("Not root"); - - pw = xgetpwuid(myuid); - - if (*toys.optargs) name = toys.optargs[0]; - else name = xstrdup(pw->pw_name); - - pw = xgetpwnam(name); - - if (myuid && (myuid != pw->pw_uid)) error_exit("Not root"); - - pass = pw->pw_passwd; - if (pw->pw_passwd[0] == 'x') { - //get shadow passwd - sp = getspnam(name); - if (sp) pass = sp->sp_pwdp; + // If we're root or not -lud, load specified user. Exit if not allowed. + if (!(myuid = getuid()) || !(toys.optflags&(FLAG_l|FLAG_u|FLAG_d))) { + if (*toys.optargs) pw = xgetpwnam(*toys.optargs); + else pw = xgetpwuid(myuid); } + if (!pw || (myuid && (myuid != pw->pw_uid))) error_exit("Not root"); + // Get password from /etc/passwd or /etc/shadow + // TODO: why still support non-shadow passwords...? + name = pw->pw_name; + if (*(pass = pw->pw_passwd)=='x' && (sp = getspnam(name))) pass = sp->sp_pwdp; - if (!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) { - - if (!(toys.optflags & FLAG_a)) TT.algo = "des"; - if (get_salt(salt, TT.algo) == -1) - error_exit("Error: Unkown encryption algorithm\n"); + if (toys.optflags & FLAG_l) { + if (*pass=='!') error_exit("already locked"); + printf("Locking '%s'\n", name); + encrypted = xmprintf("!%s", pass); + } else if (toys.optflags & FLAG_u) { + if (*pass!='!') error_exit("already unlocked"); + printf("Unlocking '%s'\n", name); + encrypted = pass+1; + } else if (toys.optflags & FLAG_d) { + printf("Deleting password for '%s'\n", name); + encrypted = ""; + } else { + if (get_salt(salt, TT.algo ? TT.algo : "des")<0) + error_exit("bad -a '%s'", TT.algo); - printf("Changing password for %s\n",name); - if (myuid && pass[0] == '!') - error_exit("Can't change, password is locked for %s",name); + printf("Changing password for %s\n", name); if (myuid) { - //Validate user - - if (read_password(toybuf, sizeof(toybuf), "Origial password:")) { - if (!toys.optargs[0]) free(name); - return; - } - orig = toybuf; - if (verify_passwd(pass)) error_exit("Authentication failed\n"); - } + if (*pass=='!') error_exit("'%s' locked", name); - orig = xstrdup(orig); - - // Get new password - newp = new_password(orig, name); - if (!newp) { - free(orig); - if (!toys.optargs[0]) free(name); - return; //new password is not set well. + if (read_password(toybuf+2048, 2048, "Old password:")) return; + pass = crypt(toybuf+2048, pw->pw_passwd); + if (!pass || strcmp(pass, pw->pw_passwd)) error_exit("No"); } - encrypted = crypt(newp, salt); - free(newp); - free(orig); - } else if (toys.optflags & FLAG_l) { - if (pass[0] == '!') error_exit("password is already locked for %s",name); - printf("Locking password for %s\n",name); - encrypted = xmprintf("!%s",pass); - } else if (toys.optflags & FLAG_u) { - if (pass[0] != '!') error_exit("password is already unlocked for %s",name); + if (read_password(toybuf, 2048, "New password:")) return; - printf("Unlocking password for %s\n",name); - encrypted = xstrdup(&pass[1]); - } else if (toys.optflags & FLAG_d) { - printf("Deleting password for %s\n",name); - encrypted = xstrdup(""); //1 = "", 2 = '\0' + if (CFG_PASSWD_SAD) weak_check(toybuf, toybuf+2048, name); + if (read_password(toybuf+2048, 2048, "Retype password:")) return; + if (strcmp(toybuf, toybuf+2048)) error_exit("Passwords do not match."); + + encrypted = crypt(toybuf, salt); } // Update the passwd - if (pw->pw_passwd[0] == 'x') - ret = update_password("/etc/shadow", name, encrypted); - else ret = update_password("/etc/passwd", name, encrypted); + ret = update_password(*pw->pw_passwd=='x' ? "/etc/shadow" : "/etc/passwd", + name, encrypted); - if ((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) free(encrypted); + if (ret) error_msg("Failure"); + else fprintf(stderr, "Success\n"); - if (!toys.optargs[0]) free(name); - if (!ret) error_msg("Success"); - else error_msg("Failure"); + if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_l)) free(encrypted); } -- cgit v1.2.3