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

Quelle  certhigh.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/. */

#include "nspr.h"
#include "secerr.h"
#include "secasn1.h"
#include "seccomon.h"
#include "pk11func.h"
#include "certdb.h"
#include "certt.h"
#include "cert.h"
#include "certxutl.h"

#include "certi.h"
#include "nsspki.h"
#include "pki.h"
#include "pkit.h"
#include "pkitm.h"
#include "pki3hack.h"

PRBool
CERT_MatchNickname(char *name1, char *name2)
{
    char *nickname1 = NULL;
    char *nickname2 = NULL;
    char *token1;
    char *token2;

    /* first deal with the straight comparison */
    if (PORT_Strcmp(name1, name2) == 0) {
        return PR_TRUE;
    }
    /* we need to handle the case where one name has an explicit token and the other
     * doesn't */

    token1 = PORT_Strchr(name1, ':');
    token2 = PORT_Strchr(name2, ':');
    if ((token1 && token2) || (!token1 && !token2)) {
        /* either both token names are specified or neither are, not match */
        return PR_FALSE;
    }
    if (token1) {
        nickname1 = token1;
        nickname2 = name2;
    } else {
        nickname1 = token2;
        nickname2 = name1;
    }
    nickname1++;
    if (PORT_Strcmp(nickname1, nickname2) != 0) {
        return PR_FALSE;
    }
    /* Bug 1192443 - compare the other token with the internal slot here */
    return PR_TRUE;
}

/*
 * Find all user certificates that match the given criteria.
 *
 *      "handle" - database to search
 *      "usage" - certificate usage to match
 *      "oneCertPerName" - if set then only return the "best" cert per
 *                      name
 *      "validOnly" - only return certs that are curently valid
 *      "proto_win" - window handle passed to pkcs11
 */

CERTCertList *
CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
                          SECCertUsage usage,
                          PRBool oneCertPerName,
                          PRBool validOnly,
                          void *proto_win)
{
    CERTCertNicknames *nicknames = NULL;
    char **nnptr;
    int nn;
    CERTCertificate *cert = NULL;
    CERTCertList *certList = NULL;
    SECStatus rv;
    PRTime time;
    CERTCertListNode *node = NULL;
    CERTCertListNode *freenode = NULL;
    int n;

    time = PR_Now();

    nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
                                      proto_win);

    if ((nicknames == NULL) || (nicknames->numnicknames == 0)) {
        goto loser;
    }

    nnptr = nicknames->nicknames;
    nn = nicknames->numnicknames;

    while (nn > 0) {
        cert = NULL;
        /* use the pk11 call so that we pick up any certs on tokens,
         * which may require login
         */

        if (proto_win != NULL) {
            cert = PK11_FindCertFromNickname(*nnptr, proto_win);
        }

        /* Sigh, It turns out if the cert is already in the temp db, because
         * it's in the perm db, then the nickname lookup doesn't work.
         * since we already have the cert here, though, than we can just call
         * CERT_CreateSubjectCertList directly. For those cases where we didn't
         * find the cert in pkcs #11 (because we didn't have a password arg,
         * or because the nickname is for a peer, server, or CA cert, then we
         * go look the cert up.
         */

        if (cert == NULL) {
            cert = CERT_FindCertByNickname(handle, *nnptr);
        }

        if (cert != NULL) {
            /* collect certs for this nickname, sorting them into the list */
            certList = CERT_CreateSubjectCertList(certList, handle,
                                                  &cert->derSubject, time, validOnly);

            CERT_FilterCertListForUserCerts(certList);

            /* drop the extra reference */
            CERT_DestroyCertificate(cert);
        }

        nnptr++;
        nn--;
    }

    /* remove certs with incorrect usage */
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);

    if (rv != SECSuccess) {
        goto loser;
    }

    /* remove any extra certs for each name */
    if (oneCertPerName) {
        PRBool *flags;

        nn = nicknames->numnicknames;
        nnptr = nicknames->nicknames;

        if (!certList) {
            goto loser;
        }

        flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
        if (flags == NULL) {
            goto loser;
        }

        node = CERT_LIST_HEAD(certList);

        /* treverse all certs in the list */
        while (!CERT_LIST_END(node, certList)) {

            /* find matching nickname index */
            for (n = 0; n < nn; n++) {
                if (CERT_MatchNickname(nnptr[n], node->cert->nickname)) {
                    /* We found a match.  If this is the first one, then
                     * set the flag and move on to the next cert.  If this
                     * is not the first one then delete it from the list.
                     */

                    if (flags[n]) {
                        /* We have already seen a cert with this nickname,
                         * so delete this one.
                         */

                        freenode = node;
                        node = CERT_LIST_NEXT(node);
                        CERT_RemoveCertListNode(freenode);
                    } else {
                        /* keep the first cert for each nickname, but set the
                         * flag so we know to delete any others with the same
                         * nickname.
                         */

                        flags[n] = PR_TRUE;
                        node = CERT_LIST_NEXT(node);
                    }
                    break;
                }
            }
            if (n == nn) {
                /* if we get here it means that we didn't find a matching
                 * nickname, which should not happen.
                 */

                PORT_Assert(0);
                node = CERT_LIST_NEXT(node);
            }
        }
        PORT_Free(flags);
    }

    goto done;

