diff options
author | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 17:53:41 -0800 |
---|---|---|
committer | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 18:17:08 -0800 |
commit | 212b52cf29c06cc209bc8ac0540dbab1acdf1464 (patch) | |
tree | 58da0bf39f5c4122e4a1b4da20fdeea52b97a671 /modules/pam_unix/passverify.c | |
parent | 9c52e721044e7501c3d4567b36d222dc7326224a (diff) | |
parent | 56c8282d128fb484ffc77dff73abf42229b291d3 (diff) | |
download | pam-212b52cf29c06cc209bc8ac0540dbab1acdf1464.tar.gz pam-212b52cf29c06cc209bc8ac0540dbab1acdf1464.tar.bz2 pam-212b52cf29c06cc209bc8ac0540dbab1acdf1464.zip |
New upstream version 1.1.0
Diffstat (limited to 'modules/pam_unix/passverify.c')
-rw-r--r-- | modules/pam_unix/passverify.c | 160 |
1 files changed, 87 insertions, 73 deletions
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 6d588e63..8cf95c33 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -19,7 +19,9 @@ #include <sys/time.h> #include <sys/stat.h> #include <fcntl.h> -#ifdef HAVE_CRYPT_H +#ifdef HAVE_LIBXCRYPT +#include <xcrypt.h> +#elif defined(HAVE_CRYPT_H) #include <crypt.h> #endif @@ -117,7 +119,7 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) p = NULL; /* no longer needed here */ /* the moment of truth -- do we agree with the password? */ - D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + D(("comparing state of pp[%s] and hash[%s]", pp, hash)); if (pp && strcmp(pp, hash) == 0) { retval = PAM_SUCCESS; @@ -149,15 +151,8 @@ is_pwd_shadowed(const struct passwd *pwd) return 0; } -#ifdef HELPER_COMPILE -int -get_account_info(const char *name, - struct passwd **pwd, struct spwd **spwdent) -#else -int -get_account_info(pam_handle_t *pamh, const char *name, - struct passwd **pwd, struct spwd **spwdent) -#endif +PAMH_ARG_DECL(int get_account_info, + const char *name, struct passwd **pwd, struct spwd **spwdent) { /* UNIX passwords area */ *pwd = pam_modutil_getpwnam(pamh, name); /* Get password file entry... */ @@ -217,24 +212,13 @@ get_account_info(pam_handle_t *pamh, const char *name, return PAM_SUCCESS; } -#ifdef HELPER_COMPILE -int -get_pwd_hash(const char *name, - struct passwd **pwd, char **hash) -#else -int -get_pwd_hash(pam_handle_t *pamh, const char *name, - struct passwd **pwd, char **hash) -#endif +PAMH_ARG_DECL(int get_pwd_hash, + const char *name, struct passwd **pwd, char **hash) { int retval; struct spwd *spwdent = NULL; -#ifdef HELPER_COMPILE - retval = get_account_info(name, pwd, &spwdent); -#else - retval = get_account_info(pamh, name, pwd, &spwdent); -#endif + retval = get_account_info(PAMH_ARG(name, pwd, &spwdent)); if (retval != PAM_SUCCESS) { return retval; } @@ -249,13 +233,8 @@ get_pwd_hash(pam_handle_t *pamh, const char *name, return PAM_SUCCESS; } -#ifdef HELPER_COMPILE -int -check_shadow_expiry(struct spwd *spent, int *daysleft) -#else -int -check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft) -#endif +PAMH_ARG_DECL(int check_shadow_expiry, + struct spwd *spent, int *daysleft) { long int curdays; *daysleft = -1; @@ -293,8 +272,16 @@ check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft) *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); D(("warn before expiry")); } + if ((curdays - spent->sp_lstchg < spent->sp_min) + && (spent->sp_min != -1)) { + /* + * The last password change was too recent. This error will be ignored + * if no password change is attempted. + */ + D(("password change too recent")); + return PAM_AUTHTOK_ERR; + } return PAM_SUCCESS; - } /* passwd/salt conversion macros */ @@ -384,17 +371,19 @@ crypt_md5_wrapper(const char *pass_new) return cp; } -char * -create_password_hash(const char *password, unsigned int ctrl, int rounds) +PAMH_ARG_DECL(char * create_password_hash, + const char *password, unsigned int ctrl, int rounds) { const char *algoid; char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ char *sp; if (on(UNIX_MD5_PASS, ctrl)) { + /* algoid = "$1" */ return crypt_md5_wrapper(password); - } - if (on(UNIX_SHA256_PASS, ctrl)) { + } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { + algoid = "$2a$"; + } else if (on(UNIX_SHA256_PASS, ctrl)) { algoid = "$5$"; } else if (on(UNIX_SHA512_PASS, ctrl)) { algoid = "$6$"; @@ -414,17 +403,35 @@ create_password_hash(const char *password, unsigned int ctrl, int rounds) return crypted; } - sp = stpcpy(salt, algoid); - if (on(UNIX_ALGO_ROUNDS, ctrl)) { - sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds); +#ifdef HAVE_CRYPT_GENSALT_RN + if (on(UNIX_BLOWFISH_PASS, ctrl)) { + char entropy[17]; + crypt_make_salt(entropy, sizeof(entropy) - 1); + sp = crypt_gensalt_rn(algoid, rounds, + entropy, sizeof(entropy), + salt, sizeof(salt)); + } else { +#endif + sp = stpcpy(salt, algoid); + if (on(UNIX_ALGO_ROUNDS, ctrl)) { + sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds); + } + crypt_make_salt(sp, 8); + /* For now be conservative so the resulting hashes + * are not too long. 8 bytes of salt prevents dictionary + * attacks well enough. */ +#ifdef HAVE_CRYPT_GENSALT_RN } - crypt_make_salt(sp, 8); - /* For now be conservative so the resulting hashes - * are not too long. 8 bytes of salt prevents dictionary - * attacks well enough. */ +#endif sp = crypt(password, salt); if (strncmp(algoid, sp, strlen(algoid)) != 0) { - /* libc doesn't know the algorithm, use MD5 */ + /* libxcrypt/libc doesn't know the algorithm, use MD5 */ + pam_syslog(pamh, LOG_ERR, + "Algo %s not supported by the crypto backend, " + "falling back to MD5\n", + on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : + on(UNIX_SHA256_PASS, ctrl) ? "sha256" : + on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); memset(sp, '\0', strlen(sp)); return crypt_md5_wrapper(password); } @@ -535,9 +542,15 @@ unlock_pwdf(void) } #endif +#ifdef HELPER_COMPILE int save_old_password(const char *forwho, const char *oldpass, int howmany) +#else +int +save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, + int howmany) +#endif { static char buf[16384]; static char nbuf[16384]; @@ -653,7 +666,7 @@ save_old_password(const char *forwho, const char *oldpass, fclose(opwfile); if (!found) { - pwd = getpwnam(forwho); + pwd = pam_modutil_getpwnam(pamh, forwho); if (pwd == NULL) { err = 1; } else { @@ -667,8 +680,13 @@ save_old_password(const char *forwho, const char *oldpass, } } + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to old passwords file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to old passwords file: %m")); + D(("fclose error writing entries to old passwords file: %m")); err = 1; } @@ -695,13 +713,8 @@ done: } } -#ifdef HELPER_COMPILE -int -unix_update_passwd(const char *forwho, const char *towhat) -#else -int -unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat) -#endif +PAMH_ARG_DECL(int unix_update_passwd, + const char *forwho, const char *towhat) { struct passwd *tmpent = NULL; struct stat st; @@ -787,19 +800,20 @@ unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat) } fclose(opwfile); + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to password file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to password file: %m")); + D(("fclose error writing entries to password file: %m")); err = 1; } done: if (!err) { if (!rename(PW_TMPFILE, "/etc/passwd")) -#ifdef HELPER_COMPILE - helper_log_err( -#else pam_syslog(pamh, -#endif LOG_NOTICE, "password changed for %s", forwho); else err = 1; @@ -822,13 +836,8 @@ done: } } -#ifdef HELPER_COMPILE -int -unix_update_shadow(const char *forwho, char *towhat) -#else -int -unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) -#endif +PAMH_ARG_DECL(int unix_update_shadow, + const char *forwho, char *towhat) { struct spwd *spwdent = NULL, *stmpent = NULL; struct stat st; @@ -917,19 +926,20 @@ unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) } fclose(opwfile); + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to shadow file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to shadow file: %m")); + D(("fclose error writing entries to shadow file: %m")); err = 1; } done: if (!err) { if (!rename(SH_TMPFILE, "/etc/shadow")) -#ifdef HELPER_COMPILE - helper_log_err( -#else pam_syslog(pamh, -#endif LOG_NOTICE, "password changed for %s", forwho); else err = 1; @@ -999,8 +1009,12 @@ su_sighandler(int sig) { #ifndef SA_RESETHAND /* emulate the behaviour of the SA_RESETHAND flag */ - if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) - signal(sig, SIG_DFL); + if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) { + struct sigaction sa; + memset(&sa, '\0', sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigaction(sig, &sa, NULL); + } #endif if (sig > 0) { _exit(sig); |