From b4c496856d466ff00d06cd5177cb216110f5e3b3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 18 Sep 2024 15:18:14 +0200
Subject: [PATCH] pam: only set SYSDB_LOCAL_SMARTCARD_AUTH to 'true' but never
 to 'false'.

The krb5 backend will only returns that Smartcard authentication is
available if a Smartcard is present. That means if the user
authenticates with a different method and a Smartcard is not present at
this time 'sc_allow' will be 'false' and might overwrite a 'true' value
written during a previous authentication attempt where a Smartcard was
present. To avoid this we only write 'true' values. Since the default if
SYSDB_LOCAL_SMARTCARD_AUTH is missing is 'false' local Smartcard
authentication (offline) will still only be enabled if online Smartcard
authentication was detected.

Resolves: https://github.com/SSSD/sssd/issues/7532

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(cherry picked from commit 67ba42c48abb9270982836310488e35d9fc1d451)
---
 src/responder/pam/pamsrv_cmd.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 1394147a0..941446d94 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -554,9 +554,22 @@ static errno_t set_local_auth_type(struct pam_auth_req *preq,
         goto fail;
     }
 
-    ret = sysdb_attrs_add_bool(attrs, SYSDB_LOCAL_SMARTCARD_AUTH, sc_allow);
-    if (ret != EOK) {
-        goto fail;
+    if (sc_allow) {
+        /* Only set SYSDB_LOCAL_SMARTCARD_AUTH to 'true' but never to
+         * 'false'. The krb5 backend will only returns that Smartcard
+         * authentication is available if a Smartcard is present. That means
+         * if the user authenticates with a different method and a Smartcard
+         * is not present at this time 'sc_allow' will be 'false' and might
+         * overwrite a 'true' value written during a previous authentication
+         * attempt where a Smartcard was present. To avoid this we only write
+         * 'true' values. Since the default if SYSDB_LOCAL_SMARTCARD_AUTH is
+         * missing is 'false' local Smartcard authentication (offline) will
+         * still only be enabled if online Smartcard authentication was
+         * detected. */
+        ret = sysdb_attrs_add_bool(attrs, SYSDB_LOCAL_SMARTCARD_AUTH, sc_allow);
+        if (ret != EOK) {
+            goto fail;
+        }
     }
 
     ret = sysdb_attrs_add_bool(attrs, SYSDB_LOCAL_PASSKEY_AUTH, passkey_allow);
-- 
2.45.0