From d4022a63f388f9cd0f537a4eb371e111c44b9c9c Mon Sep 17 00:00:00 2001
From: Georgij Krajnyukov <nrk63@yandex.ru>
Date: Wed, 19 Feb 2025 11:59:14 +0300
Subject: [PATCH 1/4] P11_CHILD: Invert if statement to reduce code nesting

Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
---
 src/p11_child/p11_child_openssl.c | 33 +++++++++++++++----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index 45a4930ba..8aa73c035 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -1928,26 +1928,25 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
 
     if (slot_id == (CK_SLOT_ID)-1) {
         DEBUG(SSSDBG_TRACE_ALL, "Token not present.\n");
-        if (p11_ctx->wait_for_card) {
-            /* After obtaining the module's slot list (in the loop above), this
-             * call is needed to let any changes in slots take effect. */
-            rv = module->C_GetSlotList(CK_FALSE, NULL, &num_slots);
-            if (rv != CKR_OK) {
-                DEBUG(SSSDBG_OP_FAILURE, "C_GetSlotList failed [%lu][%s].\n",
-                                         rv, p11_kit_strerror(rv));
-                ret = EIO;
-                goto done;
-            }
-
-            ret = wait_for_card(module, &slot_id, &info, &token_info, uri);
-            if (ret != EOK) {
-                DEBUG(SSSDBG_OP_FAILURE, "wait_for_card failed.\n");
-                goto done;
-            }
-        } else {
+        if (!p11_ctx->wait_for_card) {
             ret = EIO;
             goto done;
         }
+        /* After obtaining the module's slot list (in the loop above), this
+         * call is needed to let any changes in slots take effect. */
+        rv = module->C_GetSlotList(CK_FALSE, NULL, &num_slots);
+        if (rv != CKR_OK) {
+            DEBUG(SSSDBG_OP_FAILURE, "C_GetSlotList failed [%lu][%s].\n",
+                                     rv, p11_kit_strerror(rv));
+            ret = EIO;
+            goto done;
+        }
+
+        ret = wait_for_card(module, &slot_id, &info, &token_info, uri);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "wait_for_card failed.\n");
+            goto done;
+        }
     }
 
     module_id = c;
-- 
2.51.0


From 06ee7f46937b40da85628a03c59865fffea48e90 Mon Sep 17 00:00:00 2001
From: Georgij Krajnyukov <nrk63@yandex.ru>
Date: Tue, 4 Mar 2025 12:28:33 +0300
Subject: [PATCH 2/4] P11_CHILD: Implement passing const args to get_pkcs11_uri

Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
---
 src/p11_child/p11_child_openssl.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index 8aa73c035..30782d955 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -505,9 +505,9 @@ done:
     return ret;
 }
 
