--- poppassd-1.8.5/poppassd.c 2004-12-02 19:57:43.000000000 +0530 +++ poppassd-1.8.6/poppassd.c 2006-08-18 17:24:50.000000000 +0530 @@ -10,6 +10,9 @@ * Shadow file update code taken from shadow-960810 by John F. Haugh * II and Marek Michalkiewicz * + * + * Now getstate() takes care of PAM message interpretation, better handling + * of PAM LDAP and Cracklib modules by Jinesh K J * * See README for more information. */ @@ -82,13 +85,13 @@ #endif #endif -/* need to be global for poppassd_conv */ -char oldpass[BUFSIZE]; -char newpass[BUFSIZE]; #define POP_OLDPASS 0 #define POP_NEWPASS 1 #define POP_SKIPASS 2 -short int pop_state = POP_OLDPASS; + +/* need to be global for poppassd_conv */ +char oldpass[BUFSIZE]; +char newpass[BUFSIZE]; void WriteToClient (char *fmt, ...) { @@ -104,7 +107,6 @@ void ReadFromClient (char *line) { char *sp; - int i; bzero(line, BUFSIZE); fgets (line, BUFSIZE-1, stdin); @@ -117,49 +119,81 @@ line[BUFSIZE-1] = '\0'; } +static inline int getstate(const char *msg) +{ + /* Interpret possible PAM messages (not including errors) */ + if(!strcmp(msg, "Password: ")) + return POP_OLDPASS; + if(!strcmp(msg, "Enter login(LDAP) password: ")) + return POP_OLDPASS; + + if(!strcmp(msg, "New password: ")) + return POP_NEWPASS; + if(!strcmp(msg, "Re-enter new password: ")) + return POP_NEWPASS; + if(!strcmp(msg, "Enter new UNIX password: ")) + return POP_NEWPASS; + if(!strcmp(msg, "Retype new UNIX password: ")) + return POP_NEWPASS; + if(!strcmp(msg, "New UNIX password: ")) + return POP_NEWPASS; + + WriteToClient("Unknown PAM Message: %s", msg); // We should not ever reach here. + + return POP_SKIPASS; +} + int poppassd_conv(num_msg, msg, resp, appdata_ptr) int num_msg; const struct pam_message **msg; struct pam_response **resp; void *appdata_ptr; + + { int i; - struct pam_response *r = malloc(sizeof(struct pam_response) * num_msg); + struct pam_response *r; if(num_msg <= 0) return(PAM_CONV_ERR); + r = malloc(sizeof(struct pam_response) * num_msg); if(r == NULL) return(PAM_CONV_ERR); - for(i=0; imsg_style == PAM_ERROR_MSG) { WriteToClient ("500 PAM error: %s", msg[i]->msg); syslog(LOG_ERR, "PAM error: %s", msg[i]->msg); /* * If there is an error, we don't want to be sending in - * anything more, so set pop_state to invalid + * anything more, so we quit after printing the error message. */ - pop_state = POP_SKIPASS; + exit(1); } - r[i].resp_retcode = 0; - if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || + r[i].resp_retcode = 0; + if(msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || msg[i]->msg_style == PAM_PROMPT_ECHO_ON) - { - switch(pop_state) { - case POP_OLDPASS: r[i].resp = strdup(oldpass); - break; - case POP_NEWPASS: r[i].resp = strdup(newpass); - break; - case POP_SKIPASS: r[i].resp = NULL; - break; - default: syslog(LOG_ERR, "PAM error: too many switches (state=%d)", pop_state); + { + switch(getstate(msg[i]->msg)) + { + case POP_OLDPASS: + r[i].resp = strdup(oldpass); + break; + case POP_NEWPASS: + r[i].resp = strdup(newpass); + break; + case POP_SKIPASS: + r[i].resp = NULL; + break; + default: + syslog(LOG_ERR, "PAM error: unknown state - this should not happen"); + } + } else + { + r[i].resp = strdup(""); } - } else - { - r[i].resp = strdup(""); - } } *resp = r; @@ -175,16 +209,8 @@ { char line[BUFSIZE]; char user[BUFSIZE]; - char emess[BUFSIZE]; - char *slavedev; struct passwd *pw, *getpwnam(); - struct spwd *sp; - int c, master; - pid_t pid, wpid; - int wstat; - int ret; pam_handle_t *pamh=NULL; - char *item=oldpass; *user = *oldpass = *newpass = 0; @@ -222,6 +248,7 @@ WriteToClient("500 Password required."); exit(1); } + if(pam_authenticate(pamh, 0) != PAM_SUCCESS) { WriteToClient ("500 Old password is incorrect."); @@ -233,14 +260,12 @@ pw=getpwnam(user); - if(pw->pw_uidpw_uid