diff options
Diffstat (limited to 'security/nss/lib/pki/tdcache.c')
-rw-r--r-- | security/nss/lib/pki/tdcache.c | 1150 |
1 files changed, 0 insertions, 1150 deletions
diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c deleted file mode 100644 index ff2d09ba1..000000000 --- a/security/nss/lib/pki/tdcache.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; -#endif /* DEBUG */ - -#ifndef PKIM_H -#include "pkim.h" -#endif /* PKIM_H */ - -#ifndef PKIT_H -#include "pkit.h" -#endif /* PKIT_H */ - -#ifndef NSSPKI_H -#include "nsspki.h" -#endif /* NSSPKI_H */ - -#ifndef PKI_H -#include "pki.h" -#endif /* PKI_H */ - -#ifndef NSSBASE_H -#include "nssbase.h" -#endif /* NSSBASE_H */ - -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ - -#include "cert.h" -#include "dev.h" -#include "pki3hack.h" - -#ifdef DEBUG_CACHE -static PRLogModuleInfo *s_log = NULL; -#endif - -#ifdef DEBUG_CACHE -static void log_item_dump(const char *msg, NSSItem *it) -{ - char buf[33]; - int i, j; - for (i=0; i<10 && i<it->size; i++) { - sprintf(&buf[2*i], "%02X", ((PRUint8 *)it->data)[i]); - } - if (it->size>10) { - sprintf(&buf[2*i], ".."); - i += 1; - for (j=it->size-1; i<=16 && j>10; i++, j--) { - sprintf(&buf[2*i], "%02X", ((PRUint8 *)it->data)[j]); - } - } - PR_LOG(s_log, PR_LOG_DEBUG, ("%s: %s", msg, buf)); -} -#endif - -#ifdef DEBUG_CACHE -static void log_cert_ref(const char *msg, NSSCertificate *c) -{ - PR_LOG(s_log, PR_LOG_DEBUG, ("%s: %s", msg, - (c->nickname) ? c->nickname : c->email)); - log_item_dump("\tserial", &c->serial); - log_item_dump("\tsubject", &c->subject); -} -#endif - -/* Certificate cache routines */ - -/* XXX - * Locking is not handled well at all. A single, global lock with sub-locks - * in the collection types. Cleanup needed. - */ - -/* should it live in its own arena? */ -struct nssTDCertificateCacheStr -{ - PZLock *lock; - NSSArena *arena; - nssHash *issuerAndSN; - nssHash *subject; - nssHash *nickname; - nssHash *email; -}; - -struct cache_entry_str -{ - union { - NSSCertificate *cert; - nssList *list; - void *value; - } entry; - PRUint32 hits; - PRTime lastHit; - NSSArena *arena; - NSSUTF8 *nickname; -}; - -typedef struct cache_entry_str cache_entry; - -static cache_entry * -new_cache_entry(NSSArena *arena, void *value, PRBool ownArena) -{ - cache_entry *ce = nss_ZNEW(arena, cache_entry); - if (ce) { - ce->entry.value = value; - ce->hits = 1; - ce->lastHit = PR_Now(); - if (ownArena) { - ce->arena = arena; - } - ce->nickname = NULL; - } - return ce; -} - -/* this should not be exposed in a header, but is here to keep the above - * types/functions static - */ -NSS_IMPLEMENT PRStatus -nssTrustDomain_InitializeCache ( - NSSTrustDomain *td, - PRUint32 cacheSize -) -{ - NSSArena *arena; - nssTDCertificateCache *cache = td->cache; -#ifdef DEBUG_CACHE - s_log = PR_NewLogModule("nss_cache"); - PR_ASSERT(s_log); -#endif - PR_ASSERT(!cache); - arena = nssArena_Create(); - if (!arena) { - return PR_FAILURE; - } - cache = nss_ZNEW(arena, nssTDCertificateCache); - if (!cache) { - nssArena_Destroy(arena); - return PR_FAILURE; - } - cache->lock = PZ_NewLock(nssILockCache); - if (!cache->lock) { - nssArena_Destroy(arena); - return PR_FAILURE; - } - /* Create the issuer and serial DER --> certificate hash */ - cache->issuerAndSN = nssHash_CreateCertificate(arena, cacheSize); - if (!cache->issuerAndSN) { - goto loser; - } - /* Create the subject DER --> subject list hash */ - cache->subject = nssHash_CreateItem(arena, cacheSize); - if (!cache->subject) { - goto loser; - } - /* Create the nickname --> subject list hash */ - cache->nickname = nssHash_CreateString(arena, cacheSize); - if (!cache->nickname) { - goto loser; - } - /* Create the email --> list of subject lists hash */ - cache->email = nssHash_CreateString(arena, cacheSize); - if (!cache->email) { - goto loser; - } - cache->arena = arena; - td->cache = cache; -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialized.")); -#endif - return PR_SUCCESS; -loser: - PZ_DestroyLock(cache->lock); - nssArena_Destroy(arena); - td->cache = NULL; -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialization failed.")); -#endif - return PR_FAILURE; -} - -/* The entries of the hashtable are currently dependent on the certificate(s) - * that produced them. That is, the entries will be freed when the cert is - * released from the cache. If there are certs in the cache at any time, - * including shutdown, the hash table entries will hold memory. In order for - * clean shutdown, it is necessary for there to be no certs in the cache. - */ - -extern const NSSError NSS_ERROR_INTERNAL_ERROR; -extern const NSSError NSS_ERROR_BUSY; - -NSS_IMPLEMENT PRStatus -nssTrustDomain_DestroyCache ( - NSSTrustDomain *td -) -{ - if (!td->cache) { - nss_SetError(NSS_ERROR_INTERNAL_ERROR); - return PR_FAILURE; - } - if (nssHash_Count(td->cache->issuerAndSN) > 0) { - nss_SetError(NSS_ERROR_BUSY); - return PR_FAILURE; - } - PZ_DestroyLock(td->cache->lock); - nssHash_Destroy(td->cache->issuerAndSN); - nssHash_Destroy(td->cache->subject); - nssHash_Destroy(td->cache->nickname); - nssHash_Destroy(td->cache->email); - nssArena_Destroy(td->cache->arena); - td->cache = NULL; -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("Cache destroyed.")); -#endif - return PR_SUCCESS; -} - -static PRStatus -remove_issuer_and_serial_entry ( - nssTDCertificateCache *cache, - NSSCertificate *cert -) -{ - /* Remove the cert from the issuer/serial hash */ - nssHash_Remove(cache->issuerAndSN, cert); -#ifdef DEBUG_CACHE - log_cert_ref("removed issuer/sn", cert); -#endif - return PR_SUCCESS; -} - -static PRStatus -remove_subject_entry ( - nssTDCertificateCache *cache, - NSSCertificate *cert, - nssList **subjectList, - NSSUTF8 **nickname, - NSSArena **arena -) -{ - PRStatus nssrv; - cache_entry *ce; - *subjectList = NULL; - *arena = NULL; - /* Get the subject list for the cert's subject */ - ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject); - if (ce) { - /* Remove the cert from the subject hash */ - nssList_Remove(ce->entry.list, cert); - *subjectList = ce->entry.list; - *nickname = ce->nickname; - *arena = ce->arena; - nssrv = PR_SUCCESS; -#ifdef DEBUG_CACHE - log_cert_ref("removed cert", cert); - log_item_dump("from subject list", &cert->subject); -#endif - } else { - nssrv = PR_FAILURE; - } - return nssrv; -} - -static PRStatus -remove_nickname_entry ( - nssTDCertificateCache *cache, - NSSUTF8 *nickname, - nssList *subjectList -) -{ - PRStatus nssrv; - if (nickname) { - nssHash_Remove(cache->nickname, nickname); - nssrv = PR_SUCCESS; -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("removed nickname %s", nickname)); -#endif - } else { - nssrv = PR_FAILURE; - } - return nssrv; -} - -static PRStatus -remove_email_entry ( - nssTDCertificateCache *cache, - NSSCertificate *cert, - nssList *subjectList -) -{ - PRStatus nssrv = PR_FAILURE; - cache_entry *ce; - /* Find the subject list in the email hash */ - if (cert->email) { - ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email); - if (ce) { - nssList *subjects = ce->entry.list; - /* Remove the subject list from the email hash */ - nssList_Remove(subjects, subjectList); -#ifdef DEBUG_CACHE - log_item_dump("removed subject list", &cert->subject); - PR_LOG(s_log, PR_LOG_DEBUG, ("for email %s", cert->email)); -#endif - if (nssList_Count(subjects) == 0) { - /* No more subject lists for email, delete list and - * remove hash entry - */ - (void)nssList_Destroy(subjects); - nssHash_Remove(cache->email, cert->email); - /* there are no entries left for this address, free space - * used for email entries - */ - nssArena_Destroy(ce->arena); -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("removed email %s", cert->email)); -#endif - } - nssrv = PR_SUCCESS; - } - } - return nssrv; -} - -NSS_IMPLEMENT void -nssTrustDomain_RemoveCertFromCacheLOCKED ( - NSSTrustDomain *td, - NSSCertificate *cert -) -{ - nssList *subjectList; - cache_entry *ce; - NSSArena *arena; - NSSUTF8 *nickname; - -#ifdef DEBUG_CACHE - log_cert_ref("attempt to remove cert", cert); -#endif - ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert); - if (!ce || ce->entry.cert != cert) { - /* If it's not in the cache, or a different cert is (this is really - * for safety reasons, though it shouldn't happen), do nothing - */ -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("but it wasn't in the cache")); -#endif - return; - } - (void)remove_issuer_and_serial_entry(td->cache, cert); - (void)remove_subject_entry(td->cache, cert, &subjectList, - &nickname, &arena); - if (nssList_Count(subjectList) == 0) { - (void)remove_nickname_entry(td->cache, nickname, subjectList); - (void)remove_email_entry(td->cache, cert, subjectList); - (void)nssList_Destroy(subjectList); - nssHash_Remove(td->cache->subject, &cert->subject); - /* there are no entries left for this subject, free the space used - * for both the nickname and subject entries - */ - if (arena) { - nssArena_Destroy(arena); - } - } -} - -NSS_IMPLEMENT void -nssTrustDomain_LockCertCache ( - NSSTrustDomain *td -) -{ - PZ_Lock(td->cache->lock); -} - -NSS_IMPLEMENT void -nssTrustDomain_UnlockCertCache ( - NSSTrustDomain *td -) -{ - PZ_Unlock(td->cache->lock); -} - -struct token_cert_dtor { - NSSToken *token; - nssTDCertificateCache *cache; - NSSCertificate **certs; - PRUint32 numCerts, arrSize; -}; - -static void -remove_token_certs(const void *k, void *v, void *a) -{ - NSSCertificate *c = (NSSCertificate *)k; - nssPKIObject *object = &c->object; - struct token_cert_dtor *dtor = a; - PRUint32 i; - nssPKIObject_Lock(object); - for (i=0; i<object->numInstances; i++) { - if (object->instances[i]->token == dtor->token) { - nssCryptokiObject_Destroy(object->instances[i]); - object->instances[i] = object->instances[object->numInstances-1]; - object->instances[object->numInstances-1] = NULL; - object->numInstances--; - dtor->certs[dtor->numCerts++] = c; - if (dtor->numCerts == dtor->arrSize) { - dtor->arrSize *= 2; - dtor->certs = nss_ZREALLOCARRAY(dtor->certs, - NSSCertificate *, - dtor->arrSize); - } - break; - } - } - nssPKIObject_Unlock(object); - return; -} - -/* - * Remove all certs for the given token from the cache. This is - * needed if the token is removed. - */ -NSS_IMPLEMENT PRStatus -nssTrustDomain_RemoveTokenCertsFromCache ( - NSSTrustDomain *td, - NSSToken *token -) -{ - NSSCertificate **certs; - PRUint32 i, arrSize = 10; - struct token_cert_dtor dtor; - certs = nss_ZNEWARRAY(NULL, NSSCertificate *, arrSize); - if (!certs) { - return PR_FAILURE; - } - dtor.cache = td->cache; - dtor.token = token; - dtor.certs = certs; - dtor.numCerts = 0; - dtor.arrSize = arrSize; - PZ_Lock(td->cache->lock); - nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, (void *)&dtor); - for (i=0; i<dtor.numCerts; i++) { - if (dtor.certs[i]->object.numInstances == 0) { - nssTrustDomain_RemoveCertFromCacheLOCKED(td, dtor.certs[i]); - dtor.certs[i] = NULL; /* skip this cert in the second for loop */ - } - } - PZ_Unlock(td->cache->lock); - for (i=0; i<dtor.numCerts; i++) { - if (dtor.certs[i]) { - STAN_ForceCERTCertificateUpdate(dtor.certs[i]); - } - } - nss_ZFreeIf(dtor.certs); - return PR_SUCCESS; -} - -NSS_IMPLEMENT PRStatus -nssTrustDomain_UpdateCachedTokenCerts ( - NSSTrustDomain *td, - NSSToken *token -) -{ - NSSCertificate **cp, **cached = NULL; - nssList *certList; - PRUint32 count; - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) return PR_FAILURE; - (void)nssTrustDomain_GetCertsFromCache(td, certList); - count = nssList_Count(certList); - if (count > 0) { - cached = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); - if (!cached) { - return PR_FAILURE; - } - nssList_GetArray(certList, (void **)cached, count); - nssList_Destroy(certList); - for (cp = cached; *cp; cp++) { - nssCryptokiObject *instance; - NSSCertificate *c = *cp; - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - instance = nssToken_FindCertificateByIssuerAndSerialNumber( - token, - NULL, - &c->issuer, - &c->serial, - tokenOnly, - NULL); - if (instance) { - nssPKIObject_AddInstance(&c->object, instance); - STAN_ForceCERTCertificateUpdate(c); - } - } - nssCertificateArray_Destroy(cached); - } - return PR_SUCCESS; -} - -static PRStatus -add_issuer_and_serial_entry ( - NSSArena *arena, - nssTDCertificateCache *cache, - NSSCertificate *cert -) -{ - cache_entry *ce; - ce = new_cache_entry(arena, (void *)cert, PR_FALSE); -#ifdef DEBUG_CACHE - log_cert_ref("added to issuer/sn", cert); -#endif - return nssHash_Add(cache->issuerAndSN, cert, (void *)ce); -} - -static PRStatus -add_subject_entry ( - NSSArena *arena, - nssTDCertificateCache *cache, - NSSCertificate *cert, - NSSUTF8 *nickname, - nssList **subjectList -) -{ - PRStatus nssrv; - nssList *list; - cache_entry *ce; - *subjectList = NULL; /* this is only set if a new one is created */ - ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject); - if (ce) { - ce->hits++; - ce->lastHit = PR_Now(); - /* The subject is already in, add this cert to the list */ - nssrv = nssList_AddUnique(ce->entry.list, cert); -#ifdef DEBUG_CACHE - log_cert_ref("added to existing subject list", cert); -#endif - } else { - NSSDER *subject; - /* Create a new subject list for the subject */ - list = nssList_Create(arena, PR_FALSE); - if (!list) { - return PR_FAILURE; - } - ce = new_cache_entry(arena, (void *)list, PR_TRUE); - if (!ce) { - return PR_FAILURE; - } - if (nickname) { - ce->nickname = nssUTF8_Duplicate(nickname, arena); - } - nssList_SetSortFunction(list, nssCertificate_SubjectListSort); - /* Add the cert entry to this list of subjects */ - nssrv = nssList_AddUnique(list, cert); - if (nssrv != PR_SUCCESS) { - return nssrv; - } - /* Add the subject list to the cache */ - subject = nssItem_Duplicate(&cert->subject, arena, NULL); - if (!subject) { - return PR_FAILURE; - } - nssrv = nssHash_Add(cache->subject, subject, ce); - if (nssrv != PR_SUCCESS) { - return nssrv; - } - *subjectList = list; -#ifdef DEBUG_CACHE - log_cert_ref("created subject list", cert); -#endif - } - return nssrv; -} - -static PRStatus -add_nickname_entry ( - NSSArena *arena, - nssTDCertificateCache *cache, - NSSUTF8 *certNickname, - nssList *subjectList -) -{ - PRStatus nssrv = PR_SUCCESS; - cache_entry *ce; - ce = (cache_entry *)nssHash_Lookup(cache->nickname, certNickname); - if (ce) { - /* This is a collision. A nickname entry already exists for this - * subject, but a subject entry didn't. This would imply there are - * two subjects using the same nickname, which is not allowed. - */ - return PR_FAILURE; - } else { - NSSUTF8 *nickname; - ce = new_cache_entry(arena, subjectList, PR_FALSE); - if (!ce) { - return PR_FAILURE; - } - nickname = nssUTF8_Duplicate(certNickname, arena); - if (!nickname) { - return PR_FAILURE; - } - nssrv = nssHash_Add(cache->nickname, nickname, ce); -#ifdef DEBUG_CACHE - log_cert_ref("created nickname for", cert); -#endif - } - return nssrv; -} - -static PRStatus -add_email_entry ( - nssTDCertificateCache *cache, - NSSCertificate *cert, - nssList *subjectList -) -{ - PRStatus nssrv = PR_SUCCESS; - nssList *subjects; - cache_entry *ce; - ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email); - if (ce) { - /* Already have an entry for this email address, but not subject */ - subjects = ce->entry.list; - nssrv = nssList_AddUnique(subjects, subjectList); - ce->hits++; - ce->lastHit = PR_Now(); -#ifdef DEBUG_CACHE - log_cert_ref("added subject to email for", cert); -#endif - } else { - NSSASCII7 *email; - NSSArena *arena; - arena = nssArena_Create(); - if (!arena) { - return PR_FAILURE; - } - /* Create a new list of subject lists, add this subject */ - subjects = nssList_Create(arena, PR_TRUE); - if (!subjects) { - nssArena_Destroy(arena); - return PR_FAILURE; - } - /* Add the new subject to the list */ - nssrv = nssList_AddUnique(subjects, subjectList); - if (nssrv != PR_SUCCESS) { - nssArena_Destroy(arena); - return nssrv; - } - /* Add the new entry to the cache */ - ce = new_cache_entry(arena, (void *)subjects, PR_TRUE); - if (!ce) { - nssArena_Destroy(arena); - return PR_FAILURE; - } - email = nssUTF8_Duplicate(cert->email, arena); - if (!email) { - nssArena_Destroy(arena); - return PR_FAILURE; - } - nssrv = nssHash_Add(cache->email, email, ce); - if (nssrv != PR_SUCCESS) { - nssArena_Destroy(arena); - return nssrv; - } -#ifdef DEBUG_CACHE - log_cert_ref("created email for", cert); -#endif - } - return nssrv; -} - -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, - NSSCertificate *cert -) -{ - NSSArena *arena = NULL; - nssList *subjectList = NULL; - PRStatus nssrv; - PRUint32 added = 0; - cache_entry *ce; - NSSCertificate *rvCert = NULL; - NSSUTF8 *certNickname = nssCertificate_GetNickname(cert, NULL); - - PZ_Lock(td->cache->lock); - /* If it exists in the issuer/serial hash, it's already in all */ - ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert); - if (ce) { - ce->hits++; - ce->lastHit = PR_Now(); - rvCert = nssCertificate_AddRef(ce->entry.cert); -#ifdef DEBUG_CACHE - log_cert_ref("attempted to add cert already in cache", cert); -#endif - PZ_Unlock(td->cache->lock); - nss_ZFreeIf(certNickname); - /* 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; - } - STAN_ForceCERTCertificateUpdate(rvCert); - nssCertificate_Destroy(cert); - return rvCert; - } - /* create a new cache entry for this cert within the cert's arena*/ - nssrv = add_issuer_and_serial_entry(cert->object.arena, td->cache, cert); - if (nssrv != PR_SUCCESS) { - goto loser; - } - added++; - /* create an arena for the nickname and subject entries */ - arena = nssArena_Create(); - if (!arena) { - goto loser; - } - /* create a new subject list for this cert, or add to existing */ - nssrv = add_subject_entry(arena, td->cache, cert, - certNickname, &subjectList); - if (nssrv != PR_SUCCESS) { - goto loser; - } - added++; - /* If a new subject entry was created, also need nickname and/or email */ - if (subjectList != NULL) { - PRBool handle = PR_FALSE; - if (certNickname) { - nssrv = add_nickname_entry(arena, td->cache, - certNickname, subjectList); - if (nssrv != PR_SUCCESS) { - goto loser; - } - handle = PR_TRUE; - added++; - } - if (cert->email) { - nssrv = add_email_entry(td->cache, cert, subjectList); - if (nssrv != PR_SUCCESS) { - goto loser; - } - handle = PR_TRUE; - added += 2; - } -#ifdef nodef - /* I think either a nickname or email address must be associated - * with the cert. However, certs are passed to NewTemp without - * either. This worked in the old code, so it must work now. - */ - if (!handle) { - /* Require either nickname or email handle */ - nssrv = PR_FAILURE; - goto loser; - } -#endif - } else { - /* A new subject entry was not created. arena is unused. */ - nssArena_Destroy(arena); - } - rvCert = cert; - PZ_Unlock(td->cache->lock); - nss_ZFreeIf(certNickname); - return rvCert; -loser: - nss_ZFreeIf(certNickname); - certNickname = NULL; - /* Remove any handles that have been created */ - subjectList = NULL; - if (added >= 1) { - (void)remove_issuer_and_serial_entry(td->cache, cert); - } - if (added >= 2) { - (void)remove_subject_entry(td->cache, cert, &subjectList, - &certNickname, &arena); - } - if (added == 3 || added == 5) { - (void)remove_nickname_entry(td->cache, certNickname, subjectList); - } - if (added >= 4) { - (void)remove_email_entry(td->cache, cert, subjectList); - } - if (subjectList) { - nssHash_Remove(td->cache->subject, &cert->subject); - nssList_Destroy(subjectList); - } - if (arena) { - nssArena_Destroy(arena); - } - PZ_Unlock(td->cache->lock); - return NULL; -} - -NSS_IMPLEMENT PRStatus -nssTrustDomain_AddCertsToCache ( - NSSTrustDomain *td, - NSSCertificate **certs, - PRUint32 numCerts -) -{ - PRUint32 i; - NSSCertificate *c; - for (i=0; i<numCerts && certs[i]; i++) { - c = add_cert_to_cache(td, certs[i]); - if (c == NULL) { - return PR_FAILURE; - } else { - certs[i] = c; - } - } - return PR_SUCCESS; -} - -static NSSCertificate ** -collect_subject_certs ( - nssList *subjectList, - nssList *rvCertListOpt -) -{ - NSSCertificate *c; - NSSCertificate **rvArray = NULL; - PRUint32 count; - nssCertificateList_AddReferences(subjectList); - if (rvCertListOpt) { - nssListIterator *iter = nssList_CreateIterator(subjectList); - if (!iter) { - return (NSSCertificate **)NULL; - } - for (c = (NSSCertificate *)nssListIterator_Start(iter); - c != (NSSCertificate *)NULL; - c = (NSSCertificate *)nssListIterator_Next(iter)) { - nssList_Add(rvCertListOpt, c); - } - nssListIterator_Finish(iter); - nssListIterator_Destroy(iter); - } else { - count = nssList_Count(subjectList); - rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1); - if (!rvArray) { - return (NSSCertificate **)NULL; - } - nssList_GetArray(subjectList, (void **)rvArray, count); - } - return rvArray; -} - -/* - * Find all cached certs with this subject. - */ -NSS_IMPLEMENT NSSCertificate ** -nssTrustDomain_GetCertsForSubjectFromCache ( - NSSTrustDomain *td, - NSSDER *subject, - nssList *certListOpt -) -{ - NSSCertificate **rvArray = NULL; - cache_entry *ce; -#ifdef DEBUG_CACHE - log_item_dump("looking for cert by subject", subject); -#endif - PZ_Lock(td->cache->lock); - ce = (cache_entry *)nssHash_Lookup(td->cache->subject, subject); - if (ce) { - ce->hits++; - ce->lastHit = PR_Now(); -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits)); -#endif - rvArray = collect_subject_certs(ce->entry.list, certListOpt); - } - PZ_Unlock(td->cache->lock); - return rvArray; -} - -/* - * Find all cached certs with this label. - */ -NSS_IMPLEMENT NSSCertificate ** -nssTrustDomain_GetCertsForNicknameFromCache ( - NSSTrustDomain *td, - const NSSUTF8 *nickname, - nssList *certListOpt -) -{ - NSSCertificate **rvArray = NULL; - cache_entry *ce; -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("looking for cert by nick %s", nickname)); -#endif - PZ_Lock(td->cache->lock); - ce = (cache_entry *)nssHash_Lookup(td->cache->nickname, nickname); - if (ce) { - ce->hits++; - ce->lastHit = PR_Now(); -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits)); -#endif - rvArray = collect_subject_certs(ce->entry.list, certListOpt); - } - PZ_Unlock(td->cache->lock); - return rvArray; -} - -/* - * Find all cached certs with this email address. - */ -NSS_IMPLEMENT NSSCertificate ** -nssTrustDomain_GetCertsForEmailAddressFromCache ( - NSSTrustDomain *td, - NSSASCII7 *email, - nssList *certListOpt -) -{ - NSSCertificate **rvArray = NULL; - cache_entry *ce; - nssList *collectList = NULL; - nssListIterator *iter = NULL; - nssList *subjectList; -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("looking for cert by email %s", email)); -#endif - PZ_Lock(td->cache->lock); - ce = (cache_entry *)nssHash_Lookup(td->cache->email, email); - if (ce) { - ce->hits++; - ce->lastHit = PR_Now(); -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits)); -#endif - /* loop over subject lists and get refs for certs */ - if (certListOpt) { - collectList = certListOpt; - } else { - collectList = nssList_Create(NULL, PR_FALSE); - if (!collectList) { - PZ_Unlock(td->cache->lock); - return NULL; - } - } - iter = nssList_CreateIterator(ce->entry.list); - if (!iter) { - PZ_Unlock(td->cache->lock); - if (!certListOpt) { - nssList_Destroy(collectList); - } - return NULL; - } - for (subjectList = (nssList *)nssListIterator_Start(iter); - subjectList != (nssList *)NULL; - subjectList = (nssList *)nssListIterator_Next(iter)) { - (void)collect_subject_certs(subjectList, collectList); - } - nssListIterator_Finish(iter); - nssListIterator_Destroy(iter); - } - PZ_Unlock(td->cache->lock); - if (!certListOpt && collectList) { - PRUint32 count = nssList_Count(collectList); - rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count); - if (rvArray) { - nssList_GetArray(collectList, (void **)rvArray, count); - } - nssList_Destroy(collectList); - } - return rvArray; -} - -/* - * Look for a specific cert in the cache - */ -NSS_IMPLEMENT NSSCertificate * -nssTrustDomain_GetCertForIssuerAndSNFromCache ( - NSSTrustDomain *td, - NSSDER *issuer, - NSSDER *serial -) -{ - NSSCertificate certkey; - NSSCertificate *rvCert = NULL; - cache_entry *ce; - certkey.issuer.data = issuer->data; - certkey.issuer.size = issuer->size; - certkey.serial.data = serial->data; - certkey.serial.size = serial->size; -#ifdef DEBUG_CACHE - log_item_dump("looking for cert by issuer/sn, issuer", issuer); - log_item_dump(" serial", serial); -#endif - PZ_Lock(td->cache->lock); - ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, &certkey); - if (ce) { - ce->hits++; - ce->lastHit = PR_Now(); - rvCert = nssCertificate_AddRef(ce->entry.cert); -#ifdef DEBUG_CACHE - PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits)); -#endif - } - PZ_Unlock(td->cache->lock); - return rvCert; -} - -static PRStatus -issuer_and_serial_from_encoding ( - NSSBER *encoding, - NSSDER *issuer, - NSSDER *serial -) -{ - SECItem derCert, derIssuer, derSerial; - SECStatus secrv; - derCert.data = (unsigned char *)encoding->data; - derCert.len = encoding->size; - secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer); - if (secrv != SECSuccess) { - return PR_FAILURE; - } - secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial); - if (secrv != SECSuccess) { - return PR_FAILURE; - } - issuer->data = derIssuer.data; - issuer->size = derIssuer.len; - serial->data = derSerial.data; - serial->size = derSerial.len; - return PR_SUCCESS; -} - -/* - * Look for a specific cert in the cache - */ -NSS_IMPLEMENT NSSCertificate * -nssTrustDomain_GetCertByDERFromCache ( - NSSTrustDomain *td, - NSSDER *der -) -{ - PRStatus nssrv = PR_FAILURE; - NSSDER issuer, serial; - NSSCertificate *rvCert; - nssrv = issuer_and_serial_from_encoding(der, &issuer, &serial); - if (nssrv != PR_SUCCESS) { - return NULL; - } -#ifdef DEBUG_CACHE - log_item_dump("looking for cert by DER", der); -#endif - rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, - &issuer, &serial); - PORT_Free(issuer.data); - PORT_Free(serial.data); - return rvCert; -} - -static void cert_iter(const void *k, void *v, void *a) -{ - nssList *certList = (nssList *)a; - NSSCertificate *c = (NSSCertificate *)k; - nssList_Add(certList, nssCertificate_AddRef(c)); -} - -NSS_EXTERN NSSCertificate ** -nssTrustDomain_GetCertsFromCache ( - NSSTrustDomain *td, - nssList *certListOpt -) -{ - NSSCertificate **rvArray = NULL; - nssList *certList; - if (certListOpt) { - certList = certListOpt; - } else { - certList = nssList_Create(NULL, PR_FALSE); - if (!certList) { - return NULL; - } - } - PZ_Lock(td->cache->lock); - nssHash_Iterate(td->cache->issuerAndSN, cert_iter, (void *)certList); - PZ_Unlock(td->cache->lock); - if (!certListOpt) { - PRUint32 count = nssList_Count(certList); - rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count); - nssList_GetArray(certList, (void **)rvArray, count); - /* array takes the references */ - nssList_Destroy(certList); - } - return rvArray; -} - -NSS_IMPLEMENT void -nssTrustDomain_DumpCacheInfo ( - NSSTrustDomain *td, - void (* cert_dump_iter)(const void *, void *, void *), - void *arg -) -{ - PZ_Lock(td->cache->lock); - nssHash_Iterate(td->cache->issuerAndSN, cert_dump_iter, arg); - PZ_Unlock(td->cache->lock); -} |