diff options
-rw-r--r-- | security/nss/lib/pk11wrap/pk11cert.c | 36 | ||||
-rw-r--r-- | security/nss/lib/pki/tdcache.c | 50 |
2 files changed, 81 insertions, 5 deletions
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index d2b2cd578..a100caca3 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -3525,17 +3525,40 @@ PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey) return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID); } +/* argument type for listCertsCallback */ +typedef struct { + CERTCertList *list; + PK11SlotInfo *slot; +} ListCertsArg; + static SECStatus listCertsCallback(CERTCertificate* cert, void*arg) { - CERTCertList *list = (CERTCertList*)arg; + ListCertsArg *cdata = (ListCertsArg*)arg; char *nickname = NULL; + nssCryptokiObject *instance, **ci; + nssCryptokiObject **instances; + NSSCertificate *c = STAN_GetNSSCertificate(cert); - if (cert->nickname) { - nickname = PORT_ArenaStrdup(list->arena,cert->nickname); + instances = nssPKIObject_GetInstances(&c->object); + instance = NULL; + for (ci = instances; *ci; ci++) { + if ((*ci)->token->pk11slot == cdata->slot) { + instance = *ci; + break; + } + } + PORT_Assert(instance != NULL); + if (!instance) { + nssCryptokiObjectArray_Destroy(instances); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; } + nickname = STAN_GetCERTCertificateNameForInstance(cdata->list->arena, + c, instance); + nssCryptokiObjectArray_Destroy(instances); - return CERT_AddCertToListTailWithData(list, + return CERT_AddCertToListTailWithData(cdata->list, CERT_DupCertificate(cert),nickname); } @@ -3544,12 +3567,15 @@ PK11_ListCertsInSlot(PK11SlotInfo *slot) { SECStatus status; CERTCertList *certs; + ListCertsArg cdata; certs = CERT_NewCertList(); if(certs == NULL) return NULL; + cdata.list = certs; + cdata.slot = slot; status = PK11_TraverseCertsInSlot(slot, listCertsCallback, - (void*)certs); + &cdata); if( status != SECSuccess ) { CERT_DestroyCertList(certs); diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c index c9fd8012f..2428de046 100644 --- a/security/nss/lib/pki/tdcache.c +++ b/security/nss/lib/pki/tdcache.c @@ -715,6 +715,50 @@ add_email_entry ( extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE; +static void +remove_object_instances ( + nssPKIObject *object, + nssCryptokiObject **instances, + int numInstances +) +{ + int i; + + for (i = 0; i < numInstances; i++) { + nssPKIObject_RemoveInstanceForToken(object, instances[i]->token); + } +} + +static SECStatus +merge_object_instances ( + nssPKIObject *to, + nssPKIObject *from +) +{ + nssCryptokiObject **instances, **ci; + int i; + SECStatus rv = SECSuccess; + + instances = nssPKIObject_GetInstances(from); + if (instances == NULL) { + return SECFailure; + } + for (ci = instances, i = 0; *ci; ci++, i++) { + nssCryptokiObject *instance = nssCryptokiObject_Clone(*ci); + if (instance) { + if (nssPKIObject_AddInstance(to, instance) == SECSuccess) { + continue; + } + nssCryptokiObject_Destroy(instance); + } + remove_object_instances(to, instances, i); + rv = SECFailure; + break; + } + nssCryptokiObjectArray_Destroy(instances); + return rv; +} + static NSSCertificate * add_cert_to_cache ( NSSTrustDomain *td, @@ -743,6 +787,12 @@ add_cert_to_cache ( /* collision - somebody else already added the cert * to the cache before this thread got around to it. */ + /* merge the instances of the cert */ + if (merge_object_instances(&rvCert->object, &cert->object) + != SECSuccess) { + nssCertificate_Destroy(rvCert); + return NULL; + } nssCertificate_Destroy(cert); return rvCert; } |