Version in base suite: 1.1.0-1.1 Base version: pam-u2f_1.1.0-1.1 Target version: pam-u2f_1.1.0-1.1+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/pam-u2f/pam-u2f_1.1.0-1.1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/pam-u2f/pam-u2f_1.1.0-1.1+deb12u1.dsc changelog | 9 patches/Handle-converse-returning-NULL.patch | 7 patches/check_permissions_authfile.patch | 20 + patches/do_not_return_PAM_IGNORE.patch | 113 ++++++++ patches/relax-permission.patch | 46 +++ patches/series | 5 patches/test_update_retvals.patch | 350 +++++++++++++++++++++++++++ patches/tighten_down_nouserok.patch | 176 +++++++++++++ 8 files changed, 720 insertions(+), 6 deletions(-) diff -Nru pam-u2f-1.1.0/debian/changelog pam-u2f-1.1.0/debian/changelog --- pam-u2f-1.1.0/debian/changelog 2021-06-05 13:04:24.000000000 +0000 +++ pam-u2f-1.1.0/debian/changelog 2025-01-23 16:04:59.000000000 +0000 @@ -1,3 +1,12 @@ +pam-u2f (1.1.0-1.1+deb12u1) bookworm-security; urgency=high + + * Start to backport the fixes for CVE-2025-23013 to debian stable + (CVE-2025-23013) + * Refactored the do_not_return_PAM_IGNORE patch for bookworm + (CVE-2025-23013) + + -- Patrick Winnertz Thu, 23 Jan 2025 17:04:59 +0100 + pam-u2f (1.1.0-1.1) unstable; urgency=medium * Non-maintainer upload. diff -Nru pam-u2f-1.1.0/debian/patches/Handle-converse-returning-NULL.patch pam-u2f-1.1.0/debian/patches/Handle-converse-returning-NULL.patch --- pam-u2f-1.1.0/debian/patches/Handle-converse-returning-NULL.patch 2021-06-05 13:04:24.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/Handle-converse-returning-NULL.patch 2025-01-23 09:11:01.000000000 +0000 @@ -13,11 +13,9 @@ util.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) -diff --git a/util.c b/util.c -index 3ea1bd2be7e6..fb07dc70d545 100644 --- a/util.c +++ b/util.c -@@ -1379,8 +1379,13 @@ int do_authentication(const cfg_t *cfg, const device_t *devices, +@@ -1370,8 +1370,13 @@ goto out; } @@ -32,6 +30,3 @@ if (user_presence == FIDO_OPT_TRUE || user_verification == FIDO_OPT_TRUE) { if (cfg->manual == 0 && cfg->cue && !cued) { --- -2.32.0.rc0 - diff -Nru pam-u2f-1.1.0/debian/patches/check_permissions_authfile.patch pam-u2f-1.1.0/debian/patches/check_permissions_authfile.patch --- pam-u2f-1.1.0/debian/patches/check_permissions_authfile.patch 1970-01-01 00:00:00.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/check_permissions_authfile.patch 2025-01-23 09:13:45.000000000 +0000 @@ -0,0 +1,20 @@ +commit 51cea61c89b750cad899eb2d34299d5d41d04090 +Author: Ludvig Michaelsson +Date: Mon Jan 13 12:32:25 2025 +0100 + + util: check permissions of authfile + +--- a/util.c ++++ b/util.c +@@ -945,6 +945,11 @@ + D(cfg->debug_file, "File %s is empty", cfg->auth_file); + goto err; + } ++ if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) { ++ D(cfg->debug_file, "Authentication file has insecure permissions", cfg->auth_file); ++ goto err; ++ } ++ + opwfile_size = st.st_size; + + gpu_ret = getpwuid_r(st.st_uid, &pw_s, buffer, sizeof(buffer), &pw); diff -Nru pam-u2f-1.1.0/debian/patches/do_not_return_PAM_IGNORE.patch pam-u2f-1.1.0/debian/patches/do_not_return_PAM_IGNORE.patch --- pam-u2f-1.1.0/debian/patches/do_not_return_PAM_IGNORE.patch 1970-01-01 00:00:00.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/do_not_return_PAM_IGNORE.patch 2025-01-23 16:01:10.000000000 +0000 @@ -0,0 +1,113 @@ +commit a96ef17f74b8e4ed80a97322120af1a228a1ffb7 +Author: Ludvig Michaelsson +Date: Wed Nov 20 13:36:31 2024 +0100 + + pam: do not return PAM_IGNORE on system errors + + Instead, use more meaningful status codes: + + - PAM_SYSTEM_ERR if getpwuid_r(), gethostname(), or + pam_modutil_{drop,regain}_priv() fails; + - PAM_BUF_ERR if memory allocation routines fails; and + - PAM_ABORT for any uncaught errors. + + This commit is part of a fix for YSA-2025-01 / CVE-2025-23013. + +--- a/pam-u2f.c ++++ b/pam-u2f.c +@@ -166,7 +166,7 @@ + char *default_authfile; + char *default_authfile_dir; + int pgu_ret, gpn_ret; +- int retval = PAM_IGNORE; ++ int retval = PAM_ABORT; + device_t *devices = NULL; + unsigned n_devices = 0; + int openasuser = 0; +@@ -186,6 +186,7 @@ + if (gethostname(buffer + strlen(DEFAULT_ORIGIN_PREFIX), + BUFSIZE - strlen(DEFAULT_ORIGIN_PREFIX)) == -1) { + DBG("Unable to get host name"); ++ retval = PAM_SYSTEM_ERR; + goto done; + } + } else { +@@ -195,6 +196,7 @@ + cfg->origin = strdup(buffer); + if (!cfg->origin) { + DBG("Unable to allocate memory"); ++ retval = PAM_BUF_ERR; + goto done; + } else { + should_free_origin = 1; +@@ -207,6 +209,7 @@ + cfg->appid = strdup(cfg->origin); + if (!cfg->appid) { + DBG("Unable to allocate memory") ++ retval = PAM_BUF_ERR; + goto done; + } else { + should_free_appid = 1; +@@ -221,7 +224,7 @@ + devices = calloc(cfg->max_devs, sizeof(device_t)); + if (!devices) { + DBG("Unable to allocate memory"); +- retval = PAM_IGNORE; ++ retval = PAM_BUF_ERR; + goto done; + } + +@@ -239,7 +242,7 @@ + pw->pw_dir[0] != '/') { + DBG("Unable to retrieve credentials for user %s, (%s)", user, + strerror(errno)); +- retval = PAM_USER_UNKNOWN; ++ retval = PAM_SYSTEM_ERR; + goto done; + } + +@@ -266,7 +269,7 @@ + + if (!buf) { + DBG("Unable to allocate memory"); +- retval = PAM_IGNORE; ++ retval = PAM_BUF_ERR; + goto done; + } + +@@ -282,7 +285,7 @@ + + if (!buf) { + DBG("Unable to allocate memory"); +- retval = PAM_IGNORE; ++ retval = PAM_BUF_ERR; + goto done; + } + +@@ -312,7 +315,7 @@ + + if (!buf) { + DBG("Unable to allocate memory"); +- retval = PAM_IGNORE; ++ retval = PAM_BUF_ERR; + goto done; + } + +@@ -333,7 +336,7 @@ + DBG("Dropping privileges"); + if (pam_modutil_drop_priv(pamh, &privs, pw)) { + DBG("Unable to switch user to uid %i", pw->pw_uid); +- retval = PAM_IGNORE; ++ retval = PAM_SYSTEM_ERR; + goto done; + } + DBG("Switched to uid %i", pw->pw_uid); +@@ -343,7 +346,7 @@ + if (openasuser) { + if (pam_modutil_regain_priv(pamh, &privs)) { + DBG("could not restore privileges"); +- retval = PAM_IGNORE; ++ retval = PAM_SYSTEM_ERR; + goto done; + } + DBG("Restored privileges"); diff -Nru pam-u2f-1.1.0/debian/patches/relax-permission.patch pam-u2f-1.1.0/debian/patches/relax-permission.patch --- pam-u2f-1.1.0/debian/patches/relax-permission.patch 1970-01-01 00:00:00.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/relax-permission.patch 2025-01-23 09:27:31.000000000 +0000 @@ -0,0 +1,46 @@ +commit f573707012f92e31172a7b14b6e36f8e93a02478 +Author: Ludvig Michaelsson +Date: Wed Jan 15 16:57:18 2025 +0100 + + util: soften authfile permission check to a warning + + We'd like to make this a hard error but it has proven to break existing + installations. To avoid breaking changes, revert to trying our hardest + to inform the administrator that this user is authenticating with a + potentially unsafe authfile. + +--- a/util.c ++++ b/util.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -946,8 +947,22 @@ + goto err; + } + if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) { +- D(cfg->debug_file, "Authentication file has insecure permissions", cfg->auth_file); +- goto err; ++ /* XXX: attempt to prevent two messages to syslog */ ++ if (cfg->debug_file) { ++ D(cfg->debug_file, ++ "Permissions %04o for '%s' are too open. Please change the " ++ "file mode bits to 0644 or more restrictive. This may become " ++ "an error in the future!", ++ (unsigned int) st.st_mode & 0777, cfg->auth_file); ++ } ++#ifndef WITH_FUZZING ++ /* XXX: force a message to syslog, regardless of the debug level */ ++ syslog(LOG_AUTHPRIV | LOG_WARNING, ++ "warning(pam_u2f): Permissions %04o for '%s' are too open. Please " ++ "change the file mode bits to 0644 or more restrictive. This may " ++ "become an error in the future!", ++ (unsigned int) st.st_mode & 0777, cfg->auth_file); ++#endif + } + + opwfile_size = st.st_size; diff -Nru pam-u2f-1.1.0/debian/patches/series pam-u2f-1.1.0/debian/patches/series --- pam-u2f-1.1.0/debian/patches/series 2021-06-05 13:04:24.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/series 2025-01-23 16:04:59.000000000 +0000 @@ -1 +1,6 @@ Handle-converse-returning-NULL.patch +check_permissions_authfile.patch +relax-permission.patch +tighten_down_nouserok.patch +do_not_return_PAM_IGNORE.patch +test_update_retvals.patch diff -Nru pam-u2f-1.1.0/debian/patches/test_update_retvals.patch pam-u2f-1.1.0/debian/patches/test_update_retvals.patch --- pam-u2f-1.1.0/debian/patches/test_update_retvals.patch 1970-01-01 00:00:00.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/test_update_retvals.patch 2025-01-23 16:04:59.000000000 +0000 @@ -0,0 +1,350 @@ +commit cf68862af2dbe7730ed7c5fd8a02ac8aada9e7b5 +Author: Ludvig Michaelsson +Date: Thu Nov 21 13:53:14 2024 +0100 + + tests: update return value + +--- a/tests/get_devices.c ++++ b/tests/get_devices.c +@@ -43,7 +43,7 @@ + + rc = get_devices_from_authfile(&cfg, username /* not used for SSH format */, + dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + assert(strcmp(dev[0].coseType, "es256") == 0); + assert(strcmp(dev[0].attributes, "+presence") == 0); +@@ -64,7 +64,7 @@ + cfg.auth_file = "credentials/new_.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -88,7 +88,7 @@ + cfg.auth_file = "credentials/new_-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -112,7 +112,7 @@ + cfg.auth_file = "credentials/new_-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -137,7 +137,7 @@ + cfg.auth_file = "credentials/new_-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -161,7 +161,7 @@ + cfg.auth_file = "credentials/new_-P.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -185,7 +185,7 @@ + cfg.auth_file = "credentials/new_-P-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -208,7 +208,7 @@ + cfg.auth_file = "credentials/new_-P-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -232,7 +232,7 @@ + cfg.auth_file = "credentials/new_-P-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -256,7 +256,7 @@ + cfg.auth_file = "credentials/new_-r.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -278,7 +278,7 @@ + cfg.auth_file = "credentials/new_-r-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -300,7 +300,7 @@ + cfg.auth_file = "credentials/new_-r-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -321,7 +321,7 @@ + cfg.auth_file = "credentials/new_-r-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -342,7 +342,7 @@ + cfg.auth_file = "credentials/new_-r-P.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -363,7 +363,7 @@ + cfg.auth_file = "credentials/new_-r-P-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -384,7 +384,7 @@ + cfg.auth_file = "credentials/new_-r-P-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -405,7 +405,7 @@ + cfg.auth_file = "credentials/new_-r-P-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -427,7 +427,7 @@ + cfg.auth_file = "credentials/new_double_.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -465,7 +465,7 @@ + cfg.auth_file = "credentials/new_double_-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -504,7 +504,7 @@ + cfg.auth_file = "credentials/new_double_-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -543,7 +543,7 @@ + cfg.auth_file = "credentials/new_double_-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -581,7 +581,7 @@ + cfg.auth_file = "credentials/new_double_-P.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -621,7 +621,7 @@ + cfg.auth_file = "credentials/new_double_-P-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -660,7 +660,7 @@ + cfg.auth_file = "credentials/new_double_-P-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -699,7 +699,7 @@ + cfg.auth_file = "credentials/new_double_-P-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -738,7 +738,7 @@ + cfg.auth_file = "credentials/new_double_-r.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -772,7 +772,7 @@ + cfg.auth_file = "credentials/new_double_-r-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -807,7 +807,7 @@ + cfg.auth_file = "credentials/new_double_-r-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -842,7 +842,7 @@ + cfg.auth_file = "credentials/new_double_-r-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -876,7 +876,7 @@ + cfg.auth_file = "credentials/new_double_-r-P.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -911,7 +911,7 @@ + cfg.auth_file = "credentials/new_double_-r-P-V.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -945,7 +945,7 @@ + cfg.auth_file = "credentials/new_double_-r-P-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -979,7 +979,7 @@ + cfg.auth_file = "credentials/new_double_-r-P-V-N.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -1016,7 +1016,7 @@ + cfg.auth_file = "credentials/new_mixed_12.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -1055,7 +1055,7 @@ + cfg.auth_file = "credentials/new_mixed_1-P2.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -1094,7 +1094,7 @@ + cfg.auth_file = "credentials/new_mixed_-P12.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -1132,7 +1132,7 @@ + cfg.auth_file = "credentials/new_mixed_-P1-P2.cred"; + cfg.sshformat = 0; + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 2); + + assert(strcmp(dev[0].coseType, "es256") == 0); +@@ -1171,7 +1171,7 @@ + cfg.sshformat = 0; + + rc = get_devices_from_authfile(&cfg, username, dev, &n_devs); +- assert(rc == 1); ++ assert(rc == PAM_SUCCESS); + assert(n_devs == 1); + assert(strcmp(dev[0].coseType, "es256") == 0); + assert(strcmp(dev[0].attributes, "+presence") == 0); diff -Nru pam-u2f-1.1.0/debian/patches/tighten_down_nouserok.patch pam-u2f-1.1.0/debian/patches/tighten_down_nouserok.patch --- pam-u2f-1.1.0/debian/patches/tighten_down_nouserok.patch 1970-01-01 00:00:00.000000000 +0000 +++ pam-u2f-1.1.0/debian/patches/tighten_down_nouserok.patch 2025-01-23 16:04:59.000000000 +0000 @@ -0,0 +1,176 @@ +commit 08199144d870a63275a4601dbc6751ac68d48301 +Author: Ludvig Michaelsson +Date: Thu Nov 21 09:40:52 2024 +0100 + + pam: tighten down nouserok + + Move PAM return value handling to get_devices_from_authfile(): + + If `nouserok` is set, return + + - PAM_IGNORE if open() returns ENOENT; + - PAM_IGNORE if user is not found in the authfile; + - PAM_IGNORE if user is found in the but have no credentials; + - PAM_AUTHINFO_UNAVAIL otherwise. + + If `nouserok` is *not* set, return + + - PAM_USER_UNKNOWN if user is not found in the authfile; + - PAM_USER_UNKNOWN if user is found but have no credentials; + - PAM_AUTHINFO_UNAVAIL otherwise. + + This commit is part of a fix for YSA-2025-01 / CVE-2025-23013. + +--- a/README ++++ b/README +@@ -123,9 +123,9 @@ + /var/run/user/$UID/pam-u2f-authpending + + nouserok:: +-Set to enable authentication attempts to succeed even if the user +-trying to authenticate is not found inside `authfile` or if `authfile` +-is missing/malformed. ++Set to make authentication attempts not fail if the user trying to ++authenticate is not found inside `authfile`, is found but has no ++credentials, or if the `authfile` is missing. + + openasuser:: + Setuid to the authenticating user when opening the authfile. Useful +--- a/pam-u2f.c ++++ b/pam-u2f.c +@@ -349,26 +349,8 @@ + DBG("Restored privileges"); + } + +- if (retval != 1) { +- // for nouserok; make sure errors in get_devices_from_authfile don't +- // result in valid devices +- n_devices = 0; +- } +- +- if (n_devices == 0) { +- if (cfg->nouserok) { +- DBG("Found no devices but nouserok specified. Skipping authentication"); +- retval = PAM_SUCCESS; +- goto done; +- } else if (retval != 1) { +- DBG("Unable to get devices from file %s", cfg->auth_file); +- retval = PAM_AUTHINFO_UNAVAIL; +- goto done; +- } else { +- DBG("Found no devices. Aborting."); +- retval = PAM_AUTHINFO_UNAVAIL; ++ if (retval != PAM_SUCCESS) { + goto done; +- } + } + + // Determine the full path for authpending_file in order to emit touch request +--- a/util.c ++++ b/util.c +@@ -907,7 +907,7 @@ + device_t *devices, unsigned *n_devs) { + + char *buf = NULL; +- int retval = 0; ++ int r = PAM_AUTHINFO_UNAVAIL; + int fd = -1; + struct stat st; + struct passwd *pw = NULL, pw_s; +@@ -922,6 +922,11 @@ + + fd = open(cfg->auth_file, O_RDONLY | O_CLOEXEC | O_NOCTTY); + if (fd < 0) { ++ if (errno == ENOENT && cfg->nouserok) { ++ if (cfg->debug) ++ D(cfg->debug_file, "Set PAM_IGNORE if nouserok and ENOENT!"); ++ r = PAM_IGNORE; ++ } + if (cfg->debug) + D(cfg->debug_file, "Cannot open file: %s (%s)", cfg->auth_file, + strerror(errno)); +@@ -941,11 +946,6 @@ + goto err; + } + +- if (st.st_size == 0) { +- if (cfg->debug) +- D(cfg->debug_file, "File %s is empty", cfg->auth_file); +- goto err; +- } + if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) { + /* XXX: attempt to prevent two messages to syslog */ + if (cfg->debug_file) { +@@ -1002,37 +1002,43 @@ + } + + if (cfg->sshformat == 0) { +- retval = parse_native_format(cfg, username, buf, opwfile, devices, n_devs); ++ if (parse_native_format(cfg, username, buf, opwfile, devices, n_devs) != 1) { ++ if (cfg->debug) ++ D(cfg->debug_file, "parse_native_format is not 1!"); ++ goto err; ++ } + } else { +- retval = parse_ssh_format(cfg, buf, DEVSIZE * cfg->max_devs, opwfile, +- opwfile_size, devices, n_devs); +- } +- +- if (retval != 1) { +- // NOTE(adma): error message is logged by the previous function +- goto err; ++ if (parse_ssh_format(cfg, buf, DEVSIZE * cfg->max_devs, opwfile, ++ opwfile_size, devices, n_devs) != 1) { ++ if (cfg->debug) ++ D(cfg->debug_file, "parse_ssh_format is not 1!"); ++ goto err; ++ } + } + + if (cfg->debug) + D(cfg->debug_file, "Found %d device(s) for user %s", *n_devs, username); + +- retval = 1; ++ r = PAM_SUCCESS; + goto out; + + err: +- for (i = 0; i < *n_devs; i++) { +- free(devices[i].keyHandle); +- free(devices[i].publicKey); +- free(devices[i].coseType); +- free(devices[i].attributes); +- devices[i].keyHandle = NULL; +- devices[i].publicKey = NULL; +- devices[i].coseType = NULL; +- devices[i].attributes = NULL; ++ if (r != PAM_SUCCESS) { ++ for (i = 0; i < *n_devs; i++) { ++ free(devices[i].keyHandle); ++ free(devices[i].publicKey); ++ free(devices[i].coseType); ++ free(devices[i].attributes); ++ devices[i].keyHandle = NULL; ++ devices[i].publicKey = NULL; ++ devices[i].coseType = NULL; ++ devices[i].attributes = NULL; ++ } ++ *n_devs = 0; ++ } else if (*n_devs == 0) { ++ r = cfg->nouserok ? PAM_IGNORE : PAM_USER_UNKNOWN; + } + +- *n_devs = 0; +- + out: + if (buf) { + free(buf); +@@ -1045,7 +1051,7 @@ + if (fd != -1) + close(fd); + +- return retval; ++ return r; + } + + void free_devices(device_t *devices, const unsigned n_devs) {