loser:
    if (certList != NULL) {
        CERT_DestroyCertList(certList);
        certList = NULL;
    }

done:
    if (nicknames != NULL) {
        CERT_FreeNicknames(nicknames);
    }

    return (certList);
}

/*
 * Find a user certificate that matchs the given criteria.
 *
 *      "handle" - database to search
 *      "nickname" - nickname to match
 *      "usage" - certificate usage to match
 *      "validOnly" - only return certs that are curently valid
 *      "proto_win" - window handle passed to pkcs11
 */

CERTCertificate *
CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
                         const char *nickname,
                         SECCertUsage usage,
                         PRBool validOnly,
                         void *proto_win)
{
    CERTCertificate *cert = NULL;
    CERTCertList *certList = NULL;
    SECStatus rv;
    PRTime time;

    time = PR_Now();

    /* use the pk11 call so that we pick up any certs on tokens,
     * which may require login
     */

    /* XXX - why is this restricted? */
    if (proto_win != NULL) {
        cert = PK11_FindCertFromNickname(nickname, proto_win);
    }

    /* sigh, There are still problems find smart cards from the temp
     * db. This will get smart cards working again. The real fix
     * is to make sure we can search the temp db by their token nickname.
     */

    if (cert == NULL) {
        cert = CERT_FindCertByNickname(handle, nickname);
    }

    if (cert != NULL) {
        unsigned int requiredKeyUsage;
        unsigned int requiredCertType;

        rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
                                              &requiredKeyUsage, &requiredCertType);
        if (rv != SECSuccess) {
            /* drop the extra reference */
            CERT_DestroyCertificate(cert);
            cert = NULL;
            goto loser;
        }
        /* If we already found the right cert, just return it */
        if ((!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE) == secCertTimeValid) &&
            (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
            (cert->nsCertType & requiredCertType) &&
            CERT_IsUserCert(cert)) {
            return (cert);
        }

        /* collect certs for this nickname, sorting them into the list */
        certList = CERT_CreateSubjectCertList(certList, handle,
                                              &cert->derSubject, time, validOnly);

        CERT_FilterCertListForUserCerts(certList);

        /* drop the extra reference */
        CERT_DestroyCertificate(cert);
        cert = NULL;
    }

    if (certList == NULL) {
        goto loser;
    }

    /* remove certs with incorrect usage */
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);

    if (rv != SECSuccess) {
        goto loser;
    }

    if (!CERT_LIST_EMPTY(certList)) {
        cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
    }

loser:
    if (certList != NULL) {
        CERT_DestroyCertList(certList);
    }

    return (cert);
}

CERTCertList *
CERT_MatchUserCert(CERTCertDBHandle *handle,
                   SECCertUsage usage,
                   int nCANames, char **caNames,
                   void *proto_win)
{
    CERTCertList *certList = NULL;
    SECStatus rv;

    certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
                                         proto_win);
    if (certList == NULL) {
        goto loser;
    }

    rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
    if (rv != SECSuccess) {
        goto loser;
    }

    goto done;

