Lines 10-15
Link Here
|
10 |
* Shadow file update code taken from shadow-960810 by John F. Haugh |
10 |
* Shadow file update code taken from shadow-960810 by John F. Haugh |
11 |
* II <jfh@rpp386.cactus.org> and Marek Michalkiewicz |
11 |
* II <jfh@rpp386.cactus.org> and Marek Michalkiewicz |
12 |
* <marekm@i17linuxb.ists.pwr.wroc.pl> |
12 |
* <marekm@i17linuxb.ists.pwr.wroc.pl> |
|
|
13 |
* |
14 |
* Now getstate() takes care of PAM message interpretation, better handling |
15 |
* of PAM LDAP and Cracklib modules by Jinesh K J <jinesh_kj@rediffmail.com> |
13 |
* |
16 |
* |
14 |
* See README for more information. |
17 |
* See README for more information. |
15 |
*/ |
18 |
*/ |
Lines 82-94
Link Here
|
82 |
#endif |
85 |
#endif |
83 |
#endif |
86 |
#endif |
84 |
|
87 |
|
85 |
/* need to be global for poppassd_conv */ |
|
|
86 |
char oldpass[BUFSIZE]; |
87 |
char newpass[BUFSIZE]; |
88 |
#define POP_OLDPASS 0 |
88 |
#define POP_OLDPASS 0 |
89 |
#define POP_NEWPASS 1 |
89 |
#define POP_NEWPASS 1 |
90 |
#define POP_SKIPASS 2 |
90 |
#define POP_SKIPASS 2 |
91 |
short int pop_state = POP_OLDPASS; |
91 |
|
|
|
92 |
/* need to be global for poppassd_conv */ |
93 |
char oldpass[BUFSIZE]; |
94 |
char newpass[BUFSIZE]; |
92 |
|
95 |
|
93 |
void WriteToClient (char *fmt, ...) |
96 |
void WriteToClient (char *fmt, ...) |
94 |
{ |
97 |
{ |
Lines 104-110
Link Here
|
104 |
void ReadFromClient (char *line) |
107 |
void ReadFromClient (char *line) |
105 |
{ |
108 |
{ |
106 |
char *sp; |
109 |
char *sp; |
107 |
int i; |
|
|
108 |
|
110 |
|
109 |
bzero(line, BUFSIZE); |
111 |
bzero(line, BUFSIZE); |
110 |
fgets (line, BUFSIZE-1, stdin); |
112 |
fgets (line, BUFSIZE-1, stdin); |
Lines 117-165
Link Here
|
117 |
line[BUFSIZE-1] = '\0'; |
119 |
line[BUFSIZE-1] = '\0'; |
118 |
} |
120 |
} |
119 |
|
121 |
|
|
|
122 |
static inline int getstate(const char *msg) |
123 |
{ |
124 |
/* Interpret possible PAM messages (not including errors) */ |
125 |
if(!strcmp(msg, "Password: ")) |
126 |
return POP_OLDPASS; |
127 |
if(!strcmp(msg, "Enter login(LDAP) password: ")) |
128 |
return POP_OLDPASS; |
129 |
|
130 |
if(!strcmp(msg, "New password: ")) |
131 |
return POP_NEWPASS; |
132 |
if(!strcmp(msg, "Re-enter new password: ")) |
133 |
return POP_NEWPASS; |
134 |
if(!strcmp(msg, "Enter new UNIX password: ")) |
135 |
return POP_NEWPASS; |
136 |
if(!strcmp(msg, "Retype new UNIX password: ")) |
137 |
return POP_NEWPASS; |
138 |
if(!strcmp(msg, "New UNIX password: ")) |
139 |
return POP_NEWPASS; |
140 |
|
141 |
WriteToClient("Unknown PAM Message: %s", msg); // We should not ever reach here. |
142 |
|
143 |
return POP_SKIPASS; |
144 |
} |
145 |
|
120 |
int poppassd_conv(num_msg, msg, resp, appdata_ptr) |
146 |
int poppassd_conv(num_msg, msg, resp, appdata_ptr) |
121 |
int num_msg; |
147 |
int num_msg; |
122 |
const struct pam_message **msg; |
148 |
const struct pam_message **msg; |
123 |
struct pam_response **resp; |
149 |
struct pam_response **resp; |
124 |
void *appdata_ptr; |
150 |
void *appdata_ptr; |
|
|
151 |
|
152 |
|
125 |
{ |
153 |
{ |
126 |
int i; |
154 |
int i; |
127 |
struct pam_response *r = malloc(sizeof(struct pam_response) * num_msg); |
155 |
struct pam_response *r; |
128 |
|
156 |
|
129 |
if(num_msg <= 0) |
157 |
if(num_msg <= 0) |
130 |
return(PAM_CONV_ERR); |
158 |
return(PAM_CONV_ERR); |
131 |
|
159 |
|
|
|
160 |
r = malloc(sizeof(struct pam_response) * num_msg); |
132 |
if(r == NULL) |
161 |
if(r == NULL) |
133 |
return(PAM_CONV_ERR); |
162 |
return(PAM_CONV_ERR); |
134 |
|
163 |
|
135 |
for(i=0; i<num_msg; i++) { |
164 |
for(i = 0; i < num_msg; i++) { |
136 |
if(msg[i]->msg_style == PAM_ERROR_MSG) { |
165 |
if(msg[i]->msg_style == PAM_ERROR_MSG) { |
137 |
WriteToClient ("500 PAM error: %s", msg[i]->msg); |
166 |
WriteToClient ("500 PAM error: %s", msg[i]->msg); |
138 |
syslog(LOG_ERR, "PAM error: %s", msg[i]->msg); |
167 |
syslog(LOG_ERR, "PAM error: %s", msg[i]->msg); |
139 |
/* |
168 |
/* |
140 |
* If there is an error, we don't want to be sending in |
169 |
* If there is an error, we don't want to be sending in |
141 |
* anything more, so set pop_state to invalid |
170 |
* anything more, so we quit after printing the error message. |
142 |
*/ |
171 |
*/ |
143 |
pop_state = POP_SKIPASS; |
172 |
exit(1); |
144 |
} |
173 |
} |
145 |
|
174 |
|
146 |
r[i].resp_retcode = 0; |
175 |
r[i].resp_retcode = 0; |
147 |
if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || |
176 |
if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || |
148 |
msg[i]->msg_style == PAM_PROMPT_ECHO_ON) |
177 |
msg[i]->msg_style == PAM_PROMPT_ECHO_ON) |
149 |
{ |
178 |
{ |
150 |
switch(pop_state) { |
179 |
switch(getstate(msg[i]->msg)) |
151 |
case POP_OLDPASS: r[i].resp = strdup(oldpass); |
180 |
{ |
152 |
break; |
181 |
case POP_OLDPASS: |
153 |
case POP_NEWPASS: r[i].resp = strdup(newpass); |
182 |
r[i].resp = strdup(oldpass); |
154 |
break; |
183 |
break; |
155 |
case POP_SKIPASS: r[i].resp = NULL; |
184 |
case POP_NEWPASS: |
156 |
break; |
185 |
r[i].resp = strdup(newpass); |
157 |
default: syslog(LOG_ERR, "PAM error: too many switches (state=%d)", pop_state); |
186 |
break; |
|
|
187 |
case POP_SKIPASS: |
188 |
r[i].resp = NULL; |
189 |
break; |
190 |
default: |
191 |
syslog(LOG_ERR, "PAM error: unknown state - this should not happen"); |
192 |
} |
193 |
} else |
194 |
{ |
195 |
r[i].resp = strdup(""); |
158 |
} |
196 |
} |
159 |
} else |
|
|
160 |
{ |
161 |
r[i].resp = strdup(""); |
162 |
} |
163 |
} |
197 |
} |
164 |
|
198 |
|
165 |
*resp = r; |
199 |
*resp = r; |
Lines 175-190
Link Here
|
175 |
{ |
209 |
{ |
176 |
char line[BUFSIZE]; |
210 |
char line[BUFSIZE]; |
177 |
char user[BUFSIZE]; |
211 |
char user[BUFSIZE]; |
178 |
char emess[BUFSIZE]; |
|
|
179 |
char *slavedev; |
180 |
struct passwd *pw, *getpwnam(); |
212 |
struct passwd *pw, *getpwnam(); |
181 |
struct spwd *sp; |
|
|
182 |
int c, master; |
183 |
pid_t pid, wpid; |
184 |
int wstat; |
185 |
int ret; |
186 |
pam_handle_t *pamh=NULL; |
213 |
pam_handle_t *pamh=NULL; |
187 |
char *item=oldpass; |
|
|
188 |
|
214 |
|
189 |
*user = *oldpass = *newpass = 0; |
215 |
*user = *oldpass = *newpass = 0; |
190 |
|
216 |
|
Lines 222-227
Link Here
|
222 |
WriteToClient("500 Password required."); |
248 |
WriteToClient("500 Password required."); |
223 |
exit(1); |
249 |
exit(1); |
224 |
} |
250 |
} |
|
|
251 |
|
225 |
if(pam_authenticate(pamh, 0) != PAM_SUCCESS) |
252 |
if(pam_authenticate(pamh, 0) != PAM_SUCCESS) |
226 |
{ |
253 |
{ |
227 |
WriteToClient ("500 Old password is incorrect."); |
254 |
WriteToClient ("500 Old password is incorrect."); |
Lines 233-246
Link Here
|
233 |
|
260 |
|
234 |
pw=getpwnam(user); |
261 |
pw=getpwnam(user); |
235 |
|
262 |
|
236 |
if(pw->pw_uid<POP_MIN_UID || pw == NULL) { |
263 |
if(pw == NULL || pw->pw_uid<POP_MIN_UID) { |
237 |
WriteToClient("500 Old password is incorrect."); |
264 |
WriteToClient("500 Old password is incorrect."); |
238 |
syslog(LOG_ERR, "failed attempt to change password for %s", user); |
265 |
syslog(LOG_ERR, "failed attempt to change password for %s", user); |
239 |
exit(1); |
266 |
exit(1); |
240 |
} |
267 |
} |
241 |
|
268 |
|
242 |
pop_state = POP_NEWPASS; |
|
|
243 |
|
244 |
WriteToClient ("200 Your new password please."); |
269 |
WriteToClient ("200 Your new password please."); |
245 |
ReadFromClient (line); |
270 |
ReadFromClient (line); |
246 |
sscanf (line, "newpass %" MAX_LEN_PASS "c", newpass); |
271 |
sscanf (line, "newpass %" MAX_LEN_PASS "c", newpass); |
Lines 269-273
Link Here
|
269 |
WriteToClient("200 Bye."); |
294 |
WriteToClient("200 Bye."); |
270 |
closelog(); |
295 |
closelog(); |
271 |
exit(0); |
296 |
exit(0); |
272 |
} |
297 |
} |
273 |
|
|
|