From e2d11075405898c84e50e2a98788ac4614efd2c1 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Nov 20 2013 00:33:41 +0000 Subject: Ticket #47596 attrcrypt fails to find unlocked key https://fedorahosted.org/389/ticket/47596 Reviewed by: nkinder (Thanks!) Branch: 389-ds-base-1.3.0 Fix Description: There should always be a pre-authenticated slot/token that has the servers cert and key. Just loop through all of the slots that the server's cert is found on, and use the first one that is authenticated. Platforms tested: RHEL6 x86_64 Flag Day: no Doc impact: no (cherry picked from commit b1fad4e35c0f963bf4678a2ed9a068dbe4fb159c) (cherry picked from commit cf091de4ae70ad8d683ff33c57e75e58ff900502) (cherry picked from commit 92b46296c0b4ab9aa436ae09bca95832e2276c6e) --- diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c b/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c index f0ef692..e74e951 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c @@ -425,7 +425,7 @@ attrcrypt_fetch_private_key(SECKEYPrivateKey **private_key) LDAPDebug(LDAP_DEBUG_ANY,"Can't find certificate %s in attrcrypt_fetch_private_key: %d - %s\n", cert_name, errorCode, slapd_pr_strerror(errorCode)); } if( cert != NULL ) { - key = slapd_pk11_findKeyByAnyCert(cert, NULL); + key = slapd_get_unlocked_key_for_cert(cert, NULL); } if (key == NULL) { errorCode = PR_GetError(); diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index fd9724f..550e59c 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -1004,6 +1004,7 @@ int slapd_ssl_init2(PRFileDesc **fd, int startTLS); int slapd_security_library_is_initialized(); int slapd_ssl_listener_is_initialized(); int slapd_SSL_client_auth (LDAP* ld); +SECKEYPrivateKey *slapd_get_unlocked_key_for_cert(CERTCertificate *cert, void *pin_arg); /* * security_wrappers.c diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c index f515b8e..8b80acb 100644 --- a/ldap/servers/slapd/ssl.c +++ b/ldap/servers/slapd/ssl.c @@ -1577,3 +1577,61 @@ char* slapd_get_tmp_dir() #endif return ( tmpdir ); } + +SECKEYPrivateKey * +slapd_get_unlocked_key_for_cert(CERTCertificate *cert, void *pin_arg) +{ + SECKEYPrivateKey *key = NULL; + PK11SlotListElement *sle; + PK11SlotList *slotlist = PK11_GetAllSlotsForCert(cert, NULL); + const char *certsubject = cert->subjectName ? cert->subjectName : "unknown cert"; + + if (!slotlist) { + PRErrorCode errcode = PR_GetError(); + slapi_log_error(SLAPI_LOG_FATAL, "slapd_get_unlocked_key_for_cert", + "Error: cannot get slot list for certificate [%s] (%d: %s)\n", + certsubject, errcode, slapd_pr_strerror(errcode)); + return key; + } + + for (sle = slotlist->head; sle; sle = sle->next) { + PK11SlotInfo *slot = sle->slot; + const char *slotname = (slot && PK11_GetSlotName(slot)) ? PK11_GetSlotName(slot) : "unknown slot"; + const char *tokenname = (slot && PK11_GetTokenName(slot)) ? PK11_GetTokenName(slot) : "unknown token"; + if (!slot) { + slapi_log_error(SLAPI_LOG_TRACE, "slapd_get_unlocked_key_for_cert", + "Missing slot for slot list element for certificate [%s]\n", + certsubject); + } else if (PK11_IsLoggedIn(slot, pin_arg)) { + key = PK11_FindKeyByDERCert(slot, cert, pin_arg); + slapi_log_error(SLAPI_LOG_TRACE, "slapd_get_unlocked_key_for_cert", + "Found unlocked slot [%s] token [%s] for certificate [%s]\n", + slotname, tokenname, certsubject); + break; + } else { + slapi_log_error(SLAPI_LOG_TRACE, "slapd_get_unlocked_key_for_cert", + "Skipping locked slot [%s] token [%s] for certificate [%s]\n", + slotname, tokenname, certsubject); + } + } + + if (!key) { + slapi_log_error(SLAPI_LOG_FATAL, "slapd_get_unlocked_key_for_cert", + "Error: could not find any unlocked slots for certificate [%s]. " + "Please review your TLS/SSL configuration. The following slots were found:\n", + certsubject); + for (sle = slotlist->head; sle; sle = sle->next) { + PK11SlotInfo *slot = sle->slot; + const char *slotname = (slot && PK11_GetSlotName(slot)) ? PK11_GetSlotName(slot) : "unknown slot"; + const char *tokenname = (slot && PK11_GetTokenName(slot)) ? PK11_GetTokenName(slot) : "unknown token"; + slapi_log_error(SLAPI_LOG_FATAL, "slapd_get_unlocked_key_for_cert", + "Slot [%s] token [%s] was locked.\n", + slotname, tokenname); + } + + } + + PK11_FreeSlotList(slotlist); + return key; +} +