Blob Blame History Raw
diff --git a/lib/pki/tdcache.c b/lib/pki/tdcache.c
--- a/lib/pki/tdcache.c
+++ b/lib/pki/tdcache.c
@@ -379,23 +379,29 @@ nssTrustDomain_UnlockCertCache (
 
 struct token_cert_dtor {
     NSSToken *token;
     nssTDCertificateCache *cache;
     NSSCertificate **certs;
     PRUint32 numCerts, arrSize;
 };
 
+static void cert_iter(const void *k, void *v, void *a)
+{
+    nssList *certList = (nssList *)a;
+    NSSCertificate *c = (NSSCertificate *)k;
+    nssList_Add(certList, nssCertificate_AddRef(c));
+}
+
 static void 
-remove_token_certs(const void *k, void *v, void *a)
+remove_token_certs(NSSCertificate *c, struct token_cert_dtor *dtor) 
 {
-    NSSCertificate *c = (NSSCertificate *)k;
     nssPKIObject *object = &c->object;
-    struct token_cert_dtor *dtor = a;
     PRUint32 i;
+
     nssPKIObject_AddRef(object);
     nssPKIObject_Lock(object);
     for (i=0; i<object->numInstances; i++) {
 	if (object->instances[i]->token == dtor->token) {
 	    nssCryptokiObject_Destroy(object->instances[i]);
 	    object->instances[i] = object->instances[object->numInstances-1];
 	    object->instances[object->numInstances-1] = NULL;
 	    object->numInstances--;
@@ -422,45 +428,83 @@ NSS_IMPLEMENT PRStatus
 nssTrustDomain_RemoveTokenCertsFromCache (
   NSSTrustDomain *td,
   NSSToken *token
 )
 {
     NSSCertificate **certs;
     PRUint32 i, arrSize = 10;
     struct token_cert_dtor dtor;
+    nssList *certList;
+    PRStatus nspr_rv = PR_FAILURE;
+    nssListIterator *iter;
+    NSSCertificate *c;
+
     certs = nss_ZNEWARRAY(NULL, NSSCertificate *, arrSize);
     if (!certs) {
 	return PR_FAILURE;
     }
     dtor.cache = td->cache;
     dtor.token = token;
     dtor.certs = certs;
     dtor.numCerts = 0;
     dtor.arrSize = arrSize;
+
+    certList = nssList_Create(NULL, PR_FALSE);
+    if (!certList) {
+	goto loser;
+    }
+    /* fetch the list of certs in the cache */
     PZ_Lock(td->cache->lock);
-    nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, &dtor);
+    nssHash_Iterate(td->cache->issuerAndSN, cert_iter, (void *)certList);
+    PZ_Unlock(td->cache->lock);
+
+    /* find the certs that match this token without olding the td cache lock */
+    iter=nssList_CreateIterator(certList);
+    if (!iter) {
+	goto loser;
+    }
+    for (c  = (NSSCertificate *)nssListIterator_Start(iter);
+	 c != (NSSCertificate *)NULL;
+	 c  = (NSSCertificate *)nssListIterator_Next(iter)) {
+	remove_token_certs( c, &dtor);
+    }
+    nssListIterator_Finish(iter);
+    nssListIterator_Destroy(iter);
+    nssList_Destroy(certList);
+    certList = NULL;
+
+    /* now remove theose certs attached to this token */
+    PZ_Lock(td->cache->lock);
     for (i=0; i<dtor.numCerts; i++) {
 	if (dtor.certs[i]->object.numInstances == 0) {
 	    nssTrustDomain_RemoveCertFromCacheLOCKED(td, dtor.certs[i]);
 	    dtor.certs[i] = NULL;  /* skip this cert in the second for loop */
 	} else {
 	    /* make sure it doesn't disappear on us before we finish */
 	    nssCertificate_AddRef(dtor.certs[i]);
 	}
     }
     PZ_Unlock(td->cache->lock);
+
+    /* clean up */
     for (i=0; i<dtor.numCerts; i++) {
 	if (dtor.certs[i]) {
 	    STAN_ForceCERTCertificateUpdate(dtor.certs[i]);
 	    nssCertificate_Destroy(dtor.certs[i]);
 	}
     }
+
+    nspr_rv = PR_SUCCESS;
+loser:
+    if (certList) {
+	nssList_Destroy(certList);
+    }
     nss_ZFreeIf(dtor.certs);
-    return PR_SUCCESS;
+    return nspr_rv;
 }
 
 NSS_IMPLEMENT PRStatus
 nssTrustDomain_UpdateCachedTokenCerts (
   NSSTrustDomain *td,
   NSSToken *token
 )
 {
@@ -1073,23 +1117,16 @@ nssTrustDomain_GetCertByDERFromCache (
 #endif
     rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, 
                                                            &issuer, &serial);
     PORT_Free(issuer.data);
     PORT_Free(serial.data);
     return rvCert;
 }
 
-static void cert_iter(const void *k, void *v, void *a)
-{
-    nssList *certList = (nssList *)a;
-    NSSCertificate *c = (NSSCertificate *)k;
-    nssList_Add(certList, nssCertificate_AddRef(c));
-}
-
 NSS_EXTERN NSSCertificate **
 nssTrustDomain_GetCertsFromCache (
   NSSTrustDomain *td,
   nssList *certListOpt
 )
 {
     NSSCertificate **rvArray = NULL;
     nssList *certList;