-static char *get_pkcs11_uri(TALLOC_CTX *mem_ctx, CK_INFO *module_info,
-                            CK_SLOT_INFO *slot_info, CK_SLOT_ID slot_id,
-                            CK_TOKEN_INFO *token_info, CK_ATTRIBUTE *label,
+static char *get_pkcs11_uri(TALLOC_CTX *mem_ctx, const CK_INFO *module_info,
+                            const CK_SLOT_INFO *slot_info, CK_SLOT_ID slot_id,
+                            const CK_TOKEN_INFO *token_info, CK_ATTRIBUTE *label,
                             CK_ATTRIBUTE *id)
 {
     P11KitUri *uri;
-- 
2.51.0


From 54d3110be5146ec1d6575389bc60ad7585493984 Mon Sep 17 00:00:00 2001
From: Georgij Krajnyukov <nrk63@yandex.ru>
Date: Wed, 19 Feb 2025 12:22:30 +0300
Subject: [PATCH 3/4] P11_CHILD: Extract slot processing into separate function

Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
---
 src/p11_child/p11_child_openssl.c | 399 ++++++++++++++++--------------
 1 file changed, 212 insertions(+), 187 deletions(-)

diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index 30782d955..b96d19f88 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -1702,6 +1702,215 @@ static errno_t wait_for_card(CK_FUNCTION_LIST *module, CK_SLOT_ID *slot_id,
 
 #define MAX_SLOTS 64
 
+errno_t do_slot(CK_FUNCTION_LIST *module, size_t module_id, CK_SLOT_ID slot_id,
+                const CK_SLOT_INFO *info, const CK_TOKEN_INFO *token_info,
+                const CK_INFO *module_info, TALLOC_CTX *mem_ctx,
+                struct p11_ctx *p11_ctx, enum op_mode mode, const char *pin,
+                const char *module_name_in, const char *token_name_in,
+                const char *key_id_in, const char *label_in,
+                const char *uri_str, char **_multi) {
+    int ret;
+    CK_RV rv;
+    char *module_file_name = NULL;
+    char *slot_name = NULL;
+    char *token_name = NULL;
+    CK_SESSION_HANDLE session = 0;
+    struct cert_list *cert_list = NULL;
+    struct cert_list *item = NULL;
+    struct cert_list *next_item = NULL;
+    bool pkcs11_session = false;
+    bool pkcs11_login = false;
+
+    slot_name = p11_kit_space_strdup(info->slotDescription,
+                                     sizeof(info->slotDescription));
+    if (slot_name == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_space_strdup failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    token_name = p11_kit_space_strdup(token_info->label,
+                                      sizeof(token_info->label));
+    if (token_name == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_space_strdup failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    module_file_name = p11_kit_module_get_filename(module);
+    if (module_file_name == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_module_get_filename failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d][%s].\n",
+          token_name, slot_name, (int) slot_id, (int) module_id,
+          module_file_name);
+
+    rv = module->C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL, NULL,
+                               &session);
+    if (rv != CKR_OK) {
+        DEBUG(SSSDBG_OP_FAILURE, "C_OpenSession failed [%lu][%s].\n",
+                                 rv, p11_kit_strerror(rv));
+        ret = EIO;
+        goto done;
+    }
+    pkcs11_session = true;
+
+    /* login: do we need to check for Login Required? */
+    if (mode == OP_AUTH) {
+        DEBUG(SSSDBG_TRACE_ALL, "Login required.\n");
+        DEBUG(SSSDBG_TRACE_ALL, "Token flags [%lu].\n", token_info->flags);
+        if ((pin != NULL)
+            || (token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
+
+            if (token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
+                DEBUG(SSSDBG_TRACE_ALL, "Protected authentication path.\n");
+                pin = NULL;
+            }
+            rv = module->C_Login(session, CKU_USER, discard_const(pin),
+                                (pin != NULL) ? strlen(pin) : 0);
+            if (rv == CKR_PIN_LOCKED) {
+                DEBUG(SSSDBG_OP_FAILURE, "C_Login failed: PIN locked\n");
+                ret = ERR_P11_PIN_LOCKED;
+                goto done;
+            }
+            else if (rv != CKR_OK) {
+                DEBUG(SSSDBG_OP_FAILURE, "C_Login failed [%lu][%s].\n",
+                                 rv, p11_kit_strerror(rv));
+                ret = EIO;
+                goto done;
+            }
+            pkcs11_login = true;
+        } else {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Login required but no PIN available, continue.\n");
+        }
+    } else {
+        DEBUG(SSSDBG_TRACE_ALL, "Login NOT required.\n");
+    }
+
+    ret = read_certs(mem_ctx, module, session, p11_ctx, &cert_list);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "read_certs failed.\n");
+        goto done;
+    }
+
+    DLIST_FOR_EACH_SAFE(item, next_item, cert_list) {
+        /* Check if we found the certificates we needed for authentication or
+         * the requested ones for pre-auth. For authentication all attributes
+         * except the label must be given and match. The label is optional for
+         * authentication but if given it must match as well. For pre-auth
+         * only the given ones must match. */
+        DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s %s.\n",
+              module_name_in, module_file_name, token_name_in, token_name,
+              key_id_in, label_in == NULL ? "- no label given-" : label_in,
+              item->id);
+
+        if ((mode == OP_AUTH
+                && module_name_in != NULL
+                && token_name_in != NULL
+                && key_id_in != NULL
+                && item->id != NULL
+                && strcmp(key_id_in, item->id) == 0
+                && (label_in == NULL
+                    || (label_in != NULL && item->label != NULL
+                        && strcmp(label_in, item->label) == 0))
+                && strcmp(token_name_in, token_name) == 0
+                && strcmp(module_name_in, module_file_name) == 0)
+            || (mode == OP_PREAUTH
+                && (module_name_in == NULL
+                    || (module_name_in != NULL
+                        && strcmp(module_name_in, module_file_name) == 0))
+                && (token_name_in == NULL
+                    || (token_name_in != NULL
+                        && strcmp(token_name_in, token_name) == 0))
+                && (key_id_in == NULL
+                    || (key_id_in != NULL && item->id != NULL
+                        && strcmp(key_id_in, item->id) == 0)))) {
+
+            item->uri = get_pkcs11_uri(mem_ctx, module_info, info, slot_id,
+                                       token_info,
+                                       &item->attributes[1] /* label */,
+                                       &item->attributes[0] /* id */);
+            DEBUG(SSSDBG_TRACE_ALL, "uri: %s.\n", item->uri);
+
+        } else {
+            DLIST_REMOVE(cert_list, item);
+            talloc_free(item);
+        }
+    }
+
+    /* TODO: check module_name_in, token_name_in, key_id_in */
+
+    if (cert_list == NULL) {
+        DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
+        *_multi = NULL;
+        ret = EOK;
+        goto done;
+    }
+
+    if (mode == OP_AUTH) {
+        if (cert_list->next != NULL || cert_list->prev != NULL) {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                  "More than one certificate found for authentication, "
+                  "aborting!\n");
+            ret = EINVAL;
+            goto done;
+        }
+
+        ret = sign_data(module, session, slot_id, cert_list);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sign_data failed.\n");
+            ret = EACCES;
+            goto done;
+        }
+
+        DEBUG(SSSDBG_TRACE_ALL,
+              "Certificate verified and validated.\n");
+    }
+
+    *_multi = talloc_strdup(mem_ctx, "");
+    if (*_multi == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create output string.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    DLIST_FOR_EACH(item, cert_list) {
+        DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n",
+              item->id);
+
+        *_multi = talloc_asprintf_append(*_multi, "%s\n%s\n%s\n%s\n%s\n",
+                                         token_name, module_file_name, item->id,
+                                         item->label, item->cert_b64);
+    }
+
+    ret = EOK;
+done:
+    if (module != NULL) {
+        if (pkcs11_login) {
+            rv = module->C_Logout(session);
+            if (rv != CKR_OK) {
+                DEBUG(SSSDBG_OP_FAILURE, "C_Logout failed [%lu][%s].\n",
+                                         rv, p11_kit_strerror(rv));
+            }
+        }
+        if (pkcs11_session) {
+            rv = module->C_CloseSession(session);
+            if (rv != CKR_OK) {
+                DEBUG(SSSDBG_OP_FAILURE, "C_CloseSession failed [%lu][%s].\n",
+                                         rv, p11_kit_strerror(rv));
+            }
+        }
+    }
+    free(slot_name);
+    free(token_name);
+    free(module_file_name);
+    return ret;
+}
+
 errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
                 enum op_mode mode, const char *pin,
                 const char *module_name_in, const char *token_name_in,