loser:
    if (certList != NULL) {
        CERT_DestroyCertList(certList);
        certList = NULL;
    }

done:

    return (certList);
}

typedef struct stringNode {
    struct stringNode *next;
    char *string;
} stringNode;

static PRStatus
CollectNicknames(NSSCertificate *c, void *data)
{
    CERTCertNicknames *names;
    PRBool saveit = PR_FALSE;
    stringNode *node;
    int len;
#ifdef notdef
    NSSTrustDomain *td;
    NSSTrust *trust;
#endif
    char *stanNickname;
    char *nickname = NULL;

    names = (CERTCertNicknames *)data;

    stanNickname = nssCertificate_GetNickname(c, NULL);

    if (stanNickname) {
        nss_ZFreeIf(stanNickname);
        stanNickname = NULL;
        if (names->what == SEC_CERT_NICKNAMES_USER) {
            saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
        }
#ifdef notdef
        else {
            td = NSSCertificate_GetTrustDomain(c);
            if (!td) {
                return PR_SUCCESS;
            }
            trust = nssTrustDomain_FindTrustForCertificate(td, c);

            switch (names->what) {
                case SEC_CERT_NICKNAMES_ALL:
                    if ((trust->sslFlags & (CERTDB_VALID_CA | CERTDB_VALID_PEER)) ||
                        (trust->emailFlags & (CERTDB_VALID_CA | CERTDB_VALID_PEER)) ||
                        (trust->objectSigningFlags &
                         (CERTDB_VALID_CA | CERTDB_VALID_PEER))) {
                        saveit = PR_TRUE;
                    }

                    break;
                case SEC_CERT_NICKNAMES_SERVER:
                    if (trust->sslFlags & CERTDB_VALID_PEER) {
                        saveit = PR_TRUE;
                    }

                    break;
                case SEC_CERT_NICKNAMES_CA:
                    if (((trust->sslFlags & CERTDB_VALID_CA) == CERTDB_VALID_CA) ||
                        ((trust->emailFlags & CERTDB_VALID_CA) == CERTDB_VALID_CA) ||
                        ((trust->objectSigningFlags & CERTDB_VALID_CA) ==
                         CERTDB_VALID_CA)) {
                        saveit = PR_TRUE;
                    }
                    break;
            }
        }
#endif
    }

    /* traverse the list of collected nicknames and make sure we don't make
     * a duplicate
     */

    if (saveit) {
        nickname = STAN_GetCERTCertificateName(NULL, c);
        /* nickname can only be NULL here if we are having memory
         * alloc problems */

        if (nickname == NULL) {
            return PR_FAILURE;
        }
        node = (stringNode *)names->head;
        while (node != NULL) {
            if (PORT_Strcmp(nickname, node->string) == 0) {
                /* if the string matches, then don't save this one */
                saveit = PR_FALSE;
                break;
            }
            node = node->next;
        }
    }

    if (saveit) {

        /* allocate the node */
        node = (stringNode *)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
        if (node == NULL) {
            PORT_Free(nickname);
            return PR_FAILURE;
        }

        /* copy the string */
        len = PORT_Strlen(nickname) + 1;
        node->string = (char *)PORT_ArenaAlloc(names->arena, len);
        if (node->string == NULL) {
            PORT_Free(nickname);
            return PR_FAILURE;
        }
        PORT_Memcpy(node->string, nickname, len);

        /* link it into the list */
        node->next = (stringNode *)names->head;
        names->head = (void *)node;

        /* bump the count */
        names->numnicknames++;
    }

    if (nickname)
        PORT_Free(nickname);
    return (PR_SUCCESS);
}

