1*cf5a6c84SAndroid Build Coastguard Worker /* passwd.c - update user password.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Ashwini Kumar <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker * Modified 2012 Jason Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker *
6*cf5a6c84SAndroid Build Coastguard Worker * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
9*cf5a6c84SAndroid Build Coastguard Worker
10*cf5a6c84SAndroid Build Coastguard Worker config PASSWD
11*cf5a6c84SAndroid Build Coastguard Worker bool "passwd"
12*cf5a6c84SAndroid Build Coastguard Worker default n
13*cf5a6c84SAndroid Build Coastguard Worker help
14*cf5a6c84SAndroid Build Coastguard Worker usage: passwd [-a ALGO] [-dlu] [USER]
15*cf5a6c84SAndroid Build Coastguard Worker
16*cf5a6c84SAndroid Build Coastguard Worker Update user's login password. Defaults to current user.
17*cf5a6c84SAndroid Build Coastguard Worker
18*cf5a6c84SAndroid Build Coastguard Worker -a ALGO Encryption method (des, md5, sha256, sha512) default: md5
19*cf5a6c84SAndroid Build Coastguard Worker -d Set password to ''
20*cf5a6c84SAndroid Build Coastguard Worker -l Lock (disable) account
21*cf5a6c84SAndroid Build Coastguard Worker -u Unlock (enable) account
22*cf5a6c84SAndroid Build Coastguard Worker
23*cf5a6c84SAndroid Build Coastguard Worker config PASSWD_SAD
24*cf5a6c84SAndroid Build Coastguard Worker bool "Add sad password checking heuristics"
25*cf5a6c84SAndroid Build Coastguard Worker default n
26*cf5a6c84SAndroid Build Coastguard Worker depends on PASSWD
27*cf5a6c84SAndroid Build Coastguard Worker help
28*cf5a6c84SAndroid Build Coastguard Worker Password changes are checked to make sure they're at least 6 chars long,
29*cf5a6c84SAndroid Build Coastguard Worker don't include the entire username (but not a subset of it), or the entire
30*cf5a6c84SAndroid Build Coastguard Worker previous password (but changing password1, password2, password3 is fine).
31*cf5a6c84SAndroid Build Coastguard Worker This heuristic accepts "aaaaaa" and "123456".
32*cf5a6c84SAndroid Build Coastguard Worker */
33*cf5a6c84SAndroid Build Coastguard Worker
34*cf5a6c84SAndroid Build Coastguard Worker #define FOR_passwd
35*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
36*cf5a6c84SAndroid Build Coastguard Worker
GLOBALS(char * a;)37*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
38*cf5a6c84SAndroid Build Coastguard Worker char *a;
39*cf5a6c84SAndroid Build Coastguard Worker )
40*cf5a6c84SAndroid Build Coastguard Worker
41*cf5a6c84SAndroid Build Coastguard Worker // Sad advisory heuristic, won't find password1 password2 password3...
42*cf5a6c84SAndroid Build Coastguard Worker static void weak_check(char *new, char *old, char *user)
43*cf5a6c84SAndroid Build Coastguard Worker {
44*cf5a6c84SAndroid Build Coastguard Worker char *msg = 0;
45*cf5a6c84SAndroid Build Coastguard Worker
46*cf5a6c84SAndroid Build Coastguard Worker if (strlen(new) < 6) msg = "too short";
47*cf5a6c84SAndroid Build Coastguard Worker if (*new) {
48*cf5a6c84SAndroid Build Coastguard Worker if (strcasestr(new, user) || strcasestr(user, new)) msg = "user";
49*cf5a6c84SAndroid Build Coastguard Worker if (*old && (strcasestr(new, old) || strcasestr(old, new))) msg = "old";
50*cf5a6c84SAndroid Build Coastguard Worker }
51*cf5a6c84SAndroid Build Coastguard Worker if (msg) xprintf("BAD PASSWORD: %s\n",msg);
52*cf5a6c84SAndroid Build Coastguard Worker }
53*cf5a6c84SAndroid Build Coastguard Worker
passwd_main(void)54*cf5a6c84SAndroid Build Coastguard Worker void passwd_main(void)
55*cf5a6c84SAndroid Build Coastguard Worker {
56*cf5a6c84SAndroid Build Coastguard Worker uid_t myuid = getuid();
57*cf5a6c84SAndroid Build Coastguard Worker struct passwd *pw = 0;
58*cf5a6c84SAndroid Build Coastguard Worker struct spwd *sp;
59*cf5a6c84SAndroid Build Coastguard Worker char *pass, *name, *encrypted = 0, salt[32];
60*cf5a6c84SAndroid Build Coastguard Worker
61*cf5a6c84SAndroid Build Coastguard Worker // If we're root or not -lud, load specified user. Exit if not allowed.
62*cf5a6c84SAndroid Build Coastguard Worker if (!myuid || !(toys.optflags&(FLAG_l|FLAG_u|FLAG_d))) {
63*cf5a6c84SAndroid Build Coastguard Worker if (*toys.optargs) pw = xgetpwnam(*toys.optargs);
64*cf5a6c84SAndroid Build Coastguard Worker else pw = xgetpwuid(myuid);
65*cf5a6c84SAndroid Build Coastguard Worker }
66*cf5a6c84SAndroid Build Coastguard Worker if (!pw || (myuid && myuid != pw->pw_uid)) error_exit("Not root");
67*cf5a6c84SAndroid Build Coastguard Worker
68*cf5a6c84SAndroid Build Coastguard Worker // Get password from /etc/passwd or /etc/shadow
69*cf5a6c84SAndroid Build Coastguard Worker // TODO: why still support non-shadow passwords...?
70*cf5a6c84SAndroid Build Coastguard Worker name = pw->pw_name;
71*cf5a6c84SAndroid Build Coastguard Worker if (*(pass = pw->pw_passwd)=='x' && (sp = getspnam(name))) pass = sp->sp_pwdp;
72*cf5a6c84SAndroid Build Coastguard Worker
73*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(l)) {
74*cf5a6c84SAndroid Build Coastguard Worker if (*pass=='!') error_exit("already locked");
75*cf5a6c84SAndroid Build Coastguard Worker printf("Locking '%s'\n", name);
76*cf5a6c84SAndroid Build Coastguard Worker encrypted = xmprintf("!%s", pass);
77*cf5a6c84SAndroid Build Coastguard Worker } else if (FLAG(u)) {
78*cf5a6c84SAndroid Build Coastguard Worker if (*pass!='!') error_exit("already unlocked");
79*cf5a6c84SAndroid Build Coastguard Worker printf("Unlocking '%s'\n", name);
80*cf5a6c84SAndroid Build Coastguard Worker encrypted = pass+1;
81*cf5a6c84SAndroid Build Coastguard Worker } else if (FLAG(d)) {
82*cf5a6c84SAndroid Build Coastguard Worker printf("Deleting password for '%s'\n", name);
83*cf5a6c84SAndroid Build Coastguard Worker *(encrypted = toybuf) = 0;
84*cf5a6c84SAndroid Build Coastguard Worker } else {
85*cf5a6c84SAndroid Build Coastguard Worker if (!TT.a) TT.a = "des";
86*cf5a6c84SAndroid Build Coastguard Worker if (get_salt(salt, TT.a, 1)<0) error_exit("bad -a '%s'", TT.a);
87*cf5a6c84SAndroid Build Coastguard Worker
88*cf5a6c84SAndroid Build Coastguard Worker printf("Changing password for %s\n", name);
89*cf5a6c84SAndroid Build Coastguard Worker if (myuid) {
90*cf5a6c84SAndroid Build Coastguard Worker if (*pass=='!') error_exit("'%s' locked", name);
91*cf5a6c84SAndroid Build Coastguard Worker
92*cf5a6c84SAndroid Build Coastguard Worker if (read_password(toybuf+2048, 2048, "Old password:")) return;
93*cf5a6c84SAndroid Build Coastguard Worker pass = crypt(toybuf+2048, pw->pw_passwd);
94*cf5a6c84SAndroid Build Coastguard Worker if (!pass || strcmp(pass, pw->pw_passwd)) error_exit("No");
95*cf5a6c84SAndroid Build Coastguard Worker }
96*cf5a6c84SAndroid Build Coastguard Worker
97*cf5a6c84SAndroid Build Coastguard Worker if (read_password(toybuf, 2048, "New password:")) return;
98*cf5a6c84SAndroid Build Coastguard Worker
99*cf5a6c84SAndroid Build Coastguard Worker if (CFG_PASSWD_SAD) weak_check(toybuf, toybuf+2048, name);
100*cf5a6c84SAndroid Build Coastguard Worker if (read_password(toybuf+2048, 2048, "Retype password:")) return;
101*cf5a6c84SAndroid Build Coastguard Worker if (strcmp(toybuf, toybuf+2048)) error_exit("Passwords do not match.");
102*cf5a6c84SAndroid Build Coastguard Worker
103*cf5a6c84SAndroid Build Coastguard Worker encrypted = crypt(toybuf, salt);
104*cf5a6c84SAndroid Build Coastguard Worker }
105*cf5a6c84SAndroid Build Coastguard Worker
106*cf5a6c84SAndroid Build Coastguard Worker // Update the passwd
107*cf5a6c84SAndroid Build Coastguard Worker if (update_password(*pw->pw_passwd=='x' ? "/etc/shadow" : "/etc/passwd",
108*cf5a6c84SAndroid Build Coastguard Worker name, encrypted, 1)) error_msg("Failure");
109*cf5a6c84SAndroid Build Coastguard Worker else fprintf(stderr, "Success\n");
110*cf5a6c84SAndroid Build Coastguard Worker
111*cf5a6c84SAndroid Build Coastguard Worker memset(toybuf, 0, sizeof(toybuf));
112*cf5a6c84SAndroid Build Coastguard Worker memset(encrypted, 0, strlen(encrypted));
113*cf5a6c84SAndroid Build Coastguard Worker free(encrypted);
114*cf5a6c84SAndroid Build Coastguard Worker }
115