Commit | Line | Data |
---|---|---|
31cef89c | 1 | static 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 | ||
11 | char passwd[] = "/etc/passwd"; | |
12 | char temp[] = "/etc/ptmp"; | |
13 | struct passwd *pwd; | |
14 | struct passwd *getpwent(); | |
15 | int endpwent(); | |
16 | char *strcpy(); | |
17 | char *crypt(); | |
18 | char *getpass(); | |
19 | char *getlogin(); | |
20 | char *pw; | |
21 | char pwbuf[10]; | |
22 | char buf[BUFSIZ]; | |
23 | ||
24 | main(argc, argv) | |
25 | char *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 | } | |
66 | tryagn: | |
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 | ||
169 | out: | |
170 | unlink(temp); | |
171 | ||
172 | bex: | |
173 | exit(1); | |
174 | } |