CERTCertNicknames *
CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
{
    PLArenaPool *arena;
    CERTCertNicknames *names;
    int i;
    stringNode *node;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return (NULL);
    }

    names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
    if (names == NULL) {
        goto loser;
    }

    names->arena = arena;
    names->head = NULL;
    names->numnicknames = 0;
    names->nicknames = NULL;
    names->what = what;
    names->totallen = 0;

    /* make sure we are logged in */
    (void)pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx);

    NSSTrustDomain_TraverseCertificates(handle,
                                        CollectNicknames, (void *)names);
    if (names->numnicknames) {
        names->nicknames = (char **)PORT_ArenaAlloc(arena,
                                                    names->numnicknames *
                                                        sizeof(char *));

        if (names->nicknames == NULL) {
            goto loser;
        }

        node = (stringNode *)names->head;

        for (i = 0; i < names->numnicknames; i++) {
            PORT_Assert(node != NULL);

            names->nicknames[i] = node->string;
            names->totallen += PORT_Strlen(node->string);
            node = node->next;
        }

        PORT_Assert(node == NULL);
    }

    return (names);

loser:
    PORT_FreeArena(arena, PR_FALSE);
    return (NULL);
}

void
CERT_FreeNicknames(CERTCertNicknames *nicknames)
{
    PORT_FreeArena(nicknames->arena, PR_FALSE);

    return;
}

/* [ FROM pcertdb.c ] */

typedef struct dnameNode {
    struct dnameNode *next;
    SECItem name;
} dnameNode;

void
CERT_FreeDistNames(CERTDistNames *names)
{
    PORT_FreeArena(names->arena, PR_FALSE);

    return;
}

static SECStatus
CollectDistNames(CERTCertificate *cert, SECItem *k, void *data)
{
    CERTDistNames *names;
    PRBool saveit = PR_FALSE;
    CERTCertTrust trust;
    dnameNode *node;
    int len;

    names = (CERTDistNames *)data;

    if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
        /* only collect names of CAs trusted for issuing SSL clients */
        if (trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA) {
            saveit = PR_TRUE;
        }
    }

    if (saveit) {
        /* allocate the node */
        node = (dnameNode *)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
        if (node == NULL) {
            return (SECFailure);
        }

        /* copy the name */
        node->name.len = len = cert->derSubject.len;
        node->name.type = siBuffer;
        node->name.data = (unsigned char *)PORT_ArenaAlloc(names->arena, len);
        if (node->name.data == NULL) {
            return (SECFailure);
        }
        PORT_Memcpy(node->name.data, cert->derSubject.data, len);

        /* link it into the list */
        node->next = (dnameNode *)names->head;
        names->head = (void *)node;

        /* bump the count */
        names->nnames++;
    }

    return (SECSuccess);
}

/*
 * Return all of the CAs that are "trusted" for SSL.
 */

CERTDistNames *
CERT_DupDistNames(CERTDistNames *orig)
{
    PLArenaPool *arena;
    CERTDistNames *names;
    int i;
    SECStatus rv;

    /* allocate an arena to use */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return (NULL);
    }

    /* allocate the header structure */
    names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
    if (names == NULL) {
        goto loser;
    }

    /* initialize the header struct */
    names->arena = arena;
    names->head = NULL;
    names->nnames = orig->nnames;
    names->names = NULL;

    /* construct the array from the list */
    if (orig->nnames) {
        names->names = (SECItem *)PORT_ArenaNewArray(arena, SECItem,
                                                     orig->nnames);
        if (names->names == NULL) {
            goto loser;
        }
        for (i = 0; i < orig->nnames; i++) {
            rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]);
            if (rv != SECSuccess) {
                goto loser;
            }
        }
    }
    return (names);

loser:
    PORT_FreeArena(arena, PR_FALSE);
    return (NULL);
}

CERTDistNames *
CERT_GetSSLCACerts(CERTCertDBHandle *handle)
{
    PLArenaPool *arena;
    CERTDistNames *names;
    int i;
    SECStatus rv;
    dnameNode *node;

    /* allocate an arena to use */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return (NULL);
    }

    /* allocate the header structure */
    names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
    if (names == NULL) {
        goto loser;
    }

    /* initialize the header struct */
    names->arena = arena;
    names->head = NULL;
    names->nnames = 0;
    names->names = NULL;

    /* collect the names from the database */
    rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
    if (rv) {
        goto loser;
    }

    /* construct the array from the list */
    if (names->nnames) {
        names->names = (SECItem *)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));

        if (names->names == NULL) {
            goto loser;
        }

        node = (dnameNode *)names->head;

        for (i = 0; i < names->nnames; i++) {
            PORT_Assert(node != NULL);

            names->names[i] = node->name;
            node = node->next;
        }

        PORT_Assert(node == NULL);
    }

    return (names);

