blob: c92fb0d7c571a8bad507b797607f16e28689663c [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
13 help
Rob Landleyd0f79352013-10-16 19:30:17 -050014 usage: passwd [-a ALGO] [-dlu] <account name>
Rob Landley2c917f52012-07-17 08:54:47 -050015
Rob Landleyd0f79352013-10-16 19:30:17 -050016 update user's authentication tokens. Default : current user
Rob Landley2c917f52012-07-17 08:54:47 -050017
Rob Landley7aa651a2012-11-13 17:14:08 -060018 -a ALGO Encryption method (des, md5, sha256, sha512) default: des
19 -d Set password to ''
20 -l Lock (disable) account
21 -u Unlock (enable) account
Rob Landley2c917f52012-07-17 08:54:47 -050022*/
23
Rob Landleyc0e56ed2012-10-08 00:02:30 -050024#define FOR_passwd
Rob Landley2c917f52012-07-17 08:54:47 -050025#include "toys.h"
Rob Landley2c917f52012-07-17 08:54:47 -050026
Rob Landleyc0e56ed2012-10-08 00:02:30 -050027GLOBALS(
Rob Landley7aa651a2012-11-13 17:14:08 -060028 char *algo;
Rob Landley2c917f52012-07-17 08:54:47 -050029)
30
Rob Landley2c917f52012-07-17 08:54:47 -050031#ifndef _GNU_SOURCE
32char *strcasestr(const char *haystack, const char *needle);
33#endif
34
Rob Landley2c917f52012-07-17 08:54:47 -050035static int str_check(char *s, char *p)
36{
Rob Landleyd0f79352013-10-16 19:30:17 -050037 if (strcasestr(s, p) || strcasestr(p, s)) return 1;
Rob Landley7aa651a2012-11-13 17:14:08 -060038 return 0;
Rob Landley2c917f52012-07-17 08:54:47 -050039}
40
41static void strength_check(char *newp, char *oldp, char *user)
42{
Rob Landley7aa651a2012-11-13 17:14:08 -060043 char *msg = NULL;
Rob Landleyd0f79352013-10-16 19:30:17 -050044
Rob Landleyd364e142013-08-18 14:01:46 -050045 if (strlen(newp) < 6) { //Min passwd len
Rob Landley7aa651a2012-11-13 17:14:08 -060046 msg = "too short";
47 xprintf("BAD PASSWORD: %s\n",msg);
48 }
Rob Landleyd364e142013-08-18 14:01:46 -050049 if (!newp[0]) return; //passwd is empty
Rob Landley2c917f52012-07-17 08:54:47 -050050
Rob Landleyd364e142013-08-18 14:01:46 -050051 if (str_check(newp, user)) {
Rob Landley7aa651a2012-11-13 17:14:08 -060052 msg = "user based password";
53 xprintf("BAD PASSWORD: %s\n",msg);
54 }
Rob Landley2c917f52012-07-17 08:54:47 -050055
Rob Landleyd364e142013-08-18 14:01:46 -050056 if (oldp[0] && str_check(newp, oldp)) {
Rob Landley7aa651a2012-11-13 17:14:08 -060057 msg = "based on old passwd";
58 xprintf("BAD PASSWORD: %s\n",msg);
59 }
Rob Landley2c917f52012-07-17 08:54:47 -050060}
61
62static int verify_passwd(char * pwd)
Rob Landley7aa651a2012-11-13 17:14:08 -060063{
64 char * pass;
Rob Landley2c917f52012-07-17 08:54:47 -050065
Rob Landley7aa651a2012-11-13 17:14:08 -060066 if (!pwd) return 1;
67 if (pwd[0] == '!' || pwd[0] == '*') return 1;
Rob Landley2c917f52012-07-17 08:54:47 -050068
Rob Landley7aa651a2012-11-13 17:14:08 -060069 pass = crypt(toybuf, pwd);
Rob Landleyd0f79352013-10-16 19:30:17 -050070 if (pass && !strcmp(pass, pwd)) return 0;
Rob Landley2c917f52012-07-17 08:54:47 -050071
Rob Landley7aa651a2012-11-13 17:14:08 -060072 return 1;
Rob Landley2c917f52012-07-17 08:54:47 -050073}
74
75static char *new_password(char *oldp, char *user)
76{
Rob Landley7aa651a2012-11-13 17:14:08 -060077 char *newp = NULL;
Rob Landley2c917f52012-07-17 08:54:47 -050078
Rob Landleyd364e142013-08-18 14:01:46 -050079 if (read_password(toybuf, sizeof(toybuf), "New password:"))
Rob Landley7aa651a2012-11-13 17:14:08 -060080 return NULL; //may be due to Ctrl-C
Rob Landley2c917f52012-07-17 08:54:47 -050081
Rob Landley7aa651a2012-11-13 17:14:08 -060082 newp = xstrdup(toybuf);
83 strength_check(newp, oldp, user);
Rob Landleyd364e142013-08-18 14:01:46 -050084 if (read_password(toybuf, sizeof(toybuf), "Retype password:")) {
Rob Landley2c917f52012-07-17 08:54:47 -050085 free(newp);
Rob Landley7aa651a2012-11-13 17:14:08 -060086 return NULL; //may be due to Ctrl-C
87 }
88
Rob Landleyd0f79352013-10-16 19:30:17 -050089 if (!strcmp(newp, toybuf)) return newp;
Rob Landley7aa651a2012-11-13 17:14:08 -060090 else error_msg("Passwords do not match.\n");
Rob Landleyd0f79352013-10-16 19:30:17 -050091 // Failure Case
Rob Landley7aa651a2012-11-13 17:14:08 -060092 free(newp);
93 return NULL;
Rob Landley2c917f52012-07-17 08:54:47 -050094}
95
Rob Landley2c917f52012-07-17 08:54:47 -050096void passwd_main(void)
97{
Rob Landley7aa651a2012-11-13 17:14:08 -060098 uid_t myuid;
99 struct passwd *pw;
100 struct spwd *sp;
Rob Landleyd0f79352013-10-16 19:30:17 -0500101 char *name = NULL, *pass = NULL, *encrypted = NULL, *newp = NULL,
102 *orig = (char *)"", salt[MAX_SALT_LEN];
Rob Landley7aa651a2012-11-13 17:14:08 -0600103 int ret = -1;
Rob Landley2c917f52012-07-17 08:54:47 -0500104
Rob Landley7aa651a2012-11-13 17:14:08 -0600105 myuid = getuid();
Rob Landley5ec4ab32013-11-28 21:06:15 -0600106 if (myuid && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d)))
107 error_exit("Not root");
Rob Landley2c917f52012-07-17 08:54:47 -0500108
Rob Landley5ec4ab32013-11-28 21:06:15 -0600109 pw = xgetpwuid(myuid);
Rob Landley2c917f52012-07-17 08:54:47 -0500110
Rob Landley5ec4ab32013-11-28 21:06:15 -0600111 if (*toys.optargs) name = toys.optargs[0];
Rob Landleyd364e142013-08-18 14:01:46 -0500112 else name = xstrdup(pw->pw_name);
Rob Landley2c917f52012-07-17 08:54:47 -0500113
Rob Landley5ec4ab32013-11-28 21:06:15 -0600114 pw = xgetpwnam(name);
Rob Landley2c917f52012-07-17 08:54:47 -0500115
Rob Landleyd0f79352013-10-16 19:30:17 -0500116 if (myuid && (myuid != pw->pw_uid))
Rob Landley7aa651a2012-11-13 17:14:08 -0600117 error_exit("You need to be root to change '%s' password\n", name);
Rob Landley2c917f52012-07-17 08:54:47 -0500118
Rob Landley7aa651a2012-11-13 17:14:08 -0600119 pass = pw->pw_passwd;
Rob Landleyd364e142013-08-18 14:01:46 -0500120 if (pw->pw_passwd[0] == 'x') {
Rob Landleyd0f79352013-10-16 19:30:17 -0500121 //get shadow passwd
Rob Landley7aa651a2012-11-13 17:14:08 -0600122 sp = getspnam(name);
Rob Landleyd364e142013-08-18 14:01:46 -0500123 if (sp) pass = sp->sp_pwdp;
Rob Landley7aa651a2012-11-13 17:14:08 -0600124 }
125
126
Rob Landleyd364e142013-08-18 14:01:46 -0500127 if (!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) {
Rob Landleyd0f79352013-10-16 19:30:17 -0500128
129 if (!(toys.optflags & FLAG_a)) TT.algo = "des";
130 if (get_salt(salt, TT.algo) == -1)
131 error_exit("Error: Unkown encryption algorithm\n");
132
Rob Landley7aa651a2012-11-13 17:14:08 -0600133 printf("Changing password for %s\n",name);
Rob Landleyd0f79352013-10-16 19:30:17 -0500134 if (myuid && pass[0] == '!')
Rob Landley7aa651a2012-11-13 17:14:08 -0600135 error_exit("Can't change, password is locked for %s",name);
Rob Landleyd0f79352013-10-16 19:30:17 -0500136 if (myuid) {
137 //Validate user
Rob Landley7aa651a2012-11-13 17:14:08 -0600138
Rob Landleyd364e142013-08-18 14:01:46 -0500139 if (read_password(toybuf, sizeof(toybuf), "Origial password:")) {
140 if (!toys.optargs[0]) free(name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600141 return;
142 }
143 orig = toybuf;
Rob Landleyd364e142013-08-18 14:01:46 -0500144 if (verify_passwd(pass)) error_exit("Authentication failed\n");
Rob Landley2c917f52012-07-17 08:54:47 -0500145 }
146
Rob Landley7aa651a2012-11-13 17:14:08 -0600147 orig = xstrdup(orig);
Rob Landley2c917f52012-07-17 08:54:47 -0500148
Rob Landleyd0f79352013-10-16 19:30:17 -0500149 // Get new password
Rob Landley7aa651a2012-11-13 17:14:08 -0600150 newp = new_password(orig, name);
Rob Landleyd364e142013-08-18 14:01:46 -0500151 if (!newp) {
Rob Landley7aa651a2012-11-13 17:14:08 -0600152 free(orig);
Rob Landleyd364e142013-08-18 14:01:46 -0500153 if (!toys.optargs[0]) free(name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600154 return; //new password is not set well.
Rob Landley2c917f52012-07-17 08:54:47 -0500155 }
156
Rob Landley7aa651a2012-11-13 17:14:08 -0600157 encrypted = crypt(newp, salt);
158 free(newp);
159 free(orig);
Rob Landleyd364e142013-08-18 14:01:46 -0500160 } else if (toys.optflags & FLAG_l) {
Rob Landleyd0f79352013-10-16 19:30:17 -0500161 if (pass[0] == '!') error_exit("password is already locked for %s",name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600162 printf("Locking password for %s\n",name);
Rob Landley59d85e22014-01-16 09:26:50 -0600163 encrypted = xmprintf("!%s",pass);
Rob Landleyd364e142013-08-18 14:01:46 -0500164 } else if (toys.optflags & FLAG_u) {
Rob Landleyd0f79352013-10-16 19:30:17 -0500165 if (pass[0] != '!') error_exit("password is already unlocked for %s",name);
Rob Landley7aa651a2012-11-13 17:14:08 -0600166
167 printf("Unlocking password for %s\n",name);
168 encrypted = xstrdup(&pass[1]);
Rob Landleyd364e142013-08-18 14:01:46 -0500169 } else if (toys.optflags & FLAG_d) {
Rob Landley7aa651a2012-11-13 17:14:08 -0600170 printf("Deleting password for %s\n",name);
Rob Landleyd0f79352013-10-16 19:30:17 -0500171 encrypted = xstrdup(""); //1 = "", 2 = '\0'
Rob Landley7aa651a2012-11-13 17:14:08 -0600172 }
173
Rob Landleyd0f79352013-10-16 19:30:17 -0500174 // Update the passwd
Rob Landleyd364e142013-08-18 14:01:46 -0500175 if (pw->pw_passwd[0] == 'x')
Rob Landley7aa651a2012-11-13 17:14:08 -0600176 ret = update_password("/etc/shadow", name, encrypted);
Rob Landleyd364e142013-08-18 14:01:46 -0500177 else ret = update_password("/etc/passwd", name, encrypted);
Rob Landley7aa651a2012-11-13 17:14:08 -0600178
Rob Landleyd364e142013-08-18 14:01:46 -0500179 if ((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) free(encrypted);
Rob Landley7aa651a2012-11-13 17:14:08 -0600180
Rob Landleyd364e142013-08-18 14:01:46 -0500181 if (!toys.optargs[0]) free(name);
182 if (!ret) error_msg("Success");
183 else error_msg("Failure");
Rob Landley2c917f52012-07-17 08:54:47 -0500184}