You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.5 KiB
116 lines
3.5 KiB
4 months ago
|
/* passwd.c - Program to update user password.
|
||
|
*
|
||
|
* Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
|
||
|
* Modified 2012 Jason Kyungwan Han <asura321@gmail.com>
|
||
|
*
|
||
|
* http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html
|
||
|
|
||
|
USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
|
||
|
|
||
|
config PASSWD
|
||
|
bool "passwd"
|
||
|
default y
|
||
|
depends on TOYBOX_SHADOW
|
||
|
help
|
||
|
usage: passwd [-a ALGO] [-dlu] [USER]
|
||
|
|
||
|
Update user's authentication tokens. Defaults to current user.
|
||
|
|
||
|
-a ALGO Encryption method (des, md5, sha256, sha512) default: des
|
||
|
-d Set password to ''
|
||
|
-l Lock (disable) account
|
||
|
-u Unlock (enable) account
|
||
|
|
||
|
config PASSWD_SAD
|
||
|
bool "Add sad password checking heuristics"
|
||
|
default n
|
||
|
depends on PASSWD
|
||
|
help
|
||
|
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
|
||
|
#include "toys.h"
|
||
|
|
||
|
GLOBALS(
|
||
|
char *a;
|
||
|
)
|
||
|
|
||
|
// Sad advisory heuristic, won't find password1 password2 password3...
|
||
|
static void weak_check(char *new, char *old, char *user)
|
||
|
{
|
||
|
char *msg = 0;
|
||
|
|
||
|
if (strlen(new) < 6) msg = "too short";
|
||
|
if (*new) {
|
||
|
if (strcasestr(new, user) || strcasestr(user, new)) msg = "user";
|
||
|
if (*old && (strcasestr(new, old) || strcasestr(old, new))) msg = "old";
|
||
|
}
|
||
|
if (msg) xprintf("BAD PASSWORD: %s\n",msg);
|
||
|
}
|
||
|
|
||
|
void passwd_main(void)
|
||
|
{
|
||
|
uid_t myuid;
|
||
|
struct passwd *pw = 0;
|
||
|
struct spwd *sp;
|
||
|
char *pass, *name, *encrypted = 0, salt[MAX_SALT_LEN];
|
||
|
int ret = -1;
|
||
|
|
||
|
// 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) {
|
||
|
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.a ? TT.a : "des")<0) error_exit("bad -a '%s'", TT.a);
|
||
|
|
||
|
printf("Changing password for %s\n", name);
|
||
|
if (myuid) {
|
||
|
if (*pass=='!') error_exit("'%s' locked", name);
|
||
|
|
||
|
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");
|
||
|
}
|
||
|
|
||
|
if (read_password(toybuf, 2048, "New password:")) return;
|
||
|
|
||
|
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
|
||
|
ret = update_password(*pw->pw_passwd=='x' ? "/etc/shadow" : "/etc/passwd",
|
||
|
name, encrypted);
|
||
|
|
||
|
if (ret) error_msg("Failure");
|
||
|
else fprintf(stderr, "Success\n");
|
||
|
|
||
|
if (CFG_TOYBOX_FREE && (toys.optflags & FLAG_l)) free(encrypted);
|
||
|
}
|