From d931db919e85fda2bfc195403c81b873ca94c4d4 Mon Sep 17 00:00:00 2001 From: Sumit Bose 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 (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 #include #include +#include #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 #include #include +#include #include @@ -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