@@ -1724,16 +1933,7 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
     CK_INFO module_info;
     CK_RV rv;
     size_t module_id;
-    char *module_file_name = NULL;
-    char *slot_name = NULL;
-    char *token_name = NULL;
-    CK_SESSION_HANDLE session = 0;
-    struct cert_list *cert_list = NULL;
-    struct cert_list *item = NULL;
-    struct cert_list *next_item = NULL;
     char *multi = NULL;
-    bool pkcs11_session = false;
-    bool pkcs11_login = false;
     P11KitUri *uri = NULL;
 
     if (uri_str != NULL) {
@@ -1950,188 +2150,13 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
     }
 
     module_id = c;
-    slot_name = p11_kit_space_strdup(info.slotDescription,
-                                     sizeof(info.slotDescription));
-    if (slot_name == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_space_strdup failed.\n");
-        ret = ENOMEM;
-        goto done;
-    }
-
-    token_name = p11_kit_space_strdup(token_info.label,
-                                      sizeof(token_info.label));
-    if (token_name == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_space_strdup failed.\n");
-        ret = ENOMEM;
-        goto done;
-    }
-
-    module_file_name = p11_kit_module_get_filename(module);
-    if (module_file_name == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_module_get_filename failed.\n");
-        ret = ENOMEM;
-        goto done;
-    }
-
-    DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d][%s].\n",
-          token_name, slot_name, (int) slot_id, (int) module_id,
-          module_file_name);
-
-    rv = module->C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL, NULL,
-                               &session);
-    if (rv != CKR_OK) {
-        DEBUG(SSSDBG_OP_FAILURE, "C_OpenSession failed [%lu][%s].\n",
-                                 rv, p11_kit_strerror(rv));
-        ret = EIO;
-        goto done;
-    }
-    pkcs11_session = true;
-
-    /* login: do we need to check for Login Required? */
-    if (mode == OP_AUTH) {
-        DEBUG(SSSDBG_TRACE_ALL, "Login required.\n");
-        if (pin != NULL) {
-            rv = module->C_Login(session, CKU_USER, discard_const(pin),
-                                 strlen(pin));
-            if (rv == CKR_PIN_LOCKED) {
-                DEBUG(SSSDBG_OP_FAILURE, "C_Login failed: PIN locked\n");
-                ret = ERR_P11_PIN_LOCKED;
-                goto done;
-            }
-            else if (rv != CKR_OK) {
-                DEBUG(SSSDBG_OP_FAILURE, "C_Login failed [%lu][%s].\n",
-                                 rv, p11_kit_strerror(rv));
-                ret = EIO;
-                goto done;
-            }
-            pkcs11_login = true;
-        } else {
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Login required but no PIN available, continue.\n");
-        }
-    } else {
-        DEBUG(SSSDBG_TRACE_ALL, "Login NOT required.\n");
-    }
-
-    ret = read_certs(mem_ctx, module, session, p11_ctx, &cert_list);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, "read_certs failed.\n");
-        goto done;
-    }
-
-    DLIST_FOR_EACH_SAFE(item, next_item, cert_list) {
-        /* Check if we found the certificates we needed for authentication or
-         * the requested ones for pre-auth. For authentication all attributes
-         * except the label must be given and match. The label is optional for
-         * authentication but if given it must match as well. For pre-auth
-         * only the given ones must match. */
-        DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s %s.\n",
-              module_name_in, module_file_name, token_name_in, token_name,
-              key_id_in, label_in == NULL ? "- no label given-" : label_in,
-              item->id);
-
-        if ((mode == OP_AUTH
-                && module_name_in != NULL
-                && token_name_in != NULL
-                && key_id_in != NULL
-                && item->id != NULL
-                && strcmp(key_id_in, item->id) == 0
-                && (label_in == NULL
-                    || (label_in != NULL && item->label != NULL
-                        && strcmp(label_in, item->label) == 0))
-                && strcmp(token_name_in, token_name) == 0
-                && strcmp(module_name_in, module_file_name) == 0)
-            || (mode == OP_PREAUTH
-                && (module_name_in == NULL
-                    || (module_name_in != NULL
-                        && strcmp(module_name_in, module_file_name) == 0))
-                && (token_name_in == NULL
-                    || (token_name_in != NULL
-                        && strcmp(token_name_in, token_name) == 0))
-                && (key_id_in == NULL
-                    || (key_id_in != NULL && item->id != NULL
-                        && strcmp(key_id_in, item->id) == 0)))) {
-
-            item->uri = get_pkcs11_uri(mem_ctx, &module_info, &info, slot_id,
-                                       &token_info,
-                                       &item->attributes[1] /* label */,
-                                       &item->attributes[0] /* id */);
-            DEBUG(SSSDBG_TRACE_ALL, "uri: %s.\n", item->uri);
-
-        } else {
-            DLIST_REMOVE(cert_list, item);
-            talloc_free(item);
-        }
-    }
-
-    /* TODO: check module_name_in, token_name_in, key_id_in */
-
-    if (cert_list == NULL) {
-        DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
-        *_multi = NULL;
-        ret = EOK;
-        goto done;
-    }
-
-    if (mode == OP_AUTH) {
-        if (cert_list->next != NULL || cert_list->prev != NULL) {
-            DEBUG(SSSDBG_FATAL_FAILURE,
-                  "More than one certificate found for authentication, "
-                  "aborting!\n");
-            ret = EINVAL;
-            goto done;
-        }
-
-        ret = sign_data(module, session, slot_id, cert_list);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE, "sign_data failed.\n");
-            ret = EACCES;
-            goto done;
-        }
-
-        DEBUG(SSSDBG_TRACE_ALL,
-              "Certificate verified and validated.\n");
-    }
-
-    multi = talloc_strdup(mem_ctx, "");
-    if (multi == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create output string.\n");
-        ret = ENOMEM;
-        goto done;
-    }
-
-    DLIST_FOR_EACH(item, cert_list) {
-        DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n",
-              item->id);
-
-        multi = talloc_asprintf_append(multi, "%s\n%s\n%s\n%s\n%s\n",
-                                       token_name, module_file_name, item->id,
-                                       item->label, item->cert_b64);
-    }
-
+    ret = do_slot(module, module_id, slot_id, &info, &token_info, &module_info,
+                  mem_ctx, p11_ctx, mode, pin, module_name_in, token_name_in,
+                  key_id_in, label_in, uri_str, &multi);
     *_multi = multi;
 
     ret = EOK;
 done:
