Blame SOURCES/0039-p11_child-use-options-to-select-certificate-for-auth.patch

ced1f5
From e857005c207e514c487ba75daf20ca4be5321c38 Mon Sep 17 00:00:00 2001
ced1f5
From: Sumit Bose <sbose@redhat.com>
ced1f5
Date: Fri, 27 Oct 2017 10:13:36 +0200
ced1f5
Subject: [PATCH 39/46] p11_child: use options to select certificate for
ced1f5
 authentication
ced1f5
MIME-Version: 1.0
ced1f5
Content-Type: text/plain; charset=UTF-8
ced1f5
Content-Transfer-Encoding: 8bit
ced1f5
ced1f5
New options are added to p11_child to select a specific certificate
ced1f5
during authentication.
ced1f5
ced1f5
The related unit tests are updated by adding the needed attributes to
ced1f5
the requests. The was not necessary before because although the
ced1f5
attribute were already send by pam_sss they were not used in the PAM
ced1f5
responder but only forwarded to the back where they were used by the
ced1f5
PKINIT code to select the expected certificate.
ced1f5
ced1f5
Related to https://pagure.io/SSSD/sssd/issue/3560
ced1f5
ced1f5
Reviewed-by: Fabiano FidĂȘncio <fidencio@redhat.com>
ced1f5
Tested-by: Scott Poore <spoore@redhat.com>
ced1f5
(cherry picked from commit 0a8024af282b271ad2185f68703d9f4e766d2bdc)
ced1f5
---
ced1f5
 src/p11_child/p11_child_nss.c   | 213 ++++++++++++++++++++++++++--------------
ced1f5
 src/responder/pam/pamsrv_p11.c  |  30 +++++-
ced1f5
 src/tests/cmocka/test_pam_srv.c |  64 ++++++++----
ced1f5
 3 files changed, 210 insertions(+), 97 deletions(-)
ced1f5
ced1f5
diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
ced1f5
index 50bde2f4f91f6c00260b0db383d0962112686ebc..c676375cf7f6677a1d7f38f09b9bb5fd820d60c5 100644
ced1f5
--- a/src/p11_child/p11_child_nss.c
ced1f5
+++ b/src/p11_child/p11_child_nss.c
ced1f5
@@ -67,12 +67,34 @@ static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
ced1f5
   return PL_strdup((char *)arg);
ced1f5
 }
ced1f5
 
ced1f5
+static char *get_key_id_str(PK11SlotInfo *slot, CERTCertificate *cert)
ced1f5
+{
ced1f5
+    SECItem *key_id = NULL;
ced1f5
+    char *key_id_str = NULL;
ced1f5
 
ced1f5
+    key_id = PK11_GetLowLevelKeyIDForCert(slot, cert, NULL);
ced1f5
+    if (key_id == NULL) {
ced1f5
+        DEBUG(SSSDBG_OP_FAILURE,
ced1f5
+              "PK11_GetLowLevelKeyIDForCert failed [%d].\n",
ced1f5
+              PR_GetError());
ced1f5
+        return NULL;
ced1f5
+    }
ced1f5
 
ced1f5
-int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
+    key_id_str = CERT_Hexify(key_id, PR_FALSE);
ced1f5
+    SECITEM_FreeItem(key_id, PR_TRUE);
ced1f5
+    if (key_id_str == NULL) {
ced1f5
+        DEBUG(SSSDBG_OP_FAILURE, "CERT_Hexify failed [%d].\n", PR_GetError());
ced1f5
+        return NULL;
ced1f5
+    }
ced1f5
+
ced1f5
+    return key_id_str;
ced1f5
+}
ced1f5
+
ced1f5
+int do_work(TALLOC_CTX *mem_ctx, const char *nss_db,
ced1f5
             enum op_mode mode, const char *pin,
ced1f5
             struct cert_verify_opts *cert_verify_opts,
ced1f5
-            char **_multi)
ced1f5
+            const char *module_name_in, const char *token_name_in,
ced1f5
+            const char *key_id_in, char **_multi)
ced1f5
 {
ced1f5
     int ret;
ced1f5
     SECStatus rv;
ced1f5
@@ -153,42 +175,31 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
                                 mod_list_item->module->dllName);
