Blob Blame History Raw
From d931db919e85fda2bfc195403c81b873ca94c4d4 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 8 Oct 2018 10:45:28 +0200
Subject: [PATCH 43/47] p11_child: show PKCS#11 URI in debug output

Related to https://pagure.io/SSSD/sssd/issue/3814

Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 46fd681a73ffef062cd027e7018e1a02d7a0a9df)
---
 src/p11_child/p11_child_nss.c     | 240 ++++++++++++++++++++++++++++++++++++++
 src/p11_child/p11_child_openssl.c |  80 +++++++++++++
 2 files changed, 320 insertions(+)

diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
index b2777d1d245d4942263ebf0610eef5cf6a528bd1..fff1f2525878b596e518b717476e892d1cf2ddae 100644
--- a/src/p11_child/p11_child_nss.c
+++ b/src/p11_child/p11_child_nss.c
@@ -39,6 +39,7 @@
 #include <pk11pub.h>
 #include <prerror.h>
 #include <ocsp.h>
+#include <pkcs11uri.h>
 
 #include "util/child_common.h"
 #include "providers/backend.h"
@@ -63,6 +64,239 @@ struct p11_ctx {
                     | certificateUsageStatusResponder \
                     | certificateUsageSSLCA )
 
+
+static char *get_pkcs11_string(TALLOC_CTX *mem_ctx, const char *in, size_t len)
+{
+    size_t c = len;
+
+    if (in == NULL || len == 0) {
+        return NULL;
+    }
+
+    while(c > 0 && in[c - 1] == ' ') {
+        c--;
+    }
+
+    return talloc_strndup(mem_ctx, in, c);
+}
+
+static char *pct_encode(TALLOC_CTX *mem_ctx, SECItem *data)
+{
+    char *pct;
+    size_t c;
+    int ret;
+
+    pct = talloc_zero_size(mem_ctx, sizeof(char) * (3*data->len + 1));
+    if (pct == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n");
+        return NULL;
+    }
+
+    for (c = 0; c < data->len; c++) {
+        ret = snprintf(pct + 3*c, 4, "%%%02X", data->data[c]);
+        if (ret != 3) {
+            DEBUG(SSSDBG_OP_FAILURE, "snprintf failed.\n");
+            talloc_free(pct);
+            return NULL;
+        }
+    }
+
+    return pct;
+}
+
+static char *get_key_id_pct(TALLOC_CTX *mem_ctx, PK11SlotInfo *slot,
+                            CERTCertificate *cert)
+{
+    SECItem *key_id = NULL;
+    char *key_id_str = NULL;
+
+    key_id = PK11_GetLowLevelKeyIDForCert(slot, cert, NULL);
+    if (key_id == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "PK11_GetLowLevelKeyIDForCert failed [%d][%s].\n",
+              PR_GetError(), PORT_ErrorToString(PR_GetError()));
+        return NULL;
+    }
+
+    key_id_str = pct_encode(mem_ctx, key_id);
+    SECITEM_FreeItem(key_id, PR_TRUE);
+    if (key_id_str == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "pct_encode failed.\n");
+        return NULL;
+    }
+
+    return key_id_str;
+}
+
+static char *get_pkcs11_uri(TALLOC_CTX *mem_ctx, SECMODModule *mod,
+                            PK11SlotInfo *slot,
+                            const char *label, CERTCertificate *cert)
+{
+    CK_INFO module_info;
+    CK_SLOT_INFO slot_info;
+    CK_TOKEN_INFO token_info;
+    char *values[13];
+    PK11URIAttribute attrs[13];
+    size_t nattrs = 0;
+    SECStatus rv;
+    char *tmp_str;
+    char *uri_str;
+    PK11URI *uri;
+    CK_SLOT_ID slot_id;
+    char *id_pct;
+
+    rv = PK11_GetModInfo(mod, &module_info);
+    if (rv != SECSuccess) {
+        DEBUG(SSSDBG_OP_FAILURE, "PK11_GetModInfo failed.\n");
+        return NULL;
+    }
+
+    rv = PK11_GetSlotInfo(slot, &slot_info);
+    if (rv != SECSuccess) {
+        DEBUG(SSSDBG_OP_FAILURE, "PK11_GetSlotInfo failed.\n");
+        return NULL;
+    }
+
+    rv = PK11_GetTokenInfo(slot, &token_info);
+    if (rv != SECSuccess) {
+        DEBUG(SSSDBG_OP_FAILURE, "PK11_GetTokenInfo failed.\n");
+        return NULL;
+    }
+    values[nattrs] = get_pkcs11_string(mem_ctx,
+                                       (char *)module_info.libraryDescription,
+                                       sizeof(module_info.libraryDescription));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_LIBRARY_DESCRIPTION;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx,
+                                       (char *)module_info.manufacturerID,
+                                       sizeof(module_info.manufacturerID));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_LIBRARY_MANUFACTURER;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = talloc_asprintf(mem_ctx, "%d.%d",
+                                     module_info.libraryVersion.major,
+                                     module_info.libraryVersion.minor);
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_LIBRARY_VERSION;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx,
+                                       (char *)slot_info.slotDescription,
+                                       sizeof(slot_info.slotDescription));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_SLOT_DESCRIPTION;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx,
+                                       (char *)slot_info.manufacturerID,
+                                       sizeof(slot_info.manufacturerID));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_SLOT_MANUFACTURER;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    slot_id = PK11_GetSlotID(slot);
+    values[nattrs] = talloc_asprintf(mem_ctx, "%d", (int) slot_id);
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_SLOT_ID;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx, (char *)token_info.model,
+                                       sizeof(token_info.model));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_MODEL;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx,
+                                       (char *)token_info.manufacturerID,
+                                       sizeof(token_info.manufacturerID));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_MANUFACTURER;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx,
+                                       (char *)token_info.serialNumber,
+                                       sizeof(token_info.serialNumber));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_SERIAL;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    values[nattrs] = get_pkcs11_string(mem_ctx, (char *)token_info.label,
+                                       sizeof(token_info.label));
+    if (values[nattrs] != NULL && *values[nattrs] != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_TOKEN;
+        attrs[nattrs].value = values[nattrs];
+        nattrs++;
+    }
+
+    if (label != NULL && *label != '\0') {
+        attrs[nattrs].name = PK11URI_PATTR_OBJECT;
+        attrs[nattrs].value = label;
+        nattrs++;
+    }
+
+    attrs[nattrs].name = PK11URI_PATTR_TYPE;
+    attrs[nattrs].value = "cert";
+    nattrs++;
+
+    uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0);
+    if (uri == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "PK11URI_CreateURI failed.\n");
+        return NULL;
+    }
+
+    tmp_str = PK11URI_FormatURI(NULL, uri);
+    PK11URI_DestroyURI(uri);
+    if (tmp_str == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "PK11URI_FormatURI failed.\n");
+        return NULL;
+    }
+
+    /* Currently I have no idea how to get the ID properly formatted with the
+     * NSS  PK11 calls. Since all attribute values are treated as strings zeros
+     * in the IDs cannot be handled. And the IDs cannot be set percent-encoded
+     * since all attribute values will be escaped which means the '%' sign
+     * will be escaped to '%25'. Hence for the time being the ID is added
+     * manually to the end of the URI. */
+    id_pct = get_key_id_pct(mem_ctx, slot, cert);
+    if (id_pct == NULL || *id_pct == '\0') {
+        DEBUG(SSSDBG_OP_FAILURE, "get_key_id_pct failed.\n");
+        PORT_Free(tmp_str);
+        return NULL;
+    }
+
+    uri_str = talloc_asprintf(mem_ctx, "%s;%s=%s", tmp_str,
+                                                   PK11URI_PATTR_ID, id_pct);
+    talloc_free(id_pct);
+    if (uri_str == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
+        return NULL;
+    }
+
+    return uri_str;
+
+}
+
 static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
 {
   /* give up if 1) no password was supplied, or 2) the password has already
@@ -465,6 +699,9 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
               cert_list_node->cert->nickname,
               cert_list_node->cert->subjectName);
 
+        DEBUG(SSSDBG_TRACE_ALL, "module uri: %s.\n", PK11_GetModuleURI(module));
+        DEBUG(SSSDBG_TRACE_ALL, "token uri: %s.\n", PK11_GetTokenURI(slot));
+
         if (p11_ctx->handle != NULL) {
             if (!do_verification(p11_ctx, cert_list_node->cert)) {
                 DEBUG(SSSDBG_OP_FAILURE,
@@ -651,6 +888,9 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
 
         DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n",
               key_id_str);
+        DEBUG(SSSDBG_TRACE_ALL, "uri: %s.\n", get_pkcs11_uri(mem_ctx, module,
+                                                             slot, label,
+                                                             found_cert));
 
         multi = talloc_asprintf_append(multi, "%s\n%s\n%s\n%s\n%s\n",
                                        token_name, module_name, key_id_str,
diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index d4572d99cd3a3186128b46cc4a9453d716bd7979..09edeefbdf95e151af97cd4b4e5811569386caec 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -29,6 +29,7 @@
 #include <openssl/err.h>
 #include <openssl/rand.h>
 #include <p11-kit/p11-kit.h>
+#include <p11-kit/uri.h>
 
 #include <popt.h>
 
@@ -43,6 +44,72 @@ struct p11_ctx {
     bool wait_for_card;
 };
 
+
+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,
+                            CK_ATTRIBUTE *id)
+{
+    P11KitUri *uri;
+    char *uri_str = NULL;
+    char *tmp_str = NULL;
+    int ret;
+    CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
+    CK_ATTRIBUTE class_attr = {CKA_CLASS, &cert_class, sizeof(CK_OBJECT_CLASS)};
+
+    uri = p11_kit_uri_new();
+    if (uri == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_uri_new failed.\n");
+        return NULL;
+    }
+
+    ret = p11_kit_uri_set_attribute(uri, label);
+    if (ret != P11_KIT_URI_OK) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_uri_set_attribute failed.\n");
+        goto done;
+    }
+
+    ret = p11_kit_uri_set_attribute(uri, id);
+    if (ret != P11_KIT_URI_OK) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_uri_set_attribute failed.\n");
+        goto done;
+    }
+
+    ret = p11_kit_uri_set_attribute(uri, &class_attr);
+    if (ret != P11_KIT_URI_OK) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_uri_set_attribute failed.\n");
+        goto done;
+    }
+
+
+    memcpy(p11_kit_uri_get_token_info(uri), token_info, sizeof(CK_TOKEN_INFO));
+
+    memcpy(p11_kit_uri_get_slot_info(uri), slot_info, sizeof(CK_SLOT_INFO));
+    ret = p11_kit_uri_set_slot_id(uri, slot_id);
+
+    memcpy(p11_kit_uri_get_module_info(uri), module_info, sizeof(CK_INFO));
+
+    ret = p11_kit_uri_format(uri, P11_KIT_URI_FOR_ANY, &tmp_str);
+    if (ret != P11_KIT_URI_OK) {
+        DEBUG(SSSDBG_OP_FAILURE, "p11_kit_uri_format failed [%s].\n",
+                                 p11_kit_uri_message(ret));
+        goto done;
+    }
+
+    if (tmp_str != NULL) {
+        uri_str = talloc_strdup(mem_ctx, tmp_str);
+        free(tmp_str);
+        if (uri_str == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+        }
+    }
+
+done:
+    p11_kit_uri_free(uri);
+
+    return uri_str;
+}
+
 static int talloc_cleanup_openssl(struct p11_ctx *p11_ctx)
 {
     CRYPTO_cleanup_all_ex_data();
@@ -234,6 +301,7 @@ struct cert_list {
     X509 *cert;
     char *subject_dn;
     char *cert_b64;
+    char *uri;
     CK_KEY_TYPE key_type;
     CK_OBJECT_HANDLE private_key;
 };
@@ -608,6 +676,7 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
     CK_SLOT_ID slot_id;
     CK_SLOT_INFO info;
     CK_TOKEN_INFO token_info;
+    CK_INFO module_info;
     CK_RV rv;
     size_t module_id;
     char *module_file_name = NULL;
@@ -821,6 +890,17 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
         }
     }
 
+    memset(&module_info, 0, sizeof(CK_INFO));
+    module->C_GetInfo(&module_info);
+
+    DLIST_FOR_EACH(item, cert_list) {
+        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);
+    }
+
     /* TODO: check module_name_in, token_name_in, key_id_in */
 
     if (cert_list == NULL) {
-- 
2.14.4