Blame SOURCES/0044-PAM-add-certificate-s-label-to-the-selection-prompt.patch

9f2ebf
From 35790511fd43b0c33f3b410b20a31e007b3e5d20 Mon Sep 17 00:00:00 2001
9f2ebf
From: Sumit Bose <sbose@redhat.com>
9f2ebf
Date: Tue, 7 Nov 2017 09:52:56 +0100
9f2ebf
Subject: [PATCH 44/46] PAM: add certificate's label to the selection prompt
9f2ebf
MIME-Version: 1.0
9f2ebf
Content-Type: text/plain; charset=UTF-8
9f2ebf
Content-Transfer-Encoding: 8bit
9f2ebf
9f2ebf
Some types of Smartcards contain multiple certificate with the same
9f2ebf
subject-DN for different usages. To make it easier to choose between
9f2ebf
them in case the matching rules allow more than one of them for
9f2ebf
authentication the label assigned to the certificate on the Smartcard is
9f2ebf
shown in the selection prompt as well.
9f2ebf
9f2ebf
Related to https://pagure.io/SSSD/sssd/issue/3560
9f2ebf
9f2ebf
Reviewed-by: Fabiano FidĂȘncio <fidencio@redhat.com>
9f2ebf
Tested-by: Scott Poore <spoore@redhat.com>
9f2ebf
(cherry picked from commit 57cefea8305a57c1c0491afb739813b7f17d5a25)
9f2ebf
---
9f2ebf
 src/p11_child/p11_child_nss.c   | 18 ++++++++++++++----
9f2ebf
 src/responder/pam/pamsrv.h      |  1 +
9f2ebf
 src/responder/pam/pamsrv_p11.c  | 41 +++++++++++++++++++++++++++++++++++++----
9f2ebf
 src/tests/cmocka/test_pam_srv.c | 28 ++++++++++++++--------------
9f2ebf
 4 files changed, 66 insertions(+), 22 deletions(-)
9f2ebf
9f2ebf
diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
9f2ebf
index e59aba0d1561f58206252f7251ecd88315836b1b..21c508eb1b1b68b3606d0a5eed36573b01f27a19 100644
9f2ebf
--- a/src/p11_child/p11_child_nss.c
9f2ebf
+++ b/src/p11_child/p11_child_nss.c
9f2ebf
@@ -130,7 +130,7 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db,
9f2ebf
     CERTCertificate *found_cert = NULL;
9f2ebf
     PK11SlotList *list = NULL;
9f2ebf
     PK11SlotListElement *le;
9f2ebf
-    SECItem *key_id = NULL;
9f2ebf
+    const char *label;
9f2ebf
     char *key_id_str = NULL;
9f2ebf
     CERTCertList *valid_certs = NULL;
9f2ebf
     char *cert_b64 = NULL;
9f2ebf
@@ -505,6 +505,17 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db,
9f2ebf
             goto done;
9f2ebf
         }
9f2ebf
 
9f2ebf
+        /* The NSS nickname is typically token_name:label, so the label starts
9f2ebf
+         * after the ':'. */
9f2ebf
+        if (found_cert->nickname != NULL) {
9f2ebf
+            if ((label = strchr(found_cert->nickname, ':')) == NULL) {
9f2ebf
+                label = found_cert->nickname;
9f2ebf
+            } else {
9f2ebf
+                label++;
9f2ebf
+            }
9f2ebf
+        } else {
9f2ebf
+            label = "- no label found -";
9f2ebf
+        }
9f2ebf
         talloc_free(cert_b64);
9f2ebf
         cert_b64 = sss_base64_encode(mem_ctx, found_cert->derCert.data,
9f2ebf
                                      found_cert->derCert.len);
9f2ebf
@@ -517,9 +528,9 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db,
9f2ebf
         DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n",
9f2ebf
               key_id_str);
9f2ebf
 
9f2ebf
-        multi = talloc_asprintf_append(multi, "%s\n%s\n%s\n%s\n",
9f2ebf
+        multi = talloc_asprintf_append(multi, "%s\n%s\n%s\n%s\n%s\n",
9f2ebf
                                        token_name, module_name, key_id_str,
9f2ebf
-                                       cert_b64);
9f2ebf
+                                       label, cert_b64);
9f2ebf
     }
9f2ebf
     *_multi = multi;
9f2ebf
 
9f2ebf
@@ -546,7 +557,6 @@ done:
9f2ebf
         CERT_DestroyCertList(cert_list);
9f2ebf
     }
