Skip to content

Commit

Permalink
Token and cert processing fixes:
Browse files Browse the repository at this point in the history
   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).
  • Loading branch information
relyea%netscape.com committed Apr 22, 2002
1 parent 9b3253d commit bfcafb0
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 11 deletions.
8 changes: 1 addition & 7 deletions security/nss/lib/certdb/certdb.c
Expand Up @@ -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++;
}

Expand Down
27 changes: 27 additions & 0 deletions security/nss/lib/certhigh/certhigh.c
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions security/nss/lib/dev/devm.h
Expand Up @@ -134,6 +134,12 @@ nssToken_IsLoginRequired
NSSToken *token
);

NSS_EXTERN void
nssToken_Remove
(
NSSToken *token
);

NSS_EXTERN nssCryptokiObject *
nssCryptokiObject_Create
(
Expand All @@ -157,6 +163,12 @@ nssTokenObjectCache_Destroy
nssTokenObjectCache *cache
);

NSS_EXTERN void
nssTokenObjectCache_Clear
(
nssTokenObjectCache *cache
);

NSS_EXTERN PRBool
nssTokenObjectCache_HaveObjectClass
(
Expand Down
2 changes: 2 additions & 0 deletions security/nss/lib/dev/devslot.c
Expand Up @@ -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) {
Expand Down
9 changes: 9 additions & 0 deletions security/nss/lib/dev/devtoken.c
Expand Up @@ -160,6 +160,15 @@ nssToken_Destroy
return PR_SUCCESS;
}

NSS_IMPLEMENT void
nssToken_Remove
(
NSSToken *tok
)
{
nssTokenObjectCache_Clear(tok->cache);
}

NSS_IMPLEMENT void
NSSToken_Destroy
(
Expand Down
13 changes: 12 additions & 1 deletion security/nss/lib/dev/devutil.c
Expand Up @@ -619,6 +619,17 @@ clear_cache
}
}

NSS_IMPLEMENT void
nssTokenObjectCache_Clear
(
nssTokenObjectCache *cache
)
{
if (cache) {
clear_cache(cache);
}
}

NSS_IMPLEMENT void
nssTokenObjectCache_Destroy
(
Expand Down Expand Up @@ -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;
}
Expand Down
23 changes: 20 additions & 3 deletions security/nss/lib/pk11wrap/pk11cert.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
}
Expand Down
99 changes: 99 additions & 0 deletions security/nss/lib/pki/trustdomain.c
Expand Up @@ -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;
Expand All @@ -1116,6 +1214,7 @@ NSSTrustDomain_TraverseCertificates
}
return NULL;
}
#endif

NSS_IMPLEMENT NSSTrust *
nssTrustDomain_FindTrustForCertificate
Expand Down

0 comments on commit bfcafb0

Please sign in to comment.