diff options
author | ian.mcgreer%sun.com <devnull@localhost> | 2002-02-01 17:25:15 +0000 |
---|---|---|
committer | ian.mcgreer%sun.com <devnull@localhost> | 2002-02-01 17:25:15 +0000 |
commit | 033e2aa53ec68924ec4dfcaf553ee4e0ab3ab7cd (patch) | |
tree | 6d9e0b85dd73b5b78e9e006eaa63e348ab39a828 | |
parent | c0fe98b2a7598c4335d391aef8980e2e2ce64359 (diff) | |
download | nss-hg-033e2aa53ec68924ec4dfcaf553ee4e0ab3ab7cd.tar.gz |
bug 121628, persistent cache of hardware token certs
-rw-r--r-- | security/nss/lib/dev/dev.h | 12 | ||||
-rw-r--r-- | security/nss/lib/dev/devobject.c | 17 | ||||
-rw-r--r-- | security/nss/lib/dev/devt.h | 1 | ||||
-rw-r--r-- | security/nss/lib/dev/devtoken.c | 57 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/dev3hack.c | 18 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/dev3hack.h | 5 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11cert.c | 504 | ||||
-rw-r--r-- | security/nss/lib/pki/certificate.c | 45 | ||||
-rw-r--r-- | security/nss/lib/pki/pki3hack.c | 112 | ||||
-rw-r--r-- | security/nss/lib/pki/pki3hack.h | 16 | ||||
-rw-r--r-- | security/nss/lib/pki/pkim.h | 8 | ||||
-rw-r--r-- | security/nss/lib/pki/trustdomain.c | 59 |
12 files changed, 744 insertions, 110 deletions
diff --git a/security/nss/lib/dev/dev.h b/security/nss/lib/dev/dev.h index 7290a82f9..e25d5bb28 100644 --- a/security/nss/lib/dev/dev.h +++ b/security/nss/lib/dev/dev.h @@ -158,6 +158,12 @@ nssSlot_Destroy NSSSlot *slot ); +NSS_EXTERN PRStatus +nssSlot_Refresh +( + NSSSlot *slot +); + NSS_EXTERN NSSSlot * nssSlot_AddRef ( @@ -232,6 +238,12 @@ nssToken_Destroy NSSToken *tok ); +NSS_EXTERN PRBool +nssToken_IsPresent +( + NSSToken *token +); + NSS_EXTERN NSSToken * nssToken_AddRef ( diff --git a/security/nss/lib/dev/devobject.c b/security/nss/lib/dev/devobject.c index 5a772e125..04e0b3b6f 100644 --- a/security/nss/lib/dev/devobject.c +++ b/security/nss/lib/dev/devobject.c @@ -462,12 +462,13 @@ static PRStatus retrieve_cert(NSSToken *t, nssSession *session, CK_OBJECT_HANDLE h, void *arg) { PRStatus nssrv; - PRBool found; + PRBool found, inCache; nssTokenCertSearch *search = (nssTokenCertSearch *)arg; NSSCertificate *cert = NULL; nssListIterator *instances; nssCryptokiInstance *ci; CK_ATTRIBUTE derValue = { CKA_VALUE, NULL, 0 }; + inCache = PR_FALSE; if (search->cached) { NSSCertificate csi; /* a fake cert for indexing */ nssrv = nssCKObject_GetAttributes(h, &derValue, 1, @@ -478,13 +479,19 @@ retrieve_cert(NSSToken *t, nssSession *session, CK_OBJECT_HANDLE h, void *arg) } found = PR_FALSE; if (cert) { + inCache = PR_TRUE; nssCertificate_AddRef(cert); instances = cert->object.instances; for (ci = (nssCryptokiInstance *)nssListIterator_Start(instances); ci != (nssCryptokiInstance *)NULL; ci = (nssCryptokiInstance *)nssListIterator_Next(instances)) { - if (ci->handle == h && ci->token == t) { + /* The builtins token will not return the same handle for objects + * during the lifetime of the token. Thus, assuming the found + * object is the same as the cached object if there is already an + * instance for the token. + */ + if (ci->token == t) { found = PR_TRUE; break; } @@ -509,7 +516,11 @@ retrieve_cert(NSSToken *t, nssSession *session, CK_OBJECT_HANDLE h, void *arg) nssListIterator_Destroy(cert->object.instances); cert->object.instances = nssList_CreateIterator(cert->object.instanceList); } - nssrv = (*search->callback)(cert, search->cbarg); + if (!inCache) { + nssrv = (*search->callback)(cert, search->cbarg); + } else { + nssrv = PR_SUCCESS; /* cached entries already handled */ + } NSSCertificate_Destroy(cert); return nssrv; } diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h index 2c364bdbf..cc681f9c2 100644 --- a/security/nss/lib/dev/devt.h +++ b/security/nss/lib/dev/devt.h @@ -133,6 +133,7 @@ struct NSSTokenStr NSSTrustDomain *trustDomain; #ifdef NSS_3_4_CODE PK11SlotInfo *pk11slot; + nssList *certList; /* local cache of certs for slow tokens */ #endif }; diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c index 5b5c4b320..13444ca8e 100644 --- a/security/nss/lib/dev/devtoken.c +++ b/security/nss/lib/dev/devtoken.c @@ -196,6 +196,63 @@ nssToken_GetName return tok->name; } +NSS_IMPLEMENT PRBool +nssToken_IsPresent +( + NSSToken *token +) +{ + CK_RV ckrv; + PRStatus nssrv; + nssSession *session; + CK_SLOT_INFO slotInfo; + NSSSlot *slot = token->slot; + session = token->defaultSession; + nssSession_EnterMonitor(session); + /* First obtain the slot info */ + ckrv = CKAPI(slot)->C_GetSlotInfo(slot->slotID, &slotInfo); + if (ckrv != CKR_OK) { + nssSession_ExitMonitor(session); + return PR_FALSE; + } + slot->ckFlags = slotInfo.flags; + /* check for the presence of the token */ + if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { + /* token is not present */ + if (session->handle != CK_INVALID_SESSION) { + /* session is valid, close and invalidate it */ + CKAPI(slot)->C_CloseSession(session->handle); + session->handle = CK_INVALID_SESSION; + } + nssSession_ExitMonitor(session); + return PR_FALSE; + } + /* token is present, use the session info to determine if the card + * has been removed and reinserted. + */ + if (session != CK_INVALID_SESSION) { + CK_SESSION_INFO sessionInfo; + ckrv = CKAPI(slot)->C_GetSessionInfo(session->handle, &sessionInfo); + if (ckrv != CKR_OK) { + /* session is screwy, close and invalidate it */ + CKAPI(slot)->C_CloseSession(session->handle); + session->handle = CK_INVALID_SESSION; + } + } + nssSession_ExitMonitor(session); + /* token not removed, finished */ + if (session->handle != CK_INVALID_SESSION) { + return PR_TRUE; + } else { + /* token has been removed, need to refresh with new session */ + nssrv = nssSlot_Refresh(slot); + if (nssrv != PR_SUCCESS) { + return PR_FALSE; + } + return PR_TRUE; + } +} + NSS_IMPLEMENT NSSItem * nssToken_Digest ( diff --git a/security/nss/lib/pk11wrap/dev3hack.c b/security/nss/lib/pk11wrap/dev3hack.c index cbcd468e5..bc2ad6b61 100644 --- a/security/nss/lib/pk11wrap/dev3hack.c +++ b/security/nss/lib/pk11wrap/dev3hack.c @@ -154,6 +154,24 @@ nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) return rvToken; } +NSS_IMPLEMENT PRStatus +nssSlot_Refresh +( + NSSSlot *slot +) +{ + PK11SlotInfo *nss3slot = slot->pk11slot; + if (PK11_InitToken(nss3slot, PR_FALSE) != SECSuccess) { + return PR_FAILURE; + } + slot->token->defaultSession = nssSession_ImportNSS3Session(slot->arena, + nss3slot->session, + nss3slot->sessionLock, + nss3slot->defRWSession); + nssToken_DestroyCertList(slot->token); + return nssToken_LoadCerts(slot->token); +} + NSSTrustDomain * nssToken_GetTrustDomain(NSSToken *token) diff --git a/security/nss/lib/pk11wrap/dev3hack.h b/security/nss/lib/pk11wrap/dev3hack.h index 2ae362a15..3b8f1abf8 100644 --- a/security/nss/lib/pk11wrap/dev3hack.h +++ b/security/nss/lib/pk11wrap/dev3hack.h @@ -52,6 +52,11 @@ void PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst); NSSToken * PK11Slot_GetNSSToken(PK11SlotInfo *sl); +NSS_EXTERN void +nssToken_DestroyCertList(NSSToken *token); + +NSS_IMPLEMENT PRStatus +nssToken_LoadCerts(NSSToken *token); PR_END_EXTERN_C diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index 525fb2e05..37b1e1324 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -745,7 +745,12 @@ PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx) pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx); if (privKey) { +#ifdef NSS_CLASSIC PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID); +#else + /* For 3.4, utilize the generic cert delete function */ + SEC_DeletePermCertificate(cert); +#endif PK11_DeleteTokenPrivateKey(privKey); } if ((pubKey != CK_INVALID_HANDLE) && (slot != NULL)) { @@ -999,12 +1004,25 @@ pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), return SECSuccess; } +struct fake_der_cb_argstr +{ + SECStatus(* callback)(CERTCertificate*, SECItem *, void *); + void *arg; +}; + +static PRStatus fake_der_cb(CERTCertificate *c, void *a) +{ + struct fake_der_cb_argstr *fda = (struct fake_der_cb_argstr *)a; + return (*fda->callback)(c, &c->derCert, fda->arg); +} + /* * Extract all the certs on a card from a slot. */ SECStatus PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), void *arg, void *wincx) { +#ifdef NSS_CLASSIC pk11DoCertCallback caller; pk11TraverseSlot creater; CK_ATTRIBUTE theTemplate; @@ -1022,6 +1040,17 @@ PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), creater.templateCount = 1; return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx); +#else + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); + struct fake_der_cb_argstr fda; + struct nss3_cert_cbstr pk11cb; + fda.callback = callback; + fda.arg = arg; + pk11cb.callback = fake_der_cb; + pk11cb.arg = &fda; + NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb); + return SECSuccess; +#endif } /* @@ -1181,7 +1210,106 @@ get_newest_cert(NSSCertificate *c, void *arg) return PR_SUCCESS; } - +struct token_cbstr { + NSSToken *token; + PRStatus (* callback)(NSSCertificate *c, void *arg); + void *cbarg; +}; + +/* This callback matches all certs on a given token. It is used to filter + * cert lists to only those certs on a particular token. + */ +static PRStatus +token_callback(NSSCertificate *c, void *arg) +{ + nssListIterator *instances; + nssCryptokiInstance *instance; + PRBool isToken = PR_FALSE; + struct token_cbstr *token_cb = (struct token_cbstr *)arg; + instances = c->object.instances; + for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); + instance != (nssCryptokiInstance *)NULL; + instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) + { + if (instance->token == token_cb->token) { + isToken = PR_TRUE; + break; + } + } + nssListIterator_Finish(instances); + if (isToken) { + return (*token_cb->callback)(c, token_cb->cbarg); + } else { + return PR_SUCCESS; + } +} + +/* match all token certs with a nickname */ +static nssList * +filter_token_certs_nickname(NSSToken *token, NSSUTF8 *nickname) +{ + nssListIterator *certs; + NSSCertificate *cert; + PRStatus nssrv; + nssList *rvList; + certs = nssList_CreateIterator(token->certList); + if (!certs) return NULL; + rvList = nssList_Create(NULL, PR_FALSE); + if (!rvList) { + nssListIterator_Destroy(certs); + return NULL; + } + for (cert = (NSSCertificate *)nssListIterator_Start(certs); + cert != (NSSCertificate *)NULL; + cert = (NSSCertificate *)nssListIterator_Next(certs)) + { + if (!cert->nickname) continue; + if (nssUTF8_Equal(cert->nickname, nickname, &nssrv)) { + nssList_Add(rvList, nssCertificate_AddRef(cert)); + } + } + nssListIterator_Finish(certs); + nssListIterator_Destroy(certs); + if (nssList_Count(rvList) == 0) { + nssList_Destroy(rvList); + rvList = NULL; + } + return rvList; +} + +/* match all token certs with an email address */ +static nssList * +filter_token_certs_email(NSSToken *token, NSSASCII7 *email) +{ + nssListIterator *certs; + NSSCertificate *cert; + PRStatus nssrv; + nssList *rvList; + certs = nssList_CreateIterator(token->certList); + if (!certs) return NULL; + rvList = nssList_Create(NULL, PR_FALSE); + if (!rvList) { + nssListIterator_Destroy(certs); + return NULL; + } + for (cert = (NSSCertificate *)nssListIterator_Start(certs); + cert != (NSSCertificate *)NULL; + cert = (NSSCertificate *)nssListIterator_Next(certs)) + { + if (!cert->email) continue; + if (nssUTF8_Equal(cert->email, email, &nssrv)) { + nssList_Add(rvList, nssCertificate_AddRef(cert)); + } + } + nssListIterator_Finish(certs); + nssListIterator_Destroy(certs); + if (nssList_Count(rvList) == 0) { + nssList_Destroy(rvList); + rvList = NULL; + } + return rvList; +} + CERTCertificate * PK11_FindCertFromNickname(char *nickname, void *wincx) { #ifdef NSS_CLASSIC @@ -1202,12 +1330,14 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { NSSUsage usage; NSSToken *token; PK11SlotInfo *slot = NULL; + char *nickCopy; char *delimit = NULL; char *tokenName; NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); usage.anyUsage = PR_TRUE; - if ((delimit = PORT_Strchr(nickname,':')) != NULL) { - tokenName = nickname; + nickCopy = PORT_Strdup(nickname); + if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) { + tokenName = nickCopy; nickname = delimit + 1; *delimit = '\0'; /* find token by name */ @@ -1220,6 +1350,7 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { } if (token) { nssTokenCertSearch search; + struct token_cbstr token_cb; nssList *certList; if (!PK11_IsFriendly(slot)) { if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) { @@ -1227,33 +1358,77 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { return NULL; } } - certList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - certList); - /* set the search criteria */ - search.callback = get_newest_cert; - search.cbarg = (void *)&cert; - search.cached = certList; - search.searchType = nssTokenSearchType_TokenOnly; /* find best cert on token */ - nssToken_TraverseCertificatesByNickname(token, NULL, - (NSSUTF8 *)nickname, - &search); - nssList_Clear(certList, cert_destructor); - nssList_Destroy(certList); - if (!cert) { + if (!nssToken_SearchCerts(token)) { + /* token certs are in cache, filter the list of token certs to + * match the nickname + */ + certList = filter_token_certs_nickname(token, nickname); + if (certList) { + nssCertificateList_DoCallback(certList, + get_newest_cert, + (void *)&cert); + } + } else { + /* find matching certs on the token */ certList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, - nickname, - certList); + if (!certList) return NULL; + /* first, get all matching certs from the cache */ + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + nickname, + certList); + /* set the search criteria */ + token_cb.callback = get_newest_cert; + token_cb.cbarg = (void *)&cert; + token_cb.token = token; + search.callback = token_callback; + search.cbarg = &token_cb; search.cached = certList; - nssToken_TraverseCertificatesByEmail(token, NULL, - (NSSASCII7 *)nickname, - &search); + search.searchType = nssTokenSearchType_TokenOnly; + /* then filter the list of cached certs for only those on the + * token + */ + nssCertificateList_DoCallback(certList, + token_callback, + &token_cb); + /* now search the token */ + nssToken_TraverseCertificatesByNickname(token, NULL, + (NSSUTF8 *)nickname, + &search); + } + if (certList) { nssList_Clear(certList, cert_destructor); nssList_Destroy(certList); } + /* if it wasn't found, repeat the process for email address */ + if (!cert) { + if (!nssToken_SearchCerts(token)) { + certList = filter_token_certs_email(token, nickname); + if (certList) { + nssCertificateList_DoCallback(certList, + get_newest_cert, + (void *)&cert); + } + } else { + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) return NULL; + (void)nssTrustDomain_GetCertsForEmailAddressFromCache( + defaultTD, + nickname, + certList); + search.cached = certList; + nssCertificateList_DoCallback(certList, + token_callback, + &token_cb); + nssToken_TraverseCertificatesByEmail(token, NULL, + (NSSASCII7 *)nickname, + &search); + } + if (certList) { + nssList_Clear(certList, cert_destructor); + nssList_Destroy(certList); + } + } if (cert) { (void)nssTrustDomain_AddCertsToCache(defaultTD, &cert, 1); rvCert = STAN_GetCERTCertificate(cert); @@ -1262,6 +1437,7 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { if (slot) { PK11_FreeSlot(slot); } + if (nickCopy) PORT_Free(nickCopy); return rvCert; #endif } @@ -1306,6 +1482,7 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { return certList; #else PRStatus nssrv; + char *nickCopy; char *delimit = NULL; char *tokenName; int i; @@ -1315,8 +1492,9 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { NSSCertificate *c; NSSToken *token; PK11SlotInfo *slot; - if ((delimit = PORT_Strchr(nickname,':')) != NULL) { - tokenName = nickname; + nickCopy = PORT_Strdup(nickname); + if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) { + tokenName = nickCopy; nickname = delimit + 1; *delimit = '\0'; /* find token by name */ @@ -1337,25 +1515,33 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { return NULL; } } - nameList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - nameList); - /* set the search criteria */ - search.callback = collect_certs; - search.cbarg = nameList; - search.cached = nameList; - search.searchType = nssTokenSearchType_TokenOnly; - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - nickname, &search); - count = nssList_Count(nameList); - foundCerts = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); - nssList_GetArray(nameList, (void **)foundCerts, count); - nssList_Destroy(nameList); + if (!nssToken_SearchCerts(token)) { + nameList = filter_token_certs_nickname(token, nickname); + } else { + nameList = nssList_Create(NULL, PR_FALSE); + if (!nameList) return NULL; + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + nickname, + nameList); + /* set the search criteria */ + search.callback = collect_certs; + search.cbarg = nameList; + search.cached = nameList; + search.searchType = nssTokenSearchType_TokenOnly; + nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, + nickname, &search); + } + if (nameList) { + count = nssList_Count(nameList); + foundCerts = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); + nssList_GetArray(nameList, (void **)foundCerts, count); + nssList_Destroy(nameList); + } } if (slot) { PK11_FreeSlot(slot); } + if (nickCopy) PORT_Free(nickCopy); if (foundCerts) { certList = CERT_NewCertList(); for (i=0, c = *foundCerts; c; c = foundCerts[++i]) { @@ -1504,6 +1690,7 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, CK_RV crv; SECCertUsage *certUsage = NULL; SECItem derSerial = { 0 }; + NSSToken *token; if (keyID == NULL) { PORT_SetError(SEC_ERROR_ADDING_CERT); @@ -1604,6 +1791,16 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, cert->nssCertificate = STAN_GetNSSCertificate(cert); } } + cert->trust = nssTrust_GetCERTCertTrustForCert(cert->nssCertificate, cert); + token = PK11Slot_GetNSSToken(slot); + if (token->certList) { + /* create a persistent reference for the token */ + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); + nssCertificate_AddRef(cert->nssCertificate); + nssList_Add(token->certList, cert->nssCertificate); + /* and add the cert to the cache */ + nssTrustDomain_AddCertsToCache(td, &cert->nssCertificate, 1); + } done: if (derSerial.data) PORT_Free(derSerial.data); @@ -2368,6 +2565,72 @@ PK11_TraverseCertsForSubject(CERTCertificate *cert, return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); } +/* Find all certs with a given subject in the list of token certs */ +static nssList * +filter_token_certs_subject(NSSToken *token, NSSDER *subject) +{ + nssListIterator *certs; + NSSCertificate *cert; + PRStatus nssrv; + nssList *rvList; + certs = nssList_CreateIterator(token->certList); + if (!certs) return NULL; + rvList = nssList_Create(NULL, PR_FALSE); + if (!rvList) { + nssListIterator_Destroy(certs); + return NULL; + } + for (cert = (NSSCertificate *)nssListIterator_Start(certs); + cert != (NSSCertificate *)NULL; + cert = (NSSCertificate *)nssListIterator_Next(certs)) + { + if (nssItem_Equal(&cert->subject, subject, &nssrv)) { + nssList_Add(rvList, nssCertificate_AddRef(cert)); + } + } + nssListIterator_Finish(certs); + nssListIterator_Destroy(certs); + if (nssList_Count(rvList) == 0) { + nssList_Destroy(rvList); + rvList = NULL; + } + return rvList; +} + +/* remove all certs in a list that are not on the given token */ +static void +filter_list_for_token_certs(nssList *certList, NSSToken *token) +{ + nssListIterator *instances, *certs; + nssCryptokiInstance *instance; + NSSCertificate *c; + PRBool isToken = PR_FALSE; + certs = nssList_CreateIterator(certList); + if (!certs) return; + for (c = (NSSCertificate *)nssListIterator_Start(certs); + c != (NSSCertificate *)NULL; + c = (NSSCertificate *)nssListIterator_Next(certs)) { + instances = c->object.instances; + for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances); + instance != (nssCryptokiInstance *)NULL; + instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) + { + if (instance->token == token) { + isToken = PR_TRUE; + break; + } + } + nssListIterator_Finish(instances); + if (!isToken) { + /* safe since iterator is copied */ + nssList_Remove(certList, c); + NSSCertificate_Destroy(c); + } + } + nssListIterator_Finish(certs); + nssListIterator_Destroy(certs); +} + SECStatus PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, SECStatus(* callback)(CERTCertificate*, void *), void *arg) @@ -2401,7 +2664,7 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, return PK11_TraverseSlot(slot, &callarg); #else struct nss3_cert_cbstr pk11cb; - PRStatus nssrv; + PRStatus nssrv = PR_SUCCESS; NSSToken *token; NSSDER subject; NSSTrustDomain *td; @@ -2411,19 +2674,38 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, pk11cb.arg = arg; td = STAN_GetDefaultTrustDomain(); NSSITEM_FROM_SECITEM(&subject, &cert->derSubject); - subjectList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, subjectList); - /* set the search criteria */ - search.callback = convert_and_cache_cert; - search.cbarg = &pk11cb; - search.cached = subjectList; - search.searchType = nssTokenSearchType_TokenOnly; - pk11cb.cached = subjectList; token = PK11Slot_GetNSSToken(slot); - nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, - &subject, &search); - nssList_Clear(subjectList, cert_destructor); - nssList_Destroy(subjectList); + if (!nssToken_SearchCerts(token)) { + subjectList = filter_token_certs_subject(token, &subject); + if (subjectList) { + nssrv = nssCertificateList_DoCallback(subjectList, + convert_cert, &pk11cb); + } + } else { + subjectList = nssList_Create(NULL, PR_FALSE); + if (!subjectList) { + return SECFailure; + } + (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, + subjectList); + filter_list_for_token_certs(subjectList, token); + /* set the search criteria */ + search.callback = convert_and_cache_cert; + search.cbarg = &pk11cb; + search.cached = subjectList; + search.searchType = nssTokenSearchType_TokenOnly; + pk11cb.cached = subjectList; + nssrv = nssCertificateList_DoCallback(subjectList, + convert_cert, &pk11cb); + if (nssrv == PR_SUCCESS) { + nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, + &subject, &search); + } + } + if (subjectList) { + nssList_Clear(subjectList, cert_destructor); + nssList_Destroy(subjectList); + } return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; #endif } @@ -2466,7 +2748,7 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, return PK11_TraverseSlot(slot, &callarg); #else struct nss3_cert_cbstr pk11cb; - PRStatus nssrv; + PRStatus nssrv = PR_SUCCESS; NSSToken *token; NSSTrustDomain *td; NSSUTF8 *nick; @@ -2477,25 +2759,40 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, pk11cb.arg = arg; if (nickname->data[nickname->len-1] != '\0') { nick = nssUTF8_Create(NULL, nssStringType_UTF8String, - nickname->data, nickname->len-1); + nickname->data, nickname->len); created = PR_TRUE; } else { nick = (NSSUTF8 *)nickname->data; } td = STAN_GetDefaultTrustDomain(); - nameList = nssList_Create(NULL, PR_FALSE); - (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); - /* set the search criteria */ - search.callback = convert_and_cache_cert; - search.cbarg = &pk11cb; - search.cached = nameList; - search.searchType = nssTokenSearchType_TokenOnly; - pk11cb.cached = nameList; token = PK11Slot_GetNSSToken(slot); - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - nick, &search); - nssList_Clear(nameList, cert_destructor); - nssList_Destroy(nameList); + if (!nssToken_SearchCerts(token)) { + nameList = filter_token_certs_nickname(token, nick); + if (nameList) { + nssrv = nssCertificateList_DoCallback(nameList, + convert_cert, &pk11cb); + } + } else { + nameList = nssList_Create(NULL, PR_FALSE); + (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); + filter_list_for_token_certs(nameList, token); + /* set the search criteria */ + search.callback = convert_and_cache_cert; + search.cbarg = &pk11cb; + search.cached = nameList; + search.searchType = nssTokenSearchType_TokenOnly; + pk11cb.cached = nameList; + nssrv = nssCertificateList_DoCallback(nameList, + convert_cert, &pk11cb); + if (nssrv == PR_SUCCESS) { + nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, + nick, &search); + } + } + if (nameList) { + nssList_Clear(nameList, cert_destructor); + nssList_Destroy(nameList); + } if (created) nss_ZFreeIf(nick); return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; #endif @@ -2535,29 +2832,62 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); struct nss3_cert_cbstr pk11cb; NSSToken *tok; - nssList *certList = nssList_Create(NULL, PR_FALSE); + nssList *certList = NULL; nssTokenCertSearch search; pk11cb.callback = callback; pk11cb.arg = arg; - (void *)nssTrustDomain_GetCertsFromCache(td, certList); - /* set the search criteria */ - search.callback = convert_and_cache_cert; - search.cbarg = &pk11cb; - search.cached = certList; - search.searchType = nssTokenSearchType_TokenOnly; - pk11cb.cached = certList; tok = PK11Slot_GetNSSToken(slot); - if (tok) { - nssrv = nssToken_TraverseCertificates(tok, NULL, &search); + if (!nssToken_SearchCerts(tok)) { + certList = tok->certList; + nssrv = nssCertificateList_DoCallback(certList, convert_cert, &pk11cb); } else { - nssrv = PR_FAILURE; + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) { + return SECFailure; + } + (void *)nssTrustDomain_GetCertsFromCache(td, certList); + filter_list_for_token_certs(certList, tok); + /* set the search criteria */ + search.callback = convert_and_cache_cert; + search.cbarg = &pk11cb; + search.cached = certList; + search.searchType = nssTokenSearchType_TokenOnly; + pk11cb.cached = certList; + nssrv = nssCertificateList_DoCallback(certList, + convert_cert, &pk11cb); + if (nssrv == PR_SUCCESS) { + nssrv = nssToken_TraverseCertificates(tok, NULL, &search); + } + nssList_Clear(certList, cert_destructor); + nssList_Destroy(certList); } - nssList_Clear(certList, cert_destructor); - nssList_Destroy(certList); return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; #endif } +static NSSCertificate * +filter_token_certs_DER(NSSToken *token, NSSDER *der) +{ + nssListIterator *certs; + NSSCertificate *cert, *rvCert; + PRStatus nssrv; + certs = nssList_CreateIterator(token->certList); + if (!certs) return NULL; + rvCert = NULL; + for (cert = (NSSCertificate *)nssListIterator_Start(certs); + cert != (NSSCertificate *)NULL; + cert = (NSSCertificate *)nssListIterator_Next(certs)) + { + if (nssItem_Equal(&cert->encoding, der, &nssrv)) { + rvCert = nssCertificate_AddRef(cert); + break; + } + } + nssListIterator_Finish(certs); + nssListIterator_Destroy(certs); + return rvCert; +} + /* * return the certificate associated with a derCert */ @@ -2599,11 +2929,19 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, NSSCertificate *c; NSSDER derCert; NSSToken *tok; + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); tok = PK11Slot_GetNSSToken(slot); NSSITEM_FROM_SECITEM(&derCert, &cert->derCert); - /* XXX login to slots */ - c = nssToken_FindCertificateByEncodedCertificate(tok, NULL, &derCert, + if (!nssToken_SearchCerts(tok)) { + c = filter_token_certs_DER(tok, &derCert); + } else { + c = nssTrustDomain_GetCertByDERFromCache(td, &derCert); + if (!c) { + c = nssToken_FindCertificateByEncodedCertificate(tok, NULL, + &derCert, nssTokenSearchType_TokenOnly); + } + } if (c) { rvCert = STAN_GetCERTCertificate(c); } diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c index 44dbfe4f0..1bfe1d7c8 100644 --- a/security/nss/lib/pki/certificate.c +++ b/security/nss/lib/pki/certificate.c @@ -110,13 +110,28 @@ NSSCertificate_DeleteStoredObject instance != (nssCryptokiInstance *)NULL; instance = (nssCryptokiInstance *)nssListIterator_Next(instances)) { + /* XXX this should be fixed to understand read-only tokens, for + * now, to handle the builtins, just make the attempt. + */ nssrv = nssToken_DeleteStoredObject(instance); - if (nssrv != PR_SUCCESS) { - break; + if (nssrv == PR_SUCCESS) { + nssList_Remove(c->object.instanceList, instance); +#ifdef NSS_3_4_CODE + if (instance->token->certList) { + /* If the cert has been cached locally on the token, remove + * that reference + */ + nssList_Remove(instance->token->certList, c); + NSSCertificate_Destroy(c); + } +#endif } } nssListIterator_Finish(instances); - return nssrv; + c->object.instances = nssList_CreateIterator(c->object.instanceList); + nssListIterator_Destroy(instances); + /* XXX for now, always success */ + return PR_SUCCESS; } NSS_IMPLEMENT PRStatus @@ -803,3 +818,27 @@ loser: return NULL; } +/* execute a callback function on all members of a cert list */ +NSS_EXTERN PRStatus +nssCertificateList_DoCallback +( + nssList *certList, + PRStatus (* callback)(NSSCertificate *c, void *arg), + void *arg +) +{ + nssListIterator *certs; + NSSCertificate *cert; + PRStatus nssrv; + certs = nssList_CreateIterator(certList); + for (cert = (NSSCertificate *)nssListIterator_Start(certs); + cert != (NSSCertificate *)NULL; + cert = (NSSCertificate *)nssListIterator_Next(certs)) + { + nssrv = (*callback)(cert, arg); + } + nssListIterator_Finish(certs); + nssListIterator_Destroy(certs); + return PR_SUCCESS; +} + diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c index 3239051ef..09d103119 100644 --- a/security/nss/lib/pki/pki3hack.c +++ b/security/nss/lib/pki/pki3hack.c @@ -68,6 +68,10 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #include "certt.h" #include "cert.h" #include "pk11func.h" +#include "pkistore.h" + +/* if it's got more than 10 certs, it better handle traversal well */ +#define NSSTOKEN_MAX_LOCAL_CERTS 10 NSSTrustDomain *g_default_trust_domain = NULL; @@ -95,7 +99,88 @@ STAN_GetDefaultCryptoToken return PK11Slot_GetNSSToken(pk11slot); } +/* stuff the cert in the global trust domain cache, and then add a reference + * to remain with the token in a list. + */ +static PRStatus +cache_token_cert(NSSCertificate *c, void *arg) +{ + NSSToken *token = (NSSToken *)arg; + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); + if (nssList_Count(token->certList) > NSSTOKEN_MAX_LOCAL_CERTS) { + nssToken_DestroyCertList(token); + /* terminate the traversal */ + return PR_FAILURE; + } + nssTrustDomain_AddCertsToCache(td, &c, 1); + /* This list reference persists with the token */ + nssList_Add(token->certList, nssCertificate_AddRef(c)); + /* The cert needs to become external (made into a CERTCertificate) + * in order for it to be properly released. + */ + (void)STAN_GetCERTCertificate(c); + return PR_SUCCESS; +} + +static void cert_destructor(void *el) +{ + NSSCertificate *c = (NSSCertificate *)el; + CERTCertificate *cert = STAN_GetCERTCertificate(c); + CERT_DestroyCertificate(cert); +} + +/* destroy the list of certs on a token */ NSS_IMPLEMENT void +nssToken_DestroyCertList(NSSToken *token) +{ + nssList_Clear(token->certList, cert_destructor); + nssList_Destroy(token->certList); + token->certList = NULL; +} + +/* create a list of local cert references for certain tokens */ +NSS_IMPLEMENT PRStatus +nssToken_LoadCerts(NSSToken *token) +{ + PRStatus nssrv = PR_SUCCESS; + nssTokenCertSearch search; + if (!PK11_IsInternal(token->pk11slot) && PK11_IsHW(token->pk11slot)) { + /* Hardware token certs will be immediately cached, and no searches + * will be performed on the token (the certs will be discovered by + * cache lookups) + */ + search.callback = cache_token_cert; + search.cbarg = token; + search.cached = NULL; + search.searchType = nssTokenSearchType_TokenOnly; + token->certList = nssList_Create(token->arena, PR_FALSE); + if (!token->certList) { + return PR_FAILURE; + } + /* ignore the rv, just work without the list */ + (void)nssToken_TraverseCertificates(token, NULL, &search); + /* even if there are no certs, leave a valid list pointer should + * any be imported. Having the pointer will also prevent searches, + * see below. + */ + } + return nssrv; +} + +NSS_IMPLEMENT PRBool +nssToken_SearchCerts +( + NSSToken *token +) +{ + if (!nssToken_IsPresent(token)) { + STAN_DestroyNSSToken(token); /* will free cached certs */ + } else { + return (token->certList == NULL); + } +} + +NSS_IMPLEMENT PRStatus STAN_LoadDefaultNSS3TrustDomain ( void @@ -107,8 +192,7 @@ STAN_LoadDefaultNSS3TrustDomain PK11SlotListElement *le; td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL); if (!td) { - /* um, some kind a fatal here */ - return; + return PR_FAILURE; } td->tokenList = nssList_Create(td->arena, PR_TRUE); list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL); @@ -123,9 +207,18 @@ STAN_LoadDefaultNSS3TrustDomain */ PK11_FreeSlotList(list); } - td->tokens = nssList_CreateIterator(td->tokenList); g_default_trust_domain = td; g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL); + /* Cache hardware token certs with the token to make them persistent */ + td->tokens = nssList_CreateIterator(td->tokenList); + for (token = (NSSToken *)nssListIterator_Start(td->tokens); + token != (NSSToken *)NULL; + token = (NSSToken *)nssListIterator_Next(td->tokens)) + { + nssToken_LoadCerts(token); + } + nssListIterator_Finish(td->tokens); + return PR_SUCCESS; } NSS_IMPLEMENT SECStatus @@ -141,6 +234,7 @@ STAN_AddModuleToDefaultTrustDomain for (i=0; i<module->slotCount; i++) { token = nssToken_CreateFromPK11SlotInfo(td, module->slots[i]); PK11Slot_SetNSSToken(module->slots[i], token); + nssToken_LoadCerts(token); nssList_Add(td->tokenList, token); } nssListIterator_Destroy(td->tokens); @@ -148,6 +242,15 @@ STAN_AddModuleToDefaultTrustDomain return SECSuccess; } +NSS_IMPLEMENT void +STAN_DestroyNSSToken(NSSToken *token) +{ + if (token->certList) { + nssToken_DestroyCertList(token); + } + nssToken_Destroy(token); +} + NSS_IMPLEMENT SECStatus STAN_RemoveModuleFromDefaultTrustDomain ( @@ -161,6 +264,7 @@ STAN_RemoveModuleFromDefaultTrustDomain for (i=0; i<module->slotCount; i++) { token = PK11Slot_GetNSSToken(module->slots[i]); nssList_Remove(td->tokenList, token); + STAN_DestroyNSSToken(token); } nssListIterator_Destroy(td->tokens); td->tokens = nssList_CreateIterator(td->tokenList); @@ -478,7 +582,7 @@ static int nsstoken_get_trust_order(NSSToken *token) return module->trustOrder; } -static CERTCertTrust * +CERTCertTrust * nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc) { CERTCertTrust *rvTrust; diff --git a/security/nss/lib/pki/pki3hack.h b/security/nss/lib/pki/pki3hack.h index 8688264c3..df4010285 100644 --- a/security/nss/lib/pki/pki3hack.h +++ b/security/nss/lib/pki/pki3hack.h @@ -60,7 +60,7 @@ STAN_GetDefaultTrustDomain(); NSS_EXTERN NSSCryptoContext * STAN_GetDefaultCryptoContext(); -NSS_EXTERN void +NSS_EXTERN PRStatus STAN_LoadDefaultNSS3TrustDomain ( void @@ -69,13 +69,22 @@ STAN_LoadDefaultNSS3TrustDomain NSS_EXTERN void STAN_Shutdown(); +NSS_EXTERN void +STAN_DestroyNSSToken(NSSToken *token); + +NSS_EXTERN PRBool +nssToken_SearchCerts +( + NSSToken *token +); + NSS_EXTERN SECStatus STAN_AddModuleToDefaultTrustDomain ( SECMODModule *module ); -NSS_IMPLEMENT SECStatus +NSS_EXTERN SECStatus STAN_RemoveModuleFromDefaultTrustDomain ( SECMODModule *module @@ -87,6 +96,9 @@ STAN_GetCERTCertificate(NSSCertificate *c); NSS_EXTERN NSSCertificate * STAN_GetNSSCertificate(CERTCertificate *c); +NSS_EXTERN CERTCertTrust * +nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc); + NSS_EXTERN PRStatus STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust); diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h index bd16fd3ad..5473c5a1a 100644 --- a/security/nss/lib/pki/pkim.h +++ b/security/nss/lib/pki/pkim.h @@ -282,6 +282,14 @@ nssBestCertificate_Callback ); NSS_EXTERN PRStatus +nssCertificateList_DoCallback +( + nssList *certList, + PRStatus (* callback)(NSSCertificate *c, void *arg), + void *arg +); + +NSS_EXTERN PRStatus nssPKIObject_Initialize ( struct nssPKIObjectBaseStr *object, diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c index c55a27ec1..a4047063e 100644 --- a/security/nss/lib/pki/trustdomain.c +++ b/security/nss/lib/pki/trustdomain.c @@ -109,8 +109,10 @@ token_destructor(void *t) #ifdef NSS_3_4_CODE /* in 3.4, also destroy the slot (managed separately) */ (void)nssSlot_Destroy(tok->slot); -#endif + STAN_DestroyNSSToken(tok); +#else (void)nssToken_Destroy(tok); +#endif } NSS_IMPLEMENT PRStatus @@ -419,13 +421,17 @@ NSSTrustDomain_FindBestCertificateByNickname search.cbarg = &best; search.cached = nameList; search.searchType = nssTokenSearchType_TokenOnly; + nssCertificateList_DoCallback(nameList, + nssBestCertificate_Callback, &best); /* traverse the tokens */ for (token = (NSSToken *)nssListIterator_Start(td->tokens); token != (NSSToken *)NULL; token = (NSSToken *)nssListIterator_Next(td->tokens)) { - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - name, &search); + if (nssToken_SearchCerts(token)) { + nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, + name, &search); + } } nssListIterator_Finish(td->tokens); nssList_Clear(nameList, cert_destructor); @@ -468,8 +474,10 @@ NSSTrustDomain_FindCertificatesByNickname token != (NSSToken *)NULL; token = (NSSToken *)nssListIterator_Next(td->tokens)) { - nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, - name, &search); + if (nssToken_SearchCerts(token)) { + nssrv = nssToken_TraverseCertificatesByNickname(token, NULL, + name, &search); + } } nssListIterator_Finish(td->tokens); count = nssList_Count(nameList); @@ -511,11 +519,13 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber tok != (NSSToken *)NULL; tok = (NSSToken *)nssListIterator_Next(td->tokens)) { - rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(tok, + if (nssToken_SearchCerts(tok)) { + rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(tok, NULL, issuer, serialNumber, nssTokenSearchType_TokenOnly); + } #ifdef NSS_3_4_CODE if (!rvCert) { /* Some tokens expect a decoded serial number. For compatibility, @@ -531,11 +541,14 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber if (secrv == SECSuccess) { decodedSerial.data = ds.data; decodedSerial.size = ds.len; - rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(tok, + if (nssToken_SearchCerts(tok)) { + rvCert = nssToken_FindCertificateByIssuerAndSerialNumber( + tok, NULL, issuer, &decodedSerial, nssTokenSearchType_TokenOnly); + } PORT_Free(ds.data); } } @@ -575,13 +588,17 @@ NSSTrustDomain_FindBestCertificateBySubject search.cbarg = &best; search.cached = subjectList; search.searchType = nssTokenSearchType_TokenOnly; + nssCertificateList_DoCallback(subjectList, + nssBestCertificate_Callback, &best); /* traverse the tokens */ for (token = (NSSToken *)nssListIterator_Start(td->tokens); token != (NSSToken *)NULL; token = (NSSToken *)nssListIterator_Next(td->tokens)) { - nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, - subject, &search); + if (nssToken_SearchCerts(token)) { + nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, + subject, &search); + } } nssListIterator_Finish(td->tokens); nssList_Clear(subjectList, cert_destructor); @@ -624,8 +641,10 @@ NSSTrustDomain_FindCertificatesBySubject token != (NSSToken *)NULL; token = (NSSToken *)nssListIterator_Next(td->tokens)) { - nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, - subject, &search); + if (nssToken_SearchCerts(token)) { + nssrv = nssToken_TraverseCertificatesBySubject(token, NULL, + subject, &search); + } } nssListIterator_Finish(td->tokens); count = nssList_Count(subjectList); @@ -692,9 +711,11 @@ NSSTrustDomain_FindCertificateByEncodedCertificate tok != (NSSToken *)NULL; tok = (NSSToken *)nssListIterator_Next(td->tokens)) { - rvCert = nssToken_FindCertificateByEncodedCertificate(tok, NULL, + if (nssToken_SearchCerts(tok)) { + rvCert = nssToken_FindCertificateByEncodedCertificate(tok, NULL, encodedCertificate, nssTokenSearchType_TokenOnly); + } if (rvCert) { /* cache it */ nssTrustDomain_AddCertsToCache(td, &rvCert, 1); @@ -730,13 +751,17 @@ NSSTrustDomain_FindCertificateByEmail search.cbarg = &best; search.cached = emailList; search.searchType = nssTokenSearchType_TokenOnly; + nssCertificateList_DoCallback(emailList, + nssBestCertificate_Callback, &best); /* traverse the tokens */ for (token = (NSSToken *)nssListIterator_Start(td->tokens); token != (NSSToken *)NULL; token = (NSSToken *)nssListIterator_Next(td->tokens)) { - nssrv = nssToken_TraverseCertificatesByEmail(token, NULL, - email, &search); + if (nssToken_SearchCerts(token)) { + nssrv = nssToken_TraverseCertificatesByEmail(token, NULL, + email, &search); + } } nssListIterator_Finish(td->tokens); nssList_Clear(emailList, cert_destructor); @@ -927,12 +952,16 @@ NSSTrustDomain_TraverseCertificates search.cbarg = &ta; search.cached = certList; search.searchType = nssTokenSearchType_TokenOnly; + nssCertificateList_DoCallback(certList, + traverse_callback, &ta); /* traverse the tokens */ for (token = (NSSToken *)nssListIterator_Start(td->tokens); token != (NSSToken *)NULL; token = (NSSToken *)nssListIterator_Next(td->tokens)) { - nssrv = nssToken_TraverseCertificates(token, NULL, &search); + if (nssToken_SearchCerts(token)) { + nssrv = nssToken_TraverseCertificates(token, NULL, &search); + } } nssListIterator_Finish(td->tokens); #ifdef NSS_3_4_CODE |