10f66f451Sopenharmony_ci/* passwd.c - Program to update user password. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com> 40f66f451Sopenharmony_ci * Modified 2012 Jason Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciUSE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN)) 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciconfig PASSWD 110f66f451Sopenharmony_ci bool "passwd" 120f66f451Sopenharmony_ci default y 130f66f451Sopenharmony_ci depends on TOYBOX_SHADOW 140f66f451Sopenharmony_ci help 150f66f451Sopenharmony_ci usage: passwd [-a ALGO] [-dlu] [USER] 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci Update user's authentication tokens. Defaults to current user. 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci -a ALGO Encryption method (des, md5, sha256, sha512) default: des 200f66f451Sopenharmony_ci -d Set password to '' 210f66f451Sopenharmony_ci -l Lock (disable) account 220f66f451Sopenharmony_ci -u Unlock (enable) account 230f66f451Sopenharmony_ci 240f66f451Sopenharmony_ciconfig PASSWD_SAD 250f66f451Sopenharmony_ci bool "Add sad password checking heuristics" 260f66f451Sopenharmony_ci default n 270f66f451Sopenharmony_ci depends on PASSWD 280f66f451Sopenharmony_ci help 290f66f451Sopenharmony_ci Password changes are checked to make sure they're at least 6 chars long, 300f66f451Sopenharmony_ci don't include the entire username (but not a subset of it), or the entire 310f66f451Sopenharmony_ci previous password (but changing password1, password2, password3 is fine). 320f66f451Sopenharmony_ci This heuristic accepts "aaaaaa" and "123456". 330f66f451Sopenharmony_ci*/ 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_ci#define FOR_passwd 360f66f451Sopenharmony_ci#include "toys.h" 370f66f451Sopenharmony_ci 380f66f451Sopenharmony_ciGLOBALS( 390f66f451Sopenharmony_ci char *a; 400f66f451Sopenharmony_ci) 410f66f451Sopenharmony_ci 420f66f451Sopenharmony_ci// Sad advisory heuristic, won't find password1 password2 password3... 430f66f451Sopenharmony_cistatic void weak_check(char *new, char *old, char *user) 440f66f451Sopenharmony_ci{ 450f66f451Sopenharmony_ci char *msg = 0; 460f66f451Sopenharmony_ci 470f66f451Sopenharmony_ci if (strlen(new) < 6) msg = "too short"; 480f66f451Sopenharmony_ci if (*new) { 490f66f451Sopenharmony_ci if (strcasestr(new, user) || strcasestr(user, new)) msg = "user"; 500f66f451Sopenharmony_ci if (*old && (strcasestr(new, old) || strcasestr(old, new))) msg = "old"; 510f66f451Sopenharmony_ci } 520f66f451Sopenharmony_ci if (msg) xprintf("BAD PASSWORD: %s\n",msg); 530f66f451Sopenharmony_ci} 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_civoid passwd_main(void) 560f66f451Sopenharmony_ci{ 570f66f451Sopenharmony_ci uid_t myuid; 580f66f451Sopenharmony_ci struct passwd *pw = 0; 590f66f451Sopenharmony_ci struct spwd *sp; 600f66f451Sopenharmony_ci char *pass, *name, *encrypted = 0, salt[MAX_SALT_LEN]; 610f66f451Sopenharmony_ci int ret = -1; 620f66f451Sopenharmony_ci 630f66f451Sopenharmony_ci // If we're root or not -lud, load specified user. Exit if not allowed. 640f66f451Sopenharmony_ci if (!(myuid = getuid()) || !(toys.optflags&(FLAG_l|FLAG_u|FLAG_d))) { 650f66f451Sopenharmony_ci if (*toys.optargs) pw = xgetpwnam(*toys.optargs); 660f66f451Sopenharmony_ci else pw = xgetpwuid(myuid); 670f66f451Sopenharmony_ci } 680f66f451Sopenharmony_ci if (!pw || (myuid && (myuid != pw->pw_uid))) error_exit("Not root"); 690f66f451Sopenharmony_ci 700f66f451Sopenharmony_ci // Get password from /etc/passwd or /etc/shadow 710f66f451Sopenharmony_ci // TODO: why still support non-shadow passwords...? 720f66f451Sopenharmony_ci name = pw->pw_name; 730f66f451Sopenharmony_ci if (*(pass = pw->pw_passwd)=='x' && (sp = getspnam(name))) pass = sp->sp_pwdp; 740f66f451Sopenharmony_ci 750f66f451Sopenharmony_ci if (toys.optflags & FLAG_l) { 760f66f451Sopenharmony_ci if (*pass=='!') error_exit("already locked"); 770f66f451Sopenharmony_ci printf("Locking '%s'\n", name); 780f66f451Sopenharmony_ci encrypted = xmprintf("!%s", pass); 790f66f451Sopenharmony_ci } else if (toys.optflags & FLAG_u) { 800f66f451Sopenharmony_ci if (*pass!='!') error_exit("already unlocked"); 810f66f451Sopenharmony_ci printf("Unlocking '%s'\n", name); 820f66f451Sopenharmony_ci encrypted = pass+1; 830f66f451Sopenharmony_ci } else if (toys.optflags & FLAG_d) { 840f66f451Sopenharmony_ci printf("Deleting password for '%s'\n", name); 850f66f451Sopenharmony_ci encrypted = ""; 860f66f451Sopenharmony_ci } else { 870f66f451Sopenharmony_ci if (get_salt(salt, TT.a ? TT.a : "des")<0) error_exit("bad -a '%s'", TT.a); 880f66f451Sopenharmony_ci 890f66f451Sopenharmony_ci printf("Changing password for %s\n", name); 900f66f451Sopenharmony_ci if (myuid) { 910f66f451Sopenharmony_ci if (*pass=='!') error_exit("'%s' locked", name); 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci if (read_password(toybuf+2048, 2048, "Old password:")) return; 940f66f451Sopenharmony_ci pass = crypt(toybuf+2048, pw->pw_passwd); 950f66f451Sopenharmony_ci if (!pass || strcmp(pass, pw->pw_passwd)) error_exit("No"); 960f66f451Sopenharmony_ci } 970f66f451Sopenharmony_ci 980f66f451Sopenharmony_ci if (read_password(toybuf, 2048, "New password:")) return; 990f66f451Sopenharmony_ci 1000f66f451Sopenharmony_ci if (CFG_PASSWD_SAD) weak_check(toybuf, toybuf+2048, name); 1010f66f451Sopenharmony_ci if (read_password(toybuf+2048, 2048, "Retype password:")) return; 1020f66f451Sopenharmony_ci if (strcmp(toybuf, toybuf+2048)) error_exit("Passwords do not match."); 1030f66f451Sopenharmony_ci 1040f66f451Sopenharmony_ci encrypted = crypt(toybuf, salt); 1050f66f451Sopenharmony_ci } 1060f66f451Sopenharmony_ci 1070f66f451Sopenharmony_ci // Update the passwd 1080f66f451Sopenharmony_ci ret = update_password(*pw->pw_passwd=='x' ? "/etc/shadow" : "/etc/passwd", 1090f66f451Sopenharmony_ci name, encrypted); 1100f66f451Sopenharmony_ci 1110f66f451Sopenharmony_ci if (ret) error_msg("Failure"); 1120f66f451Sopenharmony_ci else fprintf(stderr, "Success\n"); 1130f66f451Sopenharmony_ci 1140f66f451Sopenharmony_ci if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_l)) free(encrypted); 1150f66f451Sopenharmony_ci} 116