| Index: nss/lib/pki/pkibase.c
|
| diff --git a/nss/lib/pki/pkibase.c b/nss/lib/pki/pkibase.c
|
| deleted file mode 100644
|
| index 0e39e8ba6116a6f25d0f9662ac240c99eb85b29f..0000000000000000000000000000000000000000
|
| --- a/nss/lib/pki/pkibase.c
|
| +++ /dev/null
|
| @@ -1,1257 +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/. */
|
| -
|
| -#ifndef DEV_H
|
| -#include "dev.h"
|
| -#endif /* DEV_H */
|
| -
|
| -#ifndef PKIM_H
|
| -#include "pkim.h"
|
| -#endif /* PKIM_H */
|
| -
|
| -#include "pki3hack.h"
|
| -
|
| -extern const NSSError NSS_ERROR_NOT_FOUND;
|
| -
|
| -NSS_IMPLEMENT void
|
| -nssPKIObject_Lock(nssPKIObject * object)
|
| -{
|
| - switch (object->lockType) {
|
| - case nssPKIMonitor:
|
| - PZ_EnterMonitor(object->sync.mlock);
|
| - break;
|
| - case nssPKILock:
|
| - PZ_Lock(object->sync.lock);
|
| - break;
|
| - default:
|
| - PORT_Assert(0);
|
| - }
|
| -}
|
| -
|
| -NSS_IMPLEMENT void
|
| -nssPKIObject_Unlock(nssPKIObject * object)
|
| -{
|
| - switch (object->lockType) {
|
| - case nssPKIMonitor:
|
| - PZ_ExitMonitor(object->sync.mlock);
|
| - break;
|
| - case nssPKILock:
|
| - PZ_Unlock(object->sync.lock);
|
| - break;
|
| - default:
|
| - PORT_Assert(0);
|
| - }
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObject_NewLock(nssPKIObject * object, nssPKILockType lockType)
|
| -{
|
| - object->lockType = lockType;
|
| - switch (lockType) {
|
| - case nssPKIMonitor:
|
| - object->sync.mlock = PZ_NewMonitor(nssILockSSL);
|
| - return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE);
|
| - case nssPKILock:
|
| - object->sync.lock = PZ_NewLock(nssILockSSL);
|
| - return (object->sync.lock ? PR_SUCCESS : PR_FAILURE);
|
| - default:
|
| - PORT_Assert(0);
|
| - return PR_FAILURE;
|
| - }
|
| -}
|
| -
|
| -NSS_IMPLEMENT void
|
| -nssPKIObject_DestroyLock(nssPKIObject * object)
|
| -{
|
| - switch (object->lockType) {
|
| - case nssPKIMonitor:
|
| - PZ_DestroyMonitor(object->sync.mlock);
|
| - object->sync.mlock = NULL;
|
| - break;
|
| - case nssPKILock:
|
| - PZ_DestroyLock(object->sync.lock);
|
| - object->sync.lock = NULL;
|
| - break;
|
| - default:
|
| - PORT_Assert(0);
|
| - }
|
| -}
|
| -
|
| -
|
| -
|
| -NSS_IMPLEMENT nssPKIObject *
|
| -nssPKIObject_Create (
|
| - NSSArena *arenaOpt,
|
| - nssCryptokiObject *instanceOpt,
|
| - NSSTrustDomain *td,
|
| - NSSCryptoContext *cc,
|
| - nssPKILockType lockType
|
| -)
|
| -{
|
| - NSSArena *arena;
|
| - nssArenaMark *mark = NULL;
|
| - nssPKIObject *object;
|
| - if (arenaOpt) {
|
| - arena = arenaOpt;
|
| - mark = nssArena_Mark(arena);
|
| - } else {
|
| - arena = nssArena_Create();
|
| - if (!arena) {
|
| - return (nssPKIObject *)NULL;
|
| - }
|
| - }
|
| - object = nss_ZNEW(arena, nssPKIObject);
|
| - if (!object) {
|
| - goto loser;
|
| - }
|
| - object->arena = arena;
|
| - object->trustDomain = td; /* XXX */
|
| - object->cryptoContext = cc;
|
| - if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) {
|
| - goto loser;
|
| - }
|
| - if (instanceOpt) {
|
| - if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) {
|
| - goto loser;
|
| - }
|
| - }
|
| - PR_ATOMIC_INCREMENT(&object->refCount);
|
| - if (mark) {
|
| - nssArena_Unmark(arena, mark);
|
| - }
|
| - return object;
|
| -loser:
|
| - if (mark) {
|
| - nssArena_Release(arena, mark);
|
| - } else {
|
| - nssArena_Destroy(arena);
|
| - }
|
| - return (nssPKIObject *)NULL;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRBool
|
| -nssPKIObject_Destroy (
|
| - nssPKIObject *object
|
| -)
|
| -{
|
| - PRUint32 i;
|
| - PR_ASSERT(object->refCount > 0);
|
| - if (PR_ATOMIC_DECREMENT(&object->refCount) == 0) {
|
| - for (i=0; i<object->numInstances; i++) {
|
| - nssCryptokiObject_Destroy(object->instances[i]);
|
| - }
|
| - nssPKIObject_DestroyLock(object);
|
| - nssArena_Destroy(object->arena);
|
| - return PR_TRUE;
|
| - }
|
| - return PR_FALSE;
|
| -}
|
| -
|
| -NSS_IMPLEMENT nssPKIObject *
|
| -nssPKIObject_AddRef (
|
| - nssPKIObject *object
|
| -)
|
| -{
|
| - PR_ATOMIC_INCREMENT(&object->refCount);
|
| - return object;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObject_AddInstance (
|
| - nssPKIObject *object,
|
| - nssCryptokiObject *instance
|
| -)
|
| -{
|
| - nssCryptokiObject **newInstances = NULL;
|
| -
|
| - nssPKIObject_Lock(object);
|
| - if (object->numInstances == 0) {
|
| - newInstances = nss_ZNEWARRAY(object->arena,
|
| - nssCryptokiObject *,
|
| - object->numInstances + 1);
|
| - } else {
|
| - PRBool found = PR_FALSE;
|
| - PRUint32 i;
|
| - for (i=0; i<object->numInstances; i++) {
|
| - if (nssCryptokiObject_Equal(object->instances[i], instance)) {
|
| - found = PR_TRUE;
|
| - break;
|
| - }
|
| - }
|
| - if (found) {
|
| - /* The new instance is identical to one in the array, except
|
| - * perhaps that the label may be different. So replace
|
| - * the label in the array instance with the label from the
|
| - * new instance, and discard the new instance.
|
| - */
|
| - nss_ZFreeIf(object->instances[i]->label);
|
| - object->instances[i]->label = instance->label;
|
| - nssPKIObject_Unlock(object);
|
| - instance->label = NULL;
|
| - nssCryptokiObject_Destroy(instance);
|
| - return PR_SUCCESS;
|
| - }
|
| - newInstances = nss_ZREALLOCARRAY(object->instances,
|
| - nssCryptokiObject *,
|
| - object->numInstances + 1);
|
| - }
|
| - if (newInstances) {
|
| - object->instances = newInstances;
|
| - newInstances[object->numInstances++] = instance;
|
| - }
|
| - nssPKIObject_Unlock(object);
|
| - return (newInstances ? PR_SUCCESS : PR_FAILURE);
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRBool
|
| -nssPKIObject_HasInstance (
|
| - nssPKIObject *object,
|
| - nssCryptokiObject *instance
|
| -)
|
| -{
|
| - PRUint32 i;
|
| - PRBool hasIt = PR_FALSE;;
|
| - nssPKIObject_Lock(object);
|
| - for (i=0; i<object->numInstances; i++) {
|
| - if (nssCryptokiObject_Equal(object->instances[i], instance)) {
|
| - hasIt = PR_TRUE;
|
| - break;
|
| - }
|
| - }
|
| - nssPKIObject_Unlock(object);
|
| - return hasIt;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObject_RemoveInstanceForToken (
|
| - nssPKIObject *object,
|
| - NSSToken *token
|
| -)
|
| -{
|
| - PRUint32 i;
|
| - nssCryptokiObject *instanceToRemove = NULL;
|
| - nssPKIObject_Lock(object);
|
| - if (object->numInstances == 0) {
|
| - nssPKIObject_Unlock(object);
|
| - return PR_SUCCESS;
|
| - }
|
| - for (i=0; i<object->numInstances; i++) {
|
| - if (object->instances[i]->token == token) {
|
| - instanceToRemove = object->instances[i];
|
| - object->instances[i] = object->instances[object->numInstances-1];
|
| - object->instances[object->numInstances-1] = NULL;
|
| - break;
|
| - }
|
| - }
|
| - if (--object->numInstances > 0) {
|
| - nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances,
|
| - nssCryptokiObject *,
|
| - object->numInstances);
|
| - if (instances) {
|
| - object->instances = instances;
|
| - }
|
| - } else {
|
| - nss_ZFreeIf(object->instances);
|
| - }
|
| - nssCryptokiObject_Destroy(instanceToRemove);
|
| - nssPKIObject_Unlock(object);
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -/* this needs more thought on what will happen when there are multiple
|
| - * instances
|
| - */
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObject_DeleteStoredObject (
|
| - nssPKIObject *object,
|
| - NSSCallback *uhh,
|
| - PRBool isFriendly
|
| -)
|
| -{
|
| - PRUint32 i, numNotDestroyed;
|
| - PRStatus status = PR_SUCCESS;
|
| - numNotDestroyed = 0;
|
| - nssPKIObject_Lock(object);
|
| - for (i=0; i<object->numInstances; i++) {
|
| - nssCryptokiObject *instance = object->instances[i];
|
| - status = nssToken_DeleteStoredObject(instance);
|
| - object->instances[i] = NULL;
|
| - if (status == PR_SUCCESS) {
|
| - nssCryptokiObject_Destroy(instance);
|
| - } else {
|
| - object->instances[numNotDestroyed++] = instance;
|
| - }
|
| - }
|
| - if (numNotDestroyed == 0) {
|
| - nss_ZFreeIf(object->instances);
|
| - object->numInstances = 0;
|
| - } else {
|
| - object->numInstances = numNotDestroyed;
|
| - }
|
| - nssPKIObject_Unlock(object);
|
| - return status;
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSToken **
|
| -nssPKIObject_GetTokens (
|
| - nssPKIObject *object,
|
| - PRStatus *statusOpt
|
| -)
|
| -{
|
| - NSSToken **tokens = NULL;
|
| - nssPKIObject_Lock(object);
|
| - if (object->numInstances > 0) {
|
| - tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1);
|
| - if (tokens) {
|
| - PRUint32 i;
|
| - for (i=0; i<object->numInstances; i++) {
|
| - tokens[i] = nssToken_AddRef(object->instances[i]->token);
|
| - }
|
| - }
|
| - }
|
| - nssPKIObject_Unlock(object);
|
| - if (statusOpt) *statusOpt = PR_SUCCESS; /* until more logic here */
|
| - return tokens;
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSUTF8 *
|
| -nssPKIObject_GetNicknameForToken (
|
| - nssPKIObject *object,
|
| - NSSToken *tokenOpt
|
| -)
|
| -{
|
| - PRUint32 i;
|
| - NSSUTF8 *nickname = NULL;
|
| - nssPKIObject_Lock(object);
|
| - for (i=0; i<object->numInstances; i++) {
|
| - if ((!tokenOpt && object->instances[i]->label) ||
|
| - (object->instances[i]->token == tokenOpt))
|
| - {
|
| - /* Must copy, see bug 745548 */
|
| - nickname = nssUTF8_Duplicate(object->instances[i]->label, NULL);
|
| - break;
|
| - }
|
| - }
|
| - nssPKIObject_Unlock(object);
|
| - return nickname;
|
| -}
|
| -
|
| -NSS_IMPLEMENT nssCryptokiObject **
|
| -nssPKIObject_GetInstances (
|
| - nssPKIObject *object
|
| -)
|
| -{
|
| - nssCryptokiObject **instances = NULL;
|
| - PRUint32 i;
|
| - if (object->numInstances == 0) {
|
| - return (nssCryptokiObject **)NULL;
|
| - }
|
| - nssPKIObject_Lock(object);
|
| - instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *,
|
| - object->numInstances + 1);
|
| - if (instances) {
|
| - for (i=0; i<object->numInstances; i++) {
|
| - instances[i] = nssCryptokiObject_Clone(object->instances[i]);
|
| - }
|
| - }
|
| - nssPKIObject_Unlock(object);
|
| - return instances;
|
| -}
|
| -
|
| -NSS_IMPLEMENT void
|
| -nssCertificateArray_Destroy (
|
| - NSSCertificate **certs
|
| -)
|
| -{
|
| - if (certs) {
|
| - NSSCertificate **certp;
|
| - for (certp = certs; *certp; certp++) {
|
| - if ((*certp)->decoding) {
|
| - CERTCertificate *cc = STAN_GetCERTCertificate(*certp);
|
| - if (cc) {
|
| - CERT_DestroyCertificate(cc);
|
| - }
|
| - continue;
|
| - }
|
| - nssCertificate_Destroy(*certp);
|
| - }
|
| - nss_ZFreeIf(certs);
|
| - }
|
| -}
|
| -
|
| -NSS_IMPLEMENT void
|
| -NSSCertificateArray_Destroy (
|
| - NSSCertificate **certs
|
| -)
|
| -{
|
| - nssCertificateArray_Destroy(certs);
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSCertificate **
|
| -nssCertificateArray_Join (
|
| - NSSCertificate **certs1,
|
| - NSSCertificate **certs2
|
| -)
|
| -{
|
| - if (certs1 && certs2) {
|
| - NSSCertificate **certs, **cp;
|
| - PRUint32 count = 0;
|
| - PRUint32 count1 = 0;
|
| - cp = certs1;
|
| - while (*cp++) count1++;
|
| - count = count1;
|
| - cp = certs2;
|
| - while (*cp++) count++;
|
| - certs = nss_ZREALLOCARRAY(certs1, NSSCertificate *, count + 1);
|
| - if (!certs) {
|
| - nss_ZFreeIf(certs1);
|
| - nss_ZFreeIf(certs2);
|
| - return (NSSCertificate **)NULL;
|
| - }
|
| - for (cp = certs2; *cp; cp++, count1++) {
|
| - certs[count1] = *cp;
|
| - }
|
| - nss_ZFreeIf(certs2);
|
| - return certs;
|
| - } else if (certs1) {
|
| - return certs1;
|
| - } else {
|
| - return certs2;
|
| - }
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSCertificate *
|
| -nssCertificateArray_FindBestCertificate (
|
| - NSSCertificate **certs,
|
| - NSSTime *timeOpt,
|
| - const NSSUsage *usage,
|
| - NSSPolicies *policiesOpt
|
| -)
|
| -{
|
| - NSSCertificate *bestCert = NULL;
|
| - nssDecodedCert *bestdc = NULL;
|
| - NSSTime *time, sTime;
|
| - PRBool bestCertMatches = PR_FALSE;
|
| - PRBool thisCertMatches;
|
| - PRBool bestCertIsValidAtTime = PR_FALSE;
|
| - PRBool bestCertIsTrusted = PR_FALSE;
|
| -
|
| - if (timeOpt) {
|
| - time = timeOpt;
|
| - } else {
|
| - NSSTime_Now(&sTime);
|
| - time = &sTime;
|
| - }
|
| - if (!certs) {
|
| - return (NSSCertificate *)NULL;
|
| - }
|
| - for (; *certs; certs++) {
|
| - nssDecodedCert *dc;
|
| - NSSCertificate *c = *certs;
|
| - dc = nssCertificate_GetDecoding(c);
|
| - if (!dc) continue;
|
| - thisCertMatches = dc->matchUsage(dc, usage);
|
| - if (!bestCert) {
|
| - /* always take the first cert, but remember whether or not
|
| - * the usage matched
|
| - */
|
| - bestCert = nssCertificate_AddRef(c);
|
| - bestCertMatches = thisCertMatches;
|
| - bestdc = dc;
|
| - continue;
|
| - } else {
|
| - if (bestCertMatches && !thisCertMatches) {
|
| - /* if already have a cert for this usage, and if this cert
|
| - * doesn't have the correct usage, continue
|
| - */
|
| - continue;
|
| - } else if (!bestCertMatches && thisCertMatches) {
|
| - /* this one does match usage, replace the other */
|
| - nssCertificate_Destroy(bestCert);
|
| - bestCert = nssCertificate_AddRef(c);
|
| - bestCertMatches = thisCertMatches;
|
| - bestdc = dc;
|
| - continue;
|
| - }
|
| - /* this cert match as well as any cert we've found so far,
|
| - * defer to time/policies
|
| - * */
|
| - }
|
| - /* time */
|
| - if (bestCertIsValidAtTime || bestdc->isValidAtTime(bestdc, time)) {
|
| - /* The current best cert is valid at time */
|
| - bestCertIsValidAtTime = PR_TRUE;
|
| - if (!dc->isValidAtTime(dc, time)) {
|
| - /* If the new cert isn't valid at time, it's not better */
|
| - continue;
|
| - }
|
| - } else {
|
| - /* The current best cert is not valid at time */
|
| - if (dc->isValidAtTime(dc, time)) {
|
| - /* If the new cert is valid at time, it's better */
|
| - nssCertificate_Destroy(bestCert);
|
| - bestCert = nssCertificate_AddRef(c);
|
| - bestdc = dc;
|
| - bestCertIsValidAtTime = PR_TRUE;
|
| - continue;
|
| - }
|
| - }
|
| - /* Either they are both valid at time, or neither valid.
|
| - * If only one is trusted for this usage, take it.
|
| - */
|
| - if (bestCertIsTrusted || bestdc->isTrustedForUsage(bestdc, usage)) {
|
| - bestCertIsTrusted = PR_TRUE;
|
| - if (!dc->isTrustedForUsage(dc, usage)) {
|
| - continue;
|
| - }
|
| - } else {
|
| - /* The current best cert is not trusted */
|
| - if (dc->isTrustedForUsage(dc, usage)) {
|
| - /* If the new cert is trusted, it's better */
|
| - nssCertificate_Destroy(bestCert);
|
| - bestCert = nssCertificate_AddRef(c);
|
| - bestdc = dc;
|
| - bestCertIsTrusted = PR_TRUE;
|
| - continue;
|
| - }
|
| - }
|
| - /* Otherwise, take the newer one. */
|
| - if (!bestdc->isNewerThan(bestdc, dc)) {
|
| - nssCertificate_Destroy(bestCert);
|
| - bestCert = nssCertificate_AddRef(c);
|
| - bestdc = dc;
|
| - continue;
|
| - }
|
| - /* policies */
|
| - /* XXX later -- defer to policies */
|
| - }
|
| - return bestCert;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssCertificateArray_Traverse (
|
| - NSSCertificate **certs,
|
| - PRStatus (* callback)(NSSCertificate *c, void *arg),
|
| - void *arg
|
| -)
|
| -{
|
| - PRStatus status = PR_SUCCESS;
|
| - if (certs) {
|
| - NSSCertificate **certp;
|
| - for (certp = certs; *certp; certp++) {
|
| - status = (*callback)(*certp, arg);
|
| - if (status != PR_SUCCESS) {
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - return status;
|
| -}
|
| -
|
| -
|
| -NSS_IMPLEMENT void
|
| -nssCRLArray_Destroy (
|
| - NSSCRL **crls
|
| -)
|
| -{
|
| - if (crls) {
|
| - NSSCRL **crlp;
|
| - for (crlp = crls; *crlp; crlp++) {
|
| - nssCRL_Destroy(*crlp);
|
| - }
|
| - nss_ZFreeIf(crls);
|
| - }
|
| -}
|
| -
|
| -/*
|
| - * Object collections
|
| - */
|
| -
|
| -typedef enum
|
| -{
|
| - pkiObjectType_Certificate = 0,
|
| - pkiObjectType_CRL = 1,
|
| - pkiObjectType_PrivateKey = 2,
|
| - pkiObjectType_PublicKey = 3
|
| -} pkiObjectType;
|
| -
|
| -/* Each object is defined by a set of items that uniquely identify it.
|
| - * Here are the uid sets:
|
| - *
|
| - * NSSCertificate ==> { issuer, serial }
|
| - * NSSPrivateKey
|
| - * (RSA) ==> { modulus, public exponent }
|
| - *
|
| - */
|
| -#define MAX_ITEMS_FOR_UID 2
|
| -
|
| -/* pkiObjectCollectionNode
|
| - *
|
| - * A node in the collection is the set of unique identifiers for a single
|
| - * object, along with either the actual object or a proto-object.
|
| - */
|
| -typedef struct
|
| -{
|
| - PRCList link;
|
| - PRBool haveObject;
|
| - nssPKIObject *object;
|
| - NSSItem uid[MAX_ITEMS_FOR_UID];
|
| -}
|
| -pkiObjectCollectionNode;
|
| -
|
| -/* nssPKIObjectCollection
|
| - *
|
| - * The collection is the set of all objects, plus the interfaces needed
|
| - * to manage the objects.
|
| - *
|
| - */
|
| -struct nssPKIObjectCollectionStr
|
| -{
|
| - NSSArena *arena;
|
| - NSSTrustDomain *td;
|
| - NSSCryptoContext *cc;
|
| - PRCList head; /* list of pkiObjectCollectionNode's */
|
| - PRUint32 size;
|
| - pkiObjectType objectType;
|
| - void (* destroyObject)(nssPKIObject *o);
|
| - PRStatus (* getUIDFromObject)(nssPKIObject *o, NSSItem *uid);
|
| - PRStatus (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid,
|
| - NSSArena *arena);
|
| - nssPKIObject * (* createObject)(nssPKIObject *o);
|
| - nssPKILockType lockType; /* type of lock to use for new proto-objects */
|
| -};
|
| -
|
| -static nssPKIObjectCollection *
|
| -nssPKIObjectCollection_Create (
|
| - NSSTrustDomain *td,
|
| - NSSCryptoContext *ccOpt,
|
| - nssPKILockType lockType
|
| -)
|
| -{
|
| - NSSArena *arena;
|
| - nssPKIObjectCollection *rvCollection = NULL;
|
| - arena = nssArena_Create();
|
| - if (!arena) {
|
| - return (nssPKIObjectCollection *)NULL;
|
| - }
|
| - rvCollection = nss_ZNEW(arena, nssPKIObjectCollection);
|
| - if (!rvCollection) {
|
| - goto loser;
|
| - }
|
| - PR_INIT_CLIST(&rvCollection->head);
|
| - rvCollection->arena = arena;
|
| - rvCollection->td = td; /* XXX */
|
| - rvCollection->cc = ccOpt;
|
| - rvCollection->lockType = lockType;
|
| - return rvCollection;
|
| -loser:
|
| - nssArena_Destroy(arena);
|
| - return (nssPKIObjectCollection *)NULL;
|
| -}
|
| -
|
| -NSS_IMPLEMENT void
|
| -nssPKIObjectCollection_Destroy (
|
| - nssPKIObjectCollection *collection
|
| -)
|
| -{
|
| - if (collection) {
|
| - PRCList *link;
|
| - pkiObjectCollectionNode *node;
|
| - /* first destroy any objects in the collection */
|
| - link = PR_NEXT_LINK(&collection->head);
|
| - while (link != &collection->head) {
|
| - node = (pkiObjectCollectionNode *)link;
|
| - if (node->haveObject) {
|
| - (*collection->destroyObject)(node->object);
|
| - } else {
|
| - nssPKIObject_Destroy(node->object);
|
| - }
|
| - link = PR_NEXT_LINK(link);
|
| - }
|
| - /* then destroy it */
|
| - nssArena_Destroy(collection->arena);
|
| - }
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRUint32
|
| -nssPKIObjectCollection_Count (
|
| - nssPKIObjectCollection *collection
|
| -)
|
| -{
|
| - return collection->size;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObjectCollection_AddObject (
|
| - nssPKIObjectCollection *collection,
|
| - nssPKIObject *object
|
| -)
|
| -{
|
| - pkiObjectCollectionNode *node;
|
| - node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
|
| - if (!node) {
|
| - return PR_FAILURE;
|
| - }
|
| - node->haveObject = PR_TRUE;
|
| - node->object = nssPKIObject_AddRef(object);
|
| - (*collection->getUIDFromObject)(object, node->uid);
|
| - PR_INIT_CLIST(&node->link);
|
| - PR_INSERT_BEFORE(&node->link, &collection->head);
|
| - collection->size++;
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -static pkiObjectCollectionNode *
|
| -find_instance_in_collection (
|
| - nssPKIObjectCollection *collection,
|
| - nssCryptokiObject *instance
|
| -)
|
| -{
|
| - PRCList *link;
|
| - pkiObjectCollectionNode *node;
|
| - link = PR_NEXT_LINK(&collection->head);
|
| - while (link != &collection->head) {
|
| - node = (pkiObjectCollectionNode *)link;
|
| - if (nssPKIObject_HasInstance(node->object, instance)) {
|
| - return node;
|
| - }
|
| - link = PR_NEXT_LINK(link);
|
| - }
|
| - return (pkiObjectCollectionNode *)NULL;
|
| -}
|
| -
|
| -static pkiObjectCollectionNode *
|
| -find_object_in_collection (
|
| - nssPKIObjectCollection *collection,
|
| - NSSItem *uid
|
| -)
|
| -{
|
| - PRUint32 i;
|
| - PRStatus status;
|
| - PRCList *link;
|
| - pkiObjectCollectionNode *node;
|
| - link = PR_NEXT_LINK(&collection->head);
|
| - while (link != &collection->head) {
|
| - node = (pkiObjectCollectionNode *)link;
|
| - for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
|
| - if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) {
|
| - break;
|
| - }
|
| - }
|
| - if (i == MAX_ITEMS_FOR_UID) {
|
| - return node;
|
| - }
|
| - link = PR_NEXT_LINK(link);
|
| - }
|
| - return (pkiObjectCollectionNode *)NULL;
|
| -}
|
| -
|
| -static pkiObjectCollectionNode *
|
| -add_object_instance (
|
| - nssPKIObjectCollection *collection,
|
| - nssCryptokiObject *instance,
|
| - PRBool *foundIt
|
| -)
|
| -{
|
| - PRUint32 i;
|
| - PRStatus status;
|
| - pkiObjectCollectionNode *node;
|
| - nssArenaMark *mark = NULL;
|
| - NSSItem uid[MAX_ITEMS_FOR_UID];
|
| - nsslibc_memset(uid, 0, sizeof uid);
|
| - /* The list is traversed twice, first (here) looking to match the
|
| - * { token, handle } tuple, and if that is not found, below a search
|
| - * for unique identifier is done. Here, a match means this exact object
|
| - * instance is already in the collection, and we have nothing to do.
|
| - */
|
| - *foundIt = PR_FALSE;
|
| - node = find_instance_in_collection(collection, instance);
|
| - if (node) {
|
| - /* The collection is assumed to take over the instance. Since we
|
| - * are not using it, it must be destroyed.
|
| - */
|
| - nssCryptokiObject_Destroy(instance);
|
| - *foundIt = PR_TRUE;
|
| - return node;
|
| - }
|
| - mark = nssArena_Mark(collection->arena);
|
| - if (!mark) {
|
| - goto loser;
|
| - }
|
| - status = (*collection->getUIDFromInstance)(instance, uid,
|
| - collection->arena);
|
| - if (status != PR_SUCCESS) {
|
| - goto loser;
|
| - }
|
| - /* Search for unique identifier. A match here means the object exists
|
| - * in the collection, but does not have this instance, so the instance
|
| - * needs to be added.
|
| - */
|
| - node = find_object_in_collection(collection, uid);
|
| - if (node) {
|
| - /* This is an object with multiple instances */
|
| - status = nssPKIObject_AddInstance(node->object, instance);
|
| - } else {
|
| - /* This is a completely new object. Create a node for it. */
|
| - node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
|
| - if (!node) {
|
| - goto loser;
|
| - }
|
| - node->object = nssPKIObject_Create(NULL, instance,
|
| - collection->td, collection->cc,
|
| - collection->lockType);
|
| - if (!node->object) {
|
| - goto loser;
|
| - }
|
| - for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
|
| - node->uid[i] = uid[i];
|
| - }
|
| - node->haveObject = PR_FALSE;
|
| - PR_INIT_CLIST(&node->link);
|
| - PR_INSERT_BEFORE(&node->link, &collection->head);
|
| - collection->size++;
|
| - status = PR_SUCCESS;
|
| - }
|
| - nssArena_Unmark(collection->arena, mark);
|
| - return node;
|
| -loser:
|
| - if (mark) {
|
| - nssArena_Release(collection->arena, mark);
|
| - }
|
| - nssCryptokiObject_Destroy(instance);
|
| - return (pkiObjectCollectionNode *)NULL;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObjectCollection_AddInstances (
|
| - nssPKIObjectCollection *collection,
|
| - nssCryptokiObject **instances,
|
| - PRUint32 numInstances
|
| -)
|
| -{
|
| - PRStatus status = PR_SUCCESS;
|
| - PRUint32 i = 0;
|
| - PRBool foundIt;
|
| - pkiObjectCollectionNode *node;
|
| - if (instances) {
|
| - while ((!numInstances || i < numInstances) && *instances) {
|
| - if (status == PR_SUCCESS) {
|
| - node = add_object_instance(collection, *instances, &foundIt);
|
| - if (node == NULL) {
|
| - /* add_object_instance freed the current instance */
|
| - /* free the remaining instances */
|
| - status = PR_FAILURE;
|
| - }
|
| - } else {
|
| - nssCryptokiObject_Destroy(*instances);
|
| - }
|
| - instances++;
|
| - i++;
|
| - }
|
| - }
|
| - return status;
|
| -}
|
| -
|
| -static void
|
| -nssPKIObjectCollection_RemoveNode (
|
| - nssPKIObjectCollection *collection,
|
| - pkiObjectCollectionNode *node
|
| -)
|
| -{
|
| - PR_REMOVE_LINK(&node->link);
|
| - collection->size--;
|
| -}
|
| -
|
| -static PRStatus
|
| -nssPKIObjectCollection_GetObjects (
|
| - nssPKIObjectCollection *collection,
|
| - nssPKIObject **rvObjects,
|
| - PRUint32 rvSize
|
| -)
|
| -{
|
| - PRUint32 i = 0;
|
| - PRCList *link = PR_NEXT_LINK(&collection->head);
|
| - pkiObjectCollectionNode *node;
|
| - int error=0;
|
| - while ((i < rvSize) && (link != &collection->head)) {
|
| - node = (pkiObjectCollectionNode *)link;
|
| - if (!node->haveObject) {
|
| - /* Convert the proto-object to an object */
|
| - node->object = (*collection->createObject)(node->object);
|
| - if (!node->object) {
|
| - link = PR_NEXT_LINK(link);
|
| - /*remove bogus object from list*/
|
| - nssPKIObjectCollection_RemoveNode(collection,node);
|
| - error++;
|
| - continue;
|
| - }
|
| - node->haveObject = PR_TRUE;
|
| - }
|
| - rvObjects[i++] = nssPKIObject_AddRef(node->object);
|
| - link = PR_NEXT_LINK(link);
|
| - }
|
| - if (!error && *rvObjects == NULL) {
|
| - nss_SetError(NSS_ERROR_NOT_FOUND);
|
| - }
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObjectCollection_Traverse (
|
| - nssPKIObjectCollection *collection,
|
| - nssPKIObjectCallback *callback
|
| -)
|
| -{
|
| - PRCList *link = PR_NEXT_LINK(&collection->head);
|
| - pkiObjectCollectionNode *node;
|
| - while (link != &collection->head) {
|
| - node = (pkiObjectCollectionNode *)link;
|
| - if (!node->haveObject) {
|
| - node->object = (*collection->createObject)(node->object);
|
| - if (!node->object) {
|
| - link = PR_NEXT_LINK(link);
|
| - /*remove bogus object from list*/
|
| - nssPKIObjectCollection_RemoveNode(collection,node);
|
| - continue;
|
| - }
|
| - node->haveObject = PR_TRUE;
|
| - }
|
| - switch (collection->objectType) {
|
| - case pkiObjectType_Certificate:
|
| - (void)(*callback->func.cert)((NSSCertificate *)node->object,
|
| - callback->arg);
|
| - break;
|
| - case pkiObjectType_CRL:
|
| - (void)(*callback->func.crl)((NSSCRL *)node->object,
|
| - callback->arg);
|
| - break;
|
| - case pkiObjectType_PrivateKey:
|
| - (void)(*callback->func.pvkey)((NSSPrivateKey *)node->object,
|
| - callback->arg);
|
| - break;
|
| - case pkiObjectType_PublicKey:
|
| - (void)(*callback->func.pbkey)((NSSPublicKey *)node->object,
|
| - callback->arg);
|
| - break;
|
| - }
|
| - link = PR_NEXT_LINK(link);
|
| - }
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRStatus
|
| -nssPKIObjectCollection_AddInstanceAsObject (
|
| - nssPKIObjectCollection *collection,
|
| - nssCryptokiObject *instance
|
| -)
|
| -{
|
| - pkiObjectCollectionNode *node;
|
| - PRBool foundIt;
|
| - node = add_object_instance(collection, instance, &foundIt);
|
| - if (node == NULL) {
|
| - return PR_FAILURE;
|
| - }
|
| - if (!node->haveObject) {
|
| - node->object = (*collection->createObject)(node->object);
|
| - if (!node->object) {
|
| - /*remove bogus object from list*/
|
| - nssPKIObjectCollection_RemoveNode(collection,node);
|
| - return PR_FAILURE;
|
| - }
|
| - node->haveObject = PR_TRUE;
|
| - } else if (!foundIt) {
|
| - /* The instance was added to a pre-existing node. This
|
| - * function is *only* being used for certificates, and having
|
| - * multiple instances of certs in 3.X requires updating the
|
| - * CERTCertificate.
|
| - * But only do it if it was a new instance!!! If the same instance
|
| - * is encountered, we set *foundIt to true. Detect that here and
|
| - * ignore it.
|
| - */
|
| - STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
|
| - }
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -/*
|
| - * Certificate collections
|
| - */
|
| -
|
| -static void
|
| -cert_destroyObject(nssPKIObject *o)
|
| -{
|
| - NSSCertificate *c = (NSSCertificate *)o;
|
| - if (c->decoding) {
|
| - CERTCertificate *cc = STAN_GetCERTCertificate(c);
|
| - if (cc) {
|
| - CERT_DestroyCertificate(cc);
|
| - return;
|
| - } /* else destroy it as NSSCertificate below */
|
| - }
|
| - nssCertificate_Destroy(c);
|
| -}
|
| -
|
| -static PRStatus
|
| -cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
|
| -{
|
| - NSSCertificate *c = (NSSCertificate *)o;
|
| - /* The builtins are still returning decoded serial numbers. Until
|
| - * this compatibility issue is resolved, use the full DER of the
|
| - * cert to uniquely identify it.
|
| - */
|
| - NSSDER *derCert;
|
| - derCert = nssCertificate_GetEncoding(c);
|
| - uid[0].data = NULL; uid[0].size = 0;
|
| - uid[1].data = NULL; uid[1].size = 0;
|
| - if (derCert != NULL) {
|
| - uid[0] = *derCert;
|
| - }
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -static PRStatus
|
| -cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
|
| - NSSArena *arena)
|
| -{
|
| - /* The builtins are still returning decoded serial numbers. Until
|
| - * this compatibility issue is resolved, use the full DER of the
|
| - * cert to uniquely identify it.
|
| - */
|
| - uid[1].data = NULL; uid[1].size = 0;
|
| - return nssCryptokiCertificate_GetAttributes(instance,
|
| - NULL, /* XXX sessionOpt */
|
| - arena, /* arena */
|
| - NULL, /* type */
|
| - NULL, /* id */
|
| - &uid[0], /* encoding */
|
| - NULL, /* issuer */
|
| - NULL, /* serial */
|
| - NULL); /* subject */
|
| -}
|
| -
|
| -static nssPKIObject *
|
| -cert_createObject(nssPKIObject *o)
|
| -{
|
| - NSSCertificate *cert;
|
| - cert = nssCertificate_Create(o);
|
| -/* if (STAN_GetCERTCertificate(cert) == NULL) {
|
| - nssCertificate_Destroy(cert);
|
| - return (nssPKIObject *)NULL;
|
| - } */
|
| - /* In 3.4, have to maintain uniqueness of cert pointers by caching all
|
| - * certs. Cache the cert here, before returning. If it is already
|
| - * cached, take the cached entry.
|
| - */
|
| - {
|
| - NSSTrustDomain *td = o->trustDomain;
|
| - nssTrustDomain_AddCertsToCache(td, &cert, 1);
|
| - }
|
| - return (nssPKIObject *)cert;
|
| -}
|
| -
|
| -NSS_IMPLEMENT nssPKIObjectCollection *
|
| -nssCertificateCollection_Create (
|
| - NSSTrustDomain *td,
|
| - NSSCertificate **certsOpt
|
| -)
|
| -{
|
| - nssPKIObjectCollection *collection;
|
| - collection = nssPKIObjectCollection_Create(td, NULL, nssPKIMonitor);
|
| - if (!collection) {
|
| - return NULL;
|
| - }
|
| - collection->objectType = pkiObjectType_Certificate;
|
| - collection->destroyObject = cert_destroyObject;
|
| - collection->getUIDFromObject = cert_getUIDFromObject;
|
| - collection->getUIDFromInstance = cert_getUIDFromInstance;
|
| - collection->createObject = cert_createObject;
|
| - if (certsOpt) {
|
| - for (; *certsOpt; certsOpt++) {
|
| - nssPKIObject *object = (nssPKIObject *)(*certsOpt);
|
| - (void)nssPKIObjectCollection_AddObject(collection, object);
|
| - }
|
| - }
|
| - return collection;
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSCertificate **
|
| -nssPKIObjectCollection_GetCertificates (
|
| - nssPKIObjectCollection *collection,
|
| - NSSCertificate **rvOpt,
|
| - PRUint32 maximumOpt,
|
| - NSSArena *arenaOpt
|
| -)
|
| -{
|
| - PRStatus status;
|
| - PRUint32 rvSize;
|
| - PRBool allocated = PR_FALSE;
|
| - if (collection->size == 0) {
|
| - return (NSSCertificate **)NULL;
|
| - }
|
| - if (maximumOpt == 0) {
|
| - rvSize = collection->size;
|
| - } else {
|
| - rvSize = PR_MIN(collection->size, maximumOpt);
|
| - }
|
| - if (!rvOpt) {
|
| - rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvSize + 1);
|
| - if (!rvOpt) {
|
| - return (NSSCertificate **)NULL;
|
| - }
|
| - allocated = PR_TRUE;
|
| - }
|
| - status = nssPKIObjectCollection_GetObjects(collection,
|
| - (nssPKIObject **)rvOpt,
|
| - rvSize);
|
| - if (status != PR_SUCCESS) {
|
| - if (allocated) {
|
| - nss_ZFreeIf(rvOpt);
|
| - }
|
| - return (NSSCertificate **)NULL;
|
| - }
|
| - return rvOpt;
|
| -}
|
| -
|
| -/*
|
| - * CRL/KRL collections
|
| - */
|
| -
|
| -static void
|
| -crl_destroyObject(nssPKIObject *o)
|
| -{
|
| - NSSCRL *crl = (NSSCRL *)o;
|
| - nssCRL_Destroy(crl);
|
| -}
|
| -
|
| -static PRStatus
|
| -crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
|
| -{
|
| - NSSCRL *crl = (NSSCRL *)o;
|
| - NSSDER *encoding;
|
| - encoding = nssCRL_GetEncoding(crl);
|
| - if (!encoding) {
|
| - nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
|
| - return PR_FALSE;
|
| - }
|
| - uid[0] = *encoding;
|
| - uid[1].data = NULL; uid[1].size = 0;
|
| - return PR_SUCCESS;
|
| -}
|
| -
|
| -static PRStatus
|
| -crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
|
| - NSSArena *arena)
|
| -{
|
| - return nssCryptokiCRL_GetAttributes(instance,
|
| - NULL, /* XXX sessionOpt */
|
| - arena, /* arena */
|
| - &uid[0], /* encoding */
|
| - NULL, /* subject */
|
| - NULL, /* class */
|
| - NULL, /* url */
|
| - NULL); /* isKRL */
|
| -}
|
| -
|
| -static nssPKIObject *
|
| -crl_createObject(nssPKIObject *o)
|
| -{
|
| - return (nssPKIObject *)nssCRL_Create(o);
|
| -}
|
| -
|
| -NSS_IMPLEMENT nssPKIObjectCollection *
|
| -nssCRLCollection_Create (
|
| - NSSTrustDomain *td,
|
| - NSSCRL **crlsOpt
|
| -)
|
| -{
|
| - nssPKIObjectCollection *collection;
|
| - collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
|
| - if (!collection) {
|
| - return NULL;
|
| - }
|
| - collection->objectType = pkiObjectType_CRL;
|
| - collection->destroyObject = crl_destroyObject;
|
| - collection->getUIDFromObject = crl_getUIDFromObject;
|
| - collection->getUIDFromInstance = crl_getUIDFromInstance;
|
| - collection->createObject = crl_createObject;
|
| - if (crlsOpt) {
|
| - for (; *crlsOpt; crlsOpt++) {
|
| - nssPKIObject *object = (nssPKIObject *)(*crlsOpt);
|
| - (void)nssPKIObjectCollection_AddObject(collection, object);
|
| - }
|
| - }
|
| - return collection;
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSCRL **
|
| -nssPKIObjectCollection_GetCRLs (
|
| - nssPKIObjectCollection *collection,
|
| - NSSCRL **rvOpt,
|
| - PRUint32 maximumOpt,
|
| - NSSArena *arenaOpt
|
| -)
|
| -{
|
| - PRStatus status;
|
| - PRUint32 rvSize;
|
| - PRBool allocated = PR_FALSE;
|
| - if (collection->size == 0) {
|
| - return (NSSCRL **)NULL;
|
| - }
|
| - if (maximumOpt == 0) {
|
| - rvSize = collection->size;
|
| - } else {
|
| - rvSize = PR_MIN(collection->size, maximumOpt);
|
| - }
|
| - if (!rvOpt) {
|
| - rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1);
|
| - if (!rvOpt) {
|
| - return (NSSCRL **)NULL;
|
| - }
|
| - allocated = PR_TRUE;
|
| - }
|
| - status = nssPKIObjectCollection_GetObjects(collection,
|
| - (nssPKIObject **)rvOpt,
|
| - rvSize);
|
| - if (status != PR_SUCCESS) {
|
| - if (allocated) {
|
| - nss_ZFreeIf(rvOpt);
|
| - }
|
| - return (NSSCRL **)NULL;
|
| - }
|
| - return rvOpt;
|
| -}
|
| -
|
| -/* how bad would it be to have a static now sitting around, updated whenever
|
| - * this was called? would avoid repeated allocs...
|
| - */
|
| -NSS_IMPLEMENT NSSTime *
|
| -NSSTime_Now (
|
| - NSSTime *timeOpt
|
| -)
|
| -{
|
| - return NSSTime_SetPRTime(timeOpt, PR_Now());
|
| -}
|
| -
|
| -NSS_IMPLEMENT NSSTime *
|
| -NSSTime_SetPRTime (
|
| - NSSTime *timeOpt,
|
| - PRTime prTime
|
| -)
|
| -{
|
| - NSSTime *rvTime;
|
| - rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime);
|
| - if (rvTime) {
|
| - rvTime->prTime = prTime;
|
| - }
|
| - return rvTime;
|
| -}
|
| -
|
| -NSS_IMPLEMENT PRTime
|
| -NSSTime_GetPRTime (
|
| - NSSTime *time
|
| -)
|
| -{
|
| - return time->prTime;
|
| -}
|
| -
|
|
|