8080PRFileDesc * PR_ImportTCPSocket (PRInt32 osfd );
8181static PRLock * nss_initlock = NULL ;
8282static PRLock * nss_crllock = NULL ;
83+ static PRLock * nss_findslot_lock = NULL ;
8384static struct curl_llist * nss_crl_list = NULL ;
8485static NSSInitContext * nss_context = NULL ;
8586static volatile int initialized = 0 ;
@@ -338,6 +339,19 @@ static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
338339 return NULL ;
339340}
340341
342+ /* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
343+ * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
344+ * details, go to <https://bugzilla.mozilla.org/1297397>.
345+ */
346+ static PK11SlotInfo * nss_find_slot_by_name (const char * slot_name )
347+ {
348+ PK11SlotInfo * slot ;
349+ PR_Lock (nss_initlock );
350+ slot = PK11_FindSlotByName (slot_name );
351+ PR_Unlock (nss_initlock );
352+ return slot ;
353+ }
354+
341355/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
342356 * the call succeeds, append the object handle to the list of objects so that
343357 * the object can be destroyed in Curl_nss_close(). */
@@ -360,7 +374,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
360374 if (!slot_name )
361375 return CURLE_OUT_OF_MEMORY ;
362376
363- slot = PK11_FindSlotByName (slot_name );
377+ slot = nss_find_slot_by_name (slot_name );
364378 free (slot_name );
365379 if (!slot )
366380 return result ;
@@ -561,7 +575,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
561575 return result ;
562576 }
563577
564- slot = PK11_FindSlotByName ("PEM Token #1" );
578+ slot = nss_find_slot_by_name ("PEM Token #1" );
565579 if (!slot )
566580 return CURLE_SSL_CERTPROBLEM ;
567581
@@ -1011,7 +1025,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
10111025 struct CERTCertificateStr * cert ;
10121026 struct SECKEYPrivateKeyStr * key ;
10131027
1014- PK11SlotInfo * slot = PK11_FindSlotByName (pem_slotname );
1028+ PK11SlotInfo * slot = nss_find_slot_by_name (pem_slotname );
10151029 if (NULL == slot ) {
10161030 failf (data , "NSS: PK11 slot not found: %s" , pem_slotname );
10171031 return SECFailure ;
@@ -1247,6 +1261,7 @@ int Curl_nss_init(void)
12471261 PR_Init (PR_USER_THREAD , PR_PRIORITY_NORMAL , 256 );
12481262 nss_initlock = PR_NewLock ();
12491263 nss_crllock = PR_NewLock ();
1264+ nss_findslot_lock = PR_NewLock ();
12501265 }
12511266
12521267 /* We will actually initialize NSS later */
@@ -1301,6 +1316,7 @@ void Curl_nss_cleanup(void)
13011316
13021317 PR_DestroyLock (nss_initlock );
13031318 PR_DestroyLock (nss_crllock );
1319+ PR_DestroyLock (nss_findslot_lock );
13041320 nss_initlock = NULL ;
13051321
13061322 initialized = 0 ;
0 commit comments