Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/security/nss/lib/pki/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 35 kB image not shown  

Quelle  pkibase.c   Sprache: C

 
/* 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) {
        nssPKIObject *original = node->object;
        node->object = (*collection->createObject)(node->object);
        if (!node->object) {
            /*remove bogus object from list*/
            nssPKIObject_Destroy(original);
            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;
}

Messung V0.5
C=95 H=79 G=87

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.