9f2ebf
 
9f2ebf
-    SECITEM_FreeItem(key_id, PR_TRUE);
9f2ebf
     PORT_Free(key_id_str);
9f2ebf
 
9f2ebf
     PORT_Free(signed_random_value.data);
9f2ebf
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
9f2ebf
index 0bc229212844602ed461d1c7db48bf51ac2e2194..dfd982178446d6327e09afc652018886c08fd88a 100644
9f2ebf
--- a/src/responder/pam/pamsrv.h
9f2ebf
+++ b/src/responder/pam/pamsrv.h
9f2ebf
@@ -93,6 +93,7 @@ const char *sss_cai_get_cert(struct cert_auth_info *i);
9f2ebf
 const char *sss_cai_get_token_name(struct cert_auth_info *i);
9f2ebf
 const char *sss_cai_get_module_name(struct cert_auth_info *i);
9f2ebf
 const char *sss_cai_get_key_id(struct cert_auth_info *i);
9f2ebf
+const char *sss_cai_get_label(struct cert_auth_info *i);
9f2ebf
 struct cert_auth_info *sss_cai_get_next(struct cert_auth_info *i);
9f2ebf
 struct ldb_result *sss_cai_get_cert_user_objs(struct cert_auth_info *i);
9f2ebf
 void sss_cai_set_cert_user_objs(struct cert_auth_info *i,
9f2ebf
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
9f2ebf
index ec52c5ae7163d41144fe082643a201b766a1e201..fa2435543ea305f7cdb1e18753525beb373eaf4c 100644
9f2ebf
--- a/src/responder/pam/pamsrv_p11.c
9f2ebf
+++ b/src/responder/pam/pamsrv_p11.c
9f2ebf
@@ -43,6 +43,7 @@ struct cert_auth_info {
9f2ebf
     char *token_name;
9f2ebf
     char *module_name;
9f2ebf
     char *key_id;
9f2ebf
+    char *label;
9f2ebf
     struct ldb_result *cert_user_objs;
9f2ebf
     struct cert_auth_info *prev;
9f2ebf
     struct cert_auth_info *next;
9f2ebf
@@ -68,6 +69,11 @@ const char *sss_cai_get_key_id(struct cert_auth_info *i)
9f2ebf
     return i != NULL ? i->key_id : NULL;
9f2ebf
 }
9f2ebf
 
9f2ebf
+const char *sss_cai_get_label(struct cert_auth_info *i)
9f2ebf
+{
9f2ebf
+    return i != NULL ? i->label : NULL;
9f2ebf
+}
9f2ebf
+
9f2ebf
 struct cert_auth_info *sss_cai_get_next(struct cert_auth_info *i)
9f2ebf
 {
9f2ebf
     return i != NULL ? i->next : NULL;
9f2ebf
@@ -439,6 +445,31 @@ static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
9f2ebf
         }
9f2ebf
 
9f2ebf
         if (pn == p) {
9f2ebf
+            DEBUG(SSSDBG_OP_FAILURE,
9f2ebf
+                  "Missing label in p11_child response.\n");
9f2ebf
+            ret = EINVAL;
9f2ebf
+            goto done;
9f2ebf
+        }
9f2ebf
+
9f2ebf
+        cert_auth_info->label = talloc_strndup(cert_auth_info, (char *) p,
9f2ebf
+                                               (pn - p));
9f2ebf
+        if (cert_auth_info->label == NULL) {
9f2ebf
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
9f2ebf
+            ret = ENOMEM;
9f2ebf
+            goto done;
9f2ebf
+        }
9f2ebf
+        DEBUG(SSSDBG_TRACE_ALL, "Found label [%s].\n", cert_auth_info->label);
9f2ebf
+
9f2ebf
+        p = ++pn;
9f2ebf
+        pn = memchr(p, '\n', buf_len - (p - buf));
9f2ebf
+        if (pn == NULL) {
9f2ebf
+            DEBUG(SSSDBG_OP_FAILURE,
9f2ebf
+                  "Missing new-line in p11_child response.\n");
9f2ebf
+            ret = EINVAL;
9f2ebf
+            goto done;
9f2ebf
+        }
9f2ebf
+
9f2ebf
+        if (pn == p) {
9f2ebf
             DEBUG(SSSDBG_OP_FAILURE, "Missing cert in p11_child response.\n");
9f2ebf
             ret = EINVAL;
9f2ebf
             goto done;
9f2ebf
@@ -816,7 +847,8 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
9f2ebf
     return EOK;
9f2ebf
 }
9f2ebf
 
9f2ebf
-static char *get_cert_prompt(TALLOC_CTX *mem_ctx, const char *cert)
9f2ebf
+static char *get_cert_prompt(TALLOC_CTX *mem_ctx,
9f2ebf
+                             struct cert_auth_info *cert_info)
9f2ebf
 {
9f2ebf
     int ret;
9f2ebf
     struct sss_certmap_ctx *ctx = NULL;
9f2ebf
@@ -839,7 +871,7 @@ static char *get_cert_prompt(TALLOC_CTX *mem_ctx, const char *cert)
9f2ebf
         goto done;
9f2ebf
     }
9f2ebf
 
9f2ebf
-    der = sss_base64_decode(mem_ctx, cert, &der_size);
9f2ebf
+    der = sss_base64_decode(mem_ctx, sss_cai_get_cert(cert_info), &der_size);
9f2ebf
     if (der == NULL) {
9f2ebf
         DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
9f2ebf
         goto done;
9f2ebf
@@ -851,7 +883,8 @@ static char *get_cert_prompt(TALLOC_CTX *mem_ctx, const char *cert)
9f2ebf
         goto done;
9f2ebf
     }
9f2ebf
 
9f2ebf
-    prompt = talloc_strdup(mem_ctx, filter);
9f2ebf
+    prompt = talloc_asprintf(mem_ctx, "%s\n%s", sss_cai_get_label(cert_info),
9f2ebf
+                                                filter);
9f2ebf
     if (prompt == NULL) {
9f2ebf
         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
9f2ebf
     }
9f2ebf
@@ -885,7 +918,7 @@ static errno_t pack_cert_data(TALLOC_CTX *mem_ctx, const char *sysdb_username,
9f2ebf
         username = sysdb_username;
9f2ebf
     }
9f2ebf
 
9f2ebf
-    prompt = get_cert_prompt(mem_ctx, sss_cai_get_cert(cert_info));
9f2ebf
+    prompt = get_cert_prompt(mem_ctx, cert_info);
9f2ebf
     if (prompt == NULL) {
9f2ebf
         DEBUG(SSSDBG_OP_FAILURE, "get_cert_prompt failed.\n");
9f2ebf
         return EIO;
9f2ebf
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
9f2ebf
index bccf9972dacbb414076904a783772198620fd73c..4752648796ab4c863706780a2f470853cddbcc11 100644
9f2ebf
--- a/src/tests/cmocka/test_pam_srv.c
9f2ebf
+++ b/src/tests/cmocka/test_pam_srv.c
9f2ebf
@@ -53,7 +53,7 @@
9f2ebf
 #define TEST_TOKEN_NAME "SSSD Test Token"
9f2ebf
 #define TEST_MODULE_NAME "NSS-Internal"
9f2ebf
 #define TEST_KEY_ID "A5EF7DEE625CA5996C8D1BA7D036708161FD49E7"
9f2ebf
-#define TEST_SUBJECT_DN "CN=ipa-devel.ipa.devel,O=IPA.DEVEL"
9f2ebf
+#define TEST_PROMPT "Server-Cert\nCN=ipa-devel.ipa.devel,O=IPA.DEVEL"
9f2ebf
 #define TEST_TOKEN_CERT \
9f2ebf
 "MIIECTCCAvGgAwIBAgIBCTANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \
9f2ebf
 "REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA1MjMx" \
9f2ebf
@@ -79,7 +79,7 @@
9f2ebf
 "XyQBwOYRORlnfGyu+Yc9c3E0Wx8Tlznz0lqPR9g="
9f2ebf
 
9f2ebf
 #define TEST2_KEY_ID "C8D60E009EB195D01A7083EE1D5419251AA87C2C"
9f2ebf
-#define TEST2_SUBJECT_DN "CN=IPA RA,O=IPA.DEVEL"
9f2ebf
+#define TEST2_PROMPT "ipaCert\nCN=IPA RA,O=IPA.DEVEL"
9f2ebf
 #define TEST_TOKEN_2ND_CERT \
9f2ebf
 "MIIDazCCAlOgAwIBAgIBBzANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \
9f2ebf
 "REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA1MjMx" \
9f2ebf
@@ -837,7 +837,7 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body,
9f2ebf
                                 + sizeof(TEST_TOKEN_NAME)
9f2ebf
                                 + sizeof(TEST_MODULE_NAME)
9f2ebf
                                 + sizeof(TEST_KEY_ID)
9f2ebf
-                                + sizeof(TEST_SUBJECT_DN)));
9f2ebf
+                                + sizeof(TEST_PROMPT)));
9f2ebf
 
