sssd/0050-p11_child-show-PKCS-11...

408 lines
14 KiB
Diff

From 46fd681a73ffef062cd027e7018e1a02d7a0a9df Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 8 Oct 2018 10:45:28 +0200
Subject: [PATCH 65/83] 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>
---
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 b2777d1..fff1f25 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 d4572d9..09edeef 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.9.5