BSD 4 release
[unix-history] / usr / src / cmd / passwd.c
CommitLineData
31cef89c 1static char *sccsid = "@(#)passwd.c 4.1 (Berkeley) 10/1/80";
c2b52c9d
BJ
2/*
3 * enter a password in the password file
4 * this program should be suid with owner
5 * with an owner with write permission on /etc/passwd
6 */
7#include <stdio.h>
8#include <signal.h>
9#include <pwd.h>
10
11char passwd[] = "/etc/passwd";
12char temp[] = "/etc/ptmp";
13struct passwd *pwd;
14struct passwd *getpwent();
15int endpwent();
16char *strcpy();
17char *crypt();
18char *getpass();
19char *getlogin();
20char *pw;
21char pwbuf[10];
22char buf[BUFSIZ];
23
24main(argc, argv)
25char *argv[];
26{
27 char *p;
28 int i;
29 char saltc[2];
30 long salt;
31 int u,fi,fo;
32 int insist;
33 int ok, flags;
34 int c;
35 int pwlen;
36 FILE *tf;
37 char *uname;
38
39 insist = 0;
40 if(argc < 2) {
41 if ((uname = getlogin()) == NULL) {
42 printf ("Usage: passwd user\n");
43 goto bex;
44 } else {
45 printf("Changing password for %s\n", uname);
46 }
47 } else {
48 uname = argv[1];
49 }
50 while(((pwd=getpwent()) != NULL)&&(strcmp(pwd->pw_name,uname)!=0));
51 u = getuid();
52 if((pwd==NULL) || (u!=0 && u != pwd->pw_uid))
53 {
54 printf("Permission denied.\n");
55 goto bex;
56 }
57 endpwent();
58 if (pwd->pw_passwd[0] && u != 0) {
59 strcpy(pwbuf, getpass("Old password:"));
60 pw = crypt(pwbuf, pwd->pw_passwd);
61 if(strcmp(pw, pwd->pw_passwd) != 0) {
62 printf("Sorry.\n");
63 goto bex;
64 }
65 }
66tryagn:
67 strcpy(pwbuf, getpass("New password:"));
68 pwlen = strlen(pwbuf);
69 if (pwlen == 0) {
70 printf("Password unchanged.\n");
71 goto bex;
72 }
73 ok = 0;
74 flags = 0;
75 p = pwbuf;
76 while(c = *p++){
77 if(c>='a' && c<='z') flags |= 2;
78 else if(c>='A' && c<='Z') flags |= 4;
79 else if(c>='0' && c<='9') flags |= 1;
80 else flags |= 8;
81 }
82 if(flags >=7 && pwlen>= 4) ok = 1;
83 if(((flags==2)||(flags==4)) && pwlen>=6) ok = 1;
84 if(((flags==3)||(flags==5)||(flags==6))&&pwlen>=5) ok = 1;
85
86 if((ok==0) && (insist<2)){
87 if(flags==1)
88 printf("Please use at least one non-numeric character.\n");
89 else
90 printf("Please use a longer password.\n");
91 insist++;
92 goto tryagn;
93 }
94
95 if (strcmp(pwbuf,getpass("Retype new password:")) != 0) {
96 printf ("Mismatch - password unchanged.\n");
97 goto bex;
98 }
99
100 time(&salt);
101 salt += getpid();
102
103 saltc[0] = salt & 077;
104 saltc[1] = (salt>>6) & 077;
105 for(i=0;i<2;i++){
106 c = saltc[i] + '.';
107 if(c>'9') c += 7;
108 if(c>'Z') c += 6;
109 saltc[i] = c;
110 }
111 pw = crypt(pwbuf, saltc);
112 signal(SIGHUP, SIG_IGN);
113 signal(SIGINT, SIG_IGN);
114 signal(SIGQUIT, SIG_IGN);
115
116 if(access(temp, 0) >= 0) {
117 printf("Temporary file busy -- try again\n");
118 goto bex;
119 }
31cef89c 120 signal(SIGTSTP, SIG_IGN);
c2b52c9d
BJ
121 close(creat(temp,0600));
122 if((tf=fopen(temp,"w")) == NULL) {
123 printf("Cannot create temporary file\n");
124 goto bex;
125 }
126
127/*
128 * copy passwd to temp, replacing matching lines
129 * with new password.
130 */
131
132 while((pwd=getpwent()) != NULL) {
133 if(strcmp(pwd->pw_name,uname) == 0) {
134 u = getuid();
135 if(u != 0 && u != pwd->pw_uid) {
136 printf("Permission denied.\n");
137 goto out;
138 }
139 pwd->pw_passwd = pw;
140 if (pwd->pw_gecos[0] == '*')
141 pwd->pw_gecos++;
142 }
143 fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
144 pwd->pw_name,
145 pwd->pw_passwd,
146 pwd->pw_uid,
147 pwd->pw_gid,
148 pwd->pw_gecos,
149 pwd->pw_dir,
150 pwd->pw_shell);
151 }
152 endpwent();
153 fclose(tf);
154
155/*
156 * copy temp back to passwd file
157 */
158
159 if((fi=open(temp,0)) < 0) {
160 printf("Temp file disappeared!\n");
161 goto out;
162 }
163 if((fo=creat(passwd, 0644)) < 0) {
164 printf("Cannot recreat passwd file.\n");
165 goto out;
166 }
167 while((u=read(fi,buf,sizeof(buf))) > 0) write(fo,buf,u);
168
169out:
170 unlink(temp);
171
172bex:
173 exit(1);
174}