ced1f5
     }
ced1f5
 
ced1f5
-    if (slot_name_in != NULL) {
ced1f5
-        slot = PK11_FindSlotByName(slot_name_in);
ced1f5
-        if (slot == NULL) {
ced1f5
-            DEBUG(SSSDBG_OP_FAILURE, "PK11_FindSlotByName failed for [%s]: [%d].\n",
ced1f5
-                                     slot_name_in, PR_GetError());
ced1f5
-            return EIO;
ced1f5
-        }
ced1f5
-    } else {
ced1f5
-
ced1f5
-        list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE,
ced1f5
-                                 NULL);
ced1f5
-        if (list == NULL) {
ced1f5
-            DEBUG(SSSDBG_OP_FAILURE, "PK11_GetAllTokens failed.\n");
ced1f5
-            return EIO;
ced1f5
-        }
ced1f5
+    list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE,
ced1f5
+                             NULL);
ced1f5
+    if (list == NULL) {
ced1f5
+        DEBUG(SSSDBG_OP_FAILURE, "PK11_GetAllTokens failed.\n");
ced1f5
+        return EIO;
ced1f5
+    }
ced1f5
 
ced1f5
-        for (le = list->head; le; le = le->next) {
ced1f5
-            CK_SLOT_INFO slInfo;
ced1f5
+    for (le = list->head; le; le = le->next) {
ced1f5
+        CK_SLOT_INFO slInfo;
ced1f5
 
ced1f5
-            slInfo.flags = 0;
ced1f5
-            rv = PK11_GetSlotInfo(le->slot, &slInfo);
ced1f5
-            DEBUG(SSSDBG_TRACE_ALL,
ced1f5
-                  "Description [%s] Manufacturer [%s] flags [%lu].\n",
ced1f5
-                  slInfo.slotDescription, slInfo.manufacturerID, slInfo.flags);
ced1f5
-            if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) {
ced1f5
-                slot = PK11_ReferenceSlot(le->slot);
ced1f5
-                break;
ced1f5
-           }
ced1f5
-        }
ced1f5
-        PK11_FreeSlotList(list);
ced1f5
-        if (slot == NULL) {
ced1f5
-            DEBUG(SSSDBG_OP_FAILURE, "No removable slots found.\n");
ced1f5
-            return EIO;
ced1f5
+        slInfo.flags = 0;
ced1f5
+        rv = PK11_GetSlotInfo(le->slot, &slInfo);
ced1f5
+        DEBUG(SSSDBG_TRACE_ALL,
ced1f5
+              "Description [%s] Manufacturer [%s] flags [%lu].\n",
ced1f5
+              slInfo.slotDescription, slInfo.manufacturerID, slInfo.flags);
ced1f5
+        if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) {
ced1f5
+            slot = PK11_ReferenceSlot(le->slot);
ced1f5
+            break;
ced1f5
         }
ced1f5
     }
ced1f5
-
ced1f5
+    PK11_FreeSlotList(list);
ced1f5
+    if (slot == NULL) {
ced1f5
+        DEBUG(SSSDBG_OP_FAILURE, "No removable slots found.\n");
ced1f5
+        return EIO;
ced1f5
+    }
ced1f5
 
ced1f5
     slot_id = PK11_GetSlotID(slot);
ced1f5
     module_id = PK11_GetModuleID(slot);
