From 2ecba68d404c3112546a9e802e3776b9f6c50a6a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 6 Dec 2024 03:08:38 +0100 Subject: [PATCH] Fixed possible authentication bypass: Don't return PAM_IGNORE Starting with bac6cf8e0b242e508e8b715e7f78d52f1227840a (released with pam_pkcs11-0.6.12), return codes defaulted to PAM_IGNORE in most cases where authentication was not possible. This change has not been anticipated in PAM configurations and may lead to authentication bypasses. If pam_pkcs11 was configured as the only module which could provide authentication and would silently fail with PAM_IGNORE, then this return code may be transformed to PAM_SUCCESS by subsequent PAM modules that don't actually perform authentication. This change avoids this situation by *not* returning PAM_IGNORE by default as done in 0.6.11 and before. If pam_pkcs11 is the only module providing authentication in the PAM stack, then the following PAM configuration could be used to avoid this situation as well: auth [success=ok default=bad] pam_pkcs11.so wait_for_card card_only In the configuration above, PAM_IGNORE will lead to an authentication failure even for an unpatched pam_pkcs11-0.6.12 (note the missing `ignore=ignore`). Thanks to Matthias Gerstner (@mgerstner) and the SUSE Linux team for reporting this problem providing analysis and the workaround configuration of a possibly vulnerable PAM stack. --- src/pam_pkcs11/pam_pkcs11.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) Index: pam_pkcs11-pam_pkcs11-0.6.12/src/pam_pkcs11/pam_pkcs11.c =================================================================== --- pam_pkcs11-pam_pkcs11-0.6.12.orig/src/pam_pkcs11/pam_pkcs11.c +++ pam_pkcs11-pam_pkcs11-0.6.12/src/pam_pkcs11/pam_pkcs11.c @@ -281,13 +281,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_h } } - if (!configuration->card_only || !login_token_name) { - /* Allow to pass to the next module if the auth isn't - restricted to card only. */ - pkcs11_pam_fail = PAM_IGNORE; - } else { - pkcs11_pam_fail = PAM_CRED_INSUFFICIENT; - } + pkcs11_pam_fail = PAM_CRED_INSUFFICIENT; /* fail if we are using a remote server * local login: DISPLAY=:0 @@ -366,13 +360,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_h } if (rv != 0) { - /* No token found */ - if (!configuration->card_only) { - /* If the login isn't restricted to card-only, then proceed - to the next auth. module quietly. */ - release_pkcs11_module(ph); - goto exit_ignore; - } + /* No token found */ ERR("no suitable token available"); if (!configuration->quiet) { @@ -402,18 +390,12 @@ PAM_EXTERN int pam_sm_authenticate(pam_h if (rv != 0) { release_pkcs11_module(ph); /* Still no card */ - if (pkcs11_pam_fail != PAM_IGNORE) { - if (!configuration->quiet) { - pam_prompt(pamh, PAM_ERROR_MSG, - NULL, _("Error 2308: No smartcard found")); - sleep(configuration->err_display_time); - } - } else { - pam_prompt(pamh, PAM_TEXT_INFO, - NULL, _("No smartcard found")); - goto exit_ignore; - } + if (!configuration->quiet) { + pam_prompt(pamh, PAM_ERROR_MSG, + NULL, _("Error 2308: No smart card found.")); + sleep(configuration->err_display_time); return pkcs11_pam_fail; + } } pam_prompt(pamh, PAM_TEXT_INFO, NULL, @@ -798,10 +780,8 @@ auth_failed: free( password ); } - if (PAM_IGNORE == pkcs11_pam_fail) - goto exit_ignore; - else - return pkcs11_pam_fail; + return pkcs11_pam_fail; + exit_ignore: pam_prompt( pamh, PAM_TEXT_INFO, NULL,