1 /*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)local_passwd.c 8.3 (Berkeley) 04/02/94"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 14 #include <ctype.h> 15 #include <err.h> 16 #include <errno.h> 17 #include <pwd.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <time.h> 22 #include <unistd.h> 23 24 #include <pw_copy.h> 25 #include <pw_util.h> 26 27 #include "extern.h" 28 29 static uid_t uid; 30 31 char *tempname; 32 33 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ 34 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 35 36 void 37 to64(s, v, n) 38 char *s; 39 long v; 40 int n; 41 { 42 while (--n >= 0) { 43 *s++ = itoa64[v&0x3f]; 44 v >>= 6; 45 } 46 } 47 48 char * 49 getnewpasswd(pw) 50 struct passwd *pw; 51 { 52 int tries; 53 char *p, *t; 54 char buf[_PASSWORD_LEN+1], salt[9]; 55 56 (void)printf("Changing local password for %s.\n", pw->pw_name); 57 58 if (uid && pw->pw_passwd[0] && 59 strcmp(crypt(getpass("Old password:"), pw->pw_passwd), 60 pw->pw_passwd)) { 61 errno = EACCES; 62 pw_error(NULL, 1, 1); 63 } 64 65 for (buf[0] = '\0', tries = 0;;) { 66 p = getpass("New password:"); 67 if (!*p) { 68 (void)printf("Password unchanged.\n"); 69 pw_error(NULL, 0, 0); 70 } 71 if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) { 72 (void)printf("Please enter a longer password.\n"); 73 continue; 74 } 75 for (t = p; *t && islower(*t); ++t); 76 if (!*t && (uid != 0 || ++tries < 2)) { 77 (void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n"); 78 continue; 79 } 80 (void)strcpy(buf, p); 81 if (!strcmp(buf, getpass("Retype new password:"))) 82 break; 83 (void)printf("Mismatch; try again, EOF to quit.\n"); 84 } 85 /* grab a random printable character that isn't a colon */ 86 (void)srandom((int)time((time_t *)NULL)); 87 #ifdef NEWSALT 88 salt[0] = _PASSWORD_EFMT1; 89 to64(&salt[1], (long)(29 * 25), 4); 90 to64(&salt[5], random(), 4); 91 #else 92 to64(&salt[0], random(), 2); 93 #endif 94 return (crypt(buf, salt)); 95 } 96 97 int 98 local_passwd(uname) 99 char *uname; 100 { 101 struct passwd *pw; 102 int pfd, tfd; 103 104 if (!(pw = getpwnam(uname))) 105 errx(1, "unknown user %s", uname); 106 107 uid = getuid(); 108 if (uid && uid != pw->pw_uid) 109 errx(1, "%s", strerror(EACCES)); 110 111 pw_init(); 112 pfd = pw_lock(); 113 tfd = pw_tmp(); 114 115 /* 116 * Get the new password. Reset passwd change time to zero; when 117 * classes are implemented, go and get the "offset" value for this 118 * class and reset the timer. 119 */ 120 pw->pw_passwd = getnewpasswd(pw); 121 pw->pw_change = 0; 122 pw_copy(pfd, tfd, pw); 123 124 if (!pw_mkdb()) 125 pw_error((char *)NULL, 0, 1); 126 return (0); 127 } 128