-    if (module != NULL) {
-        if (pkcs11_login) {
-            rv = module->C_Logout(session);
-            if (rv != CKR_OK) {
-                DEBUG(SSSDBG_OP_FAILURE, "C_Logout failed [%lu][%s].\n",
-                                         rv, p11_kit_strerror(rv));
-            }
-        }
-        if (pkcs11_session) {
-            rv = module->C_CloseSession(session);
-            if (rv != CKR_OK) {
-                DEBUG(SSSDBG_OP_FAILURE, "C_CloseSession failed [%lu][%s].\n",
-                                         rv, p11_kit_strerror(rv));
-            }
-        }
-    }
-    free(slot_name);
-    free(token_name);
-    free(module_file_name);
     p11_kit_modules_finalize_and_release(modules);
     p11_kit_uri_free(uri);
 
-- 
2.51.0


From 218c418e1ad34efe3922937673716c0cc657597c Mon Sep 17 00:00:00 2001
From: Georgij Krajnyukov <nrk63@yandex.ru>
Date: Fri, 14 Feb 2025 15:00:50 +0300
Subject: [PATCH 4/4] P11_CHILD: Make p11_child iterate over all slots

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

Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
---
 src/p11_child/p11_child_openssl.c | 74 +++++++++++++++++++++----------
 1 file changed, 51 insertions(+), 23 deletions(-)

diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index b96d19f88..154a3052b 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -1748,6 +1748,15 @@ errno_t do_slot(CK_FUNCTION_LIST *module, size_t module_id, CK_SLOT_ID slot_id,
           token_name, slot_name, (int) slot_id, (int) module_id,
           module_file_name);
 
+    if (mode == OP_AUTH && strcmp(token_name, token_name_in) != 0) {
+        DEBUG(SSSDBG_TRACE_ALL, "Token name [%s] does not match "
+                                "token_name_in [%s]. "
+                                "Skipping this token...\n",
+              token_name, token_name_in);
+        ret = EOK;
+        goto done;
+    }
+
     rv = module->C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL, NULL,
                                &session);
     if (rv != CKR_OK) {
@@ -1846,7 +1855,6 @@ errno_t do_slot(CK_FUNCTION_LIST *module, size_t module_id, CK_SLOT_ID slot_id,
 
     if (cert_list == NULL) {
         DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
-        *_multi = NULL;
         ret = EOK;
         goto done;
     }
@@ -1871,13 +1879,6 @@ errno_t do_slot(CK_FUNCTION_LIST *module, size_t module_id, CK_SLOT_ID slot_id,
               "Certificate verified and validated.\n");
     }
 
-    *_multi = talloc_strdup(mem_ctx, "");
-    if (*_multi == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create output string.\n");
-        ret = ENOMEM;
-        goto done;
-    }
-
     DLIST_FOR_EACH(item, cert_list) {
         DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n",
               item->id);
@@ -1885,6 +1886,12 @@ errno_t do_slot(CK_FUNCTION_LIST *module, size_t module_id, CK_SLOT_ID slot_id,
         *_multi = talloc_asprintf_append(*_multi, "%s\n%s\n%s\n%s\n%s\n",
                                          token_name, module_file_name, item->id,
                                          item->label, item->cert_b64);
+        if (*_multi == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Failed to append certiticate to the output string.\n");
+            ret = ENOMEM;
+            goto done;
+        }
     }
 
     ret = EOK;
@@ -1933,9 +1940,14 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
     CK_INFO module_info;
     CK_RV rv;
     size_t module_id;
-    char *multi = NULL;
     P11KitUri *uri = NULL;
 
+    *_multi = talloc_strdup(mem_ctx, "");
+    if (*_multi == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create output string.\n");
+        return ENOMEM;
+    }
+
     if (uri_str != NULL) {
         uri = p11_kit_uri_new();
         if (uri == NULL) {
@@ -1986,9 +1998,17 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
             }
 
             DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n", mod_name);
-            DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n", mod_file_name);
-
             free(mod_name);
+
+            DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n", mod_file_name);
+            if (mode == OP_AUTH && strcmp(mod_file_name, module_name_in) != 0) {
+                DEBUG(SSSDBG_TRACE_ALL, "Module name [%s] does not match "
+                                        "module_name_in [%s]. "
+                                        "Skipping this module...\n",
+                      mod_file_name, module_name_in);
+                free(mod_file_name);
+                continue;
+            }
             free(mod_file_name);
 
             rv = modules[c]->C_GetInfo(&module_info);
@@ -2104,10 +2124,13 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
                 }
 
                 slot_id = slots[s];
-                break;
-            }
-            if (slot_id != (CK_SLOT_ID)-1) {
-                break;
+                module_id = c;
+                ret = do_slot(module, module_id, slot_id, &info, &token_info, &module_info,
+                              mem_ctx, p11_ctx, mode, pin, module_name_in, token_name_in,
+                              key_id_in, label_in, uri_str, _multi);
+                if (ret != EOK) {
+                    goto done;
+                }
             }
         }
 