ced1f5
@@ -317,24 +328,60 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
     for (cert_list_node = CERT_LIST_HEAD(cert_list);
ced1f5
                 !CERT_LIST_END(cert_list_node, cert_list);
ced1f5
                 cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
ced1f5
-        if (cert_list_node->cert) {
ced1f5
-            DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n",
ced1f5
-                             cert_list_node->cert->nickname,
ced1f5
-                             cert_list_node->cert->subjectName);
ced1f5
+        if (cert_list_node->cert == NULL) {
ced1f5
+            DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
ced1f5
+            continue;
ced1f5
+        }
ced1f5
 
ced1f5
-            if (cert_verify_opts->do_verification) {
ced1f5
-                rv = CERT_VerifyCertificateNow(handle, cert_list_node->cert,
ced1f5
-                                               PR_TRUE,
ced1f5
-                                               certificateUsageSSLClient,
ced1f5
-                                               NULL, NULL);
ced1f5
-                if (rv != SECSuccess) {
ced1f5
-                    DEBUG(SSSDBG_OP_FAILURE,
ced1f5
-                          "Certificate [%s][%s] not valid [%d], skipping.\n",
ced1f5
-                          cert_list_node->cert->nickname,
ced1f5
-                          cert_list_node->cert->subjectName, PR_GetError());
ced1f5
-                    continue;
ced1f5
-                }
ced1f5
+        DEBUG(SSSDBG_TRACE_ALL,
ced1f5
+              "found cert[%s][%s]\n",
ced1f5
+              cert_list_node->cert->nickname,
ced1f5
+              cert_list_node->cert->subjectName);
ced1f5
+
ced1f5
+        if (cert_verify_opts->do_verification) {
ced1f5
+            rv = CERT_VerifyCertificateNow(handle, cert_list_node->cert,
ced1f5
+                                           PR_TRUE,
ced1f5
+                                           certificateUsageSSLClient,
ced1f5
+                                           NULL, NULL);
ced1f5
+            if (rv != SECSuccess) {
ced1f5
+                DEBUG(SSSDBG_OP_FAILURE,
ced1f5
+                      "Certificate [%s][%s] not valid [%d], skipping.\n",
ced1f5
+                      cert_list_node->cert->nickname,
ced1f5
+                      cert_list_node->cert->subjectName, PR_GetError());
ced1f5
+                continue;
ced1f5
             }
ced1f5
+        }
ced1f5
+
ced1f5
+        if (key_id_in != NULL) {
ced1f5
+            PORT_Free(key_id_str);
ced1f5
+            key_id_str = NULL;
ced1f5
+            key_id_str = get_key_id_str(slot, cert_list_node->cert);
ced1f5
+        }
ced1f5
+        /* Check if we found the certificates we needed for authentication or
ced1f5
+         * the requested ones for pre-auth. For authentication all attributes
ced1f5
+         * must be given and match, for pre-auth only the given ones must
ced1f5
+         * match. */
ced1f5
+        DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s.\n",
ced1f5
+              module_name_in, module_name, token_name_in, token_name,
ced1f5
+              key_id_in, key_id_str);
ced1f5
+        if ((mode == OP_AUTH
ced1f5
+                && module_name_in != NULL
ced1f5
+                && token_name_in != NULL
ced1f5
+                && key_id_in != NULL
ced1f5
+                && key_id_str != NULL
ced1f5
+                && strcmp(key_id_in, key_id_str) == 0
ced1f5
+                && strcmp(token_name_in, token_name) == 0
ced1f5
+                && strcmp(module_name_in, module_name) == 0)
ced1f5
+            || (mode == OP_PREAUTH
ced1f5
+                && (module_name_in == NULL
ced1f5
+                    || (module_name_in != NULL
ced1f5
+                        && strcmp(module_name_in, module_name) == 0))
ced1f5
+                && (token_name_in == NULL
ced1f5
+                    || (token_name_in != NULL
ced1f5
+                        && strcmp(token_name_in, token_name) == 0))
ced1f5
+                && (key_id_in == NULL
ced1f5
+                    || (key_id_in != NULL && key_id_str != NULL
ced1f5
+                        && strcmp(key_id_in, key_id_str) == 0)))) {
ced1f5
 
ced1f5
             rv = CERT_AddCertToListTail(valid_certs, cert_list_node->cert);
ced1f5
             if (rv != SECSuccess) {
ced1f5
@@ -343,15 +390,6 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
                 ret = EIO;
ced1f5
                 goto done;
ced1f5
             }
ced1f5
-
ced1f5
-            if (found_cert == NULL) {
ced1f5
-                found_cert = cert_list_node->cert;
ced1f5
-            } else {
ced1f5
-                DEBUG(SSSDBG_TRACE_ALL, "More than one certificate found, " \
ced1f5
-                                        "using just the first one.\n");
ced1f5
-            }
ced1f5
-        } else {
ced1f5
-            DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
ced1f5
         }
ced1f5
     }
