1: /*
   2:  * Copyright (c) 1988 The Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that the above copyright notice and this paragraph are
   7:  * duplicated in all such forms and that any documentation,
   8:  * advertising materials, and other materials related to such
   9:  * distribution and use acknowledge that the software was developed
  10:  * by the University of California, Berkeley.  The name of the
  11:  * University may not be used to endorse or promote products derived
  12:  * from this software without specific prior written permission.
  13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16:  */
  17: 
  18: #ifndef lint
  19: char copyright[] =
  20: "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
  21:  All rights reserved.\n";
  22: #endif /* not lint */
  23: 
  24: #ifndef lint
  25: static char sccsid[] = "@(#)passwd.c	4.35 (Berkeley) 3/16/89";
  26: #endif /* not lint */
  27: 
  28: #include <sys/param.h>
  29: #include <sys/file.h>
  30: #include <sys/signal.h>
  31: #include <sys/time.h>
  32: #include <sys/resource.h>
  33: #include <errno.h>
  34: #include <pwd.h>
  35: #include <stdio.h>
  36: #include <ctype.h>
  37: #include <strings.h>
  38: 
  39: uid_t uid;
  40: 
  41: main(argc, argv)
  42:     int argc;
  43:     char **argv;
  44: {
  45:     extern int errno;
  46:     struct passwd *pw;
  47:     struct rlimit rlim;
  48:     FILE *temp_fp;
  49:     int fd;
  50:     char *fend, *np, *passwd, *temp, *tend;
  51:     char from[MAXPATHLEN], to[MAXPATHLEN];
  52:     char *getnewpasswd();
  53: 
  54:     uid = getuid();
  55:     switch(--argc) {
  56:     case 0:
  57:         if (!(pw = getpwuid(uid))) {
  58:             fprintf(stderr, "passwd: unknown user: uid %u\n", uid);
  59:             exit(1);
  60:         }
  61:         break;
  62:     case 1:
  63:         if (!(pw = getpwnam(argv[1]))) {
  64:             fprintf(stderr, "passwd: unknown user %s.\n", argv[1]);
  65:             exit(1);
  66:         }
  67:         if (uid && uid != pw->pw_uid) {
  68:             fprintf(stderr, "passwd: %s\n", strerror(EACCES));
  69:             exit(1);
  70:         }
  71:         break;
  72:     default:
  73:         fprintf(stderr, "usage: passwd [user]\n");
  74:         exit(1);
  75:     }
  76: 
  77:     (void)signal(SIGHUP, SIG_IGN);
  78:     (void)signal(SIGINT, SIG_IGN);
  79:     (void)signal(SIGQUIT, SIG_IGN);
  80:     (void)signal(SIGTSTP, SIG_IGN);
  81: 
  82:     rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
  83:     (void)setrlimit(RLIMIT_CPU, &rlim);
  84:     (void)setrlimit(RLIMIT_FSIZE, &rlim);
  85: 
  86:     (void)umask(0);
  87: 
  88:     temp = _PATH_PTMP;
  89:     if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) {
  90:         if (errno == EEXIST) {
  91:             fprintf(stderr,
  92:                 "passwd: password file busy -- try again later.\n");
  93:             exit(0);
  94:         }
  95:         fprintf(stderr, "passwd: %s: %s", temp, strerror(errno));
  96:         goto bad;
  97:     }
  98:     if (!(temp_fp = fdopen(fd, "w"))) {
  99:         fprintf(stderr, "passwd: can't write %s\n", temp);
 100:         goto bad;
 101:     }
 102:     passwd = _PATH_MASTERPASSWD;
 103:     if (!freopen(passwd, "r", stdin)) {
 104:         fprintf(stderr, "passwd: can't read %s\n", passwd);
 105:         goto bad;
 106:     }
 107: 
 108:     printf("Changing password for %s.\n", pw->pw_name);
 109:     np = getnewpasswd(pw, temp);
 110: 
 111:     if (!copy(pw->pw_name, np, temp_fp, pw))
 112:         goto bad;
 113: 
 114:     (void)fclose(temp_fp);
 115:     (void)fclose(stdin);
 116: 
 117:     switch(fork()) {
 118:     case 0:
 119:         break;
 120:     case -1:
 121:         fprintf(stderr, "passwd: can't fork");
 122:         goto bad;
 123:         /* NOTREACHED */
 124:     default:
 125:         exit(0);
 126:         /* NOTREACHED */
 127:     }
 128: 
 129:     if (makedb(temp)) {
 130:         fprintf(stderr, "passwd: mkpasswd failed");
 131: bad:        fprintf(stderr, "; password unchanged.\n");
 132:         (void)unlink(temp);
 133:         exit(1);
 134:     }
 135: 
 136:     /*
 137: 	 * possible race; have to rename four files, and someone could slip
 138: 	 * in between them.  LOCK_EX and rename the ``passwd.dir'' file first
 139: 	 * so that getpwent(3) can't slip in; the lock should never fail and
 140: 	 * it's unclear what to do if it does.  Rename ``ptmp'' last so that
 141: 	 * passwd/vipw/chpass can't slip in.
 142: 	 */
 143:     (void)setpriority(PRIO_PROCESS, 0, -20);
 144:     fend = strcpy(from, temp) + strlen(temp);
 145:     tend = strcpy(to, _PATH_PASSWD) + strlen(_PATH_PASSWD);
 146:     bcopy(".dir", fend, 5);
 147:     bcopy(".dir", tend, 5);
 148:     if ((fd = open(from, O_RDONLY, 0)) >= 0)
 149:         (void)flock(fd, LOCK_EX);
 150:     /* here we go... */
 151:     (void)rename(from, to);
 152:     bcopy(".pag", fend, 5);
 153:     bcopy(".pag", tend, 5);
 154:     (void)rename(from, to);
 155:     bcopy(".orig", fend, 6);
 156:     (void)rename(from, _PATH_PASSWD);
 157:     (void)rename(temp, passwd);
 158:     /* done! */
 159:     exit(0);
 160: }
 161: 
 162: copy(name, np, fp, pw)
 163:     char *name, *np;
 164:     FILE *fp;
 165:     struct passwd *pw;
 166: {
 167:     register int done;
 168:     register char *p;
 169:     char buf[256];
 170: 
 171:     for (done = 0; fgets(buf, sizeof(buf), stdin);) {
 172:         /* skip lines that are too big */
 173:         if (!index(buf, '\n')) {
 174:             fprintf(stderr, "passwd: line too long.\n");
 175:             return(0);
 176:         }
 177:         if (done) {
 178:             fprintf(fp, "%s", buf);
 179:             continue;
 180:         }
 181:         if (!(p = index(buf, ':'))) {
 182:             fprintf(stderr, "passwd: corrupted entry.\n");
 183:             return(0);
 184:         }
 185:         *p = '\0';
 186:         if (strcmp(buf, name)) {
 187:             *p = ':';
 188:             fprintf(fp, "%s", buf);
 189:             continue;
 190:         }
 191:         if (!(p = index(++p, ':'))) {
 192:             fprintf(stderr, "passwd: corrupted entry.\n");
 193:             return(0);
 194:         }
 195:         /*
 196: 		 * reset change time to zero; when classes are implemented,
 197: 		 * go and get the "offset" value for this class and reset
 198: 		 * the timer.
 199: 		 */
 200:         fprintf(fp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
 201:             pw->pw_name, np, pw->pw_uid, pw->pw_gid,
 202:             pw->pw_class, 0L, pw->pw_expire, pw->pw_gecos,
 203:             pw->pw_dir, pw->pw_shell);
 204:         done = 1;
 205:     }
 206:     return(1);
 207: }
 208: 
 209: char *
 210: getnewpasswd(pw, temp)
 211:     register struct passwd *pw;
 212:     char *temp;
 213: {
 214:     register char *p, *t;
 215:     char buf[10], salt[2], *crypt(), *getpass();
 216:     time_t time();
 217: 
 218:     if (uid && pw->pw_passwd &&
 219:         strcmp(crypt(getpass("Old password:"), pw->pw_passwd),
 220:         pw->pw_passwd)) {
 221:         (void)printf("passwd: %s.\n", strerror(EACCES));
 222:         (void)unlink(temp);
 223:         exit(1);
 224:     }
 225: 
 226:     for (buf[0] = '\0';;) {
 227:         p = getpass("New password:");
 228:         if (!*p) {
 229:             (void)printf("Password unchanged.\n");
 230:             (void)unlink(temp);
 231:             exit(0);
 232:         }
 233:         if (strlen(p) <= 5) {
 234:             printf("Please enter a longer password.\n");
 235:             continue;
 236:         }
 237:         for (t = p; *t && islower(*t); ++t);
 238:         if (!*t) {
 239:             printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
 240:             continue;
 241:         }
 242:         (void)strcpy(buf, p);
 243:         if (!strcmp(buf, getpass("Retype new password:")))
 244:             break;
 245:         printf("Mismatch; try again, EOF to quit.\n");
 246:     }
 247:     /* grab a random printable character that isn't a colon */
 248:     (void)srandom((int)time((time_t *)NULL));
 249:     while ((salt[0] = random() % 93 + 33) == ':');
 250:     while ((salt[1] = random() % 93 + 33) == ':');
 251:     return(crypt(buf, salt));
 252: }
 253: 
 254: makedb(file)
 255:     char *file;
 256: {
 257:     int status, pid, w;
 258: 
 259:     if (!(pid = vfork())) {
 260:         execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL);
 261:         _exit(127);
 262:     }
 263:     while ((w = wait(&status)) != pid && w != -1);
 264:     return(w == -1 || status);
 265: }

Defined functions

copy defined in line 162; used 1 times
getnewpasswd defined in line 209; used 2 times
main defined in line 41; never used
makedb defined in line 254; used 1 times

Defined variables

copyright defined in line 19; never used
sccsid defined in line 25; never used
uid defined in line 39; used 6 times
Last modified: 1989-05-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3942
Valid CSS Valid XHTML 1.0 Strict