loser:
    PORT_FreeArena(arena, PR_FALSE);
    return (NULL);
}

CERTDistNames *
CERT_DistNamesFromCertList(CERTCertList *certList)
{
    CERTDistNames *dnames = NULL;
    PLArenaPool *arena;
    CERTCertListNode *node = NULL;
    SECItem *names = NULL;
    int listLen = 0, i = 0;

    if (certList == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    node = CERT_LIST_HEAD(certList);
    while (!CERT_LIST_END(node, certList)) {
        listLen += 1;
        node = CERT_LIST_NEXT(node);
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL)
        goto loser;
    dnames = PORT_ArenaZNew(arena, CERTDistNames);
    if (dnames == NULL)
        goto loser;

    dnames->arena = arena;
    dnames->nnames = listLen;
    dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen);
    if (names == NULL)
        goto loser;

    node = CERT_LIST_HEAD(certList);
    while (!CERT_LIST_END(node, certList)) {
        CERTCertificate *cert = node->cert;
        SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject);
        if (rv == SECFailure) {
            goto loser;
        }
        node = CERT_LIST_NEXT(node);
    }
    return dnames;
loser:
    if (arena) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

CERTDistNames *
CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
                            int nnames)
{
    CERTDistNames *dnames = NULL;
    PLArenaPool *arena;
    int i, rv;
    SECItem *names = NULL;
    CERTCertificate *cert = NULL;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL)
        goto loser;
    dnames = PORT_ArenaZNew(arena, CERTDistNames);
    if (dnames == NULL)
        goto loser;

    dnames->arena = arena;
    dnames->nnames = nnames;
    dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames);
    if (names == NULL)
        goto loser;

    for (i = 0; i < nnames; i++) {
        cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
        if (cert == NULL)
            goto loser;
        rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
        if (rv == SECFailure)
            goto loser;
        CERT_DestroyCertificate(cert);
    }
    return dnames;

loser:
    if (cert != NULL)
        CERT_DestroyCertificate(cert);
    if (arena != NULL)
        PORT_FreeArena(arena, PR_FALSE);
    return NULL;
}

/* [ from pcertdb.c - calls Ascii to Name ] */
/*
 * Lookup a certificate in the database by name
 */

CERTCertificate *
CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
{
    CERTName *name;
    SECItem *nameItem;
    CERTCertificate *cert = NULL;
    PLArenaPool *arena = NULL;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);

    if (arena == NULL) {
        goto loser;
    }

    name = CERT_AsciiToName(nameStr);

    if (name) {
        nameItem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
                                      CERT_NameTemplate);
        if (nameItem != NULL) {
            cert = CERT_FindCertByName(handle, nameItem);
        }
        CERT_DestroyName(name);
    }

loser:
    if (arena) {
        PORT_FreeArena(arena, PR_FALSE);
    }

    return (cert);
}

/* From certv3.c */

CERTCrlDistributionPoints *
CERT_FindCRLDistributionPoints(CERTCertificate *cert)
{
    SECItem encodedExtenValue;
    SECStatus rv;
    CERTCrlDistributionPoints *dps;

    encodedExtenValue.data = NULL;
    encodedExtenValue.len = 0;

    rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
                            &encodedExtenValue);
    if (rv != SECSuccess) {
        return (NULL);
    }

    dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue);

    PORT_Free(encodedExtenValue.data);

    return dps;
}

