From af0faf666c5008e54dfe43684f210e3581ff1bca Mon Sep 17 00:00:00 2001 From: ikerexxe Date: Tue, 16 Jun 2020 14:32:36 +0200 Subject: pam_unix: avoid determining if user exists Taking a look at the time for the password prompt to appear it was possible to determine if a user existed in a system. Solved it by matching the runtime until the password prompt was shown by always checking the password hash for an existing and a non-existing user. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1629598 --- modules/pam_unix/passverify.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index a571b4f7..7455eae6 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1096,6 +1096,12 @@ helper_verify_password(const char *name, const char *p, int nullok) if (pwd == NULL || hash == NULL) { helper_log_err(LOG_NOTICE, "check pass; user unknown"); retval = PAM_USER_UNKNOWN; + } else if (p[0] == '\0' && nullok) { + if (hash[0] == '\0') { + retval = PAM_SUCCESS; + } else { + retval = PAM_AUTH_ERR; + } } else { retval = verify_pwd_hash(p, hash, nullok); } -- cgit v1.2.3 From b36351dd0137034e79194023c8d687b495e785c4 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Wed, 15 Jul 2020 08:00:00 +0000 Subject: pam_unix: use PAM_MAX_RESP_SIZE instead of its alias MAXPASS * modules/pam_unix/passverify.h (MAXPASS): Remove. * modules/pam_unix/passverify.c (read_passwords): Replace MAXPASS with PAM_MAX_RESP_SIZE. * modules/pam_unix/pam_unix_passwd.c (_pam_unix_approve_pass): Likewise. * modules/pam_unix/support.c (_unix_verify_password): Likewise. * modules/pam_unix/unix_chkpwd.c (main): Likewise. * modules/pam_unix/unix_update.c (set_password): Likewise. --- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/passverify.c | 4 ++-- modules/pam_unix/passverify.h | 2 -- modules/pam_unix/support.c | 4 ++-- modules/pam_unix/unix_chkpwd.c | 4 ++-- modules/pam_unix/unix_update.c | 10 +++++----- 6 files changed, 12 insertions(+), 14 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 e988b2e3..a20e919e 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -577,7 +577,7 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh } } - if (strlen(pass_new) > MAXPASS) { + if (strlen(pass_new) > PAM_MAX_RESP_SIZE) { remark = _("You must choose a shorter password."); D(("length exceeded [%s]", remark)); } else if (off(UNIX__IAMROOT, ctrl)) { diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 7455eae6..d5cfd269 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1190,14 +1190,14 @@ int read_passwords(int fd, int npass, char **passwords) { /* The passwords array must contain npass preallocated - * buffers of length MAXPASS + 1 + * buffers of length PAM_MAX_RESP_SIZE + 1 */ int rbytes = 0; int offset = 0; int i = 0; char *pptr; while (npass > 0) { - rbytes = read(fd, passwords[i]+offset, MAXPASS+1-offset); + rbytes = read(fd, passwords[i]+offset, PAM_MAX_RESP_SIZE+1-offset); if (rbytes < 0) { if (errno == EINTR) continue; diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index e9a88fbf..47d9d4db 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -8,8 +8,6 @@ #define PAM_UNIX_RUN_HELPER PAM_CRED_INSUFFICIENT -#define MAXPASS PAM_MAX_RESP_SIZE /* the maximum length of a password */ - #define OLD_PASSWORDS_FILE "/etc/security/opasswd" int diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index dc67238c..d669e951 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -677,7 +677,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name struct passwd *pwd = NULL; char *salt = NULL; char *data_name; - char pw[MAXPASS + 1]; + char pw[PAM_MAX_RESP_SIZE + 1]; int retval; @@ -704,7 +704,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name); } - if (p != NULL && strlen(p) > MAXPASS) { + if (p != NULL && strlen(p) > PAM_MAX_RESP_SIZE) { memset(pw, 0, sizeof(pw)); p = strncpy(pw, p, sizeof(pw) - 1); } diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index 88647e58..c61759a6 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -89,7 +89,7 @@ static int _audit_log(int type, const char *uname, int rc) int main(int argc, char *argv[]) { - char pass[MAXPASS + 1]; + char pass[PAM_MAX_RESP_SIZE + 1]; char *option; int npass, nullok; int blankpass = 0; @@ -175,7 +175,7 @@ int main(int argc, char *argv[]) retval = helper_verify_password(user, pass, nullok); - memset(pass, '\0', MAXPASS); /* clear memory of the password */ + memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */ /* return pass or fail */ diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c index 6ea7ea51..ae77fe2e 100644 --- a/modules/pam_unix/unix_update.c +++ b/modules/pam_unix/unix_update.c @@ -38,8 +38,8 @@ set_password(const char *forwho, const char *shadow, const char *remember) { struct passwd *pwd = NULL; int retval; - char pass[MAXPASS + 1]; - char towhat[MAXPASS + 1]; + char pass[PAM_MAX_RESP_SIZE + 1]; + char towhat[PAM_MAX_RESP_SIZE + 1]; int npass = 0; /* we don't care about number format errors because the helper should be called internally only */ @@ -54,7 +54,7 @@ set_password(const char *forwho, const char *shadow, const char *remember) if (npass != 2) { /* is it a valid password? */ if (npass == 1) { helper_log_err(LOG_DEBUG, "no new password supplied"); - memset(pass, '\0', MAXPASS); + memset(pass, '\0', PAM_MAX_RESP_SIZE); } else { helper_log_err(LOG_DEBUG, "no valid passwords supplied"); } @@ -97,8 +97,8 @@ set_password(const char *forwho, const char *shadow, const char *remember) } done: - memset(pass, '\0', MAXPASS); - memset(towhat, '\0', MAXPASS); + memset(pass, '\0', PAM_MAX_RESP_SIZE); + memset(towhat, '\0', PAM_MAX_RESP_SIZE); unlock_pwdf(); -- cgit v1.2.3 From 48f44125fac8873237ade9e94942f82a8e6d6e1d Mon Sep 17 00:00:00 2001 From: ikerexxe Date: Wed, 15 Jul 2020 09:45:12 +0200 Subject: Move read_passwords function from pam_unix to pam_inline.h [ldv: rewrote commit message] * modules/pam_unix/passverify.h (read_passwords): Remove prototype. * modules/pam_unix/passverify.c (read_passwords): Move ... * libpam/include/pam_inline.h: ... here, rename to pam_read_passwords, add static inline qualifiers. Include and . * modules/pam_unix/unix_chkpwd.c: Include "pam_inline.h". (main): Replace read_passwords with pam_read_passwords. * modules/pam_unix/unix_update.c: Include "pam_inline.h". (set_password): Replace read_passwords with pam_read_passwords. --- libpam/include/pam_inline.h | 50 ++++++++++++++++++++++++++++++++++++++++++ modules/pam_unix/passverify.c | 43 ------------------------------------ modules/pam_unix/passverify.h | 2 -- modules/pam_unix/unix_chkpwd.c | 3 ++- modules/pam_unix/unix_update.c | 3 ++- 5 files changed, 54 insertions(+), 47 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h index ec05fe43..8040b865 100644 --- a/libpam/include/pam_inline.h +++ b/libpam/include/pam_inline.h @@ -10,6 +10,8 @@ #include "pam_cc_compat.h" #include +#include +#include /* * Evaluates to @@ -64,4 +66,52 @@ pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix #define pam_str_skip_icase_prefix(str_, prefix_) \ pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) +static inline int +pam_read_passwords(int fd, int npass, char **passwords) +{ + /* + * The passwords array must contain npass preallocated + * buffers of length PAM_MAX_RESP_SIZE + 1. + */ + int rbytes = 0; + int offset = 0; + int i = 0; + char *pptr; + while (npass > 0) { + rbytes = read(fd, passwords[i]+offset, PAM_MAX_RESP_SIZE+1-offset); + + if (rbytes < 0) { + if (errno == EINTR) { + continue; + } + break; + } + if (rbytes == 0) { + break; + } + + while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes)) + != NULL) { + rbytes -= pptr - (passwords[i]+offset) + 1; + i++; + offset = 0; + npass--; + if (rbytes > 0) { + if (npass > 0) { + memcpy(passwords[i], pptr+1, rbytes); + } + memset(pptr+1, '\0', rbytes); + } + } + offset += rbytes; + } + + /* clear up */ + if (offset > 0 && npass > 0) { + memset(passwords[i], '\0', offset); + } + + return i; +} + #endif /* PAM_INLINE_H */ diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index d5cfd269..4ab7bb2c 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1186,49 +1186,6 @@ getuidname(uid_t uid) return username; } -int -read_passwords(int fd, int npass, char **passwords) -{ - /* The passwords array must contain npass preallocated - * buffers of length PAM_MAX_RESP_SIZE + 1 - */ - int rbytes = 0; - int offset = 0; - int i = 0; - char *pptr; - while (npass > 0) { - rbytes = read(fd, passwords[i]+offset, PAM_MAX_RESP_SIZE+1-offset); - - if (rbytes < 0) { - if (errno == EINTR) continue; - break; - } - if (rbytes == 0) - break; - - while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes)) - != NULL) { - rbytes -= pptr - (passwords[i]+offset) + 1; - i++; - offset = 0; - npass--; - if (rbytes > 0) { - if (npass > 0) - memcpy(passwords[i], pptr+1, rbytes); - memset(pptr+1, '\0', rbytes); - } - } - offset += rbytes; - } - - /* clear up */ - if (offset > 0 && npass > 0) { - memset(passwords[i], '\0', offset); - } - - return i; -} - #endif /* ****************************************************************** * * Copyright (c) Jan Rękorajski 1999. diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index 47d9d4db..c07037d2 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -48,8 +48,6 @@ setup_signals(void); char * getuidname(uid_t uid); -int -read_passwords(int fd, int npass, char **passwords); #endif #ifdef HELPER_COMPILE diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index c61759a6..15a1c2a8 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -33,6 +33,7 @@ #include #include "passverify.h" +#include "pam_inline.h" static int _check_expiry(const char *uname) { @@ -162,7 +163,7 @@ int main(int argc, char *argv[]) } /* read the password from stdin (a pipe from the pam_unix module) */ - npass = read_passwords(STDIN_FILENO, 1, passwords); + npass = pam_read_passwords(STDIN_FILENO, 1, passwords); if (npass != 1) { /* is it a valid password? */ helper_log_err(LOG_DEBUG, "no password supplied"); diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c index ae77fe2e..3559972b 100644 --- a/modules/pam_unix/unix_update.c +++ b/modules/pam_unix/unix_update.c @@ -32,6 +32,7 @@ #include #include "passverify.h" +#include "pam_inline.h" static int set_password(const char *forwho, const char *shadow, const char *remember) @@ -49,7 +50,7 @@ set_password(const char *forwho, const char *shadow, const char *remember) /* read the password from stdin (a pipe from the pam_unix module) */ - npass = read_passwords(STDIN_FILENO, 2, passwords); + npass = pam_read_passwords(STDIN_FILENO, 2, passwords); if (npass != 2) { /* is it a valid password? */ if (npass == 1) { -- cgit v1.2.3 From 155e14e9e23b6dee8e95c3358b18269368110efc Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 3 Aug 2020 20:01:08 +0200 Subject: pam_unix: replace deprecated security_context_t libselinux 3.1 deprecated the typedef security_context_t. Use the underlaying type. --- modules/pam_unix/lckpwdf.-c | 2 +- modules/pam_unix/passverify.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/lckpwdf.-c b/modules/pam_unix/lckpwdf.-c index 7145617e..0bc9c5ad 100644 --- a/modules/pam_unix/lckpwdf.-c +++ b/modules/pam_unix/lckpwdf.-c @@ -73,7 +73,7 @@ static int lckpwdf(void) lockfd = open(LOCKFILE, O_WRONLY); if(lockfd == -1 && errno == ENOENT) { - security_context_t create_context; + char *create_context; int rc; if(getfilecon("/etc/passwd", &create_context)) diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 4ab7bb2c..c9af24f9 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -650,7 +650,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, struct stat st; size_t len = strlen(forwho); #ifdef WITH_SELINUX - security_context_t prev_context=NULL; + char *prev_context=NULL; #endif if (howmany < 0) { @@ -665,7 +665,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - security_context_t passwd_context=NULL; + char *passwd_context=NULL; if (getfilecon("/etc/passwd",&passwd_context)<0) { return PAM_AUTHTOK_ERR; }; @@ -821,13 +821,13 @@ PAMH_ARG_DECL(int unix_update_passwd, int err = 1; int oldmask; #ifdef WITH_SELINUX - security_context_t prev_context=NULL; + char *prev_context=NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - security_context_t passwd_context=NULL; + char *passwd_context=NULL; if (getfilecon("/etc/passwd",&passwd_context)<0) { return PAM_AUTHTOK_ERR; }; @@ -945,14 +945,14 @@ PAMH_ARG_DECL(int unix_update_shadow, int oldmask; int wroteentry = 0; #ifdef WITH_SELINUX - security_context_t prev_context=NULL; + char *prev_context=NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - security_context_t shadow_context=NULL; + char *shadow_context=NULL; if (getfilecon("/etc/shadow",&shadow_context)<0) { return PAM_AUTHTOK_ERR; }; -- cgit v1.2.3 From c7ca67d03cb8b21ceb56e925deb34a6c3337c23b Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Mon, 3 Aug 2020 20:05:00 +0200 Subject: pam_unix: skip context translation These retrieved contexts are just passed to libselinux functions and not printed or otherwise made available to the outside, so a context translation to human readable MCS/MLS labels is not needed. (see man:setrans.conf(5)) --- modules/pam_unix/lckpwdf.-c | 10 +++--- modules/pam_unix/passverify.c | 78 +++++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 44 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/lckpwdf.-c b/modules/pam_unix/lckpwdf.-c index 0bc9c5ad..c3e63155 100644 --- a/modules/pam_unix/lckpwdf.-c +++ b/modules/pam_unix/lckpwdf.-c @@ -73,17 +73,17 @@ static int lckpwdf(void) lockfd = open(LOCKFILE, O_WRONLY); if(lockfd == -1 && errno == ENOENT) { - char *create_context; + char *create_context_raw; int rc; - if(getfilecon("/etc/passwd", &create_context)) + if(getfilecon_raw("/etc/passwd", &create_context_raw)) return -1; - rc = setfscreatecon(create_context); - freecon(create_context); + rc = setfscreatecon_raw(create_context_raw); + freecon(create_context_raw); if(rc) return -1; lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); - if(setfscreatecon(NULL)) + if(setfscreatecon_raw(NULL)) return -1; } } diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index c9af24f9..c0fbc987 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -650,7 +650,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, struct stat st; size_t len = strlen(forwho); #ifdef WITH_SELINUX - char *prev_context=NULL; + char *prev_context_raw = NULL; #endif if (howmany < 0) { @@ -665,20 +665,20 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - char *passwd_context=NULL; - if (getfilecon("/etc/passwd",&passwd_context)<0) { + char *passwd_context_raw = NULL; + if (getfilecon_raw("/etc/passwd",&passwd_context_raw)<0) { return PAM_AUTHTOK_ERR; }; - if (getfscreatecon(&prev_context)<0) { - freecon(passwd_context); + if (getfscreatecon_raw(&prev_context_raw)<0) { + freecon(passwd_context_raw); return PAM_AUTHTOK_ERR; } - if (setfscreatecon(passwd_context)) { - freecon(passwd_context); - freecon(prev_context); + if (setfscreatecon_raw(passwd_context_raw)) { + freecon(passwd_context_raw); + freecon(prev_context_raw); return PAM_AUTHTOK_ERR; } - freecon(passwd_context); + freecon(passwd_context_raw); } #endif pwfile = fopen(OPW_TMPFILE, "w"); @@ -796,12 +796,12 @@ done: } #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { + if (setfscreatecon_raw(prev_context_raw)) { err = 1; } - if (prev_context) - freecon(prev_context); - prev_context=NULL; + if (prev_context_raw) + freecon(prev_context_raw); + prev_context_raw = NULL; } #endif if (!err) { @@ -821,26 +821,26 @@ PAMH_ARG_DECL(int unix_update_passwd, int err = 1; int oldmask; #ifdef WITH_SELINUX - char *prev_context=NULL; + char *prev_context_raw = NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - char *passwd_context=NULL; - if (getfilecon("/etc/passwd",&passwd_context)<0) { + char *passwd_context_raw = NULL; + if (getfilecon_raw("/etc/passwd",&passwd_context_raw)<0) { return PAM_AUTHTOK_ERR; }; - if (getfscreatecon(&prev_context)<0) { - freecon(passwd_context); + if (getfscreatecon_raw(&prev_context_raw)<0) { + freecon(passwd_context_raw); return PAM_AUTHTOK_ERR; } - if (setfscreatecon(passwd_context)) { - freecon(passwd_context); - freecon(prev_context); + if (setfscreatecon_raw(passwd_context_raw)) { + freecon(passwd_context_raw); + freecon(prev_context_raw); return PAM_AUTHTOK_ERR; } - freecon(passwd_context); + freecon(passwd_context_raw); } #endif pwfile = fopen(PW_TMPFILE, "w"); @@ -919,12 +919,12 @@ done: } #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { + if (setfscreatecon_raw(prev_context_raw)) { err = 1; } - if (prev_context) - freecon(prev_context); - prev_context=NULL; + if (prev_context_raw) + freecon(prev_context_raw); + prev_context_raw = NULL; } #endif if (!err) { @@ -945,27 +945,27 @@ PAMH_ARG_DECL(int unix_update_shadow, int oldmask; int wroteentry = 0; #ifdef WITH_SELINUX - char *prev_context=NULL; + char *prev_context_raw = NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - char *shadow_context=NULL; - if (getfilecon("/etc/shadow",&shadow_context)<0) { + char *shadow_context_raw = NULL; + if (getfilecon_raw("/etc/shadow",&shadow_context_raw)<0) { return PAM_AUTHTOK_ERR; }; - if (getfscreatecon(&prev_context)<0) { - freecon(shadow_context); + if (getfscreatecon_raw(&prev_context_raw)<0) { + freecon(shadow_context_raw); return PAM_AUTHTOK_ERR; } - if (setfscreatecon(shadow_context)) { - freecon(shadow_context); - freecon(prev_context); + if (setfscreatecon_raw(shadow_context_raw)) { + freecon(shadow_context_raw); + freecon(prev_context_raw); return PAM_AUTHTOK_ERR; } - freecon(shadow_context); + freecon(shadow_context_raw); } #endif pwfile = fopen(SH_TMPFILE, "w"); @@ -1065,12 +1065,12 @@ PAMH_ARG_DECL(int unix_update_shadow, #ifdef WITH_SELINUX if (SELINUX_ENABLED) { - if (setfscreatecon(prev_context)) { + if (setfscreatecon_raw(prev_context_raw)) { err = 1; } - if (prev_context) - freecon(prev_context); - prev_context=NULL; + if (prev_context_raw) + freecon(prev_context_raw); + prev_context_raw = NULL; } #endif -- cgit v1.2.3 From b303486bf1b812dd99f48a7bbb81838d658f7e03 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 1 Oct 2020 10:36:41 +0200 Subject: Add missing format function attributes and enable -Wmissing-format-attribute Exported functions already have these attributes, add them to other functions. This enables compilers to find format specifier mismatches, like: foo_print("Hello %d", "world") * m4/warn_lang_flags.m4 (gl_WARN_ADD): Add -Wmissing-format-attribute. * conf/pam_conv1/Makefile.am (AM_CFLAGS): Add -I$(top_srcdir)/libpam/include. * conf/pam_conv1/pam_conv_y.y: Include . (yyerror): Add printf format attribute. * modules/pam_pwhistory/opasswd.c (helper_log_err): Likewise. * modules/pam_rootok/pam_rootok.c (log_callback): Likewise. * modules/pam_tally/pam_tally.c (tally_log): Likewise. * modules/pam_tally2/pam_tally2.c (tally_log): Likewise. * modules/pam_unix/passverify.c (helper_log_err): Likewise. --- conf/pam_conv1/Makefile.am | 2 +- conf/pam_conv1/pam_conv_y.y | 3 +++ m4/warn_lang_flags.m4 | 1 + modules/pam_pwhistory/opasswd.c | 1 + modules/pam_rootok/pam_rootok.c | 1 + modules/pam_tally/pam_tally.c | 1 + modules/pam_tally2/pam_tally2.c | 1 + modules/pam_unix/passverify.c | 1 + 8 files changed, 10 insertions(+), 1 deletion(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/conf/pam_conv1/Makefile.am b/conf/pam_conv1/Makefile.am index 4c72162b..88993a20 100644 --- a/conf/pam_conv1/Makefile.am +++ b/conf/pam_conv1/Makefile.am @@ -8,7 +8,7 @@ EXTRA_DIST = README AM_YFLAGS = -d -AM_CFLAGS = $(WARN_CFLAGS) +AM_CFLAGS = -I$(top_srcdir)/libpam/include $(WARN_CFLAGS) pam_conv1_CFLAGS = $(AM_CFLAGS) -Wno-unused-function -Wno-sign-compare diff --git a/conf/pam_conv1/pam_conv_y.y b/conf/pam_conv1/pam_conv_y.y index c971abf4..66d80440 100644 --- a/conf/pam_conv1/pam_conv_y.y +++ b/conf/pam_conv1/pam_conv_y.y @@ -20,6 +20,8 @@ #include #include +#include + extern int yylex(void); int current_line=1; @@ -184,6 +186,7 @@ const char *old_to_new_ctrl_flag(const char *old) return clist[i]; } +PAM_FORMAT((printf, 1, 2)) void yyerror(const char *format, ...) { va_list args; diff --git a/m4/warn_lang_flags.m4 b/m4/warn_lang_flags.m4 index 740194f0..7c4871d6 100644 --- a/m4/warn_lang_flags.m4 +++ b/m4/warn_lang_flags.m4 @@ -11,6 +11,7 @@ gl_WARN_ADD([-Wdeprecated]) gl_WARN_ADD([-Winline]) gl_WARN_ADD([-Wmain]) gl_WARN_ADD([-Wmissing-declarations]) +gl_WARN_ADD([-Wmissing-format-attribute]) gl_WARN_ADD([-Wmissing-prototypes]) gl_WARN_ADD([-Wp64]) gl_WARN_ADD([-Wpointer-arith]) diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index ac10f691..40296d59 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -89,6 +89,7 @@ typedef struct { } opwd; #ifdef HELPER_COMPILE +PAM_FORMAT((printf, 2, 3)) void helper_log_err(int err, const char *format, ...) { diff --git a/modules/pam_rootok/pam_rootok.c b/modules/pam_rootok/pam_rootok.c index eb9c5eee..dd374c53 100644 --- a/modules/pam_rootok/pam_rootok.c +++ b/modules/pam_rootok/pam_rootok.c @@ -50,6 +50,7 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv) #ifdef WITH_SELINUX static int +PAM_FORMAT((printf, 2, 3)) log_callback (int type UNUSED, const char *fmt, ...) { int audit_fd; diff --git a/modules/pam_tally/pam_tally.c b/modules/pam_tally/pam_tally.c index 34ae6241..6fd65009 100644 --- a/modules/pam_tally/pam_tally.c +++ b/modules/pam_tally/pam_tally.c @@ -94,6 +94,7 @@ struct tally_options { #ifdef MAIN #define pam_syslog tally_log static void +PAM_FORMAT((printf, 3, 4)) tally_log (const pam_handle_t *pamh UNUSED, int priority UNUSED, const char *fmt, ...) { diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c index 117df699..bcf3188c 100644 --- a/modules/pam_tally2/pam_tally2.c +++ b/modules/pam_tally2/pam_tally2.c @@ -120,6 +120,7 @@ struct tally_options { #ifdef MAIN #define pam_syslog tally_log static void +PAM_FORMAT((printf, 3, 4)) tally_log (const pam_handle_t *pamh UNUSED, int priority UNUSED, const char *fmt, ...) { diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index c0fbc987..f6132f80 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1117,6 +1117,7 @@ helper_verify_password(const char *name, const char *p, int nullok) } void +PAM_FORMAT((printf, 2, 3)) helper_log_err(int err, const char *format, ...) { va_list args; -- cgit v1.2.3 From 980d90c9232fe5325d1a4deddd42c597cf9e1a54 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 10 Jun 2021 14:00:00 +0000 Subject: pam_unix: do not use crypt_checksalt when checking for password expiration According to Zack Weinberg, the intended meaning of CRYPT_SALT_METHOD_LEGACY is "passwd(1) should not use this hashing method", it is not supposed to mean "force a password change on next login for any user with an existing stored hash using this method". This reverts commit 4da9febc39b955892a30686e8396785b96bb8ba5. * modules/pam_unix/passverify.c (check_shadow_expiry) [CRYPT_CHECKSALT_AVAILABLE]: Remove. Closes: https://github.com/linux-pam/linux-pam/issues/367 --- modules/pam_unix/passverify.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index f6132f80..5a19ed85 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -289,13 +289,7 @@ 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; -- cgit v1.2.3 From 530c9f9e2d746e1d168c6b17863debda7664ac7c Mon Sep 17 00:00:00 2001 From: Björn Esser Date: Fri, 28 Feb 2020 15:47:52 +0100 Subject: Remove support for legacy xcrypt Since many distributions are shipping a version of libxcrypt >= 4.0.0 as a replacement for glibc's libcrypt now, older versions of xcrypt, which could be installed in parallel, are not relevant anymore. * configure.ac (AC_CHECK_HEADERS): Remove xcrypt.h. (AC_SEARCH_LIBS): Remove xcrypt. (AC_CHECK_FUNCS): Remove crypt_gensalt_r. (AC_DEFINE): Remove HAVE_LIBXCRYPT. * modules/pam_pwhistory/opasswd.c [HAVE_LIBXCRYPT]: Remove. * modules/pam_unix/bigcrypt.c [HAVE_LIBXCRYPT]: Likewise. * modules/pam_userdb/pam_userdb.c [HAVE_LIBXCRYPT]: Likewise. * modules/pam_unix/passverify.c [HAVE_LIBXCRYPT]: Likewise. (create_password_hash) [HAVE_LIBXCRYPT]: Likewise. --- configure.ac | 12 +++--------- modules/pam_pwhistory/opasswd.c | 4 +--- modules/pam_unix/bigcrypt.c | 4 +--- modules/pam_unix/passverify.c | 24 +++++------------------- modules/pam_userdb/pam_userdb.c | 4 +--- 5 files changed, 11 insertions(+), 37 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/configure.ac b/configure.ac index 8e5d0ff7..10056555 100644 --- a/configure.ac +++ b/configure.ac @@ -359,23 +359,17 @@ else fi AC_SUBST(LIBAUDIT) -AC_CHECK_HEADERS(xcrypt.h crypt.h) -AS_IF([test "x$ac_cv_header_xcrypt_h" = "xyes"], - [crypt_libs="xcrypt crypt"], - [crypt_libs="crypt"]) +AC_CHECK_HEADERS(crypt.h) BACKUP_LIBS=$LIBS -AC_SEARCH_LIBS([crypt],[$crypt_libs]) +AC_SEARCH_LIBS([crypt],[crypt]) case "$ac_cv_search_crypt" in -l*) LIBCRYPT="$ac_cv_search_crypt" ;; *) LIBCRYPT="" ;; esac -AC_CHECK_FUNCS(crypt_r crypt_gensalt_r) +AC_CHECK_FUNCS([crypt_r]) LIBS=$BACKUP_LIBS AC_SUBST(LIBCRYPT) -if test "$LIBCRYPT" = "-lxcrypt" && test "$ac_cv_header_xcrypt_h" = "yes" ; then - AC_DEFINE([HAVE_LIBXCRYPT], 1, [Define to 1 if xcrypt support should be compiled in.]) -fi AC_ARG_WITH([randomdev], AS_HELP_STRING([--with-randomdev=(|yes|no)],[use specified random device instead of /dev/urandom or 'no' to disable]), opt_randomdev=$withval) if test "$opt_randomdev" = yes || test -z "$opt_randomdev"; then diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index 40296d59..a6cd3d2a 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -54,9 +54,7 @@ #endif #include -#if defined HAVE_LIBXCRYPT -#include -#elif defined (HAVE_CRYPT_H) +#ifdef HAVE_CRYPT_H #include #endif diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c index 31be2f7b..d8d61a4b 100644 --- a/modules/pam_unix/bigcrypt.c +++ b/modules/pam_unix/bigcrypt.c @@ -29,9 +29,7 @@ #include #include #include -#ifdef HAVE_LIBXCRYPT -#include -#elif defined(HAVE_CRYPT_H) +#ifdef HAVE_CRYPT_H #include #endif diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 5a19ed85..e833402c 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -19,9 +19,7 @@ #include #include #include -#ifdef HAVE_LIBXCRYPT -#include -#elif defined(HAVE_CRYPT_H) +#ifdef HAVE_CRYPT_H #include #endif @@ -467,23 +465,11 @@ PAMH_ARG_DECL(char * create_password_hash, */ 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]; - crypt_make_salt(entropy, sizeof(entropy) - 1); - sp = crypt_gensalt_r (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) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds); - } - crypt_make_salt(sp, 16); -#ifdef HAVE_CRYPT_GENSALT_R + sp = stpcpy(salt, algoid); + if (on(UNIX_ALGO_ROUNDS, ctrl)) { + sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds); } -#endif + crypt_make_salt(sp, 16); #endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */ #ifdef HAVE_CRYPT_R sp = NULL; diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index d59801bf..f467ea4c 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -17,9 +17,7 @@ #include #include #include -#ifdef HAVE_LIBXCRYPT -#include -#elif defined(HAVE_CRYPT_H) +#ifdef HAVE_CRYPT_H #include #endif -- cgit v1.2.3 From f220cace205332a3dc34e7b37a85e7627e097e7d Mon Sep 17 00:00:00 2001 From: "Andrew G. Morgan" Date: Sat, 26 Jun 2021 14:18:08 -0700 Subject: Permit unix_chkpwd & pam_unix.so to run without being setuid-root. Remove the hard-coding of the idea that the only way pam_unix.so can read the shadow file is if it can, in some way, run setuid-root. Linux capabilities only require cap_dac_override to read the /etc/shadow file. This change achieves two things: it opens a path for a linux-pam application to run without being setuid-root; further, it allows unix_chkpwd to run non-setuid-root if it is installed: sudo setcap cap_dac_override=ep unix_chkpwd If we wanted to link against libcap, we could install this binary with cap_dac_override=p, and use cap_set_proc() to raise the effective bit at runtime. However, some distributions already link unix_chkpwd against libcap-ng for some, likely spurious, reason so "ep" is fine for now. Signed-off-by: Andrew G. Morgan --- modules/pam_unix/passverify.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index e833402c..5460b057 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -241,12 +241,16 @@ PAMH_ARG_DECL(int get_account_info, * ...and shadow password file entry for this user, * if shadowing is enabled */ + *spwdent = pam_modutil_getspnam(pamh, name); + if (*spwdent == NULL) { #ifndef HELPER_COMPILE - if (geteuid() || SELINUX_ENABLED) - return PAM_UNIX_RUN_HELPER; + /* still a chance the user can authenticate */ + if (errno == EACCES || SELINUX_ENABLED) + return PAM_UNIX_RUN_HELPER; #endif - *spwdent = pam_modutil_getspnam(pamh, name); - if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) + return PAM_AUTHINFO_UNAVAIL; + } + if ((*spwdent)->sp_pwdp == NULL) return PAM_AUTHINFO_UNAVAIL; } } else { -- cgit v1.2.3 From 470823c4aacef5cb3b1180be6ed70846b61a3752 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 19 Aug 2021 08:00:00 +0000 Subject: pam_unix: workaround the problem caused by libnss_systemd The getspnam(3) manual page says that errno shall be set to EACCES when the caller does not have permission to access the shadow password file. Unfortunately, this contract is broken when libnss_systemd is used in the nss stack. Workaround this problem by falling back to the helper invocation when pam_modutil_getspnam returns NULL regardless of errno. As pam_unix already behaves this way when selinux is enabled, it should be OK for the case when selinux is not enabled, too. * modules/pam_unix/passverify.c (get_account_info): When pam_modutil_getspnam returns NULL, unconditionally fall back to the helper invocation. Complements: f220cace2053 ("Permit unix_chkpwd & pam_unix.so to run without being setuid-root") Resolves: https://github.com/linux-pam/linux-pam/issues/379 --- modules/pam_unix/passverify.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 5460b057..fd81051d 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -245,8 +245,7 @@ PAMH_ARG_DECL(int get_account_info, if (*spwdent == NULL) { #ifndef HELPER_COMPILE /* still a chance the user can authenticate */ - if (errno == EACCES || SELINUX_ENABLED) - return PAM_UNIX_RUN_HELPER; + return PAM_UNIX_RUN_HELPER; #endif return PAM_AUTHINFO_UNAVAIL; } -- cgit v1.2.3 From 40f7d85f3736d058c26de1dafa4fed46de7d75ef Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Fri, 3 Sep 2021 08:00:00 +0000 Subject: Fix a typo found using codespell tool * modules/pam_pwhistory/pam_pwhistory.c: Replace "crypted password" with "hashed password" in comment. * modules/pam_unix/passverify.c (create_password_hash): Rename "crypted" local variable to "hashed". --- modules/pam_pwhistory/pam_pwhistory.c | 2 +- modules/pam_unix/passverify.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'modules/pam_unix/passverify.c') diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c index a16365f8..ce2c21f5 100644 --- a/modules/pam_pwhistory/pam_pwhistory.c +++ b/modules/pam_pwhistory/pam_pwhistory.c @@ -282,7 +282,7 @@ run_check_helper(pam_handle_t *pamh, const char *user, return retval; } -/* This module saves the current crypted password in /etc/security/opasswd +/* This module saves the current hashed password in /etc/security/opasswd and then compares the new password with all entries in this file. */ int diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index fd81051d..f2474a5b 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -447,7 +447,7 @@ PAMH_ARG_DECL(char * create_password_hash, algoid = "$6$"; } else { /* must be crypt/bigcrypt */ char tmppass[9]; - char *crypted; + char *hashed; crypt_make_salt(salt, 2); if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) { @@ -455,10 +455,10 @@ PAMH_ARG_DECL(char * create_password_hash, tmppass[sizeof(tmppass)-1] = '\0'; password = tmppass; } - crypted = bigcrypt(password, salt); + hashed = bigcrypt(password, salt); memset(tmppass, '\0', sizeof(tmppass)); password = NULL; - return crypted; + return hashed; } #if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY -- cgit v1.2.3