diff options
author | Christian Göttsche <cgzones@googlemail.com> | 2024-01-04 18:23:57 +0100 |
---|---|---|
committer | Dmitry V. Levin <ldv@strace.io> | 2024-01-15 20:01:23 +0000 |
commit | b23d337b86488d23b2f77fc71a5de30348af671d (patch) | |
tree | bfb4962eb53e21b4da5fcf24c0fb30ed30eacd80 | |
parent | b430e2d1c93414cb14e9a3557ac895e864138497 (diff) | |
download | pam-b23d337b86488d23b2f77fc71a5de30348af671d.tar.gz pam-b23d337b86488d23b2f77fc71a5de30348af671d.tar.bz2 pam-b23d337b86488d23b2f77fc71a5de30348af671d.zip |
pam_unix: reject unix_update(8) running on different unprivileged user
In case unix_update(8) is installed as a setuid binary, which Fedora and
Debian does not do, prevent unprivileged users to probe (and eventually
change) passwords of other users (including root).
-rw-r--r-- | modules/pam_unix/unix_update.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c index 4adaa5af..95e99494 100644 --- a/modules/pam_unix/unix_update.c +++ b/modules/pam_unix/unix_update.c @@ -42,6 +42,7 @@ static int set_password(const char *forwho, const char *shadow, const char *remember) { struct passwd *pwd = NULL; + uid_t ruid; int retval; char pass[PAM_MAX_RESP_SIZE + 1]; char towhat[PAM_MAX_RESP_SIZE + 1]; @@ -80,9 +81,18 @@ set_password(const char *forwho, const char *shadow, const char *remember) } /* If real caller uid is not root we must verify that - received old pass agrees with the current one. - We always allow change from null pass. */ - if (getuid()) { + * the target user is the caller and the + * received old pass agrees with the current one. + * We always allow change from null pass. */ + ruid = getuid(); + if (ruid != 0) { + if (pwd->pw_uid != ruid) { + helper_log_err(LOG_NOTICE, "user mismatch detected: source=%d target=%d", + ruid, pwd->pw_uid); + retval = PAM_AUTHTOK_ERR; + goto done; + } + retval = helper_verify_password(forwho, pass, 1); #ifdef HAVE_LIBAUDIT audit_log(AUDIT_USER_AUTH, getuidname(getuid()), retval); |