/* From crl.c */
CERTSignedCrl *
CERT_ImportCRL(CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
{
    CERTSignedCrl *retCrl = NULL;
    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
                            CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
    PK11_FreeSlot(slot);

    return retCrl;
}

/* From certdb.c */
static SECStatus
cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
{
    SECStatus rv;
    SECItem *derCert;
    CERTCertificate *cert = NULL;
    CERTCertificate *newcert = NULL;
    CERTCertDBHandle *handle;
    CERTCertTrust trust;
    PRBool isca;
    char *nickname;
    unsigned int certtype;
    PRBool istemp = PR_FALSE;

    handle = CERT_GetDefaultCertDB();

    while (numcerts--) {
        derCert = certs;
        certs++;

        /* decode my certificate */
        /* This use is ok -- only looks at decoded parts, calls NewTemp later */
        newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
        if (newcert == NULL) {
            goto loser;
        }

        if (!trusted) {
            /* make sure that cert is valid */
            rv = CERT_CertTimesValid(newcert);
            if (rv == SECFailure) {
                goto endloop;
            }
        }

        /* does it have the CA extension */

        /*
         * Make sure that if this is an intermediate CA in the chain that
         * it was given permission by its signer to be a CA.
         */

        isca = CERT_IsCACert(newcert, &certtype);

        if (!isca) {
            if (!trusted) {
                goto endloop;
            }
            trust.sslFlags = CERTDB_VALID_CA;
            trust.emailFlags = CERTDB_VALID_CA;
            trust.objectSigningFlags = CERTDB_VALID_CA;
        } else {
            /* SSL ca's must have the ssl bit set */
            if ((certUsage == certUsageSSLCA) &&
                ((certtype & NS_CERT_TYPE_SSL_CA) != NS_CERT_TYPE_SSL_CA)) {
                goto endloop;
            }

            /* it passed all of the tests, so lets add it to the database */
            /* mark it as a CA */
            PORT_Memset((void *)&trust, 0, sizeof(trust));
            switch (certUsage) {
                case certUsageSSLCA:
                    trust.sslFlags = CERTDB_VALID_CA;
                    break;
                case certUsageUserCertImport:
                    if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
                        trust.sslFlags = CERTDB_VALID_CA;
                    }
                    if ((certtype & NS_CERT_TYPE_EMAIL_CA) ==
                        NS_CERT_TYPE_EMAIL_CA) {
                        trust.emailFlags = CERTDB_VALID_CA;
                    }
                    if ((certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA) ==
                        NS_CERT_TYPE_OBJECT_SIGNING_CA) {
                        trust.objectSigningFlags = CERTDB_VALID_CA;
                    }
                    break;
                default:
                    PORT_Assert(0);
                    break;
            }
        }

        cert = CERT_NewTempCertificate(handle, derCert, NULL,
                                       PR_FALSE, PR_FALSE);
        if (cert == NULL) {
            goto loser;
        }

        /* if the cert is temp, make it perm; otherwise we're done */
        rv = CERT_GetCertIsTemp(cert, &istemp);
        if (rv != SECSuccess) {
            goto loser;
        }
        if (istemp) {
            /* get a default nickname for it */
            nickname = CERT_MakeCANickname(cert);

            rv = CERT_AddTempCertToPerm(cert, nickname, &trust);

            /* free the nickname */
            if (nickname) {
                PORT_Free(nickname);
            }
        } else {
            rv = SECSuccess;
        }

        if (rv != SECSuccess) {
            goto loser;
        }

    endloop:
        if (newcert) {
            CERT_DestroyCertificate(newcert);
            newcert = NULL;
        }
    }

    rv = SECSuccess;
    goto done;
loser:
    rv = SECFailure;
done:

    if (newcert) {
        CERT_DestroyCertificate(newcert);
        newcert = NULL;
    }

    if (cert) {
        CERT_DestroyCertificate(cert);
        cert = NULL;
    }

    return (rv);
}

SECStatus
CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
{
    return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
}

SECStatus
CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage)
{
    return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
}

/* Moved from certdb.c */
/*
** CERT_CertChainFromCert
**
** Construct a CERTCertificateList consisting of the given certificate and all
** of the issuer certs until we either get to a self-signed cert or can't find
** an issuer.  Since we don't know how many certs are in the chain we have to
** build a linked list first as we count them.
*/


typedef struct certNode {
    struct certNode *next;
    CERTCertificate *cert;
} certNode;

