diff options
Diffstat (limited to 'modules/pam_unix/pam_unix_passwd.c')
-rw-r--r-- | modules/pam_unix/pam_unix_passwd.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index c3417413..4a3784a5 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -67,6 +67,7 @@ #include <security/pam_modutil.h> #include "pam_inline.h" +#include "pam_i18n.h" #include "pam_cc_compat.h" #include "md5.h" #include "support.h" @@ -286,7 +287,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, DIAG_POP_IGNORE_CAST_QUAL; /* should not get here: exit with error */ - D(("helper binary is not available")); + pam_syslog(pamh, LOG_ERR, "failed to execute %s: %m", UPDATE_HELPER); _exit(PAM_AUTHINFO_UNAVAIL); } else if (child > 0) { /* wait for child */ @@ -339,25 +340,25 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, static int check_old_password(const char *forwho, const char *newpass) { - static char buf[16384]; + char *buf = NULL; char *s_pas; int retval = PAM_SUCCESS; FILE *opwfile; + size_t n = 0; size_t len = strlen(forwho); - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + opwfile = fopen(OLD_PASSWORDS_FILE, "re"); if (opwfile == NULL) return PAM_ABORT; - while (fgets(buf, 16380, opwfile)) { - if (!strncmp(buf, forwho, len) && (buf[len] == ':' || - buf[len] == ',')) { + for (; getline(&buf, &n, opwfile) != -1; pam_overwrite_n(buf, n)) { + if (!strncmp(buf, forwho, len) && buf[len] == ':') { char *sptr; buf[strlen(buf) - 1] = '\0'; - /* s_luser = */ strtok_r(buf, ":,", &sptr); - /* s_uid = */ strtok_r(NULL, ":,", &sptr); - /* s_npas = */ strtok_r(NULL, ":,", &sptr); - s_pas = strtok_r(NULL, ":,", &sptr); + /* s_luser = */ strtok_r(buf, ":", &sptr); + /* s_uid = */ strtok_r(NULL, ":", &sptr); + /* s_npas = */ strtok_r(NULL, ":", &sptr); + s_pas = strtok_r(NULL, ",", &sptr); while (s_pas != NULL) { char *md5pass = Goodcrypt_md5(newpass, s_pas); if (md5pass == NULL || !strcmp(md5pass, s_pas)) { @@ -365,12 +366,14 @@ static int check_old_password(const char *forwho, const char *newpass) retval = PAM_AUTHTOK_ERR; break; } - s_pas = strtok_r(NULL, ":,", &sptr); + s_pas = strtok_r(NULL, ",", &sptr); _pam_delete(md5pass); } break; } } + pam_overwrite_n(buf, n); + free(buf); fclose(opwfile); return retval; @@ -572,9 +575,10 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh remark = _("You must choose a shorter password."); D(("length exceeded [%s]", remark)); } else if (off(UNIX__IAMROOT, ctrl)) { - if ((int)strlen(pass_new) < pass_min_len) + if ((int)strlen(pass_new) < pass_min_len) { remark = _("You must choose a longer password."); - D(("length check [%s]", remark)); + D(("length check [%s]", remark)); + } if (on(UNIX_REMEMBER_PASSWD, ctrl)) { if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR) remark = _("Password has been already used. Choose another."); @@ -600,6 +604,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) int remember = -1; int rounds = 0; int pass_min_len = 0; + struct passwd *pwd; /* <DO NOT free() THESE> */ const char *user; @@ -645,20 +650,16 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) * getpwnam() doesn't tell you *where* the information it gives you * came from, nor should it. That's our job. */ - if (_unix_comesfromsource(pamh, user, 1, on(UNIX_NIS, ctrl)) == 0) { + if (_unix_getpwnam(pamh, user, 1, on(UNIX_NIS, ctrl), &pwd) == 0) { pam_syslog(pamh, LOG_DEBUG, "user \"%s\" does not exist in /etc/passwd%s", user, on(UNIX_NIS, ctrl) ? " or NIS" : ""); return PAM_USER_UNKNOWN; - } else { - struct passwd *pwd; - _unix_getpwnam(pamh, user, 1, 1, &pwd); - if (pwd == NULL) { - pam_syslog(pamh, LOG_DEBUG, - "user \"%s\" has corrupted passwd entry", - user); - return PAM_USER_UNKNOWN; - } + } else if (pwd == NULL) { + pam_syslog(pamh, LOG_DEBUG, + "user \"%s\" has corrupted passwd entry", + user); + return PAM_USER_UNKNOWN; } /* @@ -697,7 +698,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) } else { D(("process run by root so do nothing this time around")); pass_old = NULL; - retval = PAM_SUCCESS; /* root doesn't have too */ + retval = PAM_SUCCESS; /* root doesn't have to */ } if (retval != PAM_SUCCESS) { @@ -779,7 +780,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) * password is acceptable. */ - if (*(const char *)pass_new == '\0') { /* "\0" password = NULL */ + if (*pass_new == '\0') { /* "\0" password = NULL */ pass_new = NULL; } retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, |