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