summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2002-04-22 19:09:01 +0000
committerrelyea%netscape.com <devnull@localhost>2002-04-22 19:09:01 +0000
commit6fa9a58b44d7d3056239c783ebd31595cb92df5b (patch)
tree389232e3da51f48e36b0387a173ba5d7f9a9dbeb
parente51099ee7301832c329122b8e4548e25264ba629 (diff)
downloadnss-hg-6fa9a58b44d7d3056239c783ebd31595cb92df5b.tar.gz
Token and cert processing fixes:
1) use NewTempCert rather than DERDecode cert in all import cert cases. When DERDecode cert is used, we may wind up with a cert that gets cleared when we try to import it because it already in the cache. NewTempCert will return the version that is in the cache. 2) If we are returning the CAList, only return certs that are CA's (not usercerts). 3) Authenticate to all the tokens if necessary before we try to list certs. (Stan code should eventually get automatic authentication calls in the code itself). 4) When looking up user certs, don't return those certs with the same subject, but do not have any key material associated with them (that is don't crash if we have old certs in our database without nicknames, but match user certs on our smart cards). 5) Save the nickname associated with our subject list in the temp cache so we can correctly remove the entry even if the cert's nickname changes (because of smart card insertions and removals, or because of creation and deletions of our user cert).
-rw-r--r--security/nss/lib/certdb/certdb.c8
-rw-r--r--security/nss/lib/certhigh/certhigh.c27
-rw-r--r--security/nss/lib/dev/devm.h12
-rw-r--r--security/nss/lib/dev/devslot.c2
-rw-r--r--security/nss/lib/dev/devtoken.c9
-rw-r--r--security/nss/lib/dev/devutil.c13
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c23
-rw-r--r--security/nss/lib/pki/trustdomain.c99
8 files changed, 182 insertions, 11 deletions
diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c
index c4dca2d99..956284751 100644
--- a/security/nss/lib/certdb/certdb.c
+++ b/security/nss/lib/certdb/certdb.c
@@ -2028,17 +2028,11 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage,
/* decode all of the certs into the temporary DB */
for ( i = 0, fcerts= 0; i < ncerts; i++) {
- if ( keepCerts ) {
- certs[fcerts] = CERT_DecodeDERCertificate(derCerts[i],
- PR_FALSE,
- NULL);
- } else {
- certs[fcerts] = CERT_NewTempCertificate(certdb,
+ certs[fcerts] = CERT_NewTempCertificate(certdb,
derCerts[i],
NULL,
PR_FALSE,
PR_TRUE);
- }
if (certs[fcerts]) fcerts++;
}
diff --git a/security/nss/lib/certhigh/certhigh.c b/security/nss/lib/certhigh/certhigh.c
index 06cccb43b..59b597b3b 100644
--- a/security/nss/lib/certhigh/certhigh.c
+++ b/security/nss/lib/certhigh/certhigh.c
@@ -91,6 +91,31 @@ CERT_MatchNickname(char *name1, char *name2) {
return PR_TRUE;
}
+static SECStatus
+cert_UserCertsOnly(CERTCertList *certList)
+{
+ CERTCertListNode *node, *freenode;
+ CERTCertificate *cert;
+
+ node = CERT_LIST_HEAD(certList);
+
+ while ( ! CERT_LIST_END(node, certList) ) {
+ cert = node->cert;
+ if ( !( cert->trust->sslFlags & CERTDB_USER ) &&
+ !( cert->trust->emailFlags & CERTDB_USER ) &&
+ !( cert->trust->objectSigningFlags & CERTDB_USER ) ) {
+ /* Not a User Cert, so remove this cert from the list */
+ freenode = node;
+ node = CERT_LIST_NEXT(node);
+ CERT_RemoveCertListNode(freenode);
+ } else {
+ /* Is a User cert, so leave it in the list */
+ node = CERT_LIST_NEXT(node);
+ }
+ }
+
+ return(SECSuccess);
+}
/*
* Find all user certificates that match the given criteria.
@@ -157,6 +182,8 @@ CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
/* collect certs for this nickname, sorting them into the list */
certList = CERT_CreateSubjectCertList(certList, handle,
&cert->derSubject, time, validOnly);
+
+ cert_UserCertsOnly(certList);
/* drop the extra reference */
CERT_DestroyCertificate(cert);
diff --git a/security/nss/lib/dev/devm.h b/security/nss/lib/dev/devm.h
index 379e21470..69ec759ec 100644
--- a/security/nss/lib/dev/devm.h
+++ b/security/nss/lib/dev/devm.h
@@ -134,6 +134,12 @@ nssToken_IsLoginRequired
NSSToken *token
);
+NSS_EXTERN void
+nssToken_Remove
+(
+ NSSToken *token
+);
+
NSS_EXTERN nssCryptokiObject *
nssCryptokiObject_Create
(
@@ -157,6 +163,12 @@ nssTokenObjectCache_Destroy
nssTokenObjectCache *cache
);
+NSS_EXTERN void
+nssTokenObjectCache_Clear
+(
+ nssTokenObjectCache *cache
+);
+
NSS_EXTERN PRBool
nssTokenObjectCache_HaveObjectClass
(
diff --git a/security/nss/lib/dev/devslot.c b/security/nss/lib/dev/devslot.c
index 437fbfdb3..30f4855c3 100644
--- a/security/nss/lib/dev/devslot.c
+++ b/security/nss/lib/dev/devslot.c
@@ -301,6 +301,8 @@ nssSlot_IsTokenPresent
}
#endif
slot->token->base.name[0] = 0; /* XXX */
+ /* clear the token cache */
+ nssToken_Remove(slot->token);
return PR_FALSE;
#ifdef PURE_STAN_CODE
} else if (!slot->token) {
diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c
index 630db5740..6fde75de3 100644
--- a/security/nss/lib/dev/devtoken.c
+++ b/security/nss/lib/dev/devtoken.c
@@ -161,6 +161,15 @@ nssToken_Destroy
}
NSS_IMPLEMENT void
+nssToken_Remove
+(
+ NSSToken *tok
+)
+{
+ nssTokenObjectCache_Clear(tok->cache);
+}
+
+NSS_IMPLEMENT void
NSSToken_Destroy
(
NSSToken *tok
diff --git a/security/nss/lib/dev/devutil.c b/security/nss/lib/dev/devutil.c
index 9f537f444..5ff8c8d68 100644
--- a/security/nss/lib/dev/devutil.c
+++ b/security/nss/lib/dev/devutil.c
@@ -620,6 +620,17 @@ clear_cache
}
NSS_IMPLEMENT void
+nssTokenObjectCache_Clear
+(
+ nssTokenObjectCache *cache
+)
+{
+ if (cache) {
+ clear_cache(cache);
+ }
+}
+
+NSS_IMPLEMENT void
nssTokenObjectCache_Destroy
(
nssTokenObjectCache *cache
@@ -777,7 +788,7 @@ search_for_objects
NSSSlot *slot = nssToken_GetSlot(cache->token);
if (!nssSlot_IsTokenPresent(slot)) {
/* The token is no longer present, destroy any cached objects */
- clear_cache(cache);
+ /* clear_cache(cache); */
nssSlot_Destroy(slot);
return PR_FALSE;
}
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c
index bf1e74450..809761189 100644
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -971,7 +971,9 @@ pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *),
rv = PK11_Authenticate(le->slot, PR_FALSE, wincx);
if (rv != SECSuccess) continue;
}
- (*callback)(le->slot,arg);
+ if (callback) {
+ (*callback)(le->slot,arg);
+ }
}
PK11_FreeSlotList(list);
@@ -3206,12 +3208,16 @@ pk11ListCertCallback(CERTCertificate *cert, void *arg)
CERTCertList *certList = listCertP->certList;
CERTCertTrust *trust;
PRBool isUnique = PR_FALSE;
+ PRBool isCA = PR_FALSE;
char *nickname = NULL;
unsigned int certType;
if ((type == PK11CertListUnique) || (type == PK11CertListRootUnique)) {
isUnique = PR_TRUE;
}
+ if ((type == PK11CertListCA) || (type == PK11CertListRootUnique)) {
+ isCA = PR_TRUE;
+ }
/* at this point the nickname is correct for the cert. save it for later */
if (!isUnique && cert->nickname) {
nickname = PORT_ArenaStrdup(listCertP->certList->arena,cert->nickname);
@@ -3255,7 +3261,7 @@ pk11ListCertCallback(CERTCertificate *cert, void *arg)
}
/* if we want CA certs and it ain't one, skip it */
- if( type == PK11CertListCA && (!CERT_IsCACert(newCert, &certType)) ) {
+ if( isCA && (!CERT_IsCACert(newCert, &certType)) ) {
CERT_DestroyCertificate(newCert);
return SECSuccess;
}
@@ -3298,7 +3304,18 @@ PK11_ListCerts(PK11CertListType type, void *pwarg)
listCerts.certList = certList;
pk11cb.callback = pk11ListCertCallback;
pk11cb.arg = &listCerts;
- NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
+
+ /* authenticate to the slots */
+ (void) pk11_TraverseAllSlots( NULL, NULL, pwarg);
+#ifdef notdef
+ if (type == PK11CertListUser) {
+ NSSTrustDomain_TraverseUserCertificates(defaultTD, convert_cert &pk11cb);
+ } else {
+ NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
+ }
+#else
+ NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
+#endif
return certList;
#endif
}
diff --git a/security/nss/lib/pki/trustdomain.c b/security/nss/lib/pki/trustdomain.c
index 7c5ffaf7b..bd97153f8 100644
--- a/security/nss/lib/pki/trustdomain.c
+++ b/security/nss/lib/pki/trustdomain.c
@@ -1099,6 +1099,104 @@ NSSTrustDomain_TraverseCertificates
}
}
}
+
+ /* Traverse the collection */
+ pkiCallback.func.cert = callback;
+ pkiCallback.arg = arg;
+ status = nssPKIObjectCollection_Traverse(collection, &pkiCallback);
+ /* clean up */
+ nssPKIObjectCollection_Destroy(collection);
+ nssSlotArray_Destroy(slots);
+ return NULL;
+loser:
+ if (slots) {
+ nssSlotArray_Destroy(slots);
+ }
+ if (collection) {
+ nssPKIObjectCollection_Destroy(collection);
+ }
+ return NULL;
+}
+
+#ifdef notdef
+/*
+ * search for Public and Private keys first
+ */
+NSS_IMPLEMENT PRStatus *
+NSSTrustDomain_TraverseUserCertificates
+(
+ NSSTrustDomain *td,
+ PRStatus (*callback)(NSSCertificate *c, void *arg),
+ void *arg
+)
+{
+ PRStatus status;
+ NSSToken *token = NULL;
+ NSSSlot **slots = NULL;
+ NSSSlot **slotp;
+ nssPKIObjectCollection *collection = NULL;
+ nssPKIObjectCallback pkiCallback;
+ nssUpdateLevel updateLevel;
+ NSSCertificate **cached = NULL;
+ nssList *certList;
+ certList = nssList_Create(NULL, PR_FALSE);
+ if (!certList) return NULL;
+ (void *)nssTrustDomain_GetCertsFromCache(td, certList);
+ cached = get_certs_from_list(certList);
+ collection = nssCertificateCollection_Create(td, cached);
+ nssCertificateArray_Destroy(cached);
+ nssList_Destroy(certList);
+ if (!collection) {
+ return (PRStatus *)NULL;
+ }
+ /* obtain the current set of active slots in the trust domain */
+ slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
+ if (!slots) {
+ goto loser;
+ }
+ /* iterate over the slots */
+ for (slotp = slots; *slotp; slotp++) {
+ /* get the token for the slot, if present */
+ token = nssSlot_GetToken(*slotp);
+ if (token) {
+ nssSession *session;
+ nssCryptokiObject **instances;
+ nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
+ /* get a session for the token */
+ session = nssTrustDomain_GetSessionForToken(td, token);
+ if (!session) {
+ nssToken_Destroy(token);
+ goto loser;
+ }
+ /* perform the traversal */
+ if (!isLoggedIn(tok)) {
+ instances = nssToken_FindPublicKeys(token,
+ session,
+ tokenOnly,
+ 0, &status);
+ } else {
+ instances = nssToken_FindPrivateKeys(token,
+ session,
+ tokenOnly,
+ 0, &status);
+ }
+ nssToken_Destroy(token);
+ if (status != PR_SUCCESS) {
+ goto loser;
+ }
+ /* add the found certificates to the collection */
+ status = nssPKIObjectCollection_AddInstances(collection,
+ instances, 0);
+ nss_ZFreeIf(instances);
+ if (status != PR_SUCCESS) {
+ goto loser;
+ }
+ }
+ }
+ status = nssPKIObjectCollection_MatchCerts(collection);
+ if (status != PR_SUCCESS) {
+ goto loser;
+ }
/* Traverse the collection */
pkiCallback.func.cert = callback;
pkiCallback.arg = arg;
@@ -1116,6 +1214,7 @@ loser:
}
return NULL;
}
+#endif
NSS_IMPLEMENT NSSTrust *
nssTrustDomain_FindTrustForCertificate