summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c
blob: 4f29de2849bd897f6310fe7f40e7573bbf3b1cae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* 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/. */
/*
 * pkix_pl_crldp.c
 *
 * Crl DP Object Functions
 *
 */

#include "pkix_pl_crldp.h"

static PKIX_Error *
pkix_pl_CrlDp_Destroy(
        PKIX_PL_Object *object,
        void *plContext)
{
    pkix_pl_CrlDp *crldp = NULL;
    
    PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_Destroy");
    PKIX_NULLCHECK_ONE(object);
    
    /* Check that this object is a default CRL checker state */
    PKIX_CHECK(
        pkix_CheckType(object, PKIX_CRLDP_TYPE, plContext),
        PKIX_OBJECTNOTCRLCHECKER);
    
    crldp = (pkix_pl_CrlDp *)object;
    if (crldp->distPointType == relativeDistinguishedName) {
        CERT_DestroyName(crldp->name.issuerName);
        crldp->name.issuerName = NULL;
    }
    crldp->nssdp = NULL;
cleanup:
    PKIX_RETURN(CRLCHECKER);
}

/*
 * FUNCTION: pkix_pl_CrlDp_RegisterSelf
 *
 * DESCRIPTION:
 *  Registers PKIX_CRLDP_TYPE and its related functions
 *  with systemClasses[]
 *
 * THREAD SAFETY:
 *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 *
 *  Since this function is only called by PKIX_PL_Initialize, which should
 *  only be called once, it is acceptable that this function is not
 *  thread-safe.
 */
PKIX_Error *
pkix_pl_CrlDp_RegisterSelf(void *plContext)
{
        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
        pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLDP_TYPE];

        PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf");

        entry->description = "CrlDistPoint";
        entry->typeObjectSize = sizeof(pkix_pl_CrlDp);
        entry->destructor = pkix_pl_CrlDp_Destroy;
        entry->duplicateFunction = pkix_duplicateImmutable;

        PKIX_RETURN(CRLCHECKER);
}



PKIX_Error *
pkix_pl_CrlDp_Create(
    const CRLDistributionPoint *dp,
    const CERTName *certIssuerName,
    pkix_pl_CrlDp **pPkixDP,
    void *plContext)
{
    PLArenaPool *rdnArena = NULL;
    CERTName *issuerNameCopy = NULL;
    pkix_pl_CrlDp *dpl = NULL;

    /* Need to save the following info to update crl cache:
     * - reasons if partitioned(but can not return revocation check
     *   success if not all crl are downloaded)
     * - issuer name if different from issuer of the cert
     * - url to upload a crl if needed.
     * */
    PKIX_ENTER(CRLDP, "pkix_pl_CrlDp_Create");
    PKIX_NULLCHECK_ONE(dp);

    PKIX_CHECK(
        PKIX_PL_Object_Alloc(PKIX_CRLDP_TYPE,
                             sizeof (pkix_pl_CrlDp),
                             (PKIX_PL_Object **)&dpl,
                             plContext),
        PKIX_COULDNOTCREATEOBJECT);

    dpl->nssdp = dp;
    dpl->isPartitionedByReasonCode = PKIX_FALSE;
    if (dp->reasons.data) {
        dpl->isPartitionedByReasonCode = PKIX_TRUE;
    }
    if (dp->distPointType == generalName) {
        dpl->distPointType = generalName;
        dpl->name.fullName = dp->distPoint.fullName;
    } else {
        SECStatus rv;
        const CERTName *issuerName = NULL;
        const CERTRDN *relName = &dp->distPoint.relativeName;

        if (dp->crlIssuer) {
            if (dp->crlIssuer->l.next) {
                /* Violate RFC 5280: in this case crlIssuer
                 * should have only one name and should be
                 * a distinguish name. */
                PKIX_ERROR(PKIX_NOTCONFORMINGCRLDP);
            }
            issuerName = &dp->crlIssuer->name.directoryName;
        } else {
            issuerName = certIssuerName;
        }
        rdnArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (!rdnArena) {
            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
        }
        issuerNameCopy = (CERTName *)PORT_ArenaZNew(rdnArena, CERTName);
        if (!issuerNameCopy) {
            PKIX_ERROR(PKIX_ALLOCERROR);
        }
        rv = CERT_CopyName(rdnArena, issuerNameCopy, (CERTName*)issuerName);
        if (rv == SECFailure) {
            PKIX_ERROR(PKIX_ALLOCERROR);
        }
        rv = CERT_AddRDN(issuerNameCopy, (CERTRDN*)relName);
        if (rv == SECFailure) {
            PKIX_ERROR(PKIX_ALLOCERROR);
        }
        dpl->distPointType = relativeDistinguishedName;
        dpl->name.issuerName = issuerNameCopy;
        rdnArena = NULL;
    }
    *pPkixDP = dpl;
    dpl = NULL;

cleanup:
    if (rdnArena) {
        PORT_FreeArena(rdnArena, PR_FALSE);
    }
    PKIX_DECREF(dpl);

    PKIX_RETURN(CRLDP);
}