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 }