9f2ebf
     assert_int_equal(*(body + rp + sizeof("pamuser@"TEST_DOM_NAME) - 1), 0);
9f2ebf
     assert_string_equal(body + rp, "pamuser@"TEST_DOM_NAME);
9f2ebf
@@ -855,9 +855,9 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body,
9f2ebf
     assert_string_equal(body + rp, TEST_KEY_ID);
9f2ebf
     rp += sizeof(TEST_KEY_ID);
9f2ebf
 
9f2ebf
-    assert_int_equal(*(body + rp + sizeof(TEST_SUBJECT_DN) - 1), 0);
9f2ebf
-    assert_string_equal(body + rp, TEST_SUBJECT_DN);
9f2ebf
-    rp += sizeof(TEST_SUBJECT_DN);
9f2ebf
+    assert_int_equal(*(body + rp + sizeof(TEST_PROMPT) - 1), 0);
9f2ebf
+    assert_string_equal(body + rp, TEST_PROMPT);
9f2ebf
+    rp += sizeof(TEST_PROMPT);
9f2ebf
 
9f2ebf
     assert_int_equal(rp, blen);
9f2ebf
     return EOK;
9f2ebf
@@ -904,7 +904,7 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
9f2ebf
                                 + sizeof(TEST_TOKEN_NAME)
