include aculib in cleanup
[unix-history] / usr / src / usr.bin / passwd / passwd.c
CommitLineData
252e456d 1#ifndef lint
9a59f452 2static char sccsid[] = "@(#)passwd.c 4.3 (Berkeley) %G%";
252e456d
SL
3#endif
4
5/*
9a59f452
SL
6 * Enter a password in the password file.
7 * This program should be suid with an owner
8 * with write permission on /etc/passwd.
252e456d
SL
9 */
10#include <sys/file.h>
11
12#include <stdio.h>
13#include <signal.h>
14#include <pwd.h>
15#include <errno.h>
16
17char passwd[] = "/etc/passwd";
18char temp[] = "/etc/ptmp";
19struct passwd *pwd;
20struct passwd *getpwent();
21int endpwent();
22char *strcpy();
23char *crypt();
24char *getpass();
25char *getlogin();
26char *pw;
27char pwbuf[10];
28extern int errno;
29
30main(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 }
69tryagain:
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) {
252e456d
SL
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);
9a59f452 128 fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
252e456d
SL
129 if (fd < 0) {
130 fprintf(stderr, "passwd: ");
9a59f452 131 if (errno == EEXIST)
252e456d
SL
132 fprintf(stderr, "password file busy - try again.\n");
133 else
134 perror(temp);
135 exit(1);
136 }
137 signal(SIGTSTP, SIG_IGN);
138 if ((tf = fdopen(fd, "w")) == NULL) {
139 fprintf(stderr, "passwd: fdopen failed?\n");
140 exit(1);
141 }
142 /*
143 * Copy passwd to temp, replacing matching lines
144 * with new password.
145 */
146 while ((pwd = getpwent()) != NULL) {
147 if (strcmp(pwd->pw_name,uname) == 0) {
148 u = getuid();
149 if (u && u != pwd->pw_uid) {
150 fprintf(stderr, "passwd: permission denied.\n");
151 unlink(temp);
152 exit(1);
153 }
154 pwd->pw_passwd = pw;
155 if (pwd->pw_gecos[0] == '*')
156 pwd->pw_gecos++;
157 }
158 fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
159 pwd->pw_name,
160 pwd->pw_passwd,
161 pwd->pw_uid,
162 pwd->pw_gid,
163 pwd->pw_gecos,
164 pwd->pw_dir,
165 pwd->pw_shell);
166 }
167 endpwent();
168 if (rename(temp, passwd) < 0) {
169 fprintf(stderr, "passwd: "); perror("rename");
170 unlink(temp);
171 exit(1);
172 }
252e456d
SL
173 fclose(tf);
174}