From ad070fca8d1aac32226d38fe84612e14bc8ecc2e Mon Sep 17 00:00:00 2001 From: Jan Vcelak Date: Mon, 13 Aug 2012 15:33:35 +0200 Subject: [PATCH] prefer key from authenticated slot, allow certificate name with token Resolves TLS failures in replication in 389 Directory Server introduced by recent Mozilla NSS backend fixes. --- ...p-nss-allow-certname-with-token-name.patch | 47 +++++++++++ openldap-nss-prefer-unlocked-key.patch | 81 +++++++++++++++++++ openldap.spec | 11 ++- 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 openldap-nss-allow-certname-with-token-name.patch create mode 100644 openldap-nss-prefer-unlocked-key.patch diff --git a/openldap-nss-allow-certname-with-token-name.patch b/openldap-nss-allow-certname-with-token-name.patch new file mode 100644 index 0000000..a75e84f --- /dev/null +++ b/openldap-nss-allow-certname-with-token-name.patch @@ -0,0 +1,47 @@ +Accept nss certificate name in the form of tokenname:certnickname + +Author: Rich Megginson +Upstream ITS: #7360 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index 5022efb..7377bb1 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -2102,6 +2102,22 @@ tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) + return 0; + } + ++/* returns true if the given string looks like ++ "tokenname" ":" "certnickname" ++ This is true if there is a ':' colon character ++ in the string and the colon is not the first ++ or the last character in the string ++*/ ++static int ++tlsm_is_tokenname_certnick( const char *certfile ) ++{ ++ if ( certfile ) { ++ const char *ptr = PL_strchr( certfile, ':' ); ++ return ptr && (ptr != certfile) && (*(ptr+1)); ++ } ++ return 0; ++} ++ + static int + tlsm_deferred_ctx_init( void *arg ) + { +@@ -2268,7 +2284,10 @@ tlsm_deferred_ctx_init( void *arg ) + } else { + char *tmp_certname; + +- if (ctx->tc_certdb_slot) { ++ if (tlsm_is_tokenname_certnick(lt->lt_certfile)) { ++ /* assume already in form tokenname:certnickname */ ++ tmp_certname = PL_strdup(lt->lt_certfile); ++ } else if (ctx->tc_certdb_slot) { + tmp_certname = PR_smprintf(TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile); + } else { + tmp_certname = PR_smprintf("%s", lt->lt_certfile); +-- +1.7.11.4 + diff --git a/openldap-nss-prefer-unlocked-key.patch b/openldap-nss-prefer-unlocked-key.patch new file mode 100644 index 0000000..89f0701 --- /dev/null +++ b/openldap-nss-prefer-unlocked-key.patch @@ -0,0 +1,81 @@ +MozNSS: prefer authenticated slot when getting private key + +Author: Jan Vcelak +Upstream ITS: #7359 + +diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c +index f37da06..5022efb 100644 +--- a/libraries/libldap/tls_m.c ++++ b/libraries/libldap/tls_m.c +@@ -901,7 +901,7 @@ tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx) + * capability the server would have to be started in foreground mode + * if using an encrypted key. + */ +- if ( ctx->tc_pin_file ) { ++ if ( ctx && ctx->tc_pin_file ) { + pwdstr = tlsm_get_pin_from_file( token_name, ctx ); + if (retry && pwdstr != NULL) + return NULL; +@@ -990,6 +990,38 @@ tlsm_cert_is_self_issued( CERTCertificate *cert ) + return is_self_issued; + } + ++/* ++ * The private key for used certificate can be already unlocked by other ++ * thread or library. Find the unlocked key if possible. ++ */ ++static SECKEYPrivateKey * ++tlsm_find_unlocked_key(tlsm_ctx *ctx, void *pin_arg) ++{ ++ SECKEYPrivateKey *result = NULL; ++ ++ PK11SlotList *slots = PK11_GetAllSlotsForCert(ctx->tc_certificate, NULL); ++ if (!slots) { ++ PRErrorCode errcode = PR_GetError(); ++ Debug(LDAP_DEBUG_ANY, ++ "TLS: cannot get all slots for certificate '%s' (error %d: %s)", ++ tlsm_ctx_subject_name(ctx), errcode, ++ PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT)); ++ return result; ++ } ++ ++ PK11SlotListElement *le; ++ for (le = slots->head; le && !result; le = le->next) { ++ PK11SlotInfo *slot = le->slot; ++ if (!PK11_IsLoggedIn(slot, NULL)) ++ continue; ++ ++ result = PK11_FindKeyByDERCert(slot, ctx->tc_certificate, pin_arg); ++ } ++ ++ PK11_FreeSlotList(slots); ++ return result; ++} ++ + static SECStatus + tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg, + PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only, +@@ -1303,7 +1335,19 @@ tlsm_ctx_load_private_key(tlsm_ctx *ctx) + + void *pin_arg = SSL_RevealPinArg(ctx->tc_model); + +- ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg); ++ SECKEYPrivateKey *unlocked_key = tlsm_find_unlocked_key(ctx, pin_arg); ++ Debug(LDAP_DEBUG_ANY, ++ "TLS: %s unlocked certificate for certificate '%s'.\n", ++ unlocked_key ? "found" : "no", tlsm_ctx_subject_name(ctx), 0); ++ ++ /* prefer unlocked key, then key from opened certdb, then any other */ ++ if (unlocked_key) ++ ctx->tc_private_key = unlocked_key; ++ else if (ctx->tc_certdb_slot) ++ ctx->tc_private_key = PK11_FindKeyByDERCert(ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg); ++ else ++ ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg); ++ + if (!ctx->tc_private_key) { + PRErrorCode errcode = PR_GetError(); + Debug(LDAP_DEBUG_ANY, +-- +1.7.11.4 + diff --git a/openldap.spec b/openldap.spec index 2c329cf..dc80c00 100644 --- a/openldap.spec +++ b/openldap.spec @@ -8,7 +8,7 @@ Name: openldap Version: 2.4.32 -Release: 1%{?dist} +Release: 2%{?dist} Summary: LDAP support libraries Group: System Environment/Daemons License: OpenLDAP @@ -40,6 +40,8 @@ Patch8: openldap-syncrepl-unset-tls-options.patch Patch9: openldap-constraint-count.patch Patch10: openldap-man-sasl-nocanon.patch Patch11: openldap-ai-addrconfig.patch +Patch12: openldap-nss-prefer-unlocked-key.patch +Patch13: openldap-nss-allow-certname-with-token-name.patch # Fedora specific patches Patch100: openldap-autoconf-pkgconfig-nss.patch @@ -153,6 +155,8 @@ ln -s %{_includedir}/nspr4 include/nspr %patch9 -p1 %patch10 -p1 %patch11 -p1 +%patch12 -p1 +%patch13 -p1 %patch101 -p1 @@ -610,6 +614,11 @@ exit 0 %{evolution_connector_prefix}/ %changelog +* Mon Aug 20 2012 Jan Vcelak 2.4.32-2 +- enhancement: TLS, prefer private keys from authenticated slots +- enhancement: TLS, allow certificate specification including token name +- resolve TLS failures in replication in 389 Directory Server + * Wed Aug 01 2012 Jan Vcelak 2.4.32-1 - new upstream release + library: double free, SASL handling