CERTCertificateList *
CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
                       PRBool includeRoot)
{
    CERTCertificateList *chain = NULL;
    NSSCertificate **stanChain;
    NSSCertificate *stanCert;
    PLArenaPool *arena;
    NSSUsage nssUsage;
    int i, len;
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
    NSSCryptoContext *cc = STAN_GetDefaultCryptoContext();

    stanCert = STAN_GetNSSCertificate(cert);
    if (!stanCert) {
        /* error code is set */
        return NULL;
    }
    nssUsage.anyUsage = PR_FALSE;
    nssUsage.nss3usage = usage;
    nssUsage.nss3lookingForCA = PR_FALSE;
    stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL,
                                          CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc);
    if (!stanChain) {
        PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
        return NULL;
    }

    len = 0;
    stanCert = stanChain[0];
    while (stanCert) {
        stanCert = stanChain[++len];
    }

    arena = PORT_NewArena(4096);
    if (arena == NULL) {
        goto loser;
    }

    chain = (CERTCertificateList *)PORT_ArenaAlloc(arena,
                                                   sizeof(CERTCertificateList));
    if (!chain)
        goto loser;
    chain->certs = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
    if (!chain->certs)
        goto loser;
    i = 0;
    stanCert = stanChain[i];
    while (stanCert) {
        SECItem derCert;
        CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
        if (!cCert) {
            goto loser;
        }
        derCert.len = (unsigned int)stanCert->encoding.size;
        derCert.data = (unsigned char *)stanCert->encoding.data;
        derCert.type = siBuffer;
        if (SECITEM_CopyItem(arena, &chain->certs[i], &derCert) != SECSuccess) {
            CERT_DestroyCertificate(cCert);
            goto loser;
        }
        stanCert = stanChain[++i];
        if (!stanCert && !cCert->isRoot) {
            /* reached the end of the chain, but the final cert is
             * not a root.  Don't discard it.
             */

            includeRoot = PR_TRUE;
        }
        CERT_DestroyCertificate(cCert);
    }
    if (!includeRoot && len > 1) {
        chain->len = len - 1;
    } else {
        chain->len = len;
    }

    chain->arena = arena;
    nss_ZFreeIf(stanChain);
    return chain;
loser:
    i = 0;
    stanCert = stanChain[i];
    while (stanCert) {
        CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
        if (cCert) {
            CERT_DestroyCertificate(cCert);
        }
        stanCert = stanChain[++i];
    }
    nss_ZFreeIf(stanChain);
    if (arena) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

/* Builds a CERTCertificateList holding just one DER-encoded cert, namely
** the one for the cert passed as an argument.
*/

CERTCertificateList *
CERT_CertListFromCert(CERTCertificate *cert)
{
    CERTCertificateList *chain = NULL;
    int rv;
    PLArenaPool *arena;

    /* arena for SecCertificateList */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL)
        goto no_memory;

    /* build the CERTCertificateList */
    chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
    if (chain == NULL)
        goto no_memory;
    chain->certs = (SECItem *)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
    if (chain->certs == NULL)
        goto no_memory;
    rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
    if (rv < 0)
        goto loser;
    chain->len = 1;
    chain->arena = arena;

    return chain;

no_memory:
    PORT_SetError(SEC_ERROR_NO_MEMORY);
loser:
    if (arena != NULL) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

CERTCertificateList *
CERT_DupCertList(const CERTCertificateList *oldList)
{
    CERTCertificateList *newList = NULL;
    PLArenaPool *arena = NULL;
    SECItem *newItem;
    SECItem *oldItem;
    int len = oldList->len;
    int rv;

    /* arena for SecCertificateList */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL)
        goto no_memory;

    /* now build the CERTCertificateList */
    newList = PORT_ArenaNew(arena, CERTCertificateList);
    if (newList == NULL)
        goto no_memory;
    newList->arena = arena;
    newItem = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
    if (newItem == NULL)
        goto no_memory;
    newList->certs = newItem;
    newList->len = len;

    for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
        rv = SECITEM_CopyItem(arena, newItem, oldItem);
        if (rv < 0)
            goto loser;
    }
    return newList;

no_memory:
    PORT_SetError(SEC_ERROR_NO_MEMORY);
loser:
    if (arena != NULL) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

void
CERT_DestroyCertificateList(CERTCertificateList *list)
{
    PORT_FreeArena(list->arena, PR_FALSE);
}

Messung V0.5
C=94 H=63 G=79

¤ Dauer der Verarbeitung: 0.37 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.