From a51c2cc8cb11c340e3768d6142008862b7ce69c1 Mon Sep 17 00:00:00 2001 From: Benny Baumann Date: Mon, 13 Nov 2023 14:17:01 +0100 Subject: pam_unix: only output length check message on failure The debug message was placed outside the password length check and thus if the length check succeeded no message would have been placed. Comparing this location with other occurrences indicates this was by mistake, thus the message is now suppressed if there's nothing to print anyway. Signed-off-by: Benny Baumann --- modules/pam_unix/pam_unix_passwd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index c3417413..c1d547c7 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -572,9 +572,10 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh remark = _("You must choose a shorter password."); D(("length exceeded [%s]", remark)); } else if (off(UNIX__IAMROOT, ctrl)) { - if ((int)strlen(pass_new) < pass_min_len) + if ((int)strlen(pass_new) < pass_min_len) { remark = _("You must choose a longer password."); - D(("length check [%s]", remark)); + D(("length check [%s]", remark)); + } if (on(UNIX_REMEMBER_PASSWD, ctrl)) { if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR) remark = _("Password has been already used. Choose another."); -- cgit v1.2.3 From 0fb2978d0e139dc57878d5c82d6eae79273e2031 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Wed, 6 Dec 2023 22:48:34 +0100 Subject: treewide: fix typos in comments and documentation Signed-off-by: Tobias Stoeckmann --- doc/man/pam.3.xml | 4 ++-- doc/man/pam_open_session.3.xml | 2 +- libpam/pam_delay.c | 2 +- libpam/pam_dispatch.c | 2 +- libpam/pam_password.c | 2 +- libpam/pam_private.h | 2 +- libpam_misc/misc_conv.c | 4 ++-- modules/pam_env/pam_env.8.xml | 2 +- modules/pam_limits/pam_limits.c | 2 +- modules/pam_pwhistory/opasswd.c | 2 +- modules/pam_unix/md5_crypt.c | 2 +- modules/pam_unix/pam_unix_auth.c | 2 +- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/support.c | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/doc/man/pam.3.xml b/doc/man/pam.3.xml index 4b828016..a7d13b45 100644 --- a/doc/man/pam.3.xml +++ b/doc/man/pam.3.xml @@ -150,7 +150,7 @@ pam_get_item3 - functions allows applications and PAM service modules to set and + functions allow applications and PAM service modules to set and retrieve PAM information. @@ -169,7 +169,7 @@ pam_get_data3 - functions allows PAM service modules to set and retrieve free-form + function allows PAM service modules to set and retrieve free-form data from one invocation to another. diff --git a/doc/man/pam_open_session.3.xml b/doc/man/pam_open_session.3.xml index d37b3e59..a05e0abe 100644 --- a/doc/man/pam_open_session.3.xml +++ b/doc/man/pam_open_session.3.xml @@ -40,7 +40,7 @@ It should be noted that the effective uid, geteuid2 - . of the application should be of sufficient + , of the application should be of sufficient privilege to perform such tasks as creating or mounting the user's home directory for example. diff --git a/libpam/pam_delay.c b/libpam/pam_delay.c index b6a962d0..b8fddbb6 100644 --- a/libpam/pam_delay.c +++ b/libpam/pam_delay.c @@ -19,7 +19,7 @@ /* ********************************************************************** * initialize the time as unset, this is set on the return from the - * authenticating pair of of the libpam pam_XXX calls. + * authenticating pair of the libpam pam_XXX calls. */ void _pam_reset_timer(pam_handle_t *pamh) diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c index 31a28be3..ca78a10f 100644 --- a/libpam/pam_dispatch.c +++ b/libpam/pam_dispatch.c @@ -299,7 +299,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, } continue; -decision_made: /* by getting here we have made a decision */ +decision_made: /* by getting here we have made a decision */ while (h->next != NULL && h->next->stack_level >= stack_level) { h = h->next; ++depth; diff --git a/libpam/pam_password.c b/libpam/pam_password.c index 5bda547b..9783dbe0 100644 --- a/libpam/pam_password.c +++ b/libpam/pam_password.c @@ -22,7 +22,7 @@ int pam_chauthtok(pam_handle_t *pamh, int flags) return PAM_SYSTEM_ERR; } - /* applications are not allowed to set this flags */ + /* applications are not allowed to set these flags */ if (flags & (PAM_PRELIM_CHECK | PAM_UPDATE_AUTHTOK)) { pam_syslog (pamh, LOG_ERR, "PAM_PRELIM_CHECK or PAM_UPDATE_AUTHTOK set by application"); diff --git a/libpam/pam_private.h b/libpam/pam_private.h index da268bdf..8069b61c 100644 --- a/libpam/pam_private.h +++ b/libpam/pam_private.h @@ -255,7 +255,7 @@ const char *_pam_dlerror (void); /* For now we just use a stack and linear search for module data. */ /* If it becomes apparent that there is a lot of data, it should */ -/* changed to either a sorted list or a hash table. */ +/* be changed to either a sorted list or a hash table. */ struct pam_data { char *name; diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c index 0f213bce..7410e929 100644 --- a/libpam_misc/misc_conv.c +++ b/libpam_misc/misc_conv.c @@ -97,7 +97,7 @@ static int get_delay(void) expired = 0; /* reset flag */ (void) time(&now); - /* has the quit time past? */ + /* has the quit time passed? */ if (pam_misc_conv_die_time && now >= pam_misc_conv_die_time) { fprintf(stderr,"%s",pam_misc_conv_die_line); @@ -105,7 +105,7 @@ static int get_delay(void) return -1; /* time is up */ } - /* has the warning time past? */ + /* has the warning time passed? */ if (pam_misc_conv_warn_time && now >= pam_misc_conv_warn_time) { fprintf(stderr, "%s", pam_misc_conv_warn_line); pam_misc_conv_warn_time = 0; /* reset warn_time */ diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml index fb172e17..3af52ea6 100644 --- a/modules/pam_env/pam_env.8.xml +++ b/modules/pam_env/pam_env.8.xml @@ -181,7 +181,7 @@ Indicate an alternative .pam_environment - file to override the default.The syntax is the same as + file to override the default. The syntax is the same as for /etc/security/pam_env.conf. The filename is relative to the user home directory. This can be useful when different services need different diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index fc541330..53e2e8f2 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -914,7 +914,7 @@ parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid, for(j=0; j < strlen(value); j++) value[j]=tolower((unsigned char)value[j]); - if (strcmp(uname, domain) == 0) /* this user have a limit */ + if (strcmp(uname, domain) == 0) /* this user has a limit */ process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl); else if (domain[0]=='@') { if (ctrl & PAM_DEBUG_ARG) { diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index 5f577dfd..f1f62aaf 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -425,7 +425,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN /* increase count. */ entry.count++; - /* check that we don't remember to many passwords. */ + /* check that we don't remember too many passwords. */ while (entry.count > howmany && entry.count > 1) { char *p = strpbrk (entry.old_passwords, ","); diff --git a/modules/pam_unix/md5_crypt.c b/modules/pam_unix/md5_crypt.c index ed5ecda4..c3e77c9d 100644 --- a/modules/pam_unix/md5_crypt.c +++ b/modules/pam_unix/md5_crypt.c @@ -38,7 +38,7 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt) { const char *magic = "$1$"; /* This string is magic for this algorithm. Having - * it this way, we can get get better later on */ + * it this way, we can get better later on */ char *passwd, *p; const char *sp, *ep; unsigned char final[16]; diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c index 976699d4..ffb61547 100644 --- a/modules/pam_unix/pam_unix_auth.c +++ b/modules/pam_unix/pam_unix_auth.c @@ -118,7 +118,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) /* * Various libraries at various times have had bugs related to * '+' or '-' as the first character of a user name. Don't - * allow this characters here. + * allow these characters here. */ if (name[0] == '-' || name[0] == '+') { pam_syslog(pamh, LOG_NOTICE, "bad username [%s]", name); diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index c1d547c7..9dde2aee 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -698,7 +698,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) } else { D(("process run by root so do nothing this time around")); pass_old = NULL; - retval = PAM_SUCCESS; /* root doesn't have too */ + retval = PAM_SUCCESS; /* root doesn't have to */ } if (retval != PAM_SUCCESS) { diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index eb2fff50..9d8cac7d 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -648,7 +648,7 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name /* * This function does not have to be too smart if something goes - * wrong, return FALSE and let this case to be treated somewhere + * wrong, return FALSE and let this case be treated somewhere * else (CG) */ -- cgit v1.2.3 From 8f2ca5919b26843ef774ef0aeb9bf261dec943a0 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Tue, 2 Jan 2024 20:46:54 +0100 Subject: pam_unix: avoid reading uninitialized variable The function _unix_comesfromsource calls _unix_getpwnam internally. When changing the authentication token, it is first called to read local passwd file and optionally contacting NIS. If an entry is found, _unix_getpwnam is called, this time definitely reading passwd file and contacting NIS (if support exists) and parsing the entry. This is meant to check if the entry is not just available but also valid. Since the return value of _unix_getpwnam is not checked and the supplied pointer is only set in case of success, the check for a NULl pointer afterwards can lead to undefined behavior. It is easier to call _unix_getpwnam directly, check its return value and then check if the entry could be parsed. This in turn reduces the amount of /etc/passwd accesses (and fixes a theoretical TOCTOU race). Signed-off-by: Tobias Stoeckmann --- modules/pam_unix/pam_unix_passwd.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 9dde2aee..9947f12a 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -601,6 +601,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) int remember = -1; int rounds = 0; int pass_min_len = 0; + struct passwd *pwd; /* */ const char *user; @@ -646,21 +647,18 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) * getpwnam() doesn't tell you *where* the information it gives you * came from, nor should it. That's our job. */ - if (_unix_comesfromsource(pamh, user, 1, on(UNIX_NIS, ctrl)) == 0) { + if (_unix_getpwnam(pamh, user, 1, on(UNIX_NIS, ctrl), &pwd) == 0) { pam_syslog(pamh, LOG_DEBUG, "user \"%s\" does not exist in /etc/passwd%s", user, on(UNIX_NIS, ctrl) ? " or NIS" : ""); return PAM_USER_UNKNOWN; - } else { - struct passwd *pwd; - _unix_getpwnam(pamh, user, 1, 1, &pwd); - if (pwd == NULL) { - pam_syslog(pamh, LOG_DEBUG, - "user \"%s\" has corrupted passwd entry", - user); - return PAM_USER_UNKNOWN; - } + } else if (pwd == NULL) { + pam_syslog(pamh, LOG_DEBUG, + "user \"%s\" has corrupted passwd entry", + user); + return PAM_USER_UNKNOWN; } + _pam_drop(pwd); /* * This is not an AUTH module! -- cgit v1.2.3 From 73d009e9ea8edafc18c7fe3650b25dd6bdce88c1 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Tue, 2 Jan 2024 22:42:58 +0100 Subject: pam_unix: use getline Signed-off-by: Tobias Stoeckmann --- modules/pam_unix/pam_unix_passwd.c | 6 ++++-- modules/pam_unix/passverify.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 9947f12a..7c141c3b 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -339,17 +339,18 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, static int check_old_password(const char *forwho, const char *newpass) { - static char buf[16384]; + char *buf = NULL; char *s_pas; int retval = PAM_SUCCESS; FILE *opwfile; + size_t n = 0; size_t len = strlen(forwho); opwfile = fopen(OLD_PASSWORDS_FILE, "r"); if (opwfile == NULL) return PAM_ABORT; - while (fgets(buf, 16380, opwfile)) { + while (getline(&buf, &n, opwfile) != -1) { if (!strncmp(buf, forwho, len) && (buf[len] == ':' || buf[len] == ',')) { char *sptr; @@ -371,6 +372,7 @@ static int check_old_password(const char *forwho, const char *newpass) break; } } + free(buf); fclose(opwfile); return retval; diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 3bcfed7f..2474fa7a 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -651,7 +651,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, int howmany) #endif { - static char buf[16384]; + char *buf = NULL; char *s_luser, *s_uid, *s_npas, *s_pas, *pass; int npas; FILE *pwfile, *opwfile; @@ -660,6 +660,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, int found = 0; struct passwd *pwd = NULL; struct stat st; + size_t bufsize = 0; size_t len = strlen(forwho); #ifdef WITH_SELINUX char *prev_context_raw = NULL; @@ -727,7 +728,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, goto done; } - while (fgets(buf, 16380, opwfile)) { + while (getline(&buf, &bufsize, opwfile) == -1) { if (!strncmp(buf, forwho, len) && strchr(":,\n", buf[len]) != NULL) { char *ep, *sptr = NULL; long value; @@ -777,6 +778,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, break; } } + free(buf); fclose(opwfile); if (!found) { -- cgit v1.2.3 From e3309f060a67805e679fee55b1101b91991ea824 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Mon, 15 Jan 2024 20:05:28 +0100 Subject: pam_unix: fix regressions The returned value stored in pwd from _unix_getpwnam is inserted into pam handler through pam_set_data. Do not manually free the value. Also check getline return value for != -1 instead of == -1. Fixes 8f2ca5919b26843ef774ef0aeb9bf261dec943a0 and 73d009e9ea8edafc18c7fe3650b25dd6bdce88c1. No release affected. Signed-off-by: Tobias Stoeckmann --- modules/pam_unix/pam_unix_passwd.c | 1 - modules/pam_unix/passverify.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 7c141c3b..fe3f566a 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -660,7 +660,6 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) user); return PAM_USER_UNKNOWN; } - _pam_drop(pwd); /* * This is not an AUTH module! diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 045ea785..60d9ceca 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -729,7 +729,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, goto done; } - while (getline(&buf, &bufsize, opwfile) == -1) { + while (getline(&buf, &bufsize, opwfile) != -1) { if (!strncmp(buf, forwho, len) && strchr(":,\n", buf[len]) != NULL) { char *ep, *sptr = NULL; long value; -- cgit v1.2.3 From 9f19e7da7a014e022cdbba06accca171adef27e0 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 4 Jan 2024 18:23:59 +0100 Subject: pam_unix: set close-on-exec Since the module operates on sensitive files set the close-on-exec flag, to avoid file descriptor leaks if there is ever any sibling thread. The fopen(3) mode "e" is supported in glibc since version 2.7 (released in 2007), and ignored prior, see: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=65d834b0add966dbbdb5ed1e916c60b2b2d87f10 --- modules/pam_unix/lckpwdf.-c | 17 +++-------------- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/passverify.c | 16 ++++++++-------- modules/pam_unix/support.c | 2 +- 4 files changed, 13 insertions(+), 24 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/lckpwdf.-c b/modules/pam_unix/lckpwdf.-c index c3e63155..4d0f0ad3 100644 --- a/modules/pam_unix/lckpwdf.-c +++ b/modules/pam_unix/lckpwdf.-c @@ -35,15 +35,6 @@ static int lockfd = -1; -static int set_close_on_exec(int fd) -{ - int flags = fcntl(fd, F_GETFD, 0); - if (flags == -1) - return -1; - flags |= FD_CLOEXEC; - return fcntl(fd, F_SETFD, flags); -} - static int do_lock(int fd) { struct flock fl; @@ -70,7 +61,7 @@ static int lckpwdf(void) #ifdef WITH_SELINUX if(is_selinux_enabled()>0) { - lockfd = open(LOCKFILE, O_WRONLY); + lockfd = open(LOCKFILE, O_WRONLY | O_CLOEXEC); if(lockfd == -1 && errno == ENOENT) { char *create_context_raw; @@ -82,18 +73,16 @@ static int lckpwdf(void) freecon(create_context_raw); if(rc) return -1; - lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); + lockfd = open(LOCKFILE, O_CREAT | O_WRONLY | O_CLOEXEC, 0600); if(setfscreatecon_raw(NULL)) return -1; } } else #endif - lockfd = open(LOCKFILE, O_CREAT | O_WRONLY, 0600); + lockfd = open(LOCKFILE, O_CREAT | O_WRONLY | O_CLOEXEC, 0600); if (lockfd == -1) return -1; - if (set_close_on_exec(lockfd) == -1) - goto cleanup_fd; memset(&act, 0, sizeof act); act.sa_handler = alarm_catch; diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index fe3f566a..3a223949 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -346,7 +346,7 @@ static int check_old_password(const char *forwho, const char *newpass) size_t n = 0; size_t len = strlen(forwho); - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + opwfile = fopen(OLD_PASSWORDS_FILE, "re"); if (opwfile == NULL) return PAM_ABORT; diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 60d9ceca..303929a4 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -400,7 +400,7 @@ crypt_make_salt(char *where, int length) int fd; int rv; - if ((rv = fd = open(PAM_PATH_RANDOMDEV, O_RDONLY)) != -1) { + if ((rv = fd = open(PAM_PATH_RANDOMDEV, O_RDONLY | O_CLOEXEC)) != -1) { while ((rv = read(fd, where, length)) != length && errno == EINTR); close (fd); } @@ -557,7 +557,7 @@ unix_selinux_confined(void) } /* let's try opening shadow read only */ - if ((fd=open("/etc/shadow", O_RDONLY)) != -1) { + if ((fd=open("/etc/shadow", O_RDONLY | O_CLOEXEC)) != -1) { close(fd); confined = 0; return confined; @@ -695,14 +695,14 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, freecon(passwd_context_raw); } #endif - pwfile = fopen(OPW_TMPFILE, "w"); + pwfile = fopen(OPW_TMPFILE, "we"); umask(oldmask); if (pwfile == NULL) { err = 1; goto done; } - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + opwfile = fopen(OLD_PASSWORDS_FILE, "re"); if (opwfile == NULL) { fclose(pwfile); err = 1; @@ -858,14 +858,14 @@ PAMH_ARG_DECL(int unix_update_passwd, freecon(passwd_context_raw); } #endif - pwfile = fopen(PW_TMPFILE, "w"); + pwfile = fopen(PW_TMPFILE, "we"); umask(oldmask); if (pwfile == NULL) { err = 1; goto done; } - opwfile = fopen("/etc/passwd", "r"); + opwfile = fopen("/etc/passwd", "re"); if (opwfile == NULL) { fclose(pwfile); err = 1; @@ -983,14 +983,14 @@ PAMH_ARG_DECL(int unix_update_shadow, freecon(shadow_context_raw); } #endif - pwfile = fopen(SH_TMPFILE, "w"); + pwfile = fopen(SH_TMPFILE, "we"); umask(oldmask); if (pwfile == NULL) { err = 1; goto done; } - opwfile = fopen("/etc/shadow", "r"); + opwfile = fopen("/etc/shadow", "re"); if (opwfile == NULL) { fclose(pwfile); err = 1; diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 546ef820..d391973f 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -352,7 +352,7 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name, if (!matched && files && strchr(name, ':') == NULL) { FILE *passwd; - passwd = fopen("/etc/passwd", "r"); + passwd = fopen("/etc/passwd", "re"); if (passwd != NULL) { size_t n = 0, userlen; ssize_t r; -- cgit v1.2.3 From d5c01cfd6e47503fb597c5568f43cdf079a30719 Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 4 Jan 2024 18:24:05 +0100 Subject: pam_unix: clean additional possible sensitive buffers --- modules/pam_unix/bigcrypt.c | 3 +++ modules/pam_unix/pam_unix_passwd.c | 3 ++- modules/pam_unix/passverify.c | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c index f7c35a47..be7cdb93 100644 --- a/modules/pam_unix/bigcrypt.c +++ b/modules/pam_unix/bigcrypt.c @@ -107,6 +107,7 @@ char *bigcrypt(const char *key, const char *salt) tmp_ptr = crypt(plaintext_ptr, salt); /* libc crypt() */ #endif if (tmp_ptr == NULL) { + pam_overwrite_array(keybuf); free(dec_c2_cryptbuf); #ifdef HAVE_CRYPT_R free(cdata); @@ -136,6 +137,7 @@ char *bigcrypt(const char *key, const char *salt) tmp_ptr = crypt(plaintext_ptr, salt_ptr); #endif if (tmp_ptr == NULL) { + pam_overwrite_array(keybuf); pam_overwrite_string(dec_c2_cryptbuf); free(dec_c2_cryptbuf); #ifdef HAVE_CRYPT_R @@ -156,6 +158,7 @@ char *bigcrypt(const char *key, const char *salt) } D(("key=|%s|, salt=|%s|\nbuf=|%s|\n", key, salt, dec_c2_cryptbuf)); + pam_overwrite_array(keybuf); #ifdef HAVE_CRYPT_R pam_overwrite_object(cdata); free(cdata); diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 3a223949..b915ce66 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -350,7 +350,7 @@ static int check_old_password(const char *forwho, const char *newpass) if (opwfile == NULL) return PAM_ABORT; - while (getline(&buf, &n, opwfile) != -1) { + for (; getline(&buf, &n, opwfile) != -1; pam_overwrite_n(buf, n)) { if (!strncmp(buf, forwho, len) && (buf[len] == ':' || buf[len] == ',')) { char *sptr; @@ -372,6 +372,7 @@ static int check_old_password(const char *forwho, const char *newpass) break; } } + pam_overwrite_n(buf, n); free(buf); fclose(opwfile); diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 2c95bba2..426d4028 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -729,7 +729,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, goto done; } - while (getline(&buf, &bufsize, opwfile) != -1) { + for (; getline(&buf, &bufsize, opwfile) != -1; pam_overwrite_n(buf, bufsize)) { if (!strncmp(buf, forwho, len) && strchr(":,\n", buf[len]) != NULL) { char *ep, *sptr = NULL; long value; @@ -779,6 +779,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, break; } } + pam_overwrite_n(buf, bufsize); free(buf); fclose(opwfile); -- cgit v1.2.3 From 97325c0ca92d0d44ee77681e802b383099c91e0d Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 4 Jan 2024 18:24:07 +0100 Subject: pam_unix: log about failure to execute unix_chkpwd(8) --- modules/pam_unix/pam_unix_passwd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index b915ce66..444d61ca 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -286,7 +286,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, DIAG_POP_IGNORE_CAST_QUAL; /* should not get here: exit with error */ - D(("helper binary is not available")); + pam_syslog(pamh, LOG_ERR, "failed to execute %s: %m", UPDATE_HELPER); _exit(PAM_AUTHINFO_UNAVAIL); } else if (child > 0) { /* wait for child */ -- cgit v1.2.3 From c25a858bb548b4eb881dabbf10aed4a08b11e973 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Mon, 15 Jan 2024 21:36:38 +0100 Subject: pam_unix: do not allow comma as a field separator The opasswd file shall not use comma as a separator. Enforce colon just like pam_pwhistory does as well. A comma can be part of a user name, although its usage is discouraged. If such a user exists, it could happen that stored passwords of another user are checked. Signed-off-by: Tobias Stoeckmann --- modules/pam_unix/pam_unix_passwd.c | 13 ++++++------- modules/pam_unix/passverify.c | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 444d61ca..897de6ce 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -351,14 +351,13 @@ static int check_old_password(const char *forwho, const char *newpass) return PAM_ABORT; for (; getline(&buf, &n, opwfile) != -1; pam_overwrite_n(buf, n)) { - if (!strncmp(buf, forwho, len) && (buf[len] == ':' || - buf[len] == ',')) { + if (!strncmp(buf, forwho, len) && buf[len] == ':') { char *sptr; buf[strlen(buf) - 1] = '\0'; - /* s_luser = */ strtok_r(buf, ":,", &sptr); - /* s_uid = */ strtok_r(NULL, ":,", &sptr); - /* s_npas = */ strtok_r(NULL, ":,", &sptr); - s_pas = strtok_r(NULL, ":,", &sptr); + /* s_luser = */ strtok_r(buf, ":", &sptr); + /* s_uid = */ strtok_r(NULL, ":", &sptr); + /* s_npas = */ strtok_r(NULL, ":", &sptr); + s_pas = strtok_r(NULL, ",", &sptr); while (s_pas != NULL) { char *md5pass = Goodcrypt_md5(newpass, s_pas); if (md5pass == NULL || !strcmp(md5pass, s_pas)) { @@ -366,7 +365,7 @@ static int check_old_password(const char *forwho, const char *newpass) retval = PAM_AUTHTOK_ERR; break; } - s_pas = strtok_r(NULL, ":,", &sptr); + s_pas = strtok_r(NULL, ",", &sptr); _pam_delete(md5pass); } break; diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 426d4028..5c4f862e 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -730,7 +730,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, } for (; getline(&buf, &bufsize, opwfile) != -1; pam_overwrite_n(buf, bufsize)) { - if (!strncmp(buf, forwho, len) && strchr(":,\n", buf[len]) != NULL) { + if (!strncmp(buf, forwho, len) && strchr(":\n", buf[len]) != NULL) { char *ep, *sptr = NULL; long value; found = 1; @@ -752,7 +752,7 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, found = 0; continue; } - s_pas = strtok_r(NULL, ":", &sptr); + s_pas = strtok_r(NULL, "", &sptr); value = strtol(s_npas, &ep, 10); if (value < 0 || value >= INT_MAX || s_npas == ep || *ep != '\0') npas = 0; -- cgit v1.2.3 From bcc3b81b920491fa9ec94e3fc584cf7384e8380d Mon Sep 17 00:00:00 2001 From: Christian Göttsche Date: Thu, 22 Feb 2024 17:04:12 +0100 Subject: pam_unix: drop cast to same type --- modules/pam_unix/pam_unix_passwd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 897de6ce..c3c6ea7a 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -779,7 +779,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) * password is acceptable. */ - if (*(const char *)pass_new == '\0') { /* "\0" password = NULL */ + if (*pass_new == '\0') { /* "\0" password = NULL */ pass_new = NULL; } retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, -- cgit v1.2.3 From 4d1d4f699551f395be065e60513eaf85f01b84e6 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Wed, 21 Aug 2024 08:00:00 +0000 Subject: Include pam_i18n.h where i18n definitions are required Do not include and other i18n stuff via config.h which is included into every compilation unit, include "pam_i18n.h" explicitly where necessary. * configure.ac (AH_BOTTOM): Remove. * libpam/pam_get_authtok.c: Include "pam_i18n.h". * libpam/pam_item.c: Likewise. * libpam/pam_strerror.c: Likewise. * libpam_misc/misc_conv.c: Likewise. * modules/pam_exec/pam_exec.c: Likewise. * modules/pam_faillock/main.c: Likewise. * modules/pam_faillock/pam_faillock.c: Likewise. * modules/pam_lastlog/pam_lastlog.c: Likewise. * modules/pam_limits/pam_limits.c: Likewise. * modules/pam_mail/pam_mail.c: Likewise. * modules/pam_mkhomedir/pam_mkhomedir.c: Likewise. * modules/pam_pwhistory/pam_pwhistory.c: Likewise. * modules/pam_selinux/pam_selinux.c: Likewise. * modules/pam_selinux/pam_selinux_check.c: Likewise. * modules/pam_timestamp/pam_timestamp.c: Likewise. * modules/pam_unix/pam_unix_acct.c: Likewise. * modules/pam_unix/pam_unix_passwd.c: Likewise. * modules/pam_userdb/pam_userdb.c: Likewise. --- configure.ac | 9 --------- libpam/pam_get_authtok.c | 1 + libpam/pam_item.c | 1 + libpam/pam_start.c | 1 + libpam/pam_strerror.c | 1 + libpam_misc/misc_conv.c | 2 ++ modules/pam_exec/pam_exec.c | 1 + modules/pam_faillock/main.c | 1 + modules/pam_faillock/pam_faillock.c | 1 + modules/pam_lastlog/pam_lastlog.c | 1 + modules/pam_limits/pam_limits.c | 1 + modules/pam_mail/pam_mail.c | 1 + modules/pam_mkhomedir/pam_mkhomedir.c | 1 + modules/pam_pwhistory/pam_pwhistory.c | 1 + modules/pam_selinux/pam_selinux.c | 1 + modules/pam_selinux/pam_selinux_check.c | 2 ++ modules/pam_timestamp/pam_timestamp.c | 1 + modules/pam_unix/pam_unix_acct.c | 1 + modules/pam_unix/pam_unix_passwd.c | 1 + modules/pam_userdb/pam_userdb.c | 1 + 20 files changed, 21 insertions(+), 9 deletions(-) (limited to 'modules/pam_unix/pam_unix_passwd.c') diff --git a/configure.ac b/configure.ac index 0c5fd4cd..0bbf50ed 100644 --- a/configure.ac +++ b/configure.ac @@ -706,15 +706,6 @@ AM_GNU_GETTEXT([external]) AC_CHECK_FUNCS(bindtextdomain) AC_CHECK_FUNCS(dngettext) -AH_BOTTOM([#ifdef ENABLE_NLS -#include -#define _(msgid) dgettext(PACKAGE, msgid) -#define N_(msgid) msgid -#else -#define _(msgid) (msgid) -#define N_(msgid) msgid -#endif /* ENABLE_NLS */]) - dnl dnl Check for the availability of the kernel key management facility dnl - The pam_keyinit module only requires the syscalls, not the error codes diff --git a/libpam/pam_get_authtok.c b/libpam/pam_get_authtok.c index 7a38698a..c8973275 100644 --- a/libpam/pam_get_authtok.c +++ b/libpam/pam_get_authtok.c @@ -33,6 +33,7 @@ #include "pam_private.h" #include "pam_inline.h" +#include "pam_i18n.h" #include diff --git a/libpam/pam_item.c b/libpam/pam_item.c index c3a5a3bd..2e43d767 100644 --- a/libpam/pam_item.c +++ b/libpam/pam_item.c @@ -6,6 +6,7 @@ #include "pam_private.h" #include "pam_inline.h" +#include "pam_i18n.h" #include #include diff --git a/libpam/pam_start.c b/libpam/pam_start.c index ef9fdb02..97bc35b1 100644 --- a/libpam/pam_start.c +++ b/libpam/pam_start.c @@ -8,6 +8,7 @@ */ #include "pam_private.h" +#include "pam_i18n.h" #include #include diff --git a/libpam/pam_strerror.c b/libpam/pam_strerror.c index 17c81945..37f1e3b2 100644 --- a/libpam/pam_strerror.c +++ b/libpam/pam_strerror.c @@ -32,6 +32,7 @@ */ #include "pam_private.h" +#include "pam_i18n.h" const char *pam_strerror(pam_handle_t *pamh UNUSED, int errnum) { diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c index 6b839b48..fa3848e3 100644 --- a/libpam_misc/misc_conv.c +++ b/libpam_misc/misc_conv.c @@ -17,7 +17,9 @@ #include #include + #include "pam_inline.h" +#include "pam_i18n.h" #define INPUTSIZE PAM_MISC_CONV_BUFSIZE /* maximum length of input+1 */ #define CONV_ECHO_ON 1 /* types of echo state */ diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index 5468e179..c3ecb248 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -55,6 +55,7 @@ #include #include #include "pam_inline.h" +#include "pam_i18n.h" #define ENV_ITEM(n) { (n), #n } static struct { diff --git a/modules/pam_faillock/main.c b/modules/pam_faillock/main.c index 57989ba6..c6dd19cb 100644 --- a/modules/pam_faillock/main.c +++ b/modules/pam_faillock/main.c @@ -52,6 +52,7 @@ #endif #include "pam_inline.h" +#include "pam_i18n.h" #include "faillock.h" #include "faillock_config.h" diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c index 038a95ea..93850380 100644 --- a/modules/pam_faillock/pam_faillock.c +++ b/modules/pam_faillock/pam_faillock.c @@ -54,6 +54,7 @@ #include #include "pam_inline.h" +#include "pam_i18n.h" #include "faillock.h" #include "faillock_config.h" diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index 2daedb7c..ded76763 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -66,6 +66,7 @@ struct lastlog { #include #include #include "pam_inline.h" +#include "pam_i18n.h" /* argument parsing */ diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index 51276265..1197e25c 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -114,6 +114,7 @@ struct pam_limit_s { #include #include #include "pam_inline.h" +#include "pam_i18n.h" /* argument parsing */ diff --git a/modules/pam_mail/pam_mail.c b/modules/pam_mail/pam_mail.c index 2b77e560..3202ce0c 100644 --- a/modules/pam_mail/pam_mail.c +++ b/modules/pam_mail/pam_mail.c @@ -35,6 +35,7 @@ #include #include #include "pam_inline.h" +#include "pam_i18n.h" /* argument parsing */ diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index 72fa7840..71d02b6d 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -51,6 +51,7 @@ #include "pam_cc_compat.h" #include "pam_inline.h" +#include "pam_i18n.h" /* argument parsing */ #define MKHOMEDIR_DEBUG 020 /* be verbose about things */ diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c index 7ff74bdf..e43bd9b2 100644 --- a/modules/pam_pwhistory/pam_pwhistory.c +++ b/modules/pam_pwhistory/pam_pwhistory.c @@ -63,6 +63,7 @@ #include "opasswd.h" #include "pam_inline.h" +#include "pam_i18n.h" #include "pwhistory_config.h" diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index b0123c8f..a9276123 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -57,6 +57,7 @@ #include #include #include "pam_inline.h" +#include "pam_i18n.h" #include #include diff --git a/modules/pam_selinux/pam_selinux_check.c b/modules/pam_selinux/pam_selinux_check.c index 30526d37..753aa88f 100644 --- a/modules/pam_selinux/pam_selinux_check.c +++ b/modules/pam_selinux/pam_selinux_check.c @@ -55,6 +55,8 @@ #include /* for PAM functions */ #include /* for misc_conv PAM utility function */ +#include "pam_i18n.h" + #define SERVICE_NAME "pam_selinux_check" /* the name of this program for PAM */ /* The file containing the context to run * the scripts under. */ diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c index edecc052..51fcd592 100644 --- a/modules/pam_timestamp/pam_timestamp.c +++ b/modules/pam_timestamp/pam_timestamp.c @@ -72,6 +72,7 @@ #include #include #include "pam_inline.h" +#include "pam_i18n.h" /* The default timeout we use is 5 minutes, which matches the sudo default * for the timestamp_timeout parameter. */ diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index 7ffcb9e3..befd3c99 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -57,6 +57,7 @@ #include #include +#include "pam_i18n.h" #include "pam_cc_compat.h" #include "support.h" #include "passverify.h" diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index c3c6ea7a..4a3784a5 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -67,6 +67,7 @@ #include #include "pam_inline.h" +#include "pam_i18n.h" #include "pam_cc_compat.h" #include "md5.h" #include "support.h" diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index 3bcb4c87..40ede6de 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -41,6 +41,7 @@ #include #include #include "pam_inline.h" +#include "pam_i18n.h" #ifndef HAVE_GDBM_H # define COND_UNUSED UNUSED -- cgit v1.2.3