summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorian.mcgreer%sun.com <devnull@localhost>2002-02-27 22:41:56 +0000
committerian.mcgreer%sun.com <devnull@localhost>2002-02-27 22:41:56 +0000
commit915a5725c6289c4e8d32c5d6851678982a4e11ac (patch)
tree91b175bd7f6e4ceb1b5c0497db5b8d162065d307
parent99ed6c467a621110f05b88aa424a491ea9d4ea0b (diff)
downloadnss-hg-915a5725c6289c4e8d32c5d6851678982a4e11ac.tar.gz
bug 125808, smart card cache fixes
-rw-r--r--security/nss/lib/pk11wrap/dev3hack.h3
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c26
-rw-r--r--security/nss/lib/pki/pki3hack.c91
-rw-r--r--security/nss/lib/pki/pki3hack.h14
-rw-r--r--security/nss/lib/pki/trustdomain.c104
5 files changed, 199 insertions, 39 deletions
diff --git a/security/nss/lib/pk11wrap/dev3hack.h b/security/nss/lib/pk11wrap/dev3hack.h
index 3b8f1abf8..0f096e3e8 100644
--- a/security/nss/lib/pk11wrap/dev3hack.h
+++ b/security/nss/lib/pk11wrap/dev3hack.h
@@ -52,9 +52,6 @@ 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);
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c
index 1ef758328..6cd9dfa53 100644
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -1400,7 +1400,7 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) {
}
}
/* find best cert on token */
- if (!nssToken_SearchCerts(token)) {
+ if (!nssToken_SearchCerts(token, NULL)) {
/* token certs are in cache, filter the list of token certs to
* match the nickname
*/
@@ -1443,7 +1443,7 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) {
}
/* if it wasn't found, repeat the process for email address */
if (!cert) {
- if (!nssToken_SearchCerts(token)) {
+ if (!nssToken_SearchCerts(token, NULL)) {
certList = filter_token_certs_email(token, nickname);
if (certList) {
nssCertificateList_DoCallback(certList,
@@ -1540,7 +1540,11 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) {
*delimit = '\0';
/* find token by name */
token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName);
- slot = PK11_ReferenceSlot(token->pk11slot);
+ if (token) {
+ slot = PK11_ReferenceSlot(token->pk11slot);
+ } else {
+ slot = NULL;
+ }
*delimit = ':';
} else {
slot = PK11_GetInternalKeySlot();
@@ -1556,7 +1560,7 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) {
return NULL;
}
}
- if (!nssToken_SearchCerts(token)) {
+ if (!nssToken_SearchCerts(token, NULL)) {
nameList = filter_token_certs_nickname(token, nickname);
} else {
nameList = nssList_Create(NULL, PR_FALSE);
@@ -2716,7 +2720,7 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot,
td = STAN_GetDefaultTrustDomain();
NSSITEM_FROM_SECITEM(&subject, &cert->derSubject);
token = PK11Slot_GetNSSToken(slot);
- if (!nssToken_SearchCerts(token)) {
+ if (!nssToken_SearchCerts(token, NULL)) {
subjectList = filter_token_certs_subject(token, &subject);
if (subjectList) {
nssrv = nssCertificateList_DoCallback(subjectList,
@@ -2807,7 +2811,7 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot,
}
td = STAN_GetDefaultTrustDomain();
token = PK11Slot_GetNSSToken(slot);
- if (!nssToken_SearchCerts(token)) {
+ if (!nssToken_SearchCerts(token, NULL)) {
nameList = filter_token_certs_nickname(token, nick);
if (nameList) {
nssrv = nssCertificateList_DoCallback(nameList,
@@ -2878,7 +2882,7 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot,
pk11cb.callback = callback;
pk11cb.arg = arg;
tok = PK11Slot_GetNSSToken(slot);
- if (!nssToken_SearchCerts(tok)) {
+ if (!nssToken_SearchCerts(tok, NULL)) {
certList = tok->certList;
nssrv = nssCertificateList_DoCallback(certList, convert_cert, &pk11cb);
} else {
@@ -2973,7 +2977,13 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert,
NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
tok = PK11Slot_GetNSSToken(slot);
NSSITEM_FROM_SECITEM(&derCert, &cert->derCert);
- if (!nssToken_SearchCerts(tok)) {
+ if (!PK11_IsFriendly(slot)) {
+ if (PK11_Authenticate(slot, PR_TRUE, wincx) != SECSuccess) {
+ PK11_FreeSlot(slot);
+ return NULL;
+ }
+ }
+ if (!nssToken_SearchCerts(tok, NULL)) {
c = filter_token_certs_DER(tok, &derCert);
} else {
c = nssTrustDomain_GetCertByDERFromCache(td, &derCert);
diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c
index 4d8d273d9..cc55218e2 100644
--- a/security/nss/lib/pki/pki3hack.c
+++ b/security/nss/lib/pki/pki3hack.c
@@ -108,12 +108,16 @@ cache_token_cert(NSSCertificate *c, void *arg)
{
NSSToken *token = (NSSToken *)arg;
NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
+ NSSCertificate *cp = nssCertificate_AddRef(c);
if (nssList_Count(token->certList) > NSSTOKEN_MAX_LOCAL_CERTS) {
nssToken_DestroyCertList(token);
/* terminate the traversal */
return PR_FAILURE;
}
nssTrustDomain_AddCertsToCache(td, &c, 1);
+ if (cp == c) {
+ NSSCertificate_Destroy(cp);
+ }
/* This list reference persists with the token */
nssList_Add(token->certList, nssCertificate_AddRef(c));
/* The cert needs to become external (made into a CERTCertificate)
@@ -123,11 +127,77 @@ cache_token_cert(NSSCertificate *c, void *arg)
return PR_SUCCESS;
}
-static void cert_destructor(void *el)
+static void remove_token_instance(NSSCertificate *c, NSSToken *token)
+{
+ nssListIterator *instances;
+ nssCryptokiInstance *instance, *rmInstance = NULL;
+ instances = c->object.instances;
+ for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances);
+ instance != (nssCryptokiInstance *)NULL;
+ instance = (nssCryptokiInstance *)nssListIterator_Next(instances))
+ {
+ if (instance->token == token) {
+ rmInstance = instance;
+ break;
+ }
+ }
+ nssListIterator_Finish(instances);
+ if (rmInstance) {
+ nssList_Remove(c->object.instanceList, rmInstance);
+ nssListIterator_Destroy(instances);
+ c->object.instances = nssList_CreateIterator(c->object.instanceList);
+ }
+}
+
+static PRBool instance_destructor(NSSCertificate *c, NSSToken *token)
{
- NSSCertificate *c = (NSSCertificate *)el;
CERTCertificate *cert = STAN_GetCERTCertificate(c);
- CERT_DestroyCertificate(cert);
+ remove_token_instance(c, token);
+ if (nssList_Count(c->object.instanceList) == 0) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NSS_IMPLEMENT void
+nssCertificateList_DestroyTokenCerts(nssList *certList, NSSToken *token)
+{
+ nssListIterator *certs;
+ NSSCertificate *cert;
+ PRBool removeIt;
+ certs = nssList_CreateIterator(certList);
+ for (cert = (NSSCertificate *)nssListIterator_Start(certs);
+ cert != (NSSCertificate *)NULL;
+ cert = (NSSCertificate *)nssListIterator_Next(certs))
+ {
+ removeIt = instance_destructor(cert, token);
+ if (removeIt) {
+ nssList_Remove(certList, cert);
+ CERT_DestroyCertificate(STAN_GetCERTCertificate(cert));
+ }
+ }
+ nssListIterator_Finish(certs);
+ nssListIterator_Destroy(certs);
+}
+
+NSS_IMPLEMENT void
+nssCertificateList_RemoveTokenCerts(nssList *certList, NSSToken *token)
+{
+ nssListIterator *certs;
+ NSSCertificate *cert;
+ PRBool removeIt;
+ certs = nssList_CreateIterator(certList);
+ for (cert = (NSSCertificate *)nssListIterator_Start(certs);
+ cert != (NSSCertificate *)NULL;
+ cert = (NSSCertificate *)nssListIterator_Next(certs))
+ {
+ removeIt = instance_destructor(cert, token);
+ if (removeIt) {
+ nssList_Remove(certList, cert);
+ }
+ }
+ nssListIterator_Finish(certs);
+ nssListIterator_Destroy(certs);
}
/* destroy the list of certs on a token */
@@ -137,9 +207,9 @@ nssToken_DestroyCertList(NSSToken *token)
if (!token->certList) {
return;
}
- nssList_Clear(token->certList, cert_destructor);
- nssList_Destroy(token->certList);
- token->certList = NULL;
+ nssCertificateList_DestroyTokenCerts(token->certList, token);
+ nssList_Clear(token->certList, NULL);
+ /* leave the list non-null to prevent it from being searched */
}
/* create a list of local cert references for certain tokens */
@@ -183,11 +253,18 @@ nssToken_LoadCerts(NSSToken *token)
NSS_IMPLEMENT PRBool
nssToken_SearchCerts
(
- NSSToken *token
+ NSSToken *token,
+ PRBool *notPresentOpt
)
{
+ if (notPresentOpt) {
+ *notPresentOpt = PR_FALSE;
+ }
if (!nssToken_IsPresent(token)) {
nssToken_DestroyCertList(token); /* will free cached certs */
+ if (notPresentOpt) {
+ *notPresentOpt = PR_TRUE;
+ }
} else if (token->certList &&
nssList_Count(token->certList) == 0 &&
!token->loggedIn) {
diff --git a/security/nss/lib/pki/pki3hack.h b/security/nss/lib/pki/pki3hack.h
index df4010285..3bbe62716 100644
--- a/security/nss/lib/pki/pki3hack.h
+++ b/security/nss/lib/pki/pki3hack.h
@@ -42,6 +42,8 @@ static const char PKINSS3HACK_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name
#include "nsspkit.h"
#endif /* NSSPKIT_H */
+#include "base.h"
+
#include "cert.h"
PR_BEGIN_EXTERN_C
@@ -75,9 +77,19 @@ STAN_DestroyNSSToken(NSSToken *token);
NSS_EXTERN PRBool
nssToken_SearchCerts
(
- NSSToken *token
+ NSSToken *token,
+ PRBool *notPresentOpt
);
+NSS_EXTERN void
+nssToken_DestroyCertList(NSSToken *token);
+
+NSS_EXTERN void
+nssCertificateList_DestroyTokenCerts(nssList *certList, NSSToken *token);
+
+NSS_EXTERN void
+nssCertificateList_RemoveTokenCerts(nssList *certList, NSSToken *token);
+
NSS_EXTERN SECStatus
STAN_AddModuleToDefaultTrustDomain
(
diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c
index ad0429da8..0d33e086d 100644
--- a/security/nss/lib/pki/trustdomain.c
+++ b/security/nss/lib/pki/trustdomain.c
@@ -411,6 +411,7 @@ NSSTrustDomain_FindBestCertificateByNickname
nssTokenCertSearch search;
nssBestCertificateCB best;
nssList *nameList;
+ PRBool notPresent;
/* set the criteria for determining the best cert */
nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt);
/* find all matching certs in the cache */
@@ -421,19 +422,21 @@ 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))
{
- if (nssToken_SearchCerts(token)) {
+ if (nssToken_SearchCerts(token, &notPresent)) {
nssrv = nssToken_TraverseCertificatesByNickname(token, NULL,
name, &search);
}
+ if (notPresent) {
+ nssCertificateList_DestroyTokenCerts(nameList, token);
+ }
}
nssListIterator_Finish(td->tokens);
+ nssCertificateList_DoCallback(nameList, nssBestCertificate_Callback, &best);
nssList_Clear(nameList, cert_destructor);
nssList_Destroy(nameList);
if (best.cert) {
@@ -457,8 +460,9 @@ NSSTrustDomain_FindCertificatesByNickname
PRUint32 count;
PRStatus nssrv;
nssList *nameList;
- struct collect_arg_str ca;
nssTokenCertSearch search;
+ struct collect_arg_str ca;
+ PRBool notPresent;
/* set up the collection */
nameList = nssList_Create(NULL, PR_FALSE);
(void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList);
@@ -474,10 +478,13 @@ NSSTrustDomain_FindCertificatesByNickname
token != (NSSToken *)NULL;
token = (NSSToken *)nssListIterator_Next(td->tokens))
{
- if (nssToken_SearchCerts(token)) {
+ if (nssToken_SearchCerts(token, &notPresent)) {
nssrv = nssToken_TraverseCertificatesByNickname(token, NULL,
name, &search);
}
+ if (notPresent) {
+ nssCertificateList_DestroyTokenCerts(nameList, token);
+ }
}
nssListIterator_Finish(td->tokens);
count = nssList_Count(nameList);
@@ -497,6 +504,32 @@ NSSTrustDomain_FindCertificatesByNickname
return rvCerts;
}
+static PRBool cert_token_not_present(NSSCertificate *c)
+{
+ nssListIterator *instances;
+ nssCryptokiInstance *instance;
+ PRBool freeIt = PR_TRUE;
+ instances = nssList_CreateIterator(c->object.instanceList);
+ for (instance = (nssCryptokiInstance *)nssListIterator_Start(instances);
+ instance != (nssCryptokiInstance *)NULL;
+ instance = (nssCryptokiInstance *)nssListIterator_Next(instances))
+ {
+ if (!nssToken_IsPresent(instance->token)) {
+ nssToken_DestroyCertList(instance->token);
+ nssList_Remove(c->object.instanceList, instance);
+ } else {
+ freeIt = PR_FALSE;
+ }
+ }
+ nssListIterator_Finish(instances);
+ nssListIterator_Destroy(instances);
+ if (!freeIt) {
+ nssListIterator_Destroy(c->object.instances);
+ c->object.instances = nssList_CreateIterator(c->object.instanceList);
+ }
+ return freeIt;
+}
+
NSS_IMPLEMENT NSSCertificate *
NSSTrustDomain_FindCertificateByIssuerAndSerialNumber
(
@@ -512,6 +545,10 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber
issuer,
serialNumber);
if (rvCert) {
+ if (cert_token_not_present(rvCert)) {
+ CERT_DestroyCertificate(STAN_GetCERTCertificate(rvCert));
+ rvCert = NULL;
+ }
return rvCert;
}
/* Not cached, look for it on tokens */
@@ -519,7 +556,7 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber
tok != (NSSToken *)NULL;
tok = (NSSToken *)nssListIterator_Next(td->tokens))
{
- if (nssToken_SearchCerts(tok)) {
+ if (nssToken_SearchCerts(tok, NULL)) {
rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(tok,
NULL,
issuer,
@@ -541,7 +578,7 @@ NSSTrustDomain_FindCertificateByIssuerAndSerialNumber
if (secrv == SECSuccess) {
decodedSerial.data = ds.data;
decodedSerial.size = ds.len;
- if (nssToken_SearchCerts(tok)) {
+ if (nssToken_SearchCerts(tok, NULL)) {
rvCert = nssToken_FindCertificateByIssuerAndSerialNumber(
tok,
NULL,
@@ -578,6 +615,7 @@ NSSTrustDomain_FindBestCertificateBySubject
nssList *subjectList;
nssBestCertificateCB best;
nssTokenCertSearch search;
+ PRBool notPresent;
/* set the criteria for determining the best cert */
nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt);
/* find all matching certs in the cache */
@@ -588,19 +626,22 @@ 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))
{
- if (nssToken_SearchCerts(token)) {
+ if (nssToken_SearchCerts(token, &notPresent)) {
nssrv = nssToken_TraverseCertificatesBySubject(token, NULL,
subject, &search);
}
+ if (notPresent) {
+ nssCertificateList_DestroyTokenCerts(subjectList, token);
+ }
}
nssListIterator_Finish(td->tokens);
+ nssCertificateList_DoCallback(subjectList,
+ nssBestCertificate_Callback, &best);
nssList_Clear(subjectList, cert_destructor);
nssList_Destroy(subjectList);
if (best.cert) {
@@ -626,6 +667,7 @@ NSSTrustDomain_FindCertificatesBySubject
nssList *subjectList;
struct collect_arg_str ca;
nssTokenCertSearch search;
+ PRBool notPresent;
/* set up the collection */
subjectList = nssList_Create(NULL, PR_FALSE);
(void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList);
@@ -641,10 +683,13 @@ NSSTrustDomain_FindCertificatesBySubject
token != (NSSToken *)NULL;
token = (NSSToken *)nssListIterator_Next(td->tokens))
{
- if (nssToken_SearchCerts(token)) {
+ if (nssToken_SearchCerts(token, &notPresent)) {
nssrv = nssToken_TraverseCertificatesBySubject(token, NULL,
subject, &search);
}
+ if (notPresent) {
+ nssCertificateList_DestroyTokenCerts(subjectList, token);
+ }
}
nssListIterator_Finish(td->tokens);
count = nssList_Count(subjectList);
@@ -704,6 +749,10 @@ NSSTrustDomain_FindCertificateByEncodedCertificate
/* Try the cache */
rvCert = nssTrustDomain_GetCertByDERFromCache(td, encodedCertificate);
if (rvCert) {
+ if (cert_token_not_present(rvCert)) {
+ CERT_DestroyCertificate(STAN_GetCERTCertificate(rvCert));
+ rvCert = NULL;
+ }
return rvCert;
}
/* Not cached, look for it on tokens */
@@ -711,7 +760,7 @@ NSSTrustDomain_FindCertificateByEncodedCertificate
tok != (NSSToken *)NULL;
tok = (NSSToken *)nssListIterator_Next(td->tokens))
{
- if (nssToken_SearchCerts(tok)) {
+ if (nssToken_SearchCerts(tok, NULL)) {
rvCert = nssToken_FindCertificateByEncodedCertificate(tok, NULL,
encodedCertificate,
nssTokenSearchType_TokenOnly);
@@ -741,6 +790,7 @@ NSSTrustDomain_FindCertificateByEmail
nssBestCertificateCB best;
nssTokenCertSearch search;
nssList *emailList;
+ PRBool notPresent;
/* set the criteria for determining the best cert */
nssBestCertificate_SetArgs(&best, timeOpt, usage, policiesOpt);
/* find all matching certs in the cache */
@@ -751,19 +801,22 @@ 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))
{
- if (nssToken_SearchCerts(token)) {
+ if (nssToken_SearchCerts(token, &notPresent)) {
nssrv = nssToken_TraverseCertificatesByEmail(token, NULL,
email, &search);
}
+ if (notPresent) {
+ nssCertificateList_DestroyTokenCerts(emailList, token);
+ }
}
nssListIterator_Finish(td->tokens);
+ nssCertificateList_DoCallback(emailList,
+ nssBestCertificate_Callback, &best);
nssList_Clear(emailList, cert_destructor);
nssList_Destroy(emailList);
if (best.cert) {
@@ -946,7 +999,7 @@ static void cert_destructor_with_cache(void *el)
CERT_DestroyCertificate(cert);
}
#endif
-
+
NSS_IMPLEMENT PRStatus *
NSSTrustDomain_TraverseCertificates
(
@@ -957,13 +1010,18 @@ NSSTrustDomain_TraverseCertificates
{
PRStatus nssrv;
NSSToken *token;
- nssList *certList;
+ nssList *certList, *cacheList;
nssTokenCertSearch search;
struct traverse_arg ta;
nssListIterator *tokens;
+ PRBool notPresent;
certList = nssList_Create(NULL, PR_FALSE);
if (!certList) return NULL;
(void *)nssTrustDomain_GetCertsFromCache(td, certList);
+ cacheList = nssList_Clone(certList);
+ if (!cacheList) {
+ goto cleanup;
+ }
/* set traverse args */
ta.callback = callback;
ta.cached = certList;
@@ -973,8 +1031,6 @@ NSSTrustDomain_TraverseCertificates
search.cbarg = &ta;
search.cached = certList;
search.searchType = nssTokenSearchType_TokenOnly;
- nssCertificateList_DoCallback(certList,
- traverse_callback, &ta);
/* Must create a local copy of the token list, because the callback
* above may want to traverse the tokens as well.
*/
@@ -987,12 +1043,20 @@ NSSTrustDomain_TraverseCertificates
token != (NSSToken *)NULL;
token = (NSSToken *)nssListIterator_Next(tokens))
{
- if (nssToken_SearchCerts(token)) {
+ if (nssToken_SearchCerts(token, &notPresent)) {
nssrv = nssToken_TraverseCertificates(token, NULL, &search);
}
+ if (notPresent) {
+ nssCertificateList_RemoveTokenCerts(cacheList, token);
+ }
}
nssListIterator_Finish(tokens);
nssListIterator_Destroy(tokens);
+ /* now do the callback on the cached certs,
+ * sans certs from removed tokens
+ */
+ nssCertificateList_DoCallback(cacheList, callback, arg);
+ nssList_Destroy(cacheList);
cleanup:
#ifdef NSS_3_4_CODE
nssList_Clear(certList, cert_destructor_with_cache);