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