From f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Thu, 15 Nov 2018 15:01:57 +0100 Subject: pam_unix: Use bcrypt b-variant for computing new hashes. Bcrypt hashes used the "$2a$" prefix since 1997. However, in 2011 an implementation bug was discovered in bcrypt affecting the handling of characters in passphrases with the 8th bit set. Besides fixing the bug, OpenBSD 5.5 introduced the "$2b$" prefix for a behavior that exactly matches crypt_blowfish's "$2y$", and the crypt_blowfish implementation supports it as well since v1.1. That said new computed bcrypt hashes should use the "$2b$" prefix. * modules/pam_unix/passverify.c: Use bcrypt b-variant. --- modules/pam_unix/passverify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 9c1771e2..1f433b3a 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -385,7 +385,7 @@ PAMH_ARG_DECL(char * create_password_hash, /* algoid = "$1" */ return crypt_md5_wrapper(password); } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { - algoid = "$2a$"; + algoid = "$2b$"; } else if (on(UNIX_SHA256_PASS, ctrl)) { algoid = "$5$"; } else if (on(UNIX_SHA512_PASS, ctrl)) { -- cgit v1.2.3 From dce80b3f11b3c3aa137d18f22699809094dd64b6 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Thu, 15 Nov 2018 15:58:56 +0100 Subject: pam_unix: Prefer a gensalt function, that supports auto entropy. * modules/pam_unix/pam_unix_passwd.c: Initialize rounds parameter to 0. * modules/pam_unix/passverify.c: Prefer gensalt with auto entropy. * modules/pam_unix/support.c: Fix sanitizing of rounds parameter. --- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/passverify.c | 13 +++++++++++++ modules/pam_unix/support.c | 7 +++++-- 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 9d0aa733..f2c42513 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -603,7 +603,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) unsigned int ctrl, lctrl; int retval; int remember = -1; - int rounds = -1; + int rounds = 0; int pass_min_len = 0; /* */ diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 1f433b3a..0d2c8029 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -375,7 +375,12 @@ PAMH_ARG_DECL(char * create_password_hash, const char *password, unsigned int ctrl, int rounds) { const char *algoid; +#if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64 + /* Strings returned by crypt_gensalt_rn will be no longer than this. */ + char salt[CRYPT_GENSALT_OUTPUT_SIZE]; +#else char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ +#endif char *sp; #ifdef HAVE_CRYPT_R struct crypt_data *cdata = NULL; @@ -406,6 +411,13 @@ PAMH_ARG_DECL(char * create_password_hash, return crypted; } +#if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY + /* + * Any version of libcrypt supporting auto entropy is + * guaranteed to have crypt_gensalt_rn(). + */ + sp = crypt_gensalt_rn(algoid, rounds, NULL, 0, salt, sizeof(salt)); +#else #ifdef HAVE_CRYPT_GENSALT_R if (on(UNIX_BLOWFISH_PASS, ctrl)) { char entropy[17]; @@ -423,6 +435,7 @@ PAMH_ARG_DECL(char * create_password_hash, #ifdef HAVE_CRYPT_GENSALT_R } #endif +#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */ #ifdef HAVE_CRYPT_R sp = NULL; cdata = malloc(sizeof(*cdata)); diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index f2e28d35..753e5f89 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -175,6 +175,7 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, if (val) { *rounds = strtol(val, NULL, 10); + set(UNIX_ALGO_ROUNDS, ctrl); free (val); } } @@ -254,11 +255,13 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, if (*rounds < 4 || *rounds > 31) *rounds = 5; } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) { - if ((*rounds < 1000) || (*rounds == INT_MAX)) + if ((*rounds < 1000) || (*rounds == INT_MAX)) { /* don't care about bogus values */ + *rounds = 0; unset(UNIX_ALGO_ROUNDS, ctrl); - if (*rounds >= 10000000) + } else if (*rounds >= 10000000) { *rounds = 9999999; + { } } -- cgit v1.2.3 From 4da9febc39b955892a30686e8396785b96bb8ba5 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Thu, 15 Nov 2018 19:49:44 +0100 Subject: pam_unix: Add support for crypt_checksalt, if libcrypt supports it. libxcrypt v4.3 has added the crypt_checksalt function to whether the prefix at the begining of a given hash string refers to a supported hashing method. Future revisions of this function will add support to check whether the hashing method, the prefix refers to, was disabled or considered deprecated by the system's factory presets or system administrator. Furthermore it will be able to detect whether the parameters, which are used by the corresponding hashing method, being encoded in the hash string are not considered to be strong enough anymore. *modules/pam_unix/passverify.c: Add support for crypt_checksalt. --- modules/pam_unix/passverify.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 0d2c8029..95dfe528 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -244,7 +244,13 @@ PAMH_ARG_DECL(int check_shadow_expiry, D(("account expired")); return PAM_ACCT_EXPIRED; } +#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE + if (spent->sp_lstchg == 0 || + crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_LEGACY || + crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_TOO_CHEAP) { +#else if (spent->sp_lstchg == 0) { +#endif D(("need a new password")); *daysleft = 0; return PAM_NEW_AUTHTOK_REQD; @@ -255,10 +261,19 @@ PAMH_ARG_DECL(int check_shadow_expiry, spent->sp_namp); return PAM_SUCCESS; } +#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE + if (((curdays - spent->sp_lstchg > spent->sp_max) + && (curdays - spent->sp_lstchg > spent->sp_inact) + && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact) + && (spent->sp_max != -1) && (spent->sp_inact != -1)) + || (crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_DISABLED) + || (crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_INVALID)) { +#else if ((curdays - spent->sp_lstchg > spent->sp_max) && (curdays - spent->sp_lstchg > spent->sp_inact) && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact) && (spent->sp_max != -1) && (spent->sp_inact != -1)) { +#endif *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); D(("authtok expired")); return PAM_AUTHTOK_EXPIRED; -- cgit v1.2.3 From 16bd523f85ede9fa9115f80e826f2d803d7e61d4 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Thu, 15 Nov 2018 16:38:05 +0100 Subject: pam_unix: Add support for (gost-)yescrypt hashing methods. libxcrypt (v4.2 and later) has added support for the yescrypt hashing method; gost-yescrypt has been added in v4.3. * modules/pam_unix/pam_unix.8.xml: Documentation for (gost-)yescrypt. * modules/pam_unix/pam_unix_acct.c: Use 64 bit type for control flags. * modules/pam_unix/pam_unix_auth.c: Likewise. * modules/pam_unix/pam_unix_passwd.c: Likewise. * modules/pam_unix/pam_unix_sess.c: Likewise. * modules/pam_unix/passverify.c: Add support for (gost-)yescrypt. * modules/pam_unix/passverify.h: Use 64 bit type for control flags. * modules/pam_unix/support.c: Set sane rounds for (gost-)yescrypt. * modules/pam_unix/support.h: Add support for (gost-)yescrypt. --- modules/pam_unix/pam_unix.8.xml | 35 ++++++++++++- modules/pam_unix/pam_unix_acct.c | 4 +- modules/pam_unix/pam_unix_auth.c | 4 +- modules/pam_unix/pam_unix_passwd.c | 12 ++--- modules/pam_unix/pam_unix_sess.c | 4 +- modules/pam_unix/passverify.c | 8 ++- modules/pam_unix/passverify.h | 2 +- modules/pam_unix/support.c | 33 +++++++----- modules/pam_unix/support.h | 101 ++++++++++++++++++++----------------- 9 files changed, 128 insertions(+), 75 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index 1b318f11..cae2aeaa 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -331,14 +331,45 @@ + + + + + + + When a user changes their password next, + encrypt it with the gost-yescrypt algorithm. If the + gost-yescrypt algorithm is not known to the + crypt3 + function, + fall back to MD5. + + + + + + + + + + When a user changes their password next, + encrypt it with the yescrypt algorithm. If the + yescrypt algorithm is not known to the + crypt3 + function, + fall back to MD5. + + + - Set the optional number of rounds of the SHA256, SHA512 - and blowfish password hashing algorithms to + Set the optional number of rounds of the SHA256, SHA512, + blowfish, gost-yescrypt, and yescrypt password hashing + algorithms to n. diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index fbc84e2f..d8d084ac 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -62,7 +62,7 @@ #include "support.h" #include "passverify.h" -int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, +int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl, const char *user, int *daysleft) { int retval=0, child, fds[2]; @@ -185,7 +185,7 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { - unsigned int ctrl; + unsigned long long ctrl; const void *void_uname; const char *uname; int retval, daysleft; diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c index 9d9f709d..905fc66c 100644 --- a/modules/pam_unix/pam_unix_auth.c +++ b/modules/pam_unix/pam_unix_auth.c @@ -96,7 +96,7 @@ setcred_free (pam_handle_t *pamh UNUSED, void *ptr, int err UNUSED) int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { - unsigned int ctrl; + unsigned long long ctrl; int retval, *ret_data = NULL; const char *name; const char *p; @@ -194,7 +194,7 @@ pam_sm_setcred (pam_handle_t *pamh, int flags, { int retval; const void *pretval = NULL; - unsigned int ctrl; + unsigned long long ctrl; D(("called.")); diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index f2c42513..df4c1233 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -138,7 +138,7 @@ __taddr2port (const struct netconfig *nconf, const struct netbuf *nbuf) } #endif -static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) +static char *getNISserver(pam_handle_t *pamh, unsigned long long ctrl) { char *master; char *domainname; @@ -233,7 +233,7 @@ static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) #ifdef WITH_SELINUX -static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, +static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, const char *user, const char *fromwhat, const char *towhat, int remember) { int retval, child, fds[2]; @@ -388,7 +388,7 @@ static int check_old_password(const char *forwho, const char *newpass) static int _do_setpass(pam_handle_t* pamh, const char *forwho, const char *fromwhat, - char *towhat, unsigned int ctrl, int remember) + char *towhat, unsigned long long ctrl, int remember) { struct passwd *pwd = NULL; int retval = 0; @@ -512,7 +512,7 @@ done: return retval; } -static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned int ctrl) +static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned long long ctrl) { struct passwd *pwent = NULL; /* Password and shadow password */ struct spwd *spent = NULL; /* file entries for the user */ @@ -542,7 +542,7 @@ static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned in } static int _pam_unix_approve_pass(pam_handle_t * pamh - ,unsigned int ctrl + ,unsigned long long ctrl ,const char *pass_old ,const char *pass_new, int pass_min_len) @@ -600,7 +600,7 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { - unsigned int ctrl, lctrl; + unsigned long long ctrl, lctrl; int retval; int remember = -1; int rounds = 0; diff --git a/modules/pam_unix/pam_unix_sess.c b/modules/pam_unix/pam_unix_sess.c index 03e7dcd9..4b8af530 100644 --- a/modules/pam_unix/pam_unix_sess.c +++ b/modules/pam_unix/pam_unix_sess.c @@ -67,7 +67,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { char *user_name, *service; - unsigned int ctrl; + unsigned long long ctrl; int retval; const char *login_name; @@ -103,7 +103,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { char *user_name, *service; - unsigned int ctrl; + unsigned long long ctrl; int retval; D(("called.")); diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 95dfe528..39e2bfac 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -387,7 +387,7 @@ crypt_md5_wrapper(const char *pass_new) } PAMH_ARG_DECL(char * create_password_hash, - const char *password, unsigned int ctrl, int rounds) + const char *password, unsigned long long ctrl, int rounds) { const char *algoid; #if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64 @@ -404,6 +404,10 @@ PAMH_ARG_DECL(char * create_password_hash, if (on(UNIX_MD5_PASS, ctrl)) { /* algoid = "$1" */ return crypt_md5_wrapper(password); + } else if (on(UNIX_YESCRYPT_PASS, ctrl)) { + algoid = "$y$"; + } else if (on(UNIX_GOST_YESCRYPT_PASS, ctrl)) { + algoid = "$gy$"; } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { algoid = "$2b$"; } else if (on(UNIX_SHA256_PASS, ctrl)) { @@ -466,6 +470,8 @@ PAMH_ARG_DECL(char * create_password_hash, pam_syslog(pamh, LOG_ERR, "Algo %s not supported by the crypto backend, " "falling back to MD5\n", + on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" : + on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : on(UNIX_SHA256_PASS, ctrl) ? "sha256" : on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index caf7ae8a..086c28ac 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -66,7 +66,7 @@ read_passwords(int fd, int npass, char **passwords); #endif PAMH_ARG_DECL(char * create_password_hash, - const char *password, unsigned int ctrl, int rounds); + const char *password, unsigned long long ctrl, int rounds); PAMH_ARG_DECL(int get_account_info, const char *name, struct passwd **pwd, struct spwd **spwdent); diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 8cbc4217..6894288d 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -107,7 +107,7 @@ search_key (const char *key, const char *filename) /* this is a front-end for module-application conversations */ -int _make_remark(pam_handle_t * pamh, unsigned int ctrl, +int _make_remark(pam_handle_t * pamh, unsigned long long ctrl, int type, const char *text) { int retval = PAM_SUCCESS; @@ -122,10 +122,11 @@ int _make_remark(pam_handle_t * pamh, unsigned int ctrl, * set the control flags for the UNIX module. */ -int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, - int *pass_min_len, int argc, const char **argv) +unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, + int *rounds, int *pass_min_len, int argc, + const char **argv) { - unsigned int ctrl; + unsigned long long ctrl; char *val; int j; @@ -243,15 +244,23 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, set(UNIX__NONULL, ctrl); } - /* Set default rounds for blowfish */ - if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) { - *rounds = 5; - set(UNIX_ALGO_ROUNDS, ctrl); + /* Set default rounds for blowfish, gost-yescrypt and yescrypt */ + if (off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) { + if (on(UNIX_BLOWFISH_PASS, ctrl) || + on(UNIX_GOST_YESCRYPT_PASS, ctrl) || + on(UNIX_YESCRYPT_PASS, ctrl)) { + *rounds = 5; + set(UNIX_ALGO_ROUNDS, ctrl); + } } /* Enforce sane "rounds" values */ if (on(UNIX_ALGO_ROUNDS, ctrl)) { - if (on(UNIX_BLOWFISH_PASS, ctrl)) { + if (on(UNIX_GOST_YESCRYPT_PASS, ctrl) || + on(UNIX_YESCRYPT_PASS, ctrl)) { + if (*rounds < 3 || *rounds > 11) + *rounds = 5; + } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { if (*rounds < 4 || *rounds > 31) *rounds = 5; } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) { @@ -532,7 +541,7 @@ int _unix_comesfromsource(pam_handle_t *pamh, #include static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, - unsigned int ctrl, const char *user) + unsigned long long ctrl, const char *user) { int retval, child, fds[2]; struct sigaction newsa, oldsa; @@ -658,7 +667,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, */ int -_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name) +_unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name) { struct passwd *pwd = NULL; char *salt = NULL; @@ -706,7 +715,7 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name) } int _unix_verify_password(pam_handle_t * pamh, const char *name - ,const char *p, unsigned int ctrl) + ,const char *p, unsigned long long ctrl) { struct passwd *pwd = NULL; char *salt = NULL; diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index 543e9b9f..e02c05e0 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -22,8 +22,8 @@ typedef struct { const char *token; - unsigned int mask; /* shall assume 32 bits of flags */ - unsigned int flag; + unsigned long long mask; /* shall assume 64 bits of flags */ + unsigned long long flag; unsigned int is_hash_algo; } UNIX_Ctrls; @@ -48,7 +48,7 @@ typedef struct { /* the generic mask */ -#define _ALL_ON_ (~0U) +#define _ALL_ON_ (~0ULL) /* end of macro definitions definitions for the control flags */ @@ -98,47 +98,51 @@ typedef struct { #define UNIX_QUIET 28 /* Don't print informational messages */ #define UNIX_NO_PASS_EXPIRY 29 /* Don't check for password expiration if not used for authentication */ #define UNIX_DES 30 /* DES, default */ +#define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */ +#define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */ /* -------------- */ -#define UNIX_CTRLS_ 31 /* number of ctrl arguments defined */ +#define UNIX_CTRLS_ 33 /* number of ctrl arguments defined */ -#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)) +#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)) static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { -/* symbol token name ctrl mask ctrl * - * ----------------------- ------------------- --------------------- -------- */ - -/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0}, -/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0}, -/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0}, -/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0}, -/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020, 0}, -/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040, 0}, -/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0}, -/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200, 0}, -/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400, 0}, -/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0}, -/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0}, -/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0}, -/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0}, -/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000, 1}, -/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0, 0}, -/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0}, -/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0}, -/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0}, -/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000, 1}, -/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0}, -/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0}, -/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0}, -/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0}, -/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000, 1}, -/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000, 1}, -/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0}, -/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000, 1}, -/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0}, -/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0}, -/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0}, -/* UNIX_DES */ {"des", _ALL_ON_^(0260420000), 0, 1}, +/* symbol token name ctrl mask ctrl * + * --------------------------- -------------------- ------------------------- ---------------- */ + +/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0}, +/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0}, +/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0}, +/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0}, +/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060ULL), 020, 0}, +/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060ULL), 040, 0}, +/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0}, +/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600ULL), 0200, 0}, +/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600ULL), 0400, 0}, +/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0}, +/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0}, +/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0}, +/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0}, +/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1}, +/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0}, +/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0}, +/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0}, +/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0}, +/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1}, +/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0}, +/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0}, +/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0}, +/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0}, +/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1}, +/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1}, +/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0}, +/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1}, +/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0}, +/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0}, +/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0}, +/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1}, +/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1}, +/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1}, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) @@ -151,20 +155,23 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = _pam_drop(xx); \ } -extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl - ,int type, const char *text); -extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int *rounds, - int *pass_min_len, int argc, const char **argv); +extern int _make_remark(pam_handle_t * pamh, unsigned long long ctrl, + int type, const char *text); +extern unsigned long long _set_ctrl(pam_handle_t * pamh, int flags, + int *remember, int *rounds, + int *pass_min_len, + int argc, const char **argv); extern int _unix_getpwnam (pam_handle_t *pamh, const char *name, int files, int nis, struct passwd **ret); extern int _unix_comesfromsource (pam_handle_t *pamh, const char *name, int files, int nis); -extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl, +extern int _unix_blankpasswd(pam_handle_t *pamh, unsigned long long ctrl, const char *name); -extern int _unix_verify_password(pam_handle_t * pamh, const char *name - ,const char *p, unsigned int ctrl); +extern int _unix_verify_password(pam_handle_t * pamh, const char *name, + const char *p, unsigned long long ctrl); extern int _unix_run_verify_binary(pam_handle_t *pamh, - unsigned int ctrl, const char *user, int *daysleft); + unsigned long long ctrl, + const char *user, int *daysleft); #endif /* _PAM_UNIX_SUPPORT_H */ -- cgit v1.2.3 From 619f19d378529defa5864941caf8c4233aef46f5 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 26 Nov 2018 12:50:14 +0100 Subject: Revert part of the commit 4da9febc pam_unix: Do not return a hard failure on invalid or disabled salt as in some cases the failure actually is not interesting and can broke things such as password-less sudo. * modules/pam_unix/passverify.c (check_shadow_expiry): Revert checking of disabled or invalid salt. --- modules/pam_unix/passverify.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 39e2bfac..eb2444bb 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -261,19 +261,10 @@ PAMH_ARG_DECL(int check_shadow_expiry, spent->sp_namp); return PAM_SUCCESS; } -#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE - if (((curdays - spent->sp_lstchg > spent->sp_max) - && (curdays - spent->sp_lstchg > spent->sp_inact) - && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact) - && (spent->sp_max != -1) && (spent->sp_inact != -1)) - || (crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_DISABLED) - || (crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_INVALID)) { -#else if ((curdays - spent->sp_lstchg > spent->sp_max) && (curdays - spent->sp_lstchg > spent->sp_inact) && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact) && (spent->sp_max != -1) && (spent->sp_inact != -1)) { -#endif *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); D(("authtok expired")); return PAM_AUTHTOK_EXPIRED; -- cgit v1.2.3 From ad435b386b22b456724dc5c5b8d9f2d1beffc558 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Thu, 15 Nov 2018 16:57:35 +0100 Subject: pam_unix: Add crypt_default method, if supported. libxcrypt since v4.4.0 supports a default method for its gensalt function on most system configurations. As the default method is to be considered the strongest available hash method, it should be preferred over all other hash methods supported by pam. * modules/pam_unix/pam_unix.8.xml: Documentation for crypt_default. * modules/pam_unix/passverify.c: Add crypt_default method. * modules/pam_unix/support.h: Likewise. --- modules/pam_unix/pam_unix.8.xml | 20 ++++++++++++++++++++ modules/pam_unix/passverify.c | 9 +++++++++ modules/pam_unix/support.h | 22 ++++++++++++---------- 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index cae2aeaa..82e0c9af 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -361,6 +361,23 @@ + + + + + + + When a user changes their password next, + encrypt it with the default algorithm and the default + amount of rounds provided by the system configuration + of libcrypt. If this default algorithm is not known to + the + crypt3 + function, + fall back to MD5. + + + @@ -371,6 +388,9 @@ blowfish, gost-yescrypt, and yescrypt password hashing algorithms to n. + This option will be ignored when the crypt_default option + is used, as the default algorithm always uses the value + from the system configuration of libcrypt. diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index eb2444bb..0a4c67b4 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -395,6 +395,14 @@ PAMH_ARG_DECL(char * create_password_hash, if (on(UNIX_MD5_PASS, ctrl)) { /* algoid = "$1" */ return crypt_md5_wrapper(password); +#if (defined(CRYPT_PREFERRED_METHOD_AVAILABLE) && CRYPT_PREFERRED_METHOD_AVAILABLE) + } else if (on(UNIX_CRYPT_DEFAULT_PASS, ctrl) + && crypt_preferred_method() != NULL) { + algoid = crypt_preferred_method(); + rounds = 0; /* always use the system preset */ +#endif + } else if (on(UNIX_CRYPT_DEFAULT_PASS, ctrl)) { + algoid = "*0"; /* never ever a valid method */ } else if (on(UNIX_YESCRYPT_PASS, ctrl)) { algoid = "$y$"; } else if (on(UNIX_GOST_YESCRYPT_PASS, ctrl)) { @@ -461,6 +469,7 @@ PAMH_ARG_DECL(char * create_password_hash, pam_syslog(pamh, LOG_ERR, "Algo %s not supported by the crypto backend, " "falling back to MD5\n", + on(UNIX_CRYPT_DEFAULT_PASS, ctrl) ? "crypt_default \"" algoid "\"" : on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" : on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index e02c05e0..60a5872d 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -100,10 +100,11 @@ typedef struct { #define UNIX_DES 30 /* DES, default */ #define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */ #define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */ +#define UNIX_CRYPT_DEFAULT_PASS 33 /* new password hashes will use the libcrypt default */ /* -------------- */ -#define UNIX_CTRLS_ 33 /* number of ctrl arguments defined */ +#define UNIX_CTRLS_ 34 /* number of ctrl arguments defined */ -#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)) +#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)&&off(UNIX_CRYPT_DEFAULT_PASS,ctrl)) static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { @@ -123,26 +124,27 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = /* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0}, /* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0}, /* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0}, -/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1}, +/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(035660420000ULL), 020000, 1}, /* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0}, /* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0}, /* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0}, /* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0}, -/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1}, +/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(035660420000ULL), 0400000, 1}, /* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0}, /* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0}, /* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0}, /* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0}, -/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1}, -/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1}, +/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(035660420000ULL), 020000000, 1}, +/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(035660420000ULL), 040000000, 1}, /* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0}, -/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1}, +/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(035660420000ULL), 0200000000, 1}, /* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0}, /* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0}, /* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0}, -/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1}, -/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1}, -/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1}, +/* UNIX_DES */ {"des", _ALL_ON_^(035660420000ULL), 0, 1}, +/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(035660420000ULL), 04000000000, 1}, +/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(035660420000ULL), 010000000000, 1}, +/* UNIX_CRYPT_DEFAULT_PASS */ {"crypt_default", _ALL_ON_^(035660420000ULL), 020000000000, 1}, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) -- cgit v1.2.3 From 396ef3a1c93457fe66391627eb996b920be94fb2 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 27 Nov 2018 11:54:23 +0100 Subject: Revert "pam_unix: Add crypt_default method, if supported." This reverts commit ad435b386b22b456724dc5c5b8d9f2d1beffc558. --- modules/pam_unix/pam_unix.8.xml | 20 -------------------- modules/pam_unix/passverify.c | 9 --------- modules/pam_unix/support.h | 22 ++++++++++------------ 3 files changed, 10 insertions(+), 41 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index 82e0c9af..cae2aeaa 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -361,23 +361,6 @@ - - - - - - - When a user changes their password next, - encrypt it with the default algorithm and the default - amount of rounds provided by the system configuration - of libcrypt. If this default algorithm is not known to - the - crypt3 - function, - fall back to MD5. - - - @@ -388,9 +371,6 @@ blowfish, gost-yescrypt, and yescrypt password hashing algorithms to n. - This option will be ignored when the crypt_default option - is used, as the default algorithm always uses the value - from the system configuration of libcrypt. diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 0a4c67b4..eb2444bb 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -395,14 +395,6 @@ PAMH_ARG_DECL(char * create_password_hash, if (on(UNIX_MD5_PASS, ctrl)) { /* algoid = "$1" */ return crypt_md5_wrapper(password); -#if (defined(CRYPT_PREFERRED_METHOD_AVAILABLE) && CRYPT_PREFERRED_METHOD_AVAILABLE) - } else if (on(UNIX_CRYPT_DEFAULT_PASS, ctrl) - && crypt_preferred_method() != NULL) { - algoid = crypt_preferred_method(); - rounds = 0; /* always use the system preset */ -#endif - } else if (on(UNIX_CRYPT_DEFAULT_PASS, ctrl)) { - algoid = "*0"; /* never ever a valid method */ } else if (on(UNIX_YESCRYPT_PASS, ctrl)) { algoid = "$y$"; } else if (on(UNIX_GOST_YESCRYPT_PASS, ctrl)) { @@ -469,7 +461,6 @@ PAMH_ARG_DECL(char * create_password_hash, pam_syslog(pamh, LOG_ERR, "Algo %s not supported by the crypto backend, " "falling back to MD5\n", - on(UNIX_CRYPT_DEFAULT_PASS, ctrl) ? "crypt_default \"" algoid "\"" : on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" : on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index 60a5872d..e02c05e0 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -100,11 +100,10 @@ typedef struct { #define UNIX_DES 30 /* DES, default */ #define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */ #define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */ -#define UNIX_CRYPT_DEFAULT_PASS 33 /* new password hashes will use the libcrypt default */ /* -------------- */ -#define UNIX_CTRLS_ 34 /* number of ctrl arguments defined */ +#define UNIX_CTRLS_ 33 /* number of ctrl arguments defined */ -#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)&&off(UNIX_CRYPT_DEFAULT_PASS,ctrl)) +#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)) static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { @@ -124,27 +123,26 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = /* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0}, /* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0}, /* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0}, -/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(035660420000ULL), 020000, 1}, +/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1}, /* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0}, /* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0}, /* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0}, /* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0}, -/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(035660420000ULL), 0400000, 1}, +/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1}, /* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0}, /* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0}, /* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0}, /* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0}, -/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(035660420000ULL), 020000000, 1}, -/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(035660420000ULL), 040000000, 1}, +/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1}, +/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1}, /* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0}, -/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(035660420000ULL), 0200000000, 1}, +/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1}, /* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0}, /* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0}, /* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0}, -/* UNIX_DES */ {"des", _ALL_ON_^(035660420000ULL), 0, 1}, -/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(035660420000ULL), 04000000000, 1}, -/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(035660420000ULL), 010000000000, 1}, -/* UNIX_CRYPT_DEFAULT_PASS */ {"crypt_default", _ALL_ON_^(035660420000ULL), 020000000000, 1}, +/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1}, +/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1}, +/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1}, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) -- cgit v1.2.3 From 86eed7ca01864b9fd17099e57f10f2b9b6b568a1 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Mon, 26 Nov 2018 22:33:17 +0100 Subject: pam_unix: Report unusable hashes found by checksalt to syslog. libxcrypt can be build-time configured to support (or not support) various hashing methods. Future versions will also have support for runtime configuration by the system's vendor and/or administrator. For that reason adminstrator should be notified by pam if users cannot log into their account anymore because of such a change in the system's configuration of libxcrypt. Also check for malformed hashes, like descrypt hashes starting with "$2...", which might have been generated by unsafe base64 encoding functions as used in glibc <= 2.16. Such hashes are likely to be rejected by many recent implementations of libcrypt. * modules/pam_unix/passverify.c (verify_pwd_hash): Report unusable hashes found by checksalt to syslog. --- modules/pam_unix/passverify.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index eb2444bb..2c808eb5 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -103,6 +103,42 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) * Ok, we don't know the crypt algorithm, but maybe * libcrypt knows about it? We should try it. */ +#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE + /* Get the status of the hash from checksalt */ + int retval_checksalt = crypt_checksalt(hash); + + /* + * Check for hashing methods that are disabled by + * libcrypt configuration and/or system preset. + */ + if (retval_checksalt == CRYPT_SALT_METHOD_DISABLED) { + /* + * pam_syslog() needs a pam handle, + * but that's not available here. + */ + helper_log_err(LOG_ERR, + "pam_unix(verify_pwd_hash): The method " + "for computing the hash \"%.6s\" has been " + "disabled in libcrypt by the preset from " + "the system's vendor and/or administrator.", + hash); + } + /* + * Check for malformed hashes, like descrypt hashes + * starting with "$2...", which might have been + * generated by unsafe base64 encoding functions + * as used in glibc <= 2.16. + * Such hashes are likely to be rejected by many + * recent implementations of libcrypt. + */ + if (retval_checksalt == CRYPT_SALT_INVALID) { + helper_log_err(LOG_ERR, + "pam_unix(verify_pwd_hash): The hash \"%.6s\"" + "does not use a method known by the version " + "of libcrypt this system is supplied with.", + hash); + } +#endif #ifdef HAVE_CRYPT_R struct crypt_data *cdata; cdata = malloc(sizeof(*cdata)); -- cgit v1.2.3 From d8d11db2cef65da5d2afa7acf21aa9c8cd88abed Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 27 Nov 2018 16:11:03 +0100 Subject: pam_unix: Use pam_syslog instead of helper_log_err. * modules/pam_unix/passverify.c (verify_pwd_hash): Add pamh argument via PAMH_ARG_DECL. Call pam_syslog() instead of helper_log_err(). * modules/pam_unix/passverify.h: Adjust the declaration of verify_pwd_hash(). * modules/pam_unix/support.c (_unix_verify_password): Add the pamh argument to verify_pwd_hash() call. --- modules/pam_unix/passverify.c | 24 +++++++++++++----------- modules/pam_unix/passverify.h | 6 +++--- modules/pam_unix/support.c | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 2c808eb5..80e32767 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -65,8 +65,8 @@ strip_hpux_aging(char *hash) } } -int -verify_pwd_hash(const char *p, char *hash, unsigned int nullok) +PAMH_ARG_DECL(int verify_pwd_hash, + const char *p, char *hash, unsigned int nullok) { size_t hash_len; char *pp = NULL; @@ -116,11 +116,10 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) * pam_syslog() needs a pam handle, * but that's not available here. */ - helper_log_err(LOG_ERR, - "pam_unix(verify_pwd_hash): The method " - "for computing the hash \"%.6s\" has been " - "disabled in libcrypt by the preset from " - "the system's vendor and/or administrator.", + pam_syslog(pamh, LOG_ERR, + "The support for password hash \"%.6s\" " + "has been disabled in libcrypt " + "configuration.", hash); } /* @@ -132,12 +131,15 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) * recent implementations of libcrypt. */ if (retval_checksalt == CRYPT_SALT_INVALID) { - helper_log_err(LOG_ERR, - "pam_unix(verify_pwd_hash): The hash \"%.6s\"" - "does not use a method known by the version " - "of libcrypt this system is supplied with.", + pam_syslog(pamh, LOG_ERR, + "The password hash \"%.6s\" is unknown to " + "libcrypt.", hash); } +#else +#ifndef HELPER_COMPILE + (void)pamh; +#endif #endif #ifdef HAVE_CRYPT_R struct crypt_data *cdata; diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index 086c28ac..e9a88fbf 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -12,9 +12,6 @@ #define OLD_PASSWORDS_FILE "/etc/security/opasswd" -int -verify_pwd_hash(const char *p, char *hash, unsigned int nullok); - int is_pwd_shadowed(const struct passwd *pwd); @@ -65,6 +62,9 @@ read_passwords(int fd, int npass, char **passwords); #define PAMH_ARG(...) pamh, __VA_ARGS__ #endif +PAMH_ARG_DECL(int verify_pwd_hash, + const char *p, char *hash, unsigned int nullok); + PAMH_ARG_DECL(char * create_password_hash, const char *password, unsigned long long ctrl, int rounds); diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 6894288d..ea5594d2 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -770,7 +770,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name } } } else { - retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl)); + retval = verify_pwd_hash(pamh, p, salt, off(UNIX__NONULL, ctrl)); } if (retval == PAM_SUCCESS) { -- cgit v1.2.3 From f87a953d223d5305adfe3bbb00b4c037c9ae7cd3 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 10 Oct 2019 11:11:14 +0200 Subject: pam_unix: Fix the spelling of Jan RÄ™korajski's name. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/pam_unix/CHANGELOG | 18 +++++++++--------- modules/pam_unix/pam_unix_acct.c | 2 +- modules/pam_unix/pam_unix_auth.c | 2 +- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/pam_unix_sess.c | 2 +- modules/pam_unix/passverify.c | 2 +- modules/pam_unix/support.c | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/CHANGELOG b/modules/pam_unix/CHANGELOG index c18acc27..f8f70f59 100644 --- a/modules/pam_unix/CHANGELOG +++ b/modules/pam_unix/CHANGELOG @@ -1,6 +1,6 @@ $Id$ -* Mon Aug 16 1999 Jan Rêkorajski +* Mon Aug 16 1999 Jan RÄ™korajski - fixed reentrancy problems * Sun Jul 4 21:03:42 PDT 1999 @@ -15,7 +15,7 @@ $Id$ * Sun Jun 27 1999 Steve Langasek - fix to uid-handling code for NIS+ -* Sat Jun 26 1999 Jan Rêkorajski +* Sat Jun 26 1999 Jan RÄ™korajski - merged MD5 fix and early failure syslog by Andrey Vladimirovich Savochkin - minor fixes @@ -24,31 +24,31 @@ $Id$ * Fri Jun 25 1999 Stephen Langasek - reorganized the code to let it build as separate C files -* Sun Jun 20 1999 Jan Rêkorajski +* Sun Jun 20 1999 Jan RÄ™korajski - fixes in pam_unix_auth, it incorrectly saved and restored return value when likeauth option was used -* Tue Jun 15 1999 Jan Rêkorajski +* Tue Jun 15 1999 Jan RÄ™korajski - added NIS+ support -* Mon Jun 14 1999 Jan Rêkorajski +* Mon Jun 14 1999 Jan RÄ™korajski - total rewrite based on pam_pwdb module, now there is ONE pam_unix.so module, it accepts the same options as pam_pwdb - all of them correctly ;) (pam_pwdb dosn't understand what DISALLOW_NULL_AUTHTOK means) -* Tue Apr 20 1999 Jan Rêkorajski +* Tue Apr 20 1999 Jan RÄ™korajski - Arghhh, pam_unix_passwd was not updating /etc/shadow when used with pam_cracklib. -* Mon Apr 19 1999 Jan Rêkorajski +* Mon Apr 19 1999 Jan RÄ™korajski - added "remember=XXX" option that means 'remember XXX old passwords' Old passwords are stored in /etc/security/opasswd, there can be maximum of 400 passwords per user. -* Sat Mar 27 1999 Jan Rêkorajski +* Sat Mar 27 1999 Jan RÄ™korajski - added crypt16 to pam_unix_auth and pam_unix_passwd (check only, this algorithm is too lame to use it in real life) -* Sun Mar 21 1999 Jan Rêkorajski +* Sun Mar 21 1999 Jan RÄ™korajski - pam_unix_auth now correctly behave when user has NULL AUTHTOK - pam_unix_auth returns PAM_PERM_DENIED when seteuid fails diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index d8d084ac..e99c2d03 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -1,6 +1,6 @@ /* * Copyright Elliot Lee, 1996. All rights reserved. - * Copyright Jan Rêkorajski, 1999. All rights reserved. + * Copyright Jan RÄ™korajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c index 905fc66c..681e49db 100644 --- a/modules/pam_unix/pam_unix_auth.c +++ b/modules/pam_unix/pam_unix_auth.c @@ -1,7 +1,7 @@ /* * Copyright Alexander O. Yuriev, 1996. All rights reserved. * NIS+ support by Thorsten Kukuk - * Copyright Jan Rêkorajski, 1999. All rights reserved. + * Copyright Jan RÄ™korajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 4bb1bc56..87db7cf1 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -1,7 +1,7 @@ /* * Main coding by Elliot Lee , Red Hat Software. * Copyright (C) 1996. - * Copyright (c) Jan Rêkorajski, 1999. + * Copyright (c) Jan RÄ™korajski, 1999. * Copyright (c) Red Hat, Inc., 2007, 2008. * * Redistribution and use in source and binary forms, with or without diff --git a/modules/pam_unix/pam_unix_sess.c b/modules/pam_unix/pam_unix_sess.c index 71f5594d..437d1242 100644 --- a/modules/pam_unix/pam_unix_sess.c +++ b/modules/pam_unix/pam_unix_sess.c @@ -2,7 +2,7 @@ * $Id$ * * Copyright Alexander O. Yuriev, 1996. All rights reserved. - * Copyright Jan Rêkorajski, 1999. All rights reserved. + * Copyright Jan RÄ™korajski, 1999. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 80e32767..2f9a4306 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1217,7 +1217,7 @@ read_passwords(int fd, int npass, char **passwords) #endif /* ****************************************************************** * - * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Jan RÄ™korajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 81c7651c..4f15b61b 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -799,7 +799,7 @@ cleanup: } /* ****************************************************************** * - * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Jan RÄ™korajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. -- cgit v1.2.3 From ded7401a0bc743aaffa785a8b015ceec7780462d Mon Sep 17 00:00:00 2001 From: Hulto Date: Wed, 23 Jan 2019 22:40:23 -0500 Subject: Changed variable salt to hash helper_verify_password's variable salt is not just the salt but the whole hash. Renamed for clarity and conformity with the rest of the code. --- modules/pam_unix/passverify.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 2f9a4306..e03e75b2 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1080,21 +1080,21 @@ int helper_verify_password(const char *name, const char *p, int nullok) { struct passwd *pwd = NULL; - char *salt = NULL; + char *hash = NULL; int retval; - retval = get_pwd_hash(name, &pwd, &salt); + retval = get_pwd_hash(name, &pwd, &hash); - if (pwd == NULL || salt == NULL) { + if (pwd == NULL || hash == NULL) { helper_log_err(LOG_NOTICE, "check pass; user unknown"); retval = PAM_USER_UNKNOWN; } else { - retval = verify_pwd_hash(p, salt, nullok); + retval = verify_pwd_hash(p, hash, nullok); } - if (salt) { - _pam_overwrite(salt); - _pam_drop(salt); + if (hash) { + _pam_overwrite(hash); + _pam_drop(hash); } p = NULL; /* no longer needed here */ -- cgit v1.2.3 From a12ec8b879337c15acba04fe7f5c8e75f5a91809 Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Fri, 23 Nov 2018 19:57:43 +0100 Subject: pam_unix: Return NULL instead of calling crypt_md5_wrapper(). If the call to the crypt(3) function failed for some reason during hashing a new login passphrase, the wrapper function for computing a hash with the md5crypt method was called internally by the pam_unix module in previous versions of linux-pam. With CVE-2012-3287 in mind, the md5crypt method is not considered to be a safe nor recommended hashing method for a new login passphrase since at least 2012. Thus pam_unix should error out in case of a failure in crypt(3) instead of silently computing a hashed passphrase using a potentially unsafe method. * modules/pam_unix/pam_unix.8.xml: Update documentation. * modules/pam_unix/passverify.c (create_password_hash): Return NULL on error instead of silently invoke crypt_md5_wrapper(). --- modules/pam_unix/pam_unix.8.xml | 35 +++++++++++++++-------------------- modules/pam_unix/passverify.c | 7 +++---- 2 files changed, 18 insertions(+), 24 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index cae2aeaa..93a01c89 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -293,11 +293,10 @@ When a user changes their password next, - encrypt it with the SHA256 algorithm. If the - SHA256 algorithm is not known to the + encrypt it with the SHA256 algorithm. The + SHA256 algorithm must be supported by the crypt3 - function, - fall back to MD5. + function. @@ -308,11 +307,10 @@ When a user changes their password next, - encrypt it with the SHA512 algorithm. If the - SHA512 algorithm is not known to the + encrypt it with the SHA512 algorithm. The + SHA512 algorithm must be supported by the crypt3 - function, - fall back to MD5. + function. @@ -323,11 +321,10 @@ When a user changes their password next, - encrypt it with the blowfish algorithm. If the - blowfish algorithm is not known to the + encrypt it with the blowfish algorithm. The + blowfish algorithm must be supported by the crypt3 - function, - fall back to MD5. + function. @@ -338,11 +335,10 @@ When a user changes their password next, - encrypt it with the gost-yescrypt algorithm. If the - gost-yescrypt algorithm is not known to the + encrypt it with the gost-yescrypt algorithm. The + gost-yescrypt algorithm must be supported by the crypt3 - function, - fall back to MD5. + function. @@ -353,11 +349,10 @@ When a user changes their password next, - encrypt it with the yescrypt algorithm. If the - yescrypt algorithm is not known to the + encrypt it with the yescrypt algorithm. The + yescrypt algorithm must be supported by the crypt3 - function, - fall back to MD5. + function. diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index e03e75b2..67f9e6f7 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -495,10 +495,9 @@ PAMH_ARG_DECL(char * create_password_hash, sp = crypt(password, salt); #endif if (!sp || strncmp(algoid, sp, strlen(algoid)) != 0) { - /* libxcrypt/libc doesn't know the algorithm, use MD5 */ + /* libxcrypt/libc doesn't know the algorithm, error out */ pam_syslog(pamh, LOG_ERR, - "Algo %s not supported by the crypto backend, " - "falling back to MD5\n", + "Algo %s not supported by the crypto backend.\n", on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" : on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : @@ -510,7 +509,7 @@ PAMH_ARG_DECL(char * create_password_hash, #ifdef HAVE_CRYPT_R free(cdata); #endif - return crypt_md5_wrapper(password); + return NULL; } sp = x_strdup(sp); #ifdef HAVE_CRYPT_R -- cgit v1.2.3 From df86351adfbe6a5dc7a68dce1074403f97fd1046 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 18 Jan 2020 00:35:14 +0000 Subject: Fix remaining -Wcast-qual compilation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new internal header file with definitions of DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL macros, use them to temporary silence -Wcast-qual compilation warnings in various modules. * libpam/include/pam_cc_compat.h: New file. * libpam/Makefile.am (noinst_HEADERS): Add include/pam_cc_compat.h. * modules/pam_mkhomedir/pam_mkhomedir.c: Include "pam_cc_compat.h". (create_homedir): Wrap execve invocation in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_namespace/pam_namespace.c: Include "pam_cc_compat.h". (pam_sm_close_session): Wrap the cast that discards ‘const’ qualifier in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_tty_audit/pam_tty_audit.c: Include "pam_cc_compat.h". (nl_send): Wrap the cast that discards ‘const’ qualifier in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_unix/pam_unix_acct.c: Include "pam_cc_compat.h". (_unix_run_verify_binary): Wrap execve invocation in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_unix/pam_unix_passwd.c: Include "pam_cc_compat.h". (_unix_run_update_binary): Wrap execve invocation in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_unix/passverify.c: Include "pam_cc_compat.h". (unix_update_shadow): Wrap the cast that discards ‘const’ qualifier in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_unix/support.c: Include "pam_cc_compat.h". (_unix_run_helper_binary): Wrap execve invocation in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. * modules/pam_xauth/pam_xauth.c: Include "pam_cc_compat.h". (run_coprocess): Wrap execv invocation in DIAG_PUSH_IGNORE_CAST_QUAL and DIAG_POP_IGNORE_CAST_QUAL. --- libpam/Makefile.am | 2 +- libpam/include/pam_cc_compat.h | 35 +++++++++++++++++++++++++++++++++++ modules/pam_mkhomedir/pam_mkhomedir.c | 4 ++++ modules/pam_namespace/pam_namespace.c | 3 +++ modules/pam_tty_audit/pam_tty_audit.c | 4 ++++ modules/pam_unix/pam_unix_acct.c | 3 +++ modules/pam_unix/pam_unix_passwd.c | 3 +++ modules/pam_unix/passverify.c | 3 +++ modules/pam_unix/support.c | 3 +++ modules/pam_xauth/pam_xauth.c | 4 ++++ 10 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 libpam/include/pam_cc_compat.h (limited to 'modules/pam_unix/passverify.c') diff --git a/libpam/Makefile.am b/libpam/Makefile.am index d9f9e041..9d5c844d 100644 --- a/libpam/Makefile.am +++ b/libpam/Makefile.am @@ -23,7 +23,7 @@ include_HEADERS = include/security/_pam_compat.h \ include/security/pam_ext.h include/security/pam_modutil.h noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \ - pam_modutil_private.h + pam_modutil_private.h include/pam_cc_compat.h libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84 libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@ diff --git a/libpam/include/pam_cc_compat.h b/libpam/include/pam_cc_compat.h new file mode 100644 index 00000000..a4b84c62 --- /dev/null +++ b/libpam/include/pam_cc_compat.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Dmitry V. Levin + */ + +#ifndef PAM_CC_COMPAT_H +#define PAM_CC_COMPAT_H + +#include "config.h" +#include + +#if defined __clang__ && defined __clang_major__ && defined __clang_minor__ +# define PAM_CLANG_PREREQ(maj, min) \ + ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) +#else +# define PAM_CLANG_PREREQ(maj, min) 0 +#endif + +#if PAM_GNUC_PREREQ(4, 6) +# define DIAG_PUSH_IGNORE_CAST_QUAL \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +# define DIAG_POP_IGNORE_CAST_QUAL \ + _Pragma("GCC diagnostic pop") +#elif PAM_CLANG_PREREQ(2, 6) +# define DIAG_PUSH_IGNORE_CAST_QUAL \ + _Pragma("clang diagnostic push"); \ + _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +# define DIAG_POP_IGNORE_CAST_QUAL \ + _Pragma("clang diagnostic pop") +#else +# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */ +# define DIAG_POP_IGNORE_CAST_QUAL /* empty */ +#endif + +#endif /* PAM_CC_COMPAT_H */ diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index aec1e7e5..1a4dab47 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -58,6 +58,8 @@ #include #include +#include "pam_cc_compat.h" + /* argument parsing */ #define MKHOMEDIR_DEBUG 020 /* be verbose about things */ #define MKHOMEDIR_QUIET 040 /* keep quiet about things */ @@ -143,7 +145,9 @@ create_homedir (pam_handle_t *pamh, options_t *opt, args[2] = opt->umask; args[3] = opt->skeldir; + DIAG_PUSH_IGNORE_CAST_QUAL; execve(MKHOMEDIR_HELPER, (char **)args, envp); + DIAG_POP_IGNORE_CAST_QUAL; /* should not get here: exit with error */ D(("helper binary is not available")); diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c index d49dc621..155d3965 100644 --- a/modules/pam_namespace/pam_namespace.c +++ b/modules/pam_namespace/pam_namespace.c @@ -34,6 +34,7 @@ #define _ATFILE_SOURCE +#include "pam_cc_compat.h" #include "pam_namespace.h" #include "argv_parse.h" @@ -2230,7 +2231,9 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED, /* nothing to reset */ return PAM_SUCCESS; + DIAG_PUSH_IGNORE_CAST_QUAL; idata.polydirs_ptr = (void *)polyptr; + DIAG_POP_IGNORE_CAST_QUAL; if (idata.flags & PAMNS_DEBUG) pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d", diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c index 79e5d511..7dbcada2 100644 --- a/modules/pam_tty_audit/pam_tty_audit.c +++ b/modules/pam_tty_audit/pam_tty_audit.c @@ -54,6 +54,8 @@ #include #include +#include "pam_cc_compat.h" + #define DATANAME "pam_tty_audit_last_state" /* Open an audit netlink socket */ @@ -79,7 +81,9 @@ nl_send (int fd, unsigned type, unsigned flags, const void *data, size_t size) nlm.nlmsg_pid = 0; iov[0].iov_base = &nlm; iov[0].iov_len = sizeof (nlm); + DIAG_PUSH_IGNORE_CAST_QUAL; iov[1].iov_base = (void *)data; + DIAG_POP_IGNORE_CAST_QUAL; iov[1].iov_len = size; addr.nl_family = AF_NETLINK; addr.nl_pid = 0; diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index e99c2d03..36f68eff 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -59,6 +59,7 @@ #include #include +#include "pam_cc_compat.h" #include "support.h" #include "passverify.h" @@ -127,7 +128,9 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl, args[1] = user; args[2] = "chkexpiry"; + DIAG_PUSH_IGNORE_CAST_QUAL; execve(CHKPWD_HELPER, (char *const *) args, envp); + DIAG_POP_IGNORE_CAST_QUAL; pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m"); /* should not get here: exit with error */ diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 93300f46..636ace97 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -70,6 +70,7 @@ #include #include +#include "pam_cc_compat.h" #include "md5.h" #include "support.h" #include "passverify.h" @@ -293,7 +294,9 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, snprintf(buffer, sizeof(buffer), "%d", remember); args[4] = buffer; + DIAG_PUSH_IGNORE_CAST_QUAL; execve(UPDATE_HELPER, (char *const *) args, envp); + DIAG_POP_IGNORE_CAST_QUAL; /* should not get here: exit with error */ D(("helper binary is not available")); diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 67f9e6f7..65307e11 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -25,6 +25,7 @@ #include #endif +#include "pam_cc_compat.h" #include "md5.h" #include "bigcrypt.h" #include "passverify.h" @@ -1020,7 +1021,9 @@ PAMH_ARG_DECL(int unix_update_shadow, fclose(opwfile); if (!wroteentry && !err) { + DIAG_PUSH_IGNORE_CAST_QUAL; spwdent.sp_namp = (char *)forwho; + DIAG_POP_IGNORE_CAST_QUAL; spwdent.sp_pwdp = towhat; spwdent.sp_lstchg = time(NULL) / (60 * 60 * 24); if (spwdent.sp_lstchg == 0) diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 814d4c08..33761840 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -28,6 +28,7 @@ #include #include +#include "pam_cc_compat.h" #include "support.h" #include "passverify.h" @@ -526,7 +527,9 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, args[2]="nonull"; } + DIAG_PUSH_IGNORE_CAST_QUAL; execve(CHKPWD_HELPER, (char *const *) args, envp); + DIAG_POP_IGNORE_CAST_QUAL; /* should not get here: exit with error */ D(("helper binary is not available")); diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c index 3339def8..61e98253 100644 --- a/modules/pam_xauth/pam_xauth.c +++ b/modules/pam_xauth/pam_xauth.c @@ -65,6 +65,8 @@ #include #endif +#include "pam_cc_compat.h" + #define DATANAME "pam_xauth_cookie_file" #define XAUTHENV "XAUTHORITY" #define HOMEENV "HOME" @@ -179,7 +181,9 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output, } } /* Run the command. */ + DIAG_PUSH_IGNORE_CAST_QUAL; execv(command, (char *const *) args); + DIAG_POP_IGNORE_CAST_QUAL; /* Never reached. */ _exit(1); } -- cgit v1.2.3 From e08bc8895045babcf4c41ed3147f44c1dcd77af0 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 19 Mar 2020 18:40:16 +0000 Subject: modules/pam_unix: fix gcc compilation warnings When setreuid() fails, there is no way to proceed any further: either the process credentials are unchanged but inappropriate, or they are in an inconsistent state and nothing good could be made out of it. This fixes the following compilation warnings: modules/pam_unix/passverify.c:209:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:211:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:213:6: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:214:6: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:222:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:224:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:225:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:226:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:209:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:211:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:213:6: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:214:6: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:222:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:224:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:225:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] modules/pam_unix/passverify.c:226:5: warning: ignoring return value of 'setreuid', declared with attribute warn_unused_result [-Wunused-result] * modules/pam_unix/passverify.c (get_account_info) [HELPER_COMPILE]: Always check setreuid return code and return PAM_CRED_INSUFFICIENT if setreuid failed. --- modules/pam_unix/passverify.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 65307e11..234db341 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -205,25 +205,30 @@ PAMH_ARG_DECL(int get_account_info, save_euid = geteuid(); save_uid = getuid(); - if (save_uid == (*pwd)->pw_uid) - setreuid(save_euid, save_uid); - else { - setreuid(0, -1); - if (setreuid(-1, (*pwd)->pw_uid) == -1) { - setreuid(-1, 0); - setreuid(0, -1); - if(setreuid(-1, (*pwd)->pw_uid) == -1) + if (save_uid == (*pwd)->pw_uid) { + if (setreuid(save_euid, save_uid)) + return PAM_CRED_INSUFFICIENT; + } else { + if (setreuid(0, -1)) + return PAM_CRED_INSUFFICIENT; + if (setreuid(-1, (*pwd)->pw_uid)) { + if (setreuid(-1, 0) + || setreuid(0, -1) + || setreuid(-1, (*pwd)->pw_uid)) { return PAM_CRED_INSUFFICIENT; + } } } *spwdent = pam_modutil_getspnam(pamh, name); - if (save_uid == (*pwd)->pw_uid) - setreuid(save_uid, save_euid); - else { - setreuid(-1, 0); - setreuid(save_uid, -1); - setreuid(-1, save_euid); + if (save_uid == (*pwd)->pw_uid) { + if (setreuid(save_uid, save_euid)) + return PAM_CRED_INSUFFICIENT; + } else { + if (setreuid(-1, 0) + || setreuid(save_uid, -1) + || setreuid(-1, save_euid)) + return PAM_CRED_INSUFFICIENT; } if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) -- cgit v1.2.3 From a49bdd6697c51625a52275fe8616bce0d77431c6 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 16 Mar 2020 21:02:18 +0000 Subject: modules/pam_unix: use pam_str_skip_prefix and pam_str_skip_prefix_len * modules/pam_unix/passverify.c: Include "pam_inline.h". (verify_pwd_hash): Use pam_str_skip_prefix instead of ugly strncmp invocations. * modules/pam_unix/support.c: Include "pam_inline.h". (_set_ctrl): Use pam_str_skip_prefix_len instead of hardcoding string lengths. * modules/pam_unix/md5_crypt.c: Include "pam_inline.h". (crypt_md5): Use pam_str_skip_prefix_len. squash! modules/pam_unix: use pam_str_skip_prefix and pam_str_skip_prefix_len --- modules/pam_unix/md5_crypt.c | 5 +++-- modules/pam_unix/passverify.c | 3 ++- modules/pam_unix/support.c | 14 +++++++++----- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/md5_crypt.c b/modules/pam_unix/md5_crypt.c index 4ab9ec84..94f7b434 100644 --- a/modules/pam_unix/md5_crypt.c +++ b/modules/pam_unix/md5_crypt.c @@ -15,6 +15,7 @@ #include #include #include "md5.h" +#include "pam_inline.h" static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -55,8 +56,8 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt) return NULL; /* If it starts with the magic string, then skip that */ - if (!strncmp(sp, magic, strlen(magic))) - sp += strlen(magic); + if ((ep = pam_str_skip_prefix_len(sp, magic, strlen(magic))) != NULL) + sp = ep; /* It stops at the first '$', max 8 chars */ for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 234db341..a571b4f7 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -26,6 +26,7 @@ #endif #include "pam_cc_compat.h" +#include "pam_inline.h" #include "md5.h" #include "bigcrypt.h" #include "passverify.h" @@ -88,7 +89,7 @@ PAMH_ARG_DECL(int verify_pwd_hash, } else if (!p || *hash == '*' || *hash == '!') { retval = PAM_AUTH_ERR; } else { - if (!strncmp(hash, "$1$", 3)) { + if (pam_str_skip_prefix(hash, "$1$") != NULL) { pp = Goodcrypt_md5(p, hash); if (pp && strcmp(pp, hash) != 0) { _pam_delete(pp); diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index a04211cd..41db1f04 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -29,6 +29,7 @@ #include #include "pam_cc_compat.h" +#include "pam_inline.h" #include "support.h" #include "passverify.h" @@ -112,17 +113,20 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, /* now parse the arguments to this module */ for (; argc-- > 0; ++argv) { + const char *str = NULL; D(("pam_unix arg: %s", *argv)); for (j = 0; j < UNIX_CTRLS_; ++j) { if (unix_args[j].token - && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) { + && (str = pam_str_skip_prefix_len(*argv, + unix_args[j].token, + strlen(unix_args[j].token))) != NULL) { break; } } - if (j >= UNIX_CTRLS_) { + if (str == NULL) { pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", *argv); } else { @@ -133,7 +137,7 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, "option remember not allowed for this module type"); continue; } - *remember = strtol(*argv + 9, NULL, 10); + *remember = strtol(str, NULL, 10); if ((*remember == INT_MIN) || (*remember == INT_MAX)) *remember = -1; if (*remember > 400) @@ -144,14 +148,14 @@ unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, "option minlen not allowed for this module type"); continue; } - *pass_min_len = atoi(*argv + 7); + *pass_min_len = atoi(str); } else if (j == UNIX_ALGO_ROUNDS) { if (rounds == NULL) { pam_syslog(pamh, LOG_ERR, "option rounds not allowed for this module type"); continue; } - *rounds = strtol(*argv + 7, NULL, 10); + *rounds = strtol(str, NULL, 10); } ctrl &= unix_args[j].mask; /* for turning things off */ -- cgit v1.2.3