|
|
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.