ced1f5
 
ced1f5
@@ -367,7 +405,7 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
         }
ced1f5
     }
ced1f5
 
ced1f5
-    if (found_cert == NULL) {
ced1f5
+    if (CERT_LIST_EMPTY(valid_certs)) {
ced1f5
         DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
ced1f5
         *_multi = NULL;
ced1f5
         ret = EOK;
ced1f5
@@ -375,6 +413,23 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
     }
ced1f5
 
ced1f5
     if (mode == OP_AUTH) {
ced1f5
+        cert_list_node = CERT_LIST_HEAD(valid_certs);
ced1f5
+        if (!CERT_LIST_END(CERT_LIST_NEXT(cert_list_node), valid_certs)) {
ced1f5
+            DEBUG(SSSDBG_FATAL_FAILURE,
ced1f5
+                  "More than one certificate found for authentication, "
ced1f5
+                  "aborting!\n");
ced1f5
+            ret = EINVAL;
ced1f5
+            goto done;
ced1f5
+        }
ced1f5
+
ced1f5
+        found_cert = cert_list_node->cert;
ced1f5
+        if (found_cert == NULL) {
ced1f5
+            DEBUG(SSSDBG_FATAL_FAILURE,
ced1f5
+                  "No certificate found for authentication, aborting!\n");
ced1f5
+            ret = EINVAL;
ced1f5
+            goto done;
ced1f5
+        }
ced1f5
+
ced1f5
         rv = PK11_GenerateRandom(random_value, sizeof(random_value));
ced1f5
         if (rv != SECSuccess) {
ced1f5
             DEBUG(SSSDBG_OP_FAILURE,
ced1f5
@@ -449,21 +504,10 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ced1f5
 
ced1f5
         found_cert = cert_list_node->cert;
ced1f5
 
ced1f5
-        SECITEM_FreeItem(key_id, PR_TRUE);
ced1f5
         PORT_Free(key_id_str);
ced1f5
-        key_id = PK11_GetLowLevelKeyIDForCert(slot, found_cert, NULL);
ced1f5
-        if (key_id == NULL) {
ced1f5
-            DEBUG(SSSDBG_OP_FAILURE,
ced1f5
-                  "PK11_GetLowLevelKeyIDForCert failed [%d].\n",
ced1f5
-                  PR_GetError());
ced1f5
-            ret = EINVAL;
ced1f5
-            goto done;
ced1f5
-        }
ced1f5
-
ced1f5
-        key_id_str = CERT_Hexify(key_id, PR_FALSE);
ced1f5
+        key_id_str = get_key_id_str(slot, found_cert);
ced1f5
         if (key_id_str == NULL) {
ced1f5
-            DEBUG(SSSDBG_OP_FAILURE, "CERT_Hexify failed [%d].\n",
ced1f5
-                  PR_GetError());
ced1f5
+            DEBUG(SSSDBG_OP_FAILURE, "get_key_id_str [%d].\n", PR_GetError());
ced1f5
             ret = ENOMEM;
ced1f5
             goto done;
ced1f5
         }
ced1f5
@@ -576,11 +620,13 @@ int main(int argc, const char *argv[])
ced1f5
     enum op_mode mode = OP_NONE;
ced1f5
     enum pin_mode pin_mode = PIN_NONE;
ced1f5
     char *pin = NULL;
ced1f5
-    char *slot_name_in = NULL;
ced1f5
     char *nss_db = NULL;
ced1f5
     struct cert_verify_opts *cert_verify_opts;
ced1f5
     char *verify_opts = NULL;
ced1f5
     char *multi = NULL;
ced1f5
+    char *module_name = NULL;
ced1f5
+    char *token_name = NULL;
ced1f5
+    char *key_id = NULL;
ced1f5
 
ced1f5
     struct poptOption long_options[] = {
ced1f5
         POPT_AUTOHELP
ced1f5
@@ -605,6 +651,12 @@ int main(int argc, const char *argv[])
ced1f5
          NULL},
ced1f5
         {"nssdb", 0, POPT_ARG_STRING, &nss_db, 0, _("NSS DB to use"),
ced1f5
          NULL},
ced1f5
+        {"module_name", 0, POPT_ARG_STRING, &module_name, 0,
ced1f5
+         _("Module name for authentication"), NULL},
ced1f5
+        {"token_name", 0, POPT_ARG_STRING, &token_name, 0,
ced1f5
+         _("Token name for authentication"), NULL},
ced1f5
+        {"key_id", 0, POPT_ARG_STRING, &key_id, 0,
ced1f5
+         _("Key ID for authentication"), NULL},
ced1f5
         POPT_TABLEEND
ced1f5
     };
ced1f5
 
ced1f5
@@ -730,6 +782,15 @@ int main(int argc, const char *argv[])
ced1f5
     }
ced1f5
     talloc_steal(main_ctx, debug_prg_name);
ced1f5
 
ced1f5
+    if (mode == OP_AUTH && (module_name == NULL || token_name == NULL
ced1f5
+                                || key_id == NULL)) {
ced1f5
+        DEBUG(SSSDBG_FATAL_FAILURE,
ced1f5
+              "--module_name, --token_name and --key_id must be for "
ced1f5
+              "authentication");
ced1f5
+        ret = EINVAL;
ced1f5
+        goto fail;
ced1f5
+    }
ced1f5
+
ced1f5
     ret = parse_cert_verify_opts(main_ctx, verify_opts, &cert_verify_opts);
ced1f5
     if (ret != EOK) {
ced1f5
         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse verifiy option.\n");
ced1f5
@@ -744,8 +805,8 @@ int main(int argc, const char *argv[])
ced1f5
         }
ced1f5
     }
ced1f5
 
ced1f5
-    ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, cert_verify_opts,
ced1f5
-                  &multi);
ced1f5
+    ret = do_work(main_ctx, nss_db, mode, pin, cert_verify_opts, module_name,
ced1f5
+                  token_name, key_id, &multi);
ced1f5
     if (ret != EOK) {
ced1f5
         DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
ced1f5
         goto fail;
ced1f5
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
ced1f5
index 57c8e1e464f4262f2d78f869c52ca48bd469d90a..4d5572164763ed0b3a842019f820680a4dc2dfdc 100644
ced1f5
--- a/src/responder/pam/pamsrv_p11.c
ced1f5
+++ b/src/responder/pam/pamsrv_p11.c
ced1f5
@@ -399,10 +399,13 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
ced1f5
     struct timeval tv;
ced1f5
     int pipefd_to_child[2] = PIPE_INIT;
ced1f5
     int pipefd_from_child[2] = PIPE_INIT;
ced1f5
-    const char *extra_args[7] = { NULL };
ced1f5
+    const char *extra_args[13] = { NULL };
ced1f5
     uint8_t *write_buf = NULL;
ced1f5
     size_t write_buf_len = 0;
ced1f5
     size_t arg_c;
ced1f5
+    const char *module_name = NULL;
ced1f5
+    const char *token_name = NULL;
ced1f5
+    const char *key_id = NULL;
ced1f5
 
ced1f5
     req = tevent_req_create(mem_ctx, &state, struct pam_check_cert_state);
ced1f5
     if (req == NULL) {
ced1f5
@@ -423,6 +426,30 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
ced1f5
         extra_args[arg_c++] = verify_opts;
ced1f5
         extra_args[arg_c++] = "--verify";
ced1f5
     }
ced1f5
+
ced1f5
+    if (sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_SC_PIN
ced1f5
+            || sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD) {
ced1f5
+        ret = sss_authtok_get_sc(pd->authtok, NULL, NULL, &token_name, NULL,
ced1f5
+                                 &module_name, NULL, &key_id, NULL);
ced1f5
+        if (ret != EOK) {
ced1f5
+            DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n");
ced1f5
+            goto done;
ced1f5
+        }
ced1f5
+
ced1f5
+        if (module_name != NULL && *module_name != '\0') {
ced1f5
+            extra_args[arg_c++] = module_name;
ced1f5
+            extra_args[arg_c++] = "--module_name";
ced1f5
+        }
ced1f5
+        if (token_name != NULL && *token_name != '\0') {
ced1f5
+            extra_args[arg_c++] = token_name;
ced1f5
+            extra_args[arg_c++] = "--token_name";
ced1f5
+        }
ced1f5
+        if (key_id != NULL && *key_id != '\0') {
ced1f5
+            extra_args[arg_c++] = key_id;
ced1f5
+            extra_args[arg_c++] = "--key_id";
ced1f5
+        }
ced1f5
+    }
ced1f5
+
ced1f5
     if (pd->cmd == SSS_PAM_AUTHENTICATE) {
ced1f5
         extra_args[arg_c++] = "--auth";
ced1f5
         switch (sss_authtok_get_type(pd->authtok)) {
ced1f5
@@ -437,6 +464,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
ced1f5
             ret = EINVAL;
ced1f5
             goto done;
ced1f5
         }
ced1f5
+
ced1f5
     } else if (pd->cmd == SSS_PAM_PREAUTH) {
ced1f5
         extra_args[arg_c++] = "--pre";
ced1f5
     } else {
ced1f5
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
ced1f5
index 7f0ed706512ffe0866c0e1fb7e6baa16bec942d8..5c1f621ccead75717d1721714d953d7d4d415d7b 100644
ced1f5
--- a/src/tests/cmocka/test_pam_srv.c
ced1f5
+++ b/src/tests/cmocka/test_pam_srv.c
ced1f5
@@ -687,7 +687,9 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx,
ced1f5
 }
ced1f5
 
ced1f5
 static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
ced1f5
-                                const char *pin, const char *service,
ced1f5
+                                const char *pin, const char *token_name,
ced1f5
+                                const char *module_name, const char *key_id,
ced1f5
+                                const char *service,
ced1f5
                                 acct_cb_t acct_cb, const char *cert,
ced1f5
                                 bool only_one_provider_call)