@@ -2126,7 +2149,7 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
         goto done;
     }
 
-    if (slot_id == (CK_SLOT_ID)-1) {
+    if (slot_id == (CK_SLOT_ID)-1 || (mode == OP_AUTH && *_multi[0] == '\0')) {
         DEBUG(SSSDBG_TRACE_ALL, "Token not present.\n");
         if (!p11_ctx->wait_for_card) {
             ret = EIO;
@@ -2147,18 +2170,23 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
             DEBUG(SSSDBG_OP_FAILURE, "wait_for_card failed.\n");
             goto done;
         }
-    }
 
-    module_id = c;
-    ret = do_slot(module, module_id, slot_id, &info, &token_info, &module_info,
-                  mem_ctx, p11_ctx, mode, pin, module_name_in, token_name_in,
-                  key_id_in, label_in, uri_str, &multi);
-    *_multi = multi;
+        ret = do_slot(module, module_id, slot_id, &info, &token_info, &module_info,
+                      mem_ctx, p11_ctx, mode, pin, module_name_in, token_name_in,
+                      key_id_in, label_in, uri_str, _multi);
+        if (mode == OP_AUTH && *_multi[0] == '\0') {
+            ret = EIO;
+        }
+    }
 
-    ret = EOK;
 done:
     p11_kit_modules_finalize_and_release(modules);
     p11_kit_uri_free(uri);
 
+    if (ret != EOK) {
+        talloc_free(*_multi);
+        *_multi = NULL;
+    }
+
     return ret;
 }
-- 
2.51.0

