82 lines
2.6 KiB
Diff
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
|
||
|
|