9f2ebf
                                 + sizeof(TEST_MODULE_NAME)
9f2ebf
                                 + sizeof(TEST_KEY_ID)
9f2ebf
-                                + sizeof(TEST_SUBJECT_DN)));
9f2ebf
+                                + sizeof(TEST_PROMPT)));
9f2ebf
 
9f2ebf
     assert_int_equal(*(body + rp + strlen(name)), 0);
9f2ebf
     assert_string_equal(body + rp, name);
9f2ebf
@@ -922,9 +922,9 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
9f2ebf
     assert_string_equal(body + rp, TEST_KEY_ID);
9f2ebf
     rp += sizeof(TEST_KEY_ID);
9f2ebf
 
9f2ebf
-    assert_int_equal(*(body + rp + sizeof(TEST_SUBJECT_DN) - 1), 0);
9f2ebf
-    assert_string_equal(body + rp, TEST_SUBJECT_DN);
9f2ebf
-    rp += sizeof(TEST_SUBJECT_DN);
9f2ebf
+    assert_int_equal(*(body + rp + sizeof(TEST_PROMPT) - 1), 0);
9f2ebf
+    assert_string_equal(body + rp, TEST_PROMPT);
9f2ebf
+    rp += sizeof(TEST_PROMPT);
9f2ebf
 
9f2ebf
     if (name2 != NULL && *name2 != '\0') {
9f2ebf
         SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
9f2ebf
@@ -935,7 +935,7 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
9f2ebf
                                     + sizeof(TEST_TOKEN_NAME)
9f2ebf
                                     + sizeof(TEST_MODULE_NAME)
9f2ebf
                                     + sizeof(TEST2_KEY_ID)
9f2ebf
-                                    + sizeof(TEST2_SUBJECT_DN)));
9f2ebf
+                                    + sizeof(TEST2_PROMPT)));
9f2ebf
 
9f2ebf
         assert_int_equal(*(body + rp + strlen(name)), 0);
9f2ebf
         assert_string_equal(body + rp, name);
9f2ebf
@@ -953,9 +953,9 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen,
9f2ebf
         assert_string_equal(body + rp, TEST2_KEY_ID);
9f2ebf
         rp += sizeof(TEST2_KEY_ID);
9f2ebf
 
9f2ebf
-        assert_int_equal(*(body + rp + sizeof(TEST2_SUBJECT_DN) - 1), 0);
9f2ebf
-        assert_string_equal(body + rp, TEST2_SUBJECT_DN);
9f2ebf
-        rp += sizeof(TEST2_SUBJECT_DN);
9f2ebf
+        assert_int_equal(*(body + rp + sizeof(TEST2_PROMPT) - 1), 0);
9f2ebf
+        assert_string_equal(body + rp, TEST2_PROMPT);
9f2ebf
+        rp += sizeof(TEST2_PROMPT);
9f2ebf
     }
9f2ebf
 
9f2ebf
     assert_int_equal(rp, blen);
9f2ebf
-- 
9f2ebf
2.13.6
9f2ebf