blob: ca98f2ef962d54ed564eaf0968be6b11ac485374 [file] [log] [blame]
Rob Landley7aa651a2012-11-13 17:14:08 -06001/* passwd.c - Program to update user password.
Rob Landley2c917f52012-07-17 08:54:47 -05002 *
3 * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
4 * Modified 2012 Jason Kyungwan Han <asura321@gmail.com>
5 *
Rob Landleyf91b7c82012-08-25 18:08:51 -05006 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html
Rob Landley2c917f52012-07-17 08:54:47 -05007
8USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
9
10config PASSWD
Rob Landley7aa651a2012-11-13 17:14:08 -060011 bool "passwd"
12 default y
Isaac Dunham46ddf0e2014-11-19 16:38:46 -060013 depends on TOYBOX_SHADOW
Rob Landley7aa651a2012-11-13 17:14:08 -060014 help
Rob Landleyd0f79352013-10-16 19:30:17 -050015 usage: passwd [-a ALGO] [-dlu] <account name>
Rob Landley2c917f52012-07-17 08:54:47 -050016
Rob Landleyd0f79352013-10-16 19:30:17 -050017 update user's authentication tokens. Default : current user
Rob Landley2c917f52012-07-17 08:54:47 -050018
Rob Landley7aa651a2012-11-13 17:14:08 -060019 -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
Rob Landley2c917f52012-07-17 08:54:47 -050023*/
24
Rob Landleyc0e56ed2012-10-08 00:02:30 -050025#define FOR_passwd
Rob Landley2c917f52012-07-17 08:54:47 -050026#include "toys.h"
Rob Landley2c917f52012-07-17 08:54:47 -050027
Rob Landleyc0e56ed2012-10-08 00:02:30 -050028GLOBALS(
Rob Landley7aa651a2012-11-13 17:14:08 -060029 char *algo;
Rob Landley2c917f52012-07-17 08:54:47 -050030)
31
Rob Landley2c917f52012-07-17 08:54:47 -050032#ifndef _GNU_SOURCE
33char *strcasestr(const char *haystack, const char *needle);
34#endif
35
Rob Landley2c917f52012-07-17 08:54:47 -050036static int str_check(char *s, char *p)
37{
Rob Landleyd0f79352013-10-16 19:30:17 -050038 if (strcasestr(s, p) || strcasestr(p, s)) return 1;
Rob Landley7aa651a2012-11-13 17:14:08 -060039 return 0;
Rob Landley2c917f52012-07-17 08:54:47 -050040}
41
42static void strength_check(char *newp, char *oldp, char *user)
43{
Rob Landley7aa651a2012-11-13 17:14:08 -060044 char *msg = NULL;
Rob Landleyd0f79352013-10-16 19:30:17 -050045
Rob Landleyd364e142013-08-18 14:01:46 -050046 if (strlen(newp) < 6) { //Min passwd len
Rob Landley7aa651a2012-11-13 17:14:08 -060047 msg = "too short";
48 xprintf("BAD PASSWORD: %s\n",msg);
49 }
Rob Landleyd364e142013-08-18 14:01:46 -050050 if (!newp[0]) return; //passwd is empty
Rob Landley2c917f52012-07-17 08:54:47 -050051
Rob Landleyd364e142013-08-18 14:01:46 -050052 if (str_check(newp, user)) {
Rob Landley7aa651a2012-11-13 17:14:08 -060053 msg = "user based password";
54 xprintf("BAD PASSWORD: %s\n",msg);
55 }
Rob Landley2c917f52012-07-17 08:54:47 -050056
Rob Landleyd364e142013-08-18 14:01:46 -050057 if (oldp[0] && str_check(newp, oldp)) {
Rob Landley7aa651a2012-11-13 17:14:08 -060058 msg = "based on old passwd";
59 xprintf("BAD PASSWORD: %s\n",msg);
60 }
Rob Landley2c917f52012-07-17 08:54:47 -050061}
62
63static int verify_passwd(char * pwd)
Rob Landley7aa651a2012-11-13 17:14:08 -060064{
65 char * pass;
Rob Landley2c917f52012-07-17 08:54:47 -050066
Rob Landley7aa651a2012-11-13 17:14:08 -060067 if (!pwd) return 1;
68 if (pwd[0] == '!' || pwd[0] == '*') return 1;
Rob Landley2c917f52012-07-17 08:54:47 -050069
Rob Landley7aa651a2012-11-13 17:14:08 -060070 pass = crypt(toybuf, pwd);
Rob Landleyd0f79352013-10-16 19:30:17 -050071 if (pass && !strcmp(pass, pwd)) return 0;
Rob Landley2c917f52012-07-17 08:54:47 -050072
Rob Landley7aa651a2012-11-13 17:14:08 -060073 return 1;
Rob Landley2c917f52012-07-17 08:54:47 -050074}
75
76static char *new_password(char *oldp, char *user)
77{
Rob Landley7aa651a2012-11-13 17:14:08 -060078 char *newp = NULL;
Rob Landley2c917f52012-07-17 08:54:47 -050079
Rob Landleyd364e142013-08-18 14:01:46 -050080 if (read_password(toybuf, sizeof(toybuf), "New password:"))
Rob Landley7aa651a2012-11-13 17:14:08 -060081 return NULL; //may be due to Ctrl-C
Rob Landley2c917f52012-07-17 08:54:47 -050082
Rob Landley7aa651a2012-11-13 17:14:08 -060083 newp = xstrdup(toybuf);
84 strength_check(newp, oldp, user);
Rob Landleyd364e142013-08-18 14:01:46 -050085 if (read_password(toybuf, sizeof(toybuf), "Retype password:")) {
Rob Landley2c917f52012-07-17 08:54:47 -050086 free(newp);
Rob Landley7aa651a2012-11-13 17:14:08 -060087 return NULL; //may be due to Ctrl-C
88 }
89
Rob Landleyd0f79352013-10-16 19:30:17 -050090 if (!strcmp(newp, toybuf)) return newp;
Rob Landley7aa651a2012-11-13 17:14:08 -060091 else error_msg("Passwords do not match.\n");
Rob Landleyd0f79352013-10-16 19:30:17 -050092 // Failure Case
Rob Landley7aa651a2012-11-13 17:14:08 -060093 free(newp);
94 return NULL;
Rob Landley2c917f52012-07-17 08:54:47 -050095}
96
Rob Landley2c917f52012-07-17 08:54:47 -050097void passwd_main(void)
98{
Rob Landley7aa651a2012-11-13 17:14:08 -060099 uid_t myuid;
100 struct passwd *pw;
101 struct spwd *sp;
Rob Landleyd0f79352013-10-16 19:30:17 -0500102 char *name = NULL, *pass = NULL, *encrypted = NULL, *newp = NULL,
103 *orig = (char *)"", salt[MAX_SALT_LEN];
Rob Landley7aa651a2012-11-13 17:14:08 -0600104 int ret = -1;
Rob Landley2c917f52012-07-17 08:54:47 -0500105
Rob Landley7aa651a2012-11-13 17:14:08 -0600106 myuid = getuid();
Rob Landley5ec4ab32013-11-28 21:06:15 -0600107 if (myuid && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d)))
108 error_exit("Not root");
Rob Landley2c917f52012-07-17 08:54:47 -0500109
Rob Landley5ec4ab32013-11-28 21:06:15 -0600110 pw = xgetpwuid(myuid);
Rob Landley2c917f52012-07-17 08:54:47 -0500111
Rob Landley5ec4ab32013-11-28 21:06:15 -0600112 if (*toys.optargs) name = toys.optargs[0];
Rob Landleyd364e142013-08-18 14:01:46 -0500113 else name = xstrdup(pw->pw_name);
Rob Landley2c917f52012-07-17 08:54:47 -0500114
Rob Landley5ec4ab32013-11-28 21:06:15 -0600115 pw = xgetpwnam(name);
Rob Landley2c917f52012-07-17 08:54:47 -0500116
Rob Landleyd0f79352013-10-16 19:30:17 -0500117 if (myuid && (myuid != pw->pw_uid))
Rob Landley7aa651a2012-11-13 17:14:08 -0600118 error_exit("You need to be root to change '%s' password\n", name);
Rob Landley2c917f52012-07-17 08:54:47 -0500119
Rob Landley7aa651a2012-11-13 17:14:08 -0600120 pass = pw->pw_passwd;
Rob Landleyd364e142013-08-18 14:01:46 -0500121 if (pw->pw_passwd[0] == 'x') {
Rob Landleyd0f79352013-10-16 19:30:17 -0500122 //get shadow passwd
Rob Landley7aa651a2012-11-13 17:14:08 -0600123 sp = getspnam(name);
Rob Landleyd364e142013-08-18 14:01:46 -0500124 if (sp) pass = sp->sp_pwdp;
Rob Landley7aa651a2012-11-13 17:14:08 -0600125 }
126
127
Rob Landleyd364e142013-08-18 14:01:46 -0500128 if (!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) {
Rob Landleyd0f79352013-10-16 19:30:17 -0500129
130 if (!(toys.optflags & FLAG_a)) TT.algo = "des";
131 if (get_salt(salt, TT.algo) == -1)
132 error_exit("Error: Unkown encryption algorithm\n");
133
Rob Landley7aa651a2012-11-13 17:14:08 -0600134 printf("Changing password for %s\n",name);
Rob Landleyd0f79352013-10-16 19:30:17 -0500135 if (myuid && pass[0] == '!')
Rob Landley7aa651a2012-11-13 17:14:08 -0600136 error_exit("Can't change, password is locked for %s",name);
Rob Landleyd0f79352013-10-16 19:30:17 -0500137 if (myuid) {
138 //Validate user
Rob Landley7aa651a2012-11-13 17:14:08 -0600139
Rob Landleyd364e142013-08-18 14:01:46 -0500140 if (read_password(toybuf, sizeof(toybuf), "Origial password:")) {
141 if (!toys.optargs[0]) free(name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600142 return;
143 }
144 orig = toybuf;
Rob Landleyd364e142013-08-18 14:01:46 -0500145 if (verify_passwd(pass)) error_exit("Authentication failed\n");
Rob Landley2c917f52012-07-17 08:54:47 -0500146 }
147
Rob Landley7aa651a2012-11-13 17:14:08 -0600148 orig = xstrdup(orig);
Rob Landley2c917f52012-07-17 08:54:47 -0500149
Rob Landleyd0f79352013-10-16 19:30:17 -0500150 // Get new password
Rob Landley7aa651a2012-11-13 17:14:08 -0600151 newp = new_password(orig, name);
Rob Landleyd364e142013-08-18 14:01:46 -0500152 if (!newp) {
Rob Landley7aa651a2012-11-13 17:14:08 -0600153 free(orig);
Rob Landleyd364e142013-08-18 14:01:46 -0500154 if (!toys.optargs[0]) free(name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600155 return; //new password is not set well.
Rob Landley2c917f52012-07-17 08:54:47 -0500156 }
157
Rob Landley7aa651a2012-11-13 17:14:08 -0600158 encrypted = crypt(newp, salt);
159 free(newp);
160 free(orig);
Rob Landleyd364e142013-08-18 14:01:46 -0500161 } else if (toys.optflags & FLAG_l) {
Rob Landleyd0f79352013-10-16 19:30:17 -0500162 if (pass[0] == '!') error_exit("password is already locked for %s",name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600163 printf("Locking password for %s\n",name);
Rob Landley59d85e22014-01-16 09:26:50 -0600164 encrypted = xmprintf("!%s",pass);
Rob Landleyd364e142013-08-18 14:01:46 -0500165 } else if (toys.optflags & FLAG_u) {
Rob Landleyd0f79352013-10-16 19:30:17 -0500166 if (pass[0] != '!') error_exit("password is already unlocked for %s",name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600167
168 printf("Unlocking password for %s\n",name);
169 encrypted = xstrdup(&pass[1]);
Rob Landleyd364e142013-08-18 14:01:46 -0500170 } else if (toys.optflags & FLAG_d) {
Rob Landley7aa651a2012-11-13 17:14:08 -0600171 printf("Deleting password for %s\n",name);
Rob Landleyd0f79352013-10-16 19:30:17 -0500172 encrypted = xstrdup(""); //1 = "", 2 = '\0'
Rob Landley7aa651a2012-11-13 17:14:08 -0600173 }
174
Rob Landleyd0f79352013-10-16 19:30:17 -0500175 // Update the passwd
Rob Landleyd364e142013-08-18 14:01:46 -0500176 if (pw->pw_passwd[0] == 'x')
Rob Landley7aa651a2012-11-13 17:14:08 -0600177 ret = update_password("/etc/shadow", name, encrypted);
Rob Landleyd364e142013-08-18 14:01:46 -0500178 else ret = update_password("/etc/passwd", name, encrypted);
Rob Landley7aa651a2012-11-13 17:14:08 -0600179
Rob Landleyd364e142013-08-18 14:01:46 -0500180 if ((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) free(encrypted);
Rob Landley7aa651a2012-11-13 17:14:08 -0600181
Rob Landleyd364e142013-08-18 14:01:46 -0500182 if (!toys.optargs[0]) free(name);
183 if (!ret) error_msg("Success");
184 else error_msg("Failure");
Rob Landley2c917f52012-07-17 08:54:47 -0500185}