11772e954Sbostic /*-
2*3fa6231fSpendry  * Copyright (c) 1990, 1993, 1994
3df5f2e58Sbostic  *	The Regents of the University of California.  All rights reserved.
41772e954Sbostic  *
51772e954Sbostic  * %sccs.include.redist.c%
61772e954Sbostic  */
71772e954Sbostic 
81772e954Sbostic #ifndef lint
9*3fa6231fSpendry static char sccsid[] = "@(#)local_passwd.c	8.3 (Berkeley) 04/02/94";
101772e954Sbostic #endif /* not lint */
111772e954Sbostic 
121772e954Sbostic #include <sys/types.h>
1381dae633Spendry 
1481dae633Spendry #include <ctype.h>
1581dae633Spendry #include <err.h>
161772e954Sbostic #include <errno.h>
1781dae633Spendry #include <pwd.h>
181772e954Sbostic #include <stdio.h>
1981dae633Spendry #include <stdlib.h>
2081dae633Spendry #include <string.h>
2181dae633Spendry #include <time.h>
2281dae633Spendry #include <unistd.h>
231772e954Sbostic 
2481dae633Spendry #include <pw_copy.h>
2581dae633Spendry #include <pw_util.h>
261772e954Sbostic 
2781dae633Spendry #include "extern.h"
2881dae633Spendry 
2981dae633Spendry static uid_t uid;
3081dae633Spendry 
311772e954Sbostic char   *tempname;
321772e954Sbostic 
3381dae633Spendry static unsigned char itoa64[] =		/* 0 ... 63 => ascii - 64 */
3481dae633Spendry 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
3581dae633Spendry 
3681dae633Spendry void
to64(s,v,n)3781dae633Spendry to64(s, v, n)
3881dae633Spendry 	char *s;
3981dae633Spendry 	long v;
4081dae633Spendry 	int n;
411772e954Sbostic {
4281dae633Spendry 	while (--n >= 0) {
4381dae633Spendry 		*s++ = itoa64[v&0x3f];
4481dae633Spendry 		v >>= 6;
451772e954Sbostic 	}
461772e954Sbostic }
471772e954Sbostic 
481772e954Sbostic char *
getnewpasswd(pw)491772e954Sbostic getnewpasswd(pw)
5081dae633Spendry 	struct passwd *pw;
511772e954Sbostic {
521772e954Sbostic 	int tries;
5381dae633Spendry 	char *p, *t;
5481dae633Spendry 	char buf[_PASSWORD_LEN+1], salt[9];
551772e954Sbostic 
561772e954Sbostic 	(void)printf("Changing local password for %s.\n", pw->pw_name);
571772e954Sbostic 
5832ee89e1Sbostic 	if (uid && pw->pw_passwd[0] &&
591772e954Sbostic 	    strcmp(crypt(getpass("Old password:"), pw->pw_passwd),
601772e954Sbostic 	    pw->pw_passwd)) {
611772e954Sbostic 		errno = EACCES;
629715af67Sbostic 		pw_error(NULL, 1, 1);
631772e954Sbostic 	}
641772e954Sbostic 
651772e954Sbostic 	for (buf[0] = '\0', tries = 0;;) {
661772e954Sbostic 		p = getpass("New password:");
671772e954Sbostic 		if (!*p) {
681772e954Sbostic 			(void)printf("Password unchanged.\n");
699715af67Sbostic 			pw_error(NULL, 0, 0);
701772e954Sbostic 		}
711772e954Sbostic 		if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
721772e954Sbostic 			(void)printf("Please enter a longer password.\n");
731772e954Sbostic 			continue;
741772e954Sbostic 		}
751772e954Sbostic 		for (t = p; *t && islower(*t); ++t);
761772e954Sbostic 		if (!*t && (uid != 0 || ++tries < 2)) {
771772e954Sbostic 			(void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
781772e954Sbostic 			continue;
791772e954Sbostic 		}
801772e954Sbostic 		(void)strcpy(buf, p);
811772e954Sbostic 		if (!strcmp(buf, getpass("Retype new password:")))
821772e954Sbostic 			break;
831772e954Sbostic 		(void)printf("Mismatch; try again, EOF to quit.\n");
841772e954Sbostic 	}
851772e954Sbostic 	/* grab a random printable character that isn't a colon */
861772e954Sbostic 	(void)srandom((int)time((time_t *)NULL));
871772e954Sbostic #ifdef NEWSALT
8892b291baSbostic 	salt[0] = _PASSWORD_EFMT1;
891772e954Sbostic 	to64(&salt[1], (long)(29 * 25), 4);
901c67f779Sbostic 	to64(&salt[5], random(), 4);
911772e954Sbostic #else
921c67f779Sbostic 	to64(&salt[0], random(), 2);
931772e954Sbostic #endif
941772e954Sbostic 	return (crypt(buf, salt));
951772e954Sbostic }
961772e954Sbostic 
9781dae633Spendry int
local_passwd(uname)9881dae633Spendry local_passwd(uname)
9981dae633Spendry 	char *uname;
1001772e954Sbostic {
10181dae633Spendry 	struct passwd *pw;
10281dae633Spendry 	int pfd, tfd;
10381dae633Spendry 
10481dae633Spendry 	if (!(pw = getpwnam(uname)))
10581dae633Spendry 		errx(1, "unknown user %s", uname);
10681dae633Spendry 
10781dae633Spendry 	uid = getuid();
10881dae633Spendry 	if (uid && uid != pw->pw_uid)
10981dae633Spendry 		errx(1, "%s", strerror(EACCES));
11081dae633Spendry 
11181dae633Spendry 	pw_init();
11281dae633Spendry 	pfd = pw_lock();
11381dae633Spendry 	tfd = pw_tmp();
11481dae633Spendry 
11581dae633Spendry 	/*
11681dae633Spendry 	 * Get the new password.  Reset passwd change time to zero; when
11781dae633Spendry 	 * classes are implemented, go and get the "offset" value for this
11881dae633Spendry 	 * class and reset the timer.
11981dae633Spendry 	 */
12081dae633Spendry 	pw->pw_passwd = getnewpasswd(pw);
12181dae633Spendry 	pw->pw_change = 0;
12281dae633Spendry 	pw_copy(pfd, tfd, pw);
12381dae633Spendry 
12481dae633Spendry 	if (!pw_mkdb())
12581dae633Spendry 		pw_error((char *)NULL, 0, 1);
12681dae633Spendry 	return (0);
1271772e954Sbostic }
128