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