|
|
1.1 ! root 1: /* ! 2: * Rec'd from Lauren Weinstein, 7-16-84. ! 3: * Passwd - set login password ! 4: * for a user. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <ctype.h> ! 9: #include <sys/types.h> ! 10: #include <pwd.h> ! 11: #include <signal.h> ! 12: #include <errno.h> ! 13: ! 14: #define NSALT 64 /* Size of salt character set */ ! 15: #define NSALTC 2 /* Number of characters in salt */ ! 16: #define NPASSC 32 /* Maximum characters copied into pass. buf */ ! 17: #define AWRITE 2 /* Access for write */ ! 18: #define NLOKOUT 7 /* Maximum number of lockout attempts */ ! 19: #define NPWCHAR 256 /* Number of characters in passwd file line */ ! 20: ! 21: char notrich[] = "\ ! 22: Password is too easily broken\n\ ! 23: Try again: \ ! 24: "; ! 25: char pfile[] = "/etc/passwd"; ! 26: char tmpfile[] = "/tmp/passwd"; ! 27: ! 28: char salttab[NSALT] = ! 29: "./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; ! 30: ! 31: char pwline[NPWCHAR]; ! 32: ! 33: FILE *lockopen(); ! 34: char *crypt(); ! 35: int cleanup(); ! 36: time_t time(); ! 37: ! 38: int tmpflag; /* Says tempfile is open */ ! 39: ! 40: main(argc, argv) ! 41: char *argv[]; ! 42: { ! 43: register struct passwd *pwp; ! 44: register char *pass, *name; ! 45: char passbuf[NPASSC+1]; ! 46: int myuid; ! 47: char *myname; ! 48: extern char *getpass(); ! 49: extern char *getlogin(); ! 50: ! 51: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 52: signal(SIGINT, cleanup); ! 53: if (signal(SIGHUP, SIG_IGN) != SIG_IGN) ! 54: signal(SIGHUP, cleanup); ! 55: myuid = getuid(); ! 56: ! 57: umask(077); /* mask out file access by other users */ ! 58: ! 59: if (argc > 1) { /* By supplied argument */ ! 60: if (argc != 2) ! 61: usage(); ! 62: if ((pwp = getpwnam(argv[1])) == NULL) ! 63: perr("%s: bad user name\n", argv[1]); ! 64: if (myuid!=0 && pwp->pw_uid!=myuid) ! 65: perr("%s: not allowed to change password\n", argv[1]); ! 66: name = argv[1]; /* get name for change */ ! 67: } else /* By getlogin from /etc/utmp */ ! 68: if ((myname = getlogin()) != NULL) { ! 69: if ((pwp = getpwnam(myname)) == NULL) ! 70: perr("%s: bad login name\n", argv[1]); ! 71: if (myuid != 0 && pwp->pw_uid != myuid) ! 72: perr("%s: not allowed to change password\n", argv[1]); ! 73: name = myname; /* get name for change */ ! 74: } else { /* By user id */ ! 75: if ((pwp = getpwuid(myuid)) == NULL) ! 76: perr("Error on /etc/passwd\n"); ! 77: while ((pwp = getpwent()) != NULL) ! 78: if (pwp->pw_uid == myuid) ! 79: perr("user id is not unique\n"); ! 80: pwp = getpwuid(myuid); ! 81: name = pwp->pw_name; /* changing our own name */ ! 82: } ! 83: if (myuid!=0 && pwp->pw_passwd[0]!='\0') { ! 84: if ((pass = getpass("Old password: ")) == NULL) ! 85: exit(1); ! 86: if (!checkpass(pwp->pw_passwd, pass)) ! 87: perr("Sorry\n"); ! 88: } ! 89: if ((pass = getpass("New password: ")) == NULL) ! 90: exit(1); ! 91: if (pass[0] != 0 || (pass[0] == 0 && getuid() != 0)) ! 92: while (!richenough(pass) || !strcmp(pass, pwp->pw_name)) ! 93: if ((pass = getpass(notrich)) == NULL) ! 94: exit(1); ! 95: strncpy(passbuf, pass, NPASSC); ! 96: if ((pass = getpass("Verification: ")) == NULL) ! 97: exit(1); ! 98: if (strncmp(pass, passbuf, NPASSC) != 0) ! 99: perr("No match: password not changed\n"); ! 100: setpass(name, pass); ! 101: } ! 102: ! 103: /* ! 104: * Tests to see if a password is rich enough ! 105: * (i.e. not too easy to break by exhaustion). ! 106: * A password must be 4 characters if the alphabet ! 107: * is rich enough and 6 characters if it is in a ! 108: * single case. Perhaps the dictionary should ! 109: * be searched as well for more security-conscious ! 110: * systems. We also check (above) to make sure ! 111: * that the selected password is not the same as the username! ! 112: */ ! 113: richenough(passwd) ! 114: char *passwd; ! 115: { ! 116: register char *cp; ! 117: register int uflag=0, lflag=0, oflag=0; ! 118: register int l; ! 119: ! 120: for (cp = passwd; *cp != '\0'; cp++) { ! 121: if (islower(*cp)) ! 122: lflag = 1; ! 123: else if (isupper(*cp)) ! 124: uflag = 1; ! 125: else ! 126: oflag = 1; ! 127: } ! 128: l = cp-passwd; ! 129: if (l < 4) ! 130: return (0); ! 131: if (oflag==0 && lflag^uflag && l<6) ! 132: return (0); ! 133: return (1); ! 134: } ! 135: ! 136: /* ! 137: * Check the passwd in the password file (`rpass') ! 138: * against the typed-in (`tpass') password. ! 139: */ ! 140: checkpass(rpass, tpass) ! 141: register char *rpass, *tpass; ! 142: { ! 143: char salt[3]; ! 144: ! 145: salt[0] = rpass[0]; ! 146: salt[1] = rpass[1]; ! 147: return (strcmp(crypt(tpass, salt), rpass) == 0); ! 148: } ! 149: ! 150: /* ! 151: * Set password for specified name. ! 152: */ ! 153: setpass(name, passwd) ! 154: char *name, *passwd; ! 155: { ! 156: char salt[NSALTC+1]; ! 157: char namebuff[NPWCHAR]; /* name buffer */ ! 158: time_t xtime; ! 159: register char *p1, *p2; ! 160: register int c; ! 161: register FILE *pwf; ! 162: register FILE *tf; ! 163: ! 164: /* ! 165: * Generate the salt for crypt. ! 166: */ ! 167: time(&xtime); ! 168: srand((int)xtime); ! 169: salt[0] = salttab[rand()%NSALT]; ! 170: salt[1] = salttab[rand()%NSALT]; ! 171: salt[2] = '\0'; ! 172: if (*passwd != '\0') ! 173: passwd = crypt(passwd, salt); ! 174: /* ! 175: * Copy password file to tempfile ! 176: * looking for slot to change. ! 177: * The format of a passwd entry is: ! 178: * name:password:uid:... ! 179: */ ! 180: if ((pwf = fopen(pfile, "r")) == NULL) ! 181: perr("Cannot open %s\n", pfile); ! 182: tf = lockopen(tmpfile); ! 183: while (fgets(pwline, NPWCHAR, pwf) != NULL) { ! 184: strcpy(namebuff, pwline); /* copy line */ ! 185: p1 = namebuff; ! 186: while (*p1 != '\0') ! 187: if (*p1++ == ':') ! 188: break; ! 189: *--p1 = '\0'; /* null terminate user name */ ! 190: ! 191: p1 = pwline; ! 192: while (*p1 != '\0') ! 193: if (*p1++ == ':') ! 194: break; ! 195: p2 = p1; ! 196: while (*p2 != '\0') ! 197: if (*p2++ == ':') ! 198: break; ! 199: ! 200: if (!strcmp(namebuff, name)) { /* check for name match */ ! 201: *p1 = '\0'; ! 202: fputs(pwline, tf); ! 203: fputs(passwd, tf); ! 204: putc(':', tf); ! 205: fputs(p2, tf); ! 206: break; ! 207: } ! 208: fputs(pwline, tf); ! 209: } ! 210: while ((c = getc(pwf)) != EOF) /* copy rest of file */ ! 211: putc(c, tf); ! 212: fclose(pwf); ! 213: /* ! 214: * Copy tempfile back to password ! 215: * file -- this runs protected ! 216: * from interrupts. ! 217: */ ! 218: signal(SIGINT, SIG_IGN); ! 219: signal(SIGHUP, SIG_IGN); ! 220: signal(SIGQUIT, SIG_IGN); ! 221: if ((pwf = fopen(pfile, "w")) == NULL) ! 222: perr("Cannot create %s\n", pfile); ! 223: fflush(tf); ! 224: rewind(tf); ! 225: while ((c = getc(tf)) != EOF) ! 226: putc(c, pwf); ! 227: fflush(pwf); ! 228: unlink(tmpfile); ! 229: } ! 230: ! 231: /* ! 232: * Open the tempfile waiting ! 233: * for the tempfile to come free. ! 234: */ ! 235: FILE * ! 236: lockopen(file) ! 237: char *file; ! 238: { ! 239: register int n; ! 240: register FILE *fp; ! 241: extern int errno; ! 242: ! 243: for (n=NLOKOUT; n>0; n--) ! 244: if (access(file, AWRITE)<0 && errno==ENOENT) { ! 245: if ((fp=fopen(file, "w")) == NULL ! 246: || (fp=freopen(file, "r+w", fp)) == NULL) ! 247: perr("Cannot create tempfile\n"); ! 248: tmpflag = 1; ! 249: return (fp); ! 250: } ! 251: perr("Tempfile busy, try again later\n"); ! 252: } ! 253: ! 254: /* ! 255: * Cleanup the tempfile. ! 256: */ ! 257: cleanup() ! 258: { ! 259: if (tmpflag) ! 260: unlink(tmpfile); ! 261: exit (1); ! 262: } ! 263: ! 264: /* ! 265: * Error routines ! 266: */ ! 267: usage() ! 268: { ! 269: perr("Usage: passwd [name]\n"); ! 270: } ! 271: ! 272: perr(x) ! 273: { ! 274: fprintf(stderr, "%r", &x); ! 275: exit(1); ! 276: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.