ced1f5
 {
ced1f5
@@ -697,6 +699,7 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
ced1f5
     struct pam_items pi = { 0 };
ced1f5
     int ret;
ced1f5
     bool already_mocked = false;
ced1f5
+    size_t needed_size;
ced1f5
 
ced1f5
     if (name != NULL) {
ced1f5
         pi.pam_user = name;
ced1f5
@@ -707,9 +710,21 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
ced1f5
     }
ced1f5
 
ced1f5
     if (pin != NULL) {
ced1f5
-        pi.pam_authtok = discard_const(pin);
ced1f5
-        pi.pam_authtok_size = strlen(pi.pam_authtok) + 1;
ced1f5
+        ret = sss_auth_pack_sc_blob(pin, 0, token_name, 0, module_name, 0,
ced1f5
+                                    key_id, 0, NULL, 0, &needed_size);
ced1f5
+        assert_int_equal(ret, EAGAIN);
ced1f5
+
ced1f5
+        pi.pam_authtok = malloc(needed_size);
ced1f5
+        assert_non_null(pi.pam_authtok);
ced1f5
+
ced1f5
+        ret = sss_auth_pack_sc_blob(pin, 0, token_name, 0, module_name, 0,
ced1f5
+                                    key_id, 0,
ced1f5
+                                    (uint8_t *)pi.pam_authtok, needed_size,
ced1f5
+                                    &needed_size);
ced1f5
+        assert_int_equal(ret, EOK);
ced1f5
+
ced1f5
         pi.pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN;
ced1f5
+        pi.pam_authtok_size = needed_size;
ced1f5
     }
ced1f5
 
ced1f5
     pi.pam_service = service == NULL ? "login" : service;
ced1f5
@@ -724,6 +739,7 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
ced1f5
     pi.cli_pid = 12345;
ced1f5
 
ced1f5
     ret = pack_message_v3(&pi, &buf_size, &m_buf);
ced1f5
+    free(pi.pam_authtok);
ced1f5
     assert_int_equal(ret, 0);
ced1f5
 
ced1f5
     buf = talloc_memdup(mem_ctx, m_buf, buf_size);
ced1f5
@@ -1732,7 +1748,8 @@ void test_pam_preauth_no_logon_name(void **state)
ced1f5
 {
ced1f5
     int ret;
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, false);
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
+                        NULL, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
ced1f5
@@ -1824,7 +1841,8 @@ void test_pam_preauth_cert_nocert(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, "/no/path");
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, false);
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
ced1f5
+                        NULL, NULL, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
ced1f5
@@ -1962,7 +1980,7 @@ void test_pam_preauth_cert_nomatch(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb, NULL, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -1984,7 +2002,7 @@ void test_pam_preauth_cert_match(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb, TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -2007,8 +2025,9 @@ void test_pam_preauth_cert_match_gdm_smartcard(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, "gdm-smartcard",
ced1f5
-                        test_lookup_by_cert_cb, TEST_TOKEN_CERT, false);
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL,
ced1f5
+                        "gdm-smartcard", test_lookup_by_cert_cb,
ced1f5
+                        TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
ced1f5
@@ -2029,7 +2048,7 @@ void test_pam_preauth_cert_match_wrong_user(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_wrong_user_cb,
ced1f5
                         TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
@@ -2061,7 +2080,7 @@ void test_pam_preauth_cert_no_logon_name(void **state)
ced1f5
      * Additionally sss_parse_inp_recv() must be mocked because the cache
ced1f5
      * request will be done with the username found by the certificate
ced1f5
      * lookup. */
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb, TEST_TOKEN_CERT, false);
ced1f5
     mock_account_recv_simple();
ced1f5
     mock_parse_inp("pamuser", NULL, EOK);
ced1f5
@@ -2090,7 +2109,7 @@ void test_pam_preauth_cert_no_logon_name_with_hint(void **state)
ced1f5
      * Since user name hint is enabled we do not have to search the user
ced1f5
      * during pre-auth and there is no need for an extra mocked response as in
ced1f5
      * test_pam_preauth_cert_no_logon_name. */
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb, TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -2112,7 +2131,7 @@ void test_pam_preauth_cert_no_logon_name_double_cert(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_double_cb, TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -2135,7 +2154,7 @@ void test_pam_preauth_cert_no_logon_name_double_cert_with_hint(void **state)
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
     pam_test_ctx->rctx->domains->user_name_hint = true;
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_double_cb, TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -2157,7 +2176,8 @@ void test_pam_preauth_no_cert_no_logon_name(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, "/no/path");
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, false);
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
+                        NULL, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
ced1f5
@@ -2178,7 +2198,7 @@ void test_pam_preauth_cert_no_logon_name_no_match(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb, NULL, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -2206,7 +2226,9 @@ void test_pam_cert_auth(void **state)
ced1f5
      * is looked up. Since the first mocked reply already adds the certificate
ced1f5
      * to the user entry the lookup by certificate will already find the user
ced1f5
      * in the cache and no second request to the backend is needed. */
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token",
ced1f5
+                        "NSS-Internal",
ced1f5
+                        "A5EF7DEE625CA5996C8D1BA7D036708161FD49E7", NULL,
ced1f5
                         test_lookup_by_cert_cb, TEST_TOKEN_CERT, true);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
ced1f5
@@ -2232,7 +2254,9 @@ void test_pam_cert_auth_double_cert(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token",
ced1f5
+                        "NSS-Internal",
ced1f5
+                        "A5EF7DEE625CA5996C8D1BA7D036708161FD49E7", NULL,
ced1f5
                         test_lookup_by_cert_double_cb, TEST_TOKEN_CERT, true);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
ced1f5
@@ -2257,7 +2281,7 @@ void test_pam_cert_preauth_2certs_one_mapping(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB_2CERTS);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb, TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
ced1f5
@@ -2279,7 +2303,7 @@ void test_pam_cert_preauth_2certs_two_mappings(void **state)
ced1f5
 
ced1f5
     set_cert_auth_param(pam_test_ctx->pctx, NSS_DB_2CERTS);
ced1f5
 
ced1f5
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL,
ced1f5
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
ced1f5
                         test_lookup_by_cert_cb_2nd_cert_same_user,
ced1f5
                         TEST_TOKEN_CERT, false);
ced1f5
 
ced1f5
-- 
ced1f5
2.13.6
ced1f5