|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)passwd.c 4.4 (Berkeley) 7/10/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * Enter a password in the password file. ! 7: * This program should be suid with an owner ! 8: * with write permission on /etc/passwd. ! 9: */ ! 10: #include <sys/file.h> ! 11: ! 12: #include <stdio.h> ! 13: #include <signal.h> ! 14: #include <pwd.h> ! 15: #include <errno.h> ! 16: ! 17: char passwd[] = "/etc/passwd"; ! 18: char temp[] = "/etc/ptmp"; ! 19: struct passwd *pwd; ! 20: struct passwd *getpwent(); ! 21: int endpwent(); ! 22: char *strcpy(); ! 23: char *crypt(); ! 24: char *getpass(); ! 25: char *getlogin(); ! 26: char *pw; ! 27: char pwbuf[10]; ! 28: extern int errno; ! 29: ! 30: main(argc, argv) ! 31: char *argv[]; ! 32: { ! 33: char *p; ! 34: int i; ! 35: char saltc[2]; ! 36: long salt; ! 37: int u; ! 38: int insist; ! 39: int ok, flags; ! 40: int c, pwlen, fd; ! 41: FILE *tf; ! 42: char *uname; ! 43: ! 44: insist = 0; ! 45: if (argc < 2) { ! 46: if ((uname = getlogin()) == NULL) { ! 47: printf ("Usage: passwd user\n"); ! 48: exit(1); ! 49: } ! 50: printf("Changing password for %s\n", uname); ! 51: } else ! 52: uname = argv[1]; ! 53: while (((pwd = getpwent()) != NULL) && strcmp(pwd->pw_name, uname)) ! 54: ; ! 55: u = getuid(); ! 56: if (pwd == NULL || (u != 0 && u != pwd->pw_uid)) { ! 57: printf("Permission denied.\n"); ! 58: exit(1); ! 59: } ! 60: endpwent(); ! 61: if (pwd->pw_passwd[0] && u != 0) { ! 62: strcpy(pwbuf, getpass("Old password:")); ! 63: pw = crypt(pwbuf, pwd->pw_passwd); ! 64: if (strcmp(pw, pwd->pw_passwd) != 0) { ! 65: printf("Sorry.\n"); ! 66: exit(1); ! 67: } ! 68: } ! 69: tryagain: ! 70: strcpy(pwbuf, getpass("New password:")); ! 71: pwlen = strlen(pwbuf); ! 72: if (pwlen == 0) { ! 73: printf("Password unchanged.\n"); ! 74: exit(1); ! 75: } ! 76: /* ! 77: * Insure password is of reasonable length and ! 78: * composition. If we really wanted to make things ! 79: * sticky, we could check the dictionary for common ! 80: * words, but then things would really be slow. ! 81: */ ! 82: ok = 0; ! 83: flags = 0; ! 84: p = pwbuf; ! 85: while (c = *p++) { ! 86: if (c >= 'a' && c <= 'z') ! 87: flags |= 2; ! 88: else if (c >= 'A' && c <= 'Z') ! 89: flags |= 4; ! 90: else if (c >= '0' && c <= '9') ! 91: flags |= 1; ! 92: else ! 93: flags |= 8; ! 94: } ! 95: if (flags >= 7 && pwlen >= 4) ! 96: ok = 1; ! 97: if ((flags == 2 || flags == 4) && pwlen >= 6) ! 98: ok = 1; ! 99: if ((flags == 3 || flags == 5 || flags == 6) && pwlen >= 5) ! 100: ok = 1; ! 101: if (!ok && insist < 2) { ! 102: printf("Please use %s.\n", flags == 1 ? ! 103: "at least one non-numeric character" : ! 104: "a longer password"); ! 105: insist++; ! 106: goto tryagain; ! 107: } ! 108: if (strcmp(pwbuf, getpass("Retype new password:")) != 0) { ! 109: printf("Mismatch - password unchanged.\n"); ! 110: exit(1); ! 111: } ! 112: time(&salt); ! 113: salt = 9 * getpid(); ! 114: saltc[0] = salt & 077; ! 115: saltc[1] = (salt>>6) & 077; ! 116: for (i = 0; i < 2; i++) { ! 117: c = saltc[i] + '.'; ! 118: if (c > '9') ! 119: c += 7; ! 120: if (c > 'Z') ! 121: c += 6; ! 122: saltc[i] = c; ! 123: } ! 124: pw = crypt(pwbuf, saltc); ! 125: signal(SIGHUP, SIG_IGN); ! 126: signal(SIGINT, SIG_IGN); ! 127: signal(SIGQUIT, SIG_IGN); ! 128: (void) umask(0); ! 129: fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644); ! 130: if (fd < 0) { ! 131: fprintf(stderr, "passwd: "); ! 132: if (errno == EEXIST) ! 133: fprintf(stderr, "password file busy - try again.\n"); ! 134: else ! 135: perror(temp); ! 136: exit(1); ! 137: } ! 138: signal(SIGTSTP, SIG_IGN); ! 139: if ((tf = fdopen(fd, "w")) == NULL) { ! 140: fprintf(stderr, "passwd: fdopen failed?\n"); ! 141: exit(1); ! 142: } ! 143: /* ! 144: * Copy passwd to temp, replacing matching lines ! 145: * with new password. ! 146: */ ! 147: while ((pwd = getpwent()) != NULL) { ! 148: if (strcmp(pwd->pw_name,uname) == 0) { ! 149: u = getuid(); ! 150: if (u && u != pwd->pw_uid) { ! 151: fprintf(stderr, "passwd: permission denied.\n"); ! 152: unlink(temp); ! 153: exit(1); ! 154: } ! 155: pwd->pw_passwd = pw; ! 156: if (pwd->pw_gecos[0] == '*') ! 157: pwd->pw_gecos++; ! 158: } ! 159: fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n", ! 160: pwd->pw_name, ! 161: pwd->pw_passwd, ! 162: pwd->pw_uid, ! 163: pwd->pw_gid, ! 164: pwd->pw_gecos, ! 165: pwd->pw_dir, ! 166: pwd->pw_shell); ! 167: } ! 168: endpwent(); ! 169: if (rename(temp, passwd) < 0) { ! 170: fprintf(stderr, "passwd: "); perror("rename"); ! 171: unlink(temp); ! 172: exit(1); ! 173: } ! 174: fclose(tf); ! 175: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.