openldap/openldap-nss-prefer-unlocked-key.patch
Jan Vcelak ad070fca8d 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.
2012-08-20 20:34:34 +02:00

82 lines
2.6 KiB
Diff

MozNSS: prefer authenticated slot when getting private key
Author: Jan Vcelak <jvcelak@redhat.com>
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