tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_nameconstraintschecker.c (11648B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_nameconstraintschecker.c
      6 *
      7 * Functions for Name Constraints Checkers
      8 *
      9 */
     10 
     11 #include "pkix_nameconstraintschecker.h"
     12 
     13 /* --Private-NameConstraintsCheckerState-Functions---------------------- */
     14 
     15 /*
     16 * FUNCTION: pkix_NameConstraintsCheckerstate_Destroy
     17 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
     18 */
     19 static PKIX_Error *
     20 pkix_NameConstraintsCheckerState_Destroy(
     21        PKIX_PL_Object *object,
     22        void *plContext)
     23 {
     24        pkix_NameConstraintsCheckerState *state = NULL;
     25 
     26        PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
     27                    "pkix_NameConstraintsCheckerState_Destroy");
     28        PKIX_NULLCHECK_ONE(object);
     29 
     30        /* Check that object type */
     31        PKIX_CHECK(pkix_CheckType
     32            (object, PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, plContext),
     33            PKIX_OBJECTNOTNAMECONSTRAINTSCHECKERSTATE);
     34 
     35        state = (pkix_NameConstraintsCheckerState *)object;
     36 
     37        PKIX_DECREF(state->nameConstraints);
     38        PKIX_DECREF(state->nameConstraintsOID);
     39 
     40 cleanup:
     41 
     42        PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
     43 }
     44 
     45 /*
     46 * FUNCTION: pkix_NameConstraintsCheckerState_RegisterSelf
     47 *
     48 * DESCRIPTION:
     49 *  Registers PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE and its related
     50 *  functions with systemClasses[]
     51 *
     52 * THREAD SAFETY:
     53 *  Not Thread Safe - for performance and complexity reasons
     54 *
     55 *  Since this function is only called by PKIX_PL_Initialize, which should
     56 *  only be called once, it is acceptable that this function is not
     57 *  thread-safe.
     58 */
     59 PKIX_Error *
     60 pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext)
     61 {
     62        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
     63        pkix_ClassTable_Entry entry;
     64 
     65        PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
     66                    "pkix_NameConstraintsCheckerState_RegisterSelf");
     67 
     68        entry.description = "NameConstraintsCheckerState";
     69        entry.objCounter = 0;
     70        entry.typeObjectSize = sizeof(pkix_NameConstraintsCheckerState);
     71        entry.destructor = pkix_NameConstraintsCheckerState_Destroy;
     72        entry.equalsFunction = NULL;
     73        entry.hashcodeFunction = NULL;
     74        entry.toStringFunction = NULL;
     75        entry.comparator = NULL;
     76        entry.duplicateFunction = NULL;
     77 
     78        systemClasses[PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE] = entry;
     79 
     80        PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
     81 }
     82 
     83 /*
     84 * FUNCTION: pkix_NameConstraintsCheckerState_Create
     85 *
     86 * DESCRIPTION:
     87 *  Allocate and initialize NameConstraintsChecker state data.
     88 *
     89 * PARAMETERS
     90 *  "nameConstraints"
     91 *      Address of NameConstraints to be stored in state. May be NULL.
     92 *  "numCerts"
     93 *      Number of certificates in the validation chain. This data is used
     94 *      to identify end-entity.
     95 *  "pCheckerState"
     96 *      Address of NameConstraintsCheckerState that is returned. Must be
     97 *      non-NULL.
     98 *  "plContext" - Platform-specific context pointer.
     99 *
    100 * THREAD SAFETY:
    101 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    102 *
    103 * RETURNS:
    104 *  Returns NULL if the function succeeds.
    105 *  Returns a CERTNAMECONSTRAINTSCHECKERSTATE Error if the function fails in
    106 *  a non-fatal way.
    107 *  Returns a Fatal Error
    108 */
    109 static PKIX_Error *
    110 pkix_NameConstraintsCheckerState_Create(
    111    PKIX_PL_CertNameConstraints *nameConstraints,
    112    PKIX_UInt32 numCerts,
    113    pkix_NameConstraintsCheckerState **pCheckerState,
    114    void *plContext)
    115 {
    116        pkix_NameConstraintsCheckerState *state = NULL;
    117 
    118        PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
    119                    "pkix_NameConstraintsCheckerState_Create");
    120        PKIX_NULLCHECK_ONE(pCheckerState);
    121 
    122        PKIX_CHECK(PKIX_PL_Object_Alloc
    123                    (PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE,
    124                    sizeof (pkix_NameConstraintsCheckerState),
    125                    (PKIX_PL_Object **)&state,
    126                    plContext),
    127                    PKIX_COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT);
    128 
    129        /* Initialize fields */
    130 
    131        PKIX_CHECK(PKIX_PL_OID_Create
    132                    (PKIX_NAMECONSTRAINTS_OID,
    133                    &state->nameConstraintsOID,
    134                    plContext),
    135                    PKIX_OIDCREATEFAILED);
    136 
    137        PKIX_INCREF(nameConstraints);
    138 
    139        state->nameConstraints = nameConstraints;
    140        state->certsRemaining = numCerts;
    141 
    142        *pCheckerState = state;
    143        state = NULL;
    144 
    145 cleanup:
    146 
    147        PKIX_DECREF(state);
    148 
    149        PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
    150 }
    151 
    152 /* --Private-NameConstraintsChecker-Functions------------------------- */
    153 
    154 /*
    155 * FUNCTION: pkix_NameConstraintsChecker_Check
    156 * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
    157 */
    158 static PKIX_Error *
    159 pkix_NameConstraintsChecker_Check(
    160        PKIX_CertChainChecker *checker,
    161        PKIX_PL_Cert *cert,
    162        PKIX_List *unresolvedCriticalExtensions,
    163        void **pNBIOContext,
    164        void *plContext)
    165 {
    166        pkix_NameConstraintsCheckerState *state = NULL;
    167        PKIX_PL_CertNameConstraints *nameConstraints = NULL;
    168        PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL;
    169        PKIX_Boolean selfIssued = PKIX_FALSE;
    170        PKIX_Boolean lastCert = PKIX_FALSE;
    171        PKIX_Boolean treatCommonNameAsDNSName = PKIX_FALSE;
    172        PKIX_List *extKeyUsageList = NULL;
    173        PKIX_PL_OID *serverAuthOID = NULL;
    174 
    175        PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check");
    176        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
    177 
    178        *pNBIOContext = NULL; /* we never block on pending I/O */
    179 
    180        PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
    181                    (checker, (PKIX_PL_Object **)&state, plContext),
    182                    PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
    183 
    184        state->certsRemaining--;
    185        lastCert = state->certsRemaining == 0;
    186 
    187        /* Get status of self issued */
    188        PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
    189                    PKIX_ISCERTSELFISSUEDFAILED);
    190 
    191        if (lastCert) {
    192            /* For the last cert, treat the CN as a DNS name for name
    193             * constraint check.  But only if EKU has id-kp-serverAuth
    194             * or EKU is absent.  It does not make sense to treat CN
    195             * as a DNS name for an OCSP signing certificate, for example.
    196             */
    197            PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
    198                       (cert, &extKeyUsageList, plContext),
    199                       PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
    200            if (extKeyUsageList == NULL) {
    201                treatCommonNameAsDNSName = PKIX_TRUE;
    202            } else {
    203                PKIX_CHECK(PKIX_PL_OID_Create
    204                        (PKIX_KEY_USAGE_SERVER_AUTH_OID,
    205                        &serverAuthOID,
    206                        plContext),
    207                        PKIX_OIDCREATEFAILED);
    208 
    209                PKIX_CHECK(pkix_List_Contains
    210                           (extKeyUsageList,
    211                            (PKIX_PL_Object *) serverAuthOID,
    212                            &treatCommonNameAsDNSName,
    213                            plContext),
    214                           PKIX_LISTCONTAINSFAILED);
    215            }
    216        }
    217 
    218        /* Check on non self-issued and if so only for last cert */
    219        if (selfIssued == PKIX_FALSE ||
    220            (selfIssued == PKIX_TRUE && lastCert)) {
    221                PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
    222                    (cert, state->nameConstraints, treatCommonNameAsDNSName,
    223                      plContext),
    224                    PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
    225        }
    226 
    227        if (!lastCert) {
    228 
    229            PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
    230                    (cert, &nameConstraints, plContext),
    231                    PKIX_CERTGETNAMECONSTRAINTSFAILED);
    232 
    233            /* Merge with previous name constraints kept in state */
    234 
    235            if (nameConstraints != NULL) {
    236 
    237                if (state->nameConstraints == NULL) {
    238 
    239                        state->nameConstraints = nameConstraints;
    240 
    241                } else {
    242 
    243                        PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints
    244                                (nameConstraints,
    245                                state->nameConstraints,
    246                                &mergedNameConstraints,
    247                                plContext),
    248                                PKIX_CERTMERGENAMECONSTRAINTSFAILED);
    249 
    250                        PKIX_DECREF(nameConstraints);
    251                        PKIX_DECREF(state->nameConstraints);
    252 
    253                        state->nameConstraints = mergedNameConstraints;
    254                }
    255 
    256                /* Remove Name Constraints Extension OID from list */
    257                if (unresolvedCriticalExtensions != NULL) {
    258                        PKIX_CHECK(pkix_List_Remove
    259                                    (unresolvedCriticalExtensions,
    260                                    (PKIX_PL_Object *)state->nameConstraintsOID,
    261                                    plContext),
    262                                    PKIX_LISTREMOVEFAILED);
    263                }
    264            }
    265        }
    266 
    267        PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
    268                    (checker, (PKIX_PL_Object *)state, plContext),
    269                    PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
    270 
    271 cleanup:
    272 
    273        PKIX_DECREF(state);
    274        PKIX_DECREF(extKeyUsageList);
    275        PKIX_DECREF(serverAuthOID);
    276 
    277        PKIX_RETURN(CERTCHAINCHECKER);
    278 }
    279 
    280 /*
    281 * FUNCTION: pkix_NameConstraintsChecker_Initialize
    282 *
    283 * DESCRIPTION:
    284 *  Create a CertChainChecker with a NameConstraintsCheckerState. The
    285 *  NameConstraintsCheckerState is created with "trustedNC" and "numCerts"
    286 *  as its initial state. The CertChainChecker for the NameConstraints is
    287 *  returned at address of "pChecker".
    288 *
    289 * PARAMETERS
    290 *  "trustedNC"
    291 *      The NameConstraints from trusted anchor Cert is stored at "trustedNC"
    292 *      for initialization. May be NULL.
    293 *  "numCerts"
    294 *      Number of certificates in the validation chain. This data is used
    295 *      to identify end-entity.
    296 *  "pChecker"
    297 *      Address of CertChainChecker to bo created and returned.
    298 *      Must be non-NULL.
    299 *  "plContext" - Platform-specific context pointer.
    300 *
    301 * THREAD SAFETY:
    302 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    303 *
    304 * RETURNS:
    305 *  Returns NULL if the function succeeds.
    306 *  Returns a CERTCHAINCHECKER Error if the function fails in a non-fatal way.
    307 *  Returns a Fatal Error
    308 */
    309 PKIX_Error *
    310 pkix_NameConstraintsChecker_Initialize(
    311        PKIX_PL_CertNameConstraints *trustedNC,
    312        PKIX_UInt32 numCerts,
    313        PKIX_CertChainChecker **pChecker,
    314        void *plContext)
    315 {
    316        pkix_NameConstraintsCheckerState *state = NULL;
    317 
    318        PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Initialize");
    319        PKIX_NULLCHECK_ONE(pChecker);
    320 
    321        PKIX_CHECK(pkix_NameConstraintsCheckerState_Create
    322                    (trustedNC, numCerts, &state, plContext),
    323                    PKIX_NAMECONSTRAINTSCHECKERSTATECREATEFAILED);
    324 
    325        PKIX_CHECK(PKIX_CertChainChecker_Create
    326                    (pkix_NameConstraintsChecker_Check,
    327                    PKIX_FALSE,
    328                    PKIX_FALSE,
    329                    NULL,
    330                    (PKIX_PL_Object *) state,
    331                    pChecker,
    332                    plContext),
    333                    PKIX_CERTCHAINCHECKERCREATEFAILED);
    334 
    335 cleanup:
    336 
    337        PKIX_DECREF(state);
    338 
    339        PKIX_RETURN(CERTCHAINCHECKER);
    340 }