Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | /* |
michael@0 | 5 | * pkix_policychecker.c |
michael@0 | 6 | * |
michael@0 | 7 | * Functions for Policy Checker |
michael@0 | 8 | * |
michael@0 | 9 | */ |
michael@0 | 10 | #include "pkix_policychecker.h" |
michael@0 | 11 | |
michael@0 | 12 | /* --Forward declarations----------------------------------------------- */ |
michael@0 | 13 | |
michael@0 | 14 | static PKIX_Error * |
michael@0 | 15 | pkix_PolicyChecker_MakeSingleton( |
michael@0 | 16 | PKIX_PL_Object *listItem, |
michael@0 | 17 | PKIX_Boolean immutability, |
michael@0 | 18 | PKIX_List **pList, |
michael@0 | 19 | void *plContext); |
michael@0 | 20 | |
michael@0 | 21 | /* --Private-PolicyCheckerState-Functions---------------------------------- */ |
michael@0 | 22 | |
michael@0 | 23 | /* |
michael@0 | 24 | * FUNCTION:pkix_PolicyCheckerState_Destroy |
michael@0 | 25 | * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
michael@0 | 26 | */ |
michael@0 | 27 | static PKIX_Error * |
michael@0 | 28 | pkix_PolicyCheckerState_Destroy( |
michael@0 | 29 | PKIX_PL_Object *object, |
michael@0 | 30 | void *plContext) |
michael@0 | 31 | { |
michael@0 | 32 | PKIX_PolicyCheckerState *checkerState = NULL; |
michael@0 | 33 | |
michael@0 | 34 | PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Destroy"); |
michael@0 | 35 | PKIX_NULLCHECK_ONE(object); |
michael@0 | 36 | |
michael@0 | 37 | PKIX_CHECK(pkix_CheckType |
michael@0 | 38 | (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext), |
michael@0 | 39 | PKIX_OBJECTNOTPOLICYCHECKERSTATE); |
michael@0 | 40 | |
michael@0 | 41 | checkerState = (PKIX_PolicyCheckerState *)object; |
michael@0 | 42 | |
michael@0 | 43 | PKIX_DECREF(checkerState->certPoliciesExtension); |
michael@0 | 44 | PKIX_DECREF(checkerState->policyMappingsExtension); |
michael@0 | 45 | PKIX_DECREF(checkerState->policyConstraintsExtension); |
michael@0 | 46 | PKIX_DECREF(checkerState->inhibitAnyPolicyExtension); |
michael@0 | 47 | PKIX_DECREF(checkerState->anyPolicyOID); |
michael@0 | 48 | PKIX_DECREF(checkerState->validPolicyTree); |
michael@0 | 49 | PKIX_DECREF(checkerState->userInitialPolicySet); |
michael@0 | 50 | PKIX_DECREF(checkerState->mappedUserInitialPolicySet); |
michael@0 | 51 | |
michael@0 | 52 | checkerState->policyQualifiersRejected = PKIX_FALSE; |
michael@0 | 53 | checkerState->explicitPolicy = 0; |
michael@0 | 54 | checkerState->inhibitAnyPolicy = 0; |
michael@0 | 55 | checkerState->policyMapping = 0; |
michael@0 | 56 | checkerState->numCerts = 0; |
michael@0 | 57 | checkerState->certsProcessed = 0; |
michael@0 | 58 | checkerState->certPoliciesCritical = PKIX_FALSE; |
michael@0 | 59 | |
michael@0 | 60 | PKIX_DECREF(checkerState->anyPolicyNodeAtBottom); |
michael@0 | 61 | PKIX_DECREF(checkerState->newAnyPolicyNode); |
michael@0 | 62 | PKIX_DECREF(checkerState->mappedPolicyOIDs); |
michael@0 | 63 | |
michael@0 | 64 | cleanup: |
michael@0 | 65 | |
michael@0 | 66 | PKIX_RETURN(CERTPOLICYCHECKERSTATE); |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | /* |
michael@0 | 70 | * FUNCTION: pkix_PolicyCheckerState_ToString |
michael@0 | 71 | * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) |
michael@0 | 72 | */ |
michael@0 | 73 | static PKIX_Error * |
michael@0 | 74 | pkix_PolicyCheckerState_ToString( |
michael@0 | 75 | PKIX_PL_Object *object, |
michael@0 | 76 | PKIX_PL_String **pCheckerStateString, |
michael@0 | 77 | void *plContext) |
michael@0 | 78 | { |
michael@0 | 79 | PKIX_PolicyCheckerState *state = NULL; |
michael@0 | 80 | PKIX_PL_String *resultString = NULL; |
michael@0 | 81 | PKIX_PL_String *policiesExtOIDString = NULL; |
michael@0 | 82 | PKIX_PL_String *policyMapOIDString = NULL; |
michael@0 | 83 | PKIX_PL_String *policyConstrOIDString = NULL; |
michael@0 | 84 | PKIX_PL_String *inhAnyPolOIDString = NULL; |
michael@0 | 85 | PKIX_PL_String *anyPolicyOIDString = NULL; |
michael@0 | 86 | PKIX_PL_String *validPolicyTreeString = NULL; |
michael@0 | 87 | PKIX_PL_String *userInitialPolicySetString = NULL; |
michael@0 | 88 | PKIX_PL_String *mappedUserPolicySetString = NULL; |
michael@0 | 89 | PKIX_PL_String *mappedPolicyOIDsString = NULL; |
michael@0 | 90 | PKIX_PL_String *anyAtBottomString = NULL; |
michael@0 | 91 | PKIX_PL_String *newAnyPolicyString = NULL; |
michael@0 | 92 | PKIX_PL_String *formatString = NULL; |
michael@0 | 93 | PKIX_PL_String *trueString = NULL; |
michael@0 | 94 | PKIX_PL_String *falseString = NULL; |
michael@0 | 95 | PKIX_PL_String *nullString = NULL; |
michael@0 | 96 | PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; |
michael@0 | 97 | PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; |
michael@0 | 98 | PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; |
michael@0 | 99 | PKIX_Boolean initialIsAnyPolicy = PKIX_FALSE; |
michael@0 | 100 | PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; |
michael@0 | 101 | PKIX_Boolean certPoliciesCritical = PKIX_FALSE; |
michael@0 | 102 | char *asciiFormat = |
michael@0 | 103 | "{\n" |
michael@0 | 104 | "\tcertPoliciesExtension: \t%s\n" |
michael@0 | 105 | "\tpolicyMappingsExtension: \t%s\n" |
michael@0 | 106 | "\tpolicyConstraintsExtension:\t%s\n" |
michael@0 | 107 | "\tinhibitAnyPolicyExtension:\t%s\n" |
michael@0 | 108 | "\tanyPolicyOID: \t%s\n" |
michael@0 | 109 | "\tinitialIsAnyPolicy: \t%s\n" |
michael@0 | 110 | "\tvalidPolicyTree: \t%s\n" |
michael@0 | 111 | "\tuserInitialPolicySet: \t%s\n" |
michael@0 | 112 | "\tmappedUserPolicySet: \t%s\n" |
michael@0 | 113 | "\tpolicyQualifiersRejected: \t%s\n" |
michael@0 | 114 | "\tinitialPolMappingInhibit: \t%s\n" |
michael@0 | 115 | "\tinitialExplicitPolicy: \t%s\n" |
michael@0 | 116 | "\tinitialAnyPolicyInhibit: \t%s\n" |
michael@0 | 117 | "\texplicitPolicy: \t%d\n" |
michael@0 | 118 | "\tinhibitAnyPolicy: \t%d\n" |
michael@0 | 119 | "\tpolicyMapping: \t%d\n" |
michael@0 | 120 | "\tnumCerts: \t%d\n" |
michael@0 | 121 | "\tcertsProcessed: \t%d\n" |
michael@0 | 122 | "\tanyPolicyNodeAtBottom: \t%s\n" |
michael@0 | 123 | "\tnewAnyPolicyNode: \t%s\n" |
michael@0 | 124 | "\tcertPoliciesCritical: \t%s\n" |
michael@0 | 125 | "\tmappedPolicyOIDs: \t%s\n" |
michael@0 | 126 | "}"; |
michael@0 | 127 | |
michael@0 | 128 | PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_ToString"); |
michael@0 | 129 | |
michael@0 | 130 | PKIX_NULLCHECK_TWO(object, pCheckerStateString); |
michael@0 | 131 | |
michael@0 | 132 | PKIX_CHECK(pkix_CheckType |
michael@0 | 133 | (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext), |
michael@0 | 134 | PKIX_OBJECTNOTPOLICYCHECKERSTATE); |
michael@0 | 135 | |
michael@0 | 136 | state = (PKIX_PolicyCheckerState *)object; |
michael@0 | 137 | PKIX_NULLCHECK_THREE |
michael@0 | 138 | (state->certPoliciesExtension, |
michael@0 | 139 | state->policyMappingsExtension, |
michael@0 | 140 | state->policyConstraintsExtension); |
michael@0 | 141 | PKIX_NULLCHECK_THREE |
michael@0 | 142 | (state->inhibitAnyPolicyExtension, |
michael@0 | 143 | state->anyPolicyOID, |
michael@0 | 144 | state->userInitialPolicySet); |
michael@0 | 145 | |
michael@0 | 146 | PKIX_CHECK(PKIX_PL_String_Create |
michael@0 | 147 | (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), |
michael@0 | 148 | PKIX_STRINGCREATEFAILED); |
michael@0 | 149 | /* |
michael@0 | 150 | * Create TRUE, FALSE, and "NULL" PKIX_PL_Strings. But creating a |
michael@0 | 151 | * PKIX_PL_String is complicated enough, it's worth checking, for |
michael@0 | 152 | * each, to make sure the string is needed. |
michael@0 | 153 | */ |
michael@0 | 154 | initialPolicyMappingInhibit = state->initialPolicyMappingInhibit; |
michael@0 | 155 | initialExplicitPolicy = state->initialExplicitPolicy; |
michael@0 | 156 | initialAnyPolicyInhibit = state->initialAnyPolicyInhibit; |
michael@0 | 157 | initialIsAnyPolicy = state->initialIsAnyPolicy; |
michael@0 | 158 | policyQualifiersRejected = state->policyQualifiersRejected; |
michael@0 | 159 | certPoliciesCritical = state->certPoliciesCritical; |
michael@0 | 160 | |
michael@0 | 161 | if (initialPolicyMappingInhibit || initialExplicitPolicy || |
michael@0 | 162 | initialAnyPolicyInhibit || initialIsAnyPolicy || |
michael@0 | 163 | policyQualifiersRejected || certPoliciesCritical) { |
michael@0 | 164 | PKIX_CHECK(PKIX_PL_String_Create |
michael@0 | 165 | (PKIX_ESCASCII, "TRUE", 0, &trueString, plContext), |
michael@0 | 166 | PKIX_STRINGCREATEFAILED); |
michael@0 | 167 | } |
michael@0 | 168 | if (!initialPolicyMappingInhibit || !initialExplicitPolicy || |
michael@0 | 169 | !initialAnyPolicyInhibit || !initialIsAnyPolicy || |
michael@0 | 170 | !policyQualifiersRejected || !certPoliciesCritical) { |
michael@0 | 171 | PKIX_CHECK(PKIX_PL_String_Create |
michael@0 | 172 | (PKIX_ESCASCII, "FALSE", 0, &falseString, plContext), |
michael@0 | 173 | PKIX_STRINGCREATEFAILED); |
michael@0 | 174 | } |
michael@0 | 175 | if (!(state->anyPolicyNodeAtBottom) || !(state->newAnyPolicyNode)) { |
michael@0 | 176 | PKIX_CHECK(PKIX_PL_String_Create |
michael@0 | 177 | (PKIX_ESCASCII, "(null)", 0, &nullString, plContext), |
michael@0 | 178 | PKIX_STRINGCREATEFAILED); |
michael@0 | 179 | } |
michael@0 | 180 | |
michael@0 | 181 | PKIX_TOSTRING |
michael@0 | 182 | (state->certPoliciesExtension, &policiesExtOIDString, plContext, |
michael@0 | 183 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 184 | |
michael@0 | 185 | PKIX_TOSTRING |
michael@0 | 186 | (state->policyMappingsExtension, |
michael@0 | 187 | &policyMapOIDString, |
michael@0 | 188 | plContext, |
michael@0 | 189 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 190 | |
michael@0 | 191 | PKIX_TOSTRING |
michael@0 | 192 | (state->policyConstraintsExtension, |
michael@0 | 193 | &policyConstrOIDString, |
michael@0 | 194 | plContext, |
michael@0 | 195 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 196 | |
michael@0 | 197 | PKIX_TOSTRING |
michael@0 | 198 | (state->inhibitAnyPolicyExtension, |
michael@0 | 199 | &inhAnyPolOIDString, |
michael@0 | 200 | plContext, |
michael@0 | 201 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 202 | |
michael@0 | 203 | PKIX_TOSTRING(state->anyPolicyOID, &anyPolicyOIDString, plContext, |
michael@0 | 204 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 205 | |
michael@0 | 206 | PKIX_TOSTRING(state->validPolicyTree, &validPolicyTreeString, plContext, |
michael@0 | 207 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 208 | |
michael@0 | 209 | PKIX_TOSTRING |
michael@0 | 210 | (state->userInitialPolicySet, |
michael@0 | 211 | &userInitialPolicySetString, |
michael@0 | 212 | plContext, |
michael@0 | 213 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 214 | |
michael@0 | 215 | PKIX_TOSTRING |
michael@0 | 216 | (state->mappedUserInitialPolicySet, |
michael@0 | 217 | &mappedUserPolicySetString, |
michael@0 | 218 | plContext, |
michael@0 | 219 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 220 | |
michael@0 | 221 | if (state->anyPolicyNodeAtBottom) { |
michael@0 | 222 | PKIX_CHECK(pkix_SinglePolicyNode_ToString |
michael@0 | 223 | (state->anyPolicyNodeAtBottom, |
michael@0 | 224 | &anyAtBottomString, |
michael@0 | 225 | plContext), |
michael@0 | 226 | PKIX_SINGLEPOLICYNODETOSTRINGFAILED); |
michael@0 | 227 | } else { |
michael@0 | 228 | PKIX_INCREF(nullString); |
michael@0 | 229 | anyAtBottomString = nullString; |
michael@0 | 230 | } |
michael@0 | 231 | |
michael@0 | 232 | if (state->newAnyPolicyNode) { |
michael@0 | 233 | PKIX_CHECK(pkix_SinglePolicyNode_ToString |
michael@0 | 234 | (state->newAnyPolicyNode, |
michael@0 | 235 | &newAnyPolicyString, |
michael@0 | 236 | plContext), |
michael@0 | 237 | PKIX_SINGLEPOLICYNODETOSTRINGFAILED); |
michael@0 | 238 | } else { |
michael@0 | 239 | PKIX_INCREF(nullString); |
michael@0 | 240 | newAnyPolicyString = nullString; |
michael@0 | 241 | } |
michael@0 | 242 | |
michael@0 | 243 | PKIX_TOSTRING |
michael@0 | 244 | (state->mappedPolicyOIDs, |
michael@0 | 245 | &mappedPolicyOIDsString, |
michael@0 | 246 | plContext, |
michael@0 | 247 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 248 | |
michael@0 | 249 | PKIX_CHECK(PKIX_PL_Sprintf |
michael@0 | 250 | (&resultString, |
michael@0 | 251 | plContext, |
michael@0 | 252 | formatString, |
michael@0 | 253 | policiesExtOIDString, |
michael@0 | 254 | policyMapOIDString, |
michael@0 | 255 | policyConstrOIDString, |
michael@0 | 256 | inhAnyPolOIDString, |
michael@0 | 257 | anyPolicyOIDString, |
michael@0 | 258 | initialIsAnyPolicy?trueString:falseString, |
michael@0 | 259 | validPolicyTreeString, |
michael@0 | 260 | userInitialPolicySetString, |
michael@0 | 261 | mappedUserPolicySetString, |
michael@0 | 262 | policyQualifiersRejected?trueString:falseString, |
michael@0 | 263 | initialPolicyMappingInhibit?trueString:falseString, |
michael@0 | 264 | initialExplicitPolicy?trueString:falseString, |
michael@0 | 265 | initialAnyPolicyInhibit?trueString:falseString, |
michael@0 | 266 | state->explicitPolicy, |
michael@0 | 267 | state->inhibitAnyPolicy, |
michael@0 | 268 | state->policyMapping, |
michael@0 | 269 | state->numCerts, |
michael@0 | 270 | state->certsProcessed, |
michael@0 | 271 | anyAtBottomString, |
michael@0 | 272 | newAnyPolicyString, |
michael@0 | 273 | certPoliciesCritical?trueString:falseString, |
michael@0 | 274 | mappedPolicyOIDsString), |
michael@0 | 275 | PKIX_SPRINTFFAILED); |
michael@0 | 276 | |
michael@0 | 277 | *pCheckerStateString = resultString; |
michael@0 | 278 | |
michael@0 | 279 | cleanup: |
michael@0 | 280 | PKIX_DECREF(policiesExtOIDString); |
michael@0 | 281 | PKIX_DECREF(policyMapOIDString); |
michael@0 | 282 | PKIX_DECREF(policyConstrOIDString); |
michael@0 | 283 | PKIX_DECREF(inhAnyPolOIDString); |
michael@0 | 284 | PKIX_DECREF(anyPolicyOIDString); |
michael@0 | 285 | PKIX_DECREF(validPolicyTreeString); |
michael@0 | 286 | PKIX_DECREF(userInitialPolicySetString); |
michael@0 | 287 | PKIX_DECREF(mappedUserPolicySetString); |
michael@0 | 288 | PKIX_DECREF(anyAtBottomString); |
michael@0 | 289 | PKIX_DECREF(newAnyPolicyString); |
michael@0 | 290 | PKIX_DECREF(mappedPolicyOIDsString); |
michael@0 | 291 | PKIX_DECREF(formatString); |
michael@0 | 292 | PKIX_DECREF(trueString); |
michael@0 | 293 | PKIX_DECREF(falseString); |
michael@0 | 294 | PKIX_DECREF(nullString); |
michael@0 | 295 | |
michael@0 | 296 | PKIX_RETURN(CERTPOLICYCHECKERSTATE); |
michael@0 | 297 | } |
michael@0 | 298 | |
michael@0 | 299 | /* |
michael@0 | 300 | * FUNCTION: pkix_PolicyCheckerState_RegisterSelf |
michael@0 | 301 | * DESCRIPTION: |
michael@0 | 302 | * |
michael@0 | 303 | * Registers PKIX_POLICYCHECKERSTATE_TYPE and its related functions |
michael@0 | 304 | * with systemClasses[] |
michael@0 | 305 | * |
michael@0 | 306 | * PARAMETERS: |
michael@0 | 307 | * "plContext" |
michael@0 | 308 | * Platform-specific context pointer. |
michael@0 | 309 | * THREAD SAFETY: |
michael@0 | 310 | * Not Thread Safe - for performance and complexity reasons |
michael@0 | 311 | * |
michael@0 | 312 | * Since this function is only called by PKIX_PL_Initialize, which should |
michael@0 | 313 | * only be called once, it is acceptable that this function is not |
michael@0 | 314 | * thread-safe. |
michael@0 | 315 | */ |
michael@0 | 316 | PKIX_Error * |
michael@0 | 317 | pkix_PolicyCheckerState_RegisterSelf(void *plContext) |
michael@0 | 318 | { |
michael@0 | 319 | extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
michael@0 | 320 | pkix_ClassTable_Entry entry; |
michael@0 | 321 | |
michael@0 | 322 | PKIX_ENTER |
michael@0 | 323 | (CERTPOLICYCHECKERSTATE, |
michael@0 | 324 | "pkix_PolicyCheckerState_RegisterSelf"); |
michael@0 | 325 | |
michael@0 | 326 | entry.description = "PolicyCheckerState"; |
michael@0 | 327 | entry.objCounter = 0; |
michael@0 | 328 | entry.typeObjectSize = sizeof(PKIX_PolicyCheckerState); |
michael@0 | 329 | entry.destructor = pkix_PolicyCheckerState_Destroy; |
michael@0 | 330 | entry.equalsFunction = NULL; |
michael@0 | 331 | entry.hashcodeFunction = NULL; |
michael@0 | 332 | entry.toStringFunction = pkix_PolicyCheckerState_ToString; |
michael@0 | 333 | entry.comparator = NULL; |
michael@0 | 334 | entry.duplicateFunction = NULL; |
michael@0 | 335 | |
michael@0 | 336 | systemClasses[PKIX_CERTPOLICYCHECKERSTATE_TYPE] = entry; |
michael@0 | 337 | |
michael@0 | 338 | PKIX_RETURN(CERTPOLICYCHECKERSTATE); |
michael@0 | 339 | } |
michael@0 | 340 | |
michael@0 | 341 | /* |
michael@0 | 342 | * FUNCTION:pkix_PolicyCheckerState_Create |
michael@0 | 343 | * DESCRIPTION: |
michael@0 | 344 | * |
michael@0 | 345 | * Creates a PolicyCheckerState Object, using the List pointed to |
michael@0 | 346 | * by "initialPolicies" for the user-initial-policy-set, the Boolean value |
michael@0 | 347 | * of "policyQualifiersRejected" for the policyQualifiersRejected parameter, |
michael@0 | 348 | * the Boolean value of "initialPolicyMappingInhibit" for the |
michael@0 | 349 | * inhibitPolicyMappings parameter, the Boolean value of |
michael@0 | 350 | * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the |
michael@0 | 351 | * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy |
michael@0 | 352 | * parameter, and the UInt32 value of "numCerts" as the number of |
michael@0 | 353 | * certificates in the chain; and stores the Object at "pCheckerState". |
michael@0 | 354 | * |
michael@0 | 355 | * PARAMETERS: |
michael@0 | 356 | * "initialPolicies" |
michael@0 | 357 | * Address of List of OIDs comprising the user-initial-policy-set; the List |
michael@0 | 358 | * may be empty, but must be non-NULL |
michael@0 | 359 | * "policyQualifiersRejected" |
michael@0 | 360 | * Boolean value of the policyQualifiersRejected parameter |
michael@0 | 361 | * "initialPolicyMappingInhibit" |
michael@0 | 362 | * Boolean value of the inhibitPolicyMappings parameter |
michael@0 | 363 | * "initialExplicitPolicy" |
michael@0 | 364 | * Boolean value of the initialExplicitPolicy parameter |
michael@0 | 365 | * "initialAnyPolicyInhibit" |
michael@0 | 366 | * Boolean value of the inhibitAnyPolicy parameter |
michael@0 | 367 | * "numCerts" |
michael@0 | 368 | * Number of certificates in the chain to be validated |
michael@0 | 369 | * "pCheckerState" |
michael@0 | 370 | * Address where PolicyCheckerState will be stored. Must be non-NULL. |
michael@0 | 371 | * "plContext" |
michael@0 | 372 | * Platform-specific context pointer. |
michael@0 | 373 | * THREAD SAFETY: |
michael@0 | 374 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 375 | * RETURNS: |
michael@0 | 376 | * Returns NULL if the function succeeds |
michael@0 | 377 | * Returns a CertPolicyCheckerState Error if the functions fails in a |
michael@0 | 378 | * non-fatal way |
michael@0 | 379 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 380 | */ |
michael@0 | 381 | static PKIX_Error * |
michael@0 | 382 | pkix_PolicyCheckerState_Create( |
michael@0 | 383 | PKIX_List *initialPolicies, |
michael@0 | 384 | PKIX_Boolean policyQualifiersRejected, |
michael@0 | 385 | PKIX_Boolean initialPolicyMappingInhibit, |
michael@0 | 386 | PKIX_Boolean initialExplicitPolicy, |
michael@0 | 387 | PKIX_Boolean initialAnyPolicyInhibit, |
michael@0 | 388 | PKIX_UInt32 numCerts, |
michael@0 | 389 | PKIX_PolicyCheckerState **pCheckerState, |
michael@0 | 390 | void *plContext) |
michael@0 | 391 | { |
michael@0 | 392 | PKIX_PolicyCheckerState *checkerState = NULL; |
michael@0 | 393 | PKIX_PolicyNode *policyNode = NULL; |
michael@0 | 394 | PKIX_List *anyPolicyList = NULL; |
michael@0 | 395 | PKIX_Boolean initialPoliciesIsEmpty = PKIX_FALSE; |
michael@0 | 396 | |
michael@0 | 397 | PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Create"); |
michael@0 | 398 | PKIX_NULLCHECK_TWO(initialPolicies, pCheckerState); |
michael@0 | 399 | |
michael@0 | 400 | PKIX_CHECK(PKIX_PL_Object_Alloc |
michael@0 | 401 | (PKIX_CERTPOLICYCHECKERSTATE_TYPE, |
michael@0 | 402 | sizeof (PKIX_PolicyCheckerState), |
michael@0 | 403 | (PKIX_PL_Object **)&checkerState, |
michael@0 | 404 | plContext), |
michael@0 | 405 | PKIX_COULDNOTCREATEPOLICYCHECKERSTATEOBJECT); |
michael@0 | 406 | |
michael@0 | 407 | /* Create constant PKIX_PL_OIDs: */ |
michael@0 | 408 | |
michael@0 | 409 | PKIX_CHECK(PKIX_PL_OID_Create |
michael@0 | 410 | (PKIX_CERTIFICATEPOLICIES_OID, |
michael@0 | 411 | &(checkerState->certPoliciesExtension), |
michael@0 | 412 | plContext), |
michael@0 | 413 | PKIX_OIDCREATEFAILED); |
michael@0 | 414 | |
michael@0 | 415 | PKIX_CHECK(PKIX_PL_OID_Create |
michael@0 | 416 | (PKIX_POLICYMAPPINGS_OID, |
michael@0 | 417 | &(checkerState->policyMappingsExtension), |
michael@0 | 418 | plContext), |
michael@0 | 419 | PKIX_OIDCREATEFAILED); |
michael@0 | 420 | |
michael@0 | 421 | PKIX_CHECK(PKIX_PL_OID_Create |
michael@0 | 422 | (PKIX_POLICYCONSTRAINTS_OID, |
michael@0 | 423 | &(checkerState->policyConstraintsExtension), |
michael@0 | 424 | plContext), |
michael@0 | 425 | PKIX_OIDCREATEFAILED); |
michael@0 | 426 | |
michael@0 | 427 | PKIX_CHECK(PKIX_PL_OID_Create |
michael@0 | 428 | (PKIX_INHIBITANYPOLICY_OID, |
michael@0 | 429 | &(checkerState->inhibitAnyPolicyExtension), |
michael@0 | 430 | plContext), |
michael@0 | 431 | PKIX_OIDCREATEFAILED); |
michael@0 | 432 | |
michael@0 | 433 | PKIX_CHECK(PKIX_PL_OID_Create |
michael@0 | 434 | (PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID, |
michael@0 | 435 | &(checkerState->anyPolicyOID), |
michael@0 | 436 | plContext), |
michael@0 | 437 | PKIX_OIDCREATEFAILED); |
michael@0 | 438 | |
michael@0 | 439 | /* Create an initial policy set from argument supplied */ |
michael@0 | 440 | PKIX_INCREF(initialPolicies); |
michael@0 | 441 | checkerState->userInitialPolicySet = initialPolicies; |
michael@0 | 442 | PKIX_INCREF(initialPolicies); |
michael@0 | 443 | checkerState->mappedUserInitialPolicySet = initialPolicies; |
michael@0 | 444 | |
michael@0 | 445 | PKIX_CHECK(PKIX_List_IsEmpty |
michael@0 | 446 | (initialPolicies, |
michael@0 | 447 | &initialPoliciesIsEmpty, |
michael@0 | 448 | plContext), |
michael@0 | 449 | PKIX_LISTISEMPTYFAILED); |
michael@0 | 450 | if (initialPoliciesIsEmpty) { |
michael@0 | 451 | checkerState->initialIsAnyPolicy = PKIX_TRUE; |
michael@0 | 452 | } else { |
michael@0 | 453 | PKIX_CHECK(pkix_List_Contains |
michael@0 | 454 | (initialPolicies, |
michael@0 | 455 | (PKIX_PL_Object *)(checkerState->anyPolicyOID), |
michael@0 | 456 | &(checkerState->initialIsAnyPolicy), |
michael@0 | 457 | plContext), |
michael@0 | 458 | PKIX_LISTCONTAINSFAILED); |
michael@0 | 459 | } |
michael@0 | 460 | |
michael@0 | 461 | checkerState->policyQualifiersRejected = |
michael@0 | 462 | policyQualifiersRejected; |
michael@0 | 463 | checkerState->initialExplicitPolicy = initialExplicitPolicy; |
michael@0 | 464 | checkerState->explicitPolicy = |
michael@0 | 465 | (initialExplicitPolicy? 0: numCerts + 1); |
michael@0 | 466 | checkerState->initialAnyPolicyInhibit = initialAnyPolicyInhibit; |
michael@0 | 467 | checkerState->inhibitAnyPolicy = |
michael@0 | 468 | (initialAnyPolicyInhibit? 0: numCerts + 1); |
michael@0 | 469 | checkerState->initialPolicyMappingInhibit = initialPolicyMappingInhibit; |
michael@0 | 470 | checkerState->policyMapping = |
michael@0 | 471 | (initialPolicyMappingInhibit? 0: numCerts + 1); |
michael@0 | 472 | ; |
michael@0 | 473 | checkerState->numCerts = numCerts; |
michael@0 | 474 | checkerState->certsProcessed = 0; |
michael@0 | 475 | checkerState->certPoliciesCritical = PKIX_FALSE; |
michael@0 | 476 | |
michael@0 | 477 | /* Create a valid_policy_tree as in RFC3280 6.1.2(a) */ |
michael@0 | 478 | PKIX_CHECK(pkix_PolicyChecker_MakeSingleton |
michael@0 | 479 | ((PKIX_PL_Object *)(checkerState->anyPolicyOID), |
michael@0 | 480 | PKIX_TRUE, |
michael@0 | 481 | &anyPolicyList, |
michael@0 | 482 | plContext), |
michael@0 | 483 | PKIX_POLICYCHECKERMAKESINGLETONFAILED); |
michael@0 | 484 | |
michael@0 | 485 | PKIX_CHECK(pkix_PolicyNode_Create |
michael@0 | 486 | (checkerState->anyPolicyOID, /* validPolicy */ |
michael@0 | 487 | NULL, /* qualifier set */ |
michael@0 | 488 | PKIX_FALSE, /* criticality */ |
michael@0 | 489 | anyPolicyList, /* expectedPolicySet */ |
michael@0 | 490 | &policyNode, |
michael@0 | 491 | plContext), |
michael@0 | 492 | PKIX_POLICYNODECREATEFAILED); |
michael@0 | 493 | checkerState->validPolicyTree = policyNode; |
michael@0 | 494 | |
michael@0 | 495 | /* |
michael@0 | 496 | * Since the initial validPolicyTree specifies |
michael@0 | 497 | * ANY_POLICY, begin with a pointer to the root node. |
michael@0 | 498 | */ |
michael@0 | 499 | PKIX_INCREF(policyNode); |
michael@0 | 500 | checkerState->anyPolicyNodeAtBottom = policyNode; |
michael@0 | 501 | |
michael@0 | 502 | checkerState->newAnyPolicyNode = NULL; |
michael@0 | 503 | |
michael@0 | 504 | checkerState->mappedPolicyOIDs = NULL; |
michael@0 | 505 | |
michael@0 | 506 | *pCheckerState = checkerState; |
michael@0 | 507 | checkerState = NULL; |
michael@0 | 508 | |
michael@0 | 509 | cleanup: |
michael@0 | 510 | |
michael@0 | 511 | PKIX_DECREF(checkerState); |
michael@0 | 512 | |
michael@0 | 513 | PKIX_DECREF(anyPolicyList); |
michael@0 | 514 | |
michael@0 | 515 | PKIX_RETURN(CERTPOLICYCHECKERSTATE); |
michael@0 | 516 | } |
michael@0 | 517 | |
michael@0 | 518 | /* --Private-PolicyChecker-Functions--------------------------------------- */ |
michael@0 | 519 | |
michael@0 | 520 | /* |
michael@0 | 521 | * FUNCTION: pkix_PolicyChecker_MapContains |
michael@0 | 522 | * DESCRIPTION: |
michael@0 | 523 | * |
michael@0 | 524 | * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to |
michael@0 | 525 | * determine whether the OID pointed to by "policy" is among the |
michael@0 | 526 | * issuerDomainPolicies or subjectDomainPolicies of "certPolicyMaps", and |
michael@0 | 527 | * stores the result in "pFound". |
michael@0 | 528 | * |
michael@0 | 529 | * This function is intended to allow an efficient check that the proscription |
michael@0 | 530 | * against anyPolicy being mapped, described in RFC3280 Section 6.1.4(a), is |
michael@0 | 531 | * not violated. |
michael@0 | 532 | * |
michael@0 | 533 | * PARAMETERS: |
michael@0 | 534 | * "certPolicyMaps" |
michael@0 | 535 | * Address of List of CertPolicyMaps to be searched. May be empty, but |
michael@0 | 536 | * must be non-NULL |
michael@0 | 537 | * "policy" |
michael@0 | 538 | * Address of OID to be checked for. Must be non-NULL |
michael@0 | 539 | * "pFound" |
michael@0 | 540 | * Address where the result of the search will be stored. Must be non-NULL. |
michael@0 | 541 | * "plContext" |
michael@0 | 542 | * platform-specific context pointer |
michael@0 | 543 | * THREAD SAFETY: |
michael@0 | 544 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 545 | * RETURNS: |
michael@0 | 546 | * Returns NULL if the function succeeds |
michael@0 | 547 | * Returns a CertChainChecker Error if the function fails in a non-fatal way. |
michael@0 | 548 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 549 | */ |
michael@0 | 550 | PKIX_Error * |
michael@0 | 551 | pkix_PolicyChecker_MapContains( |
michael@0 | 552 | PKIX_List *certPolicyMaps, |
michael@0 | 553 | PKIX_PL_OID *policy, |
michael@0 | 554 | PKIX_Boolean *pFound, |
michael@0 | 555 | void *plContext) |
michael@0 | 556 | { |
michael@0 | 557 | PKIX_PL_CertPolicyMap *map = NULL; |
michael@0 | 558 | PKIX_UInt32 numEntries = 0; |
michael@0 | 559 | PKIX_UInt32 index = 0; |
michael@0 | 560 | PKIX_Boolean match = PKIX_FALSE; |
michael@0 | 561 | PKIX_PL_OID *issuerDomainPolicy = NULL; |
michael@0 | 562 | PKIX_PL_OID *subjectDomainPolicy = NULL; |
michael@0 | 563 | |
michael@0 | 564 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MapContains"); |
michael@0 | 565 | PKIX_NULLCHECK_THREE(certPolicyMaps, policy, pFound); |
michael@0 | 566 | |
michael@0 | 567 | PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext), |
michael@0 | 568 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 569 | |
michael@0 | 570 | for (index = 0; (!match) && (index < numEntries); index++) { |
michael@0 | 571 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 572 | (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), |
michael@0 | 573 | PKIX_LISTGETITEMFAILED); |
michael@0 | 574 | |
michael@0 | 575 | PKIX_NULLCHECK_ONE(map); |
michael@0 | 576 | |
michael@0 | 577 | PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy |
michael@0 | 578 | (map, &issuerDomainPolicy, plContext), |
michael@0 | 579 | PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); |
michael@0 | 580 | |
michael@0 | 581 | PKIX_EQUALS |
michael@0 | 582 | (policy, issuerDomainPolicy, &match, plContext, |
michael@0 | 583 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 584 | |
michael@0 | 585 | if (!match) { |
michael@0 | 586 | PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy |
michael@0 | 587 | (map, &subjectDomainPolicy, plContext), |
michael@0 | 588 | PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED); |
michael@0 | 589 | |
michael@0 | 590 | PKIX_EQUALS |
michael@0 | 591 | (policy, subjectDomainPolicy, &match, plContext, |
michael@0 | 592 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 593 | } |
michael@0 | 594 | |
michael@0 | 595 | PKIX_DECREF(map); |
michael@0 | 596 | PKIX_DECREF(issuerDomainPolicy); |
michael@0 | 597 | PKIX_DECREF(subjectDomainPolicy); |
michael@0 | 598 | } |
michael@0 | 599 | |
michael@0 | 600 | *pFound = match; |
michael@0 | 601 | |
michael@0 | 602 | cleanup: |
michael@0 | 603 | |
michael@0 | 604 | PKIX_DECREF(map); |
michael@0 | 605 | PKIX_DECREF(issuerDomainPolicy); |
michael@0 | 606 | PKIX_DECREF(subjectDomainPolicy); |
michael@0 | 607 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 608 | } |
michael@0 | 609 | |
michael@0 | 610 | /* |
michael@0 | 611 | * FUNCTION: pkix_PolicyChecker_MapGetSubjectDomainPolicies |
michael@0 | 612 | * DESCRIPTION: |
michael@0 | 613 | * |
michael@0 | 614 | * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to create |
michael@0 | 615 | * a list of all SubjectDomainPolicies for which the IssuerDomainPolicy is the |
michael@0 | 616 | * policy pointed to by "policy", and stores the result in |
michael@0 | 617 | * "pSubjectDomainPolicies". |
michael@0 | 618 | * |
michael@0 | 619 | * If the List of CertPolicyMaps provided in "certPolicyMaps" is NULL, the |
michael@0 | 620 | * resulting List will be NULL. If there are CertPolicyMaps, but none that |
michael@0 | 621 | * include "policy" as an IssuerDomainPolicy, the returned List pointer will |
michael@0 | 622 | * be NULL. Otherwise, the returned List will contain the SubjectDomainPolicies |
michael@0 | 623 | * of all CertPolicyMaps for which "policy" is the IssuerDomainPolicy. If a |
michael@0 | 624 | * List is returned it will be immutable. |
michael@0 | 625 | * |
michael@0 | 626 | * PARAMETERS: |
michael@0 | 627 | * "certPolicyMaps" |
michael@0 | 628 | * Address of List of CertPolicyMaps to be searched. May be empty or NULL. |
michael@0 | 629 | * "policy" |
michael@0 | 630 | * Address of OID to be checked for. Must be non-NULL |
michael@0 | 631 | * "pSubjectDomainPolicies" |
michael@0 | 632 | * Address where the result of the search will be stored. Must be non-NULL. |
michael@0 | 633 | * "plContext" |
michael@0 | 634 | * platform-specific context pointer |
michael@0 | 635 | * THREAD SAFETY: |
michael@0 | 636 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 637 | * RETURNS: |
michael@0 | 638 | * Returns NULL if the function succeeds |
michael@0 | 639 | * Returns a CertChainChecker Error if the function fails in a non-fatal way. |
michael@0 | 640 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 641 | */ |
michael@0 | 642 | PKIX_Error * |
michael@0 | 643 | pkix_PolicyChecker_MapGetSubjectDomainPolicies( |
michael@0 | 644 | PKIX_List *certPolicyMaps, |
michael@0 | 645 | PKIX_PL_OID *policy, |
michael@0 | 646 | PKIX_List **pSubjectDomainPolicies, |
michael@0 | 647 | void *plContext) |
michael@0 | 648 | { |
michael@0 | 649 | PKIX_PL_CertPolicyMap *map = NULL; |
michael@0 | 650 | PKIX_List *subjectList = NULL; |
michael@0 | 651 | PKIX_UInt32 numEntries = 0; |
michael@0 | 652 | PKIX_UInt32 index = 0; |
michael@0 | 653 | PKIX_Boolean match = PKIX_FALSE; |
michael@0 | 654 | PKIX_PL_OID *issuerDomainPolicy = NULL; |
michael@0 | 655 | PKIX_PL_OID *subjectDomainPolicy = NULL; |
michael@0 | 656 | |
michael@0 | 657 | PKIX_ENTER |
michael@0 | 658 | (CERTCHAINCHECKER, |
michael@0 | 659 | "pkix_PolicyChecker_MapGetSubjectDomainPolicies"); |
michael@0 | 660 | PKIX_NULLCHECK_TWO(policy, pSubjectDomainPolicies); |
michael@0 | 661 | |
michael@0 | 662 | if (certPolicyMaps) { |
michael@0 | 663 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 664 | (certPolicyMaps, |
michael@0 | 665 | &numEntries, |
michael@0 | 666 | plContext), |
michael@0 | 667 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 668 | } |
michael@0 | 669 | |
michael@0 | 670 | for (index = 0; index < numEntries; index++) { |
michael@0 | 671 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 672 | (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), |
michael@0 | 673 | PKIX_LISTGETITEMFAILED); |
michael@0 | 674 | |
michael@0 | 675 | PKIX_NULLCHECK_ONE(map); |
michael@0 | 676 | |
michael@0 | 677 | PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy |
michael@0 | 678 | (map, &issuerDomainPolicy, plContext), |
michael@0 | 679 | PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); |
michael@0 | 680 | |
michael@0 | 681 | PKIX_EQUALS |
michael@0 | 682 | (policy, issuerDomainPolicy, &match, plContext, |
michael@0 | 683 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 684 | |
michael@0 | 685 | if (match) { |
michael@0 | 686 | if (!subjectList) { |
michael@0 | 687 | PKIX_CHECK(PKIX_List_Create(&subjectList, plContext), |
michael@0 | 688 | PKIX_LISTCREATEFAILED); |
michael@0 | 689 | } |
michael@0 | 690 | |
michael@0 | 691 | PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy |
michael@0 | 692 | (map, &subjectDomainPolicy, plContext), |
michael@0 | 693 | PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED); |
michael@0 | 694 | |
michael@0 | 695 | PKIX_CHECK(PKIX_List_AppendItem |
michael@0 | 696 | (subjectList, |
michael@0 | 697 | (PKIX_PL_Object *)subjectDomainPolicy, |
michael@0 | 698 | plContext), |
michael@0 | 699 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 700 | } |
michael@0 | 701 | |
michael@0 | 702 | PKIX_DECREF(map); |
michael@0 | 703 | PKIX_DECREF(issuerDomainPolicy); |
michael@0 | 704 | PKIX_DECREF(subjectDomainPolicy); |
michael@0 | 705 | } |
michael@0 | 706 | |
michael@0 | 707 | if (subjectList) { |
michael@0 | 708 | PKIX_CHECK(PKIX_List_SetImmutable(subjectList, plContext), |
michael@0 | 709 | PKIX_LISTSETIMMUTABLEFAILED); |
michael@0 | 710 | } |
michael@0 | 711 | |
michael@0 | 712 | *pSubjectDomainPolicies = subjectList; |
michael@0 | 713 | |
michael@0 | 714 | cleanup: |
michael@0 | 715 | |
michael@0 | 716 | if (PKIX_ERROR_RECEIVED) { |
michael@0 | 717 | PKIX_DECREF(subjectList); |
michael@0 | 718 | } |
michael@0 | 719 | |
michael@0 | 720 | PKIX_DECREF(map); |
michael@0 | 721 | PKIX_DECREF(issuerDomainPolicy); |
michael@0 | 722 | PKIX_DECREF(subjectDomainPolicy); |
michael@0 | 723 | |
michael@0 | 724 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 725 | } |
michael@0 | 726 | |
michael@0 | 727 | /* |
michael@0 | 728 | * FUNCTION: pkix_PolicyChecker_MapGetMappedPolicies |
michael@0 | 729 | * DESCRIPTION: |
michael@0 | 730 | * |
michael@0 | 731 | * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps" to create a |
michael@0 | 732 | * List of all IssuerDomainPolicies, and stores the result in |
michael@0 | 733 | * "pMappedPolicies". |
michael@0 | 734 | * |
michael@0 | 735 | * The caller may not rely on the IssuerDomainPolicies to be in any particular |
michael@0 | 736 | * order. IssuerDomainPolicies that appear in more than one CertPolicyMap will |
michael@0 | 737 | * only appear once in "pMappedPolicies". If "certPolicyMaps" is empty the |
michael@0 | 738 | * result will be an empty List. The created List is mutable. |
michael@0 | 739 | * |
michael@0 | 740 | * PARAMETERS: |
michael@0 | 741 | * "certPolicyMaps" |
michael@0 | 742 | * Address of List of CertPolicyMaps to be searched. May be empty, but |
michael@0 | 743 | * must be non-NULL. |
michael@0 | 744 | * "pMappedPolicies" |
michael@0 | 745 | * Address where the result will be stored. Must be non-NULL. |
michael@0 | 746 | * "plContext" |
michael@0 | 747 | * platform-specific context pointer |
michael@0 | 748 | * THREAD SAFETY: |
michael@0 | 749 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 750 | * RETURNS: |
michael@0 | 751 | * Returns NULL if the function succeeds |
michael@0 | 752 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 753 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 754 | */ |
michael@0 | 755 | PKIX_Error * |
michael@0 | 756 | pkix_PolicyChecker_MapGetMappedPolicies( |
michael@0 | 757 | PKIX_List *certPolicyMaps, |
michael@0 | 758 | PKIX_List **pMappedPolicies, |
michael@0 | 759 | void *plContext) |
michael@0 | 760 | { |
michael@0 | 761 | PKIX_PL_CertPolicyMap *map = NULL; |
michael@0 | 762 | PKIX_List *mappedList = NULL; |
michael@0 | 763 | PKIX_UInt32 numEntries = 0; |
michael@0 | 764 | PKIX_UInt32 index = 0; |
michael@0 | 765 | PKIX_Boolean isContained = PKIX_FALSE; |
michael@0 | 766 | PKIX_PL_OID *issuerDomainPolicy = NULL; |
michael@0 | 767 | |
michael@0 | 768 | PKIX_ENTER |
michael@0 | 769 | (CERTCHAINCHECKER, "pkix_PolicyChecker_MapGetMappedPolicies"); |
michael@0 | 770 | PKIX_NULLCHECK_TWO(certPolicyMaps, pMappedPolicies); |
michael@0 | 771 | |
michael@0 | 772 | PKIX_CHECK(PKIX_List_Create(&mappedList, plContext), |
michael@0 | 773 | PKIX_LISTCREATEFAILED); |
michael@0 | 774 | |
michael@0 | 775 | PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext), |
michael@0 | 776 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 777 | |
michael@0 | 778 | for (index = 0; index < numEntries; index++) { |
michael@0 | 779 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 780 | (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), |
michael@0 | 781 | PKIX_LISTGETITEMFAILED); |
michael@0 | 782 | |
michael@0 | 783 | PKIX_NULLCHECK_ONE(map); |
michael@0 | 784 | |
michael@0 | 785 | PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy |
michael@0 | 786 | (map, &issuerDomainPolicy, plContext), |
michael@0 | 787 | PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); |
michael@0 | 788 | |
michael@0 | 789 | PKIX_CHECK(pkix_List_Contains |
michael@0 | 790 | (mappedList, |
michael@0 | 791 | (PKIX_PL_Object *)issuerDomainPolicy, |
michael@0 | 792 | &isContained, |
michael@0 | 793 | plContext), |
michael@0 | 794 | PKIX_LISTCONTAINSFAILED); |
michael@0 | 795 | |
michael@0 | 796 | if (isContained == PKIX_FALSE) { |
michael@0 | 797 | PKIX_CHECK(PKIX_List_AppendItem |
michael@0 | 798 | (mappedList, |
michael@0 | 799 | (PKIX_PL_Object *)issuerDomainPolicy, |
michael@0 | 800 | plContext), |
michael@0 | 801 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 802 | } |
michael@0 | 803 | |
michael@0 | 804 | PKIX_DECREF(map); |
michael@0 | 805 | PKIX_DECREF(issuerDomainPolicy); |
michael@0 | 806 | } |
michael@0 | 807 | |
michael@0 | 808 | *pMappedPolicies = mappedList; |
michael@0 | 809 | |
michael@0 | 810 | cleanup: |
michael@0 | 811 | |
michael@0 | 812 | if (PKIX_ERROR_RECEIVED) { |
michael@0 | 813 | PKIX_DECREF(mappedList); |
michael@0 | 814 | } |
michael@0 | 815 | |
michael@0 | 816 | PKIX_DECREF(map); |
michael@0 | 817 | PKIX_DECREF(issuerDomainPolicy); |
michael@0 | 818 | |
michael@0 | 819 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 820 | } |
michael@0 | 821 | |
michael@0 | 822 | /* |
michael@0 | 823 | * FUNCTION: pkix_PolicyChecker_MakeMutableCopy |
michael@0 | 824 | * DESCRIPTION: |
michael@0 | 825 | * |
michael@0 | 826 | * Creates a mutable copy of the List pointed to by "list", which may or may |
michael@0 | 827 | * not be immutable, and stores the address at "pMutableCopy". |
michael@0 | 828 | * |
michael@0 | 829 | * PARAMETERS: |
michael@0 | 830 | * "list" |
michael@0 | 831 | * Address of List to be copied. Must be non-NULL. |
michael@0 | 832 | * "pMutableCopy" |
michael@0 | 833 | * Address where mutable copy will be stored. Must be non-NULL. |
michael@0 | 834 | * "plContext" |
michael@0 | 835 | * Platform-specific context pointer. |
michael@0 | 836 | * THREAD SAFETY: |
michael@0 | 837 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 838 | * RETURNS: |
michael@0 | 839 | * Returns NULL if the function succeeds |
michael@0 | 840 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 841 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 842 | */ |
michael@0 | 843 | static PKIX_Error * |
michael@0 | 844 | pkix_PolicyChecker_MakeMutableCopy( |
michael@0 | 845 | PKIX_List *list, |
michael@0 | 846 | PKIX_List **pMutableCopy, |
michael@0 | 847 | void *plContext) |
michael@0 | 848 | { |
michael@0 | 849 | PKIX_List *newList = NULL; |
michael@0 | 850 | PKIX_UInt32 listLen = 0; |
michael@0 | 851 | PKIX_UInt32 listIx = 0; |
michael@0 | 852 | PKIX_PL_Object *object = NULL; |
michael@0 | 853 | |
michael@0 | 854 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeMutableCopy"); |
michael@0 | 855 | PKIX_NULLCHECK_TWO(list, pMutableCopy); |
michael@0 | 856 | |
michael@0 | 857 | PKIX_CHECK(PKIX_List_Create(&newList, plContext), |
michael@0 | 858 | PKIX_LISTCREATEFAILED); |
michael@0 | 859 | |
michael@0 | 860 | PKIX_CHECK(PKIX_List_GetLength(list, &listLen, plContext), |
michael@0 | 861 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 862 | |
michael@0 | 863 | for (listIx = 0; listIx < listLen; listIx++) { |
michael@0 | 864 | |
michael@0 | 865 | PKIX_CHECK(PKIX_List_GetItem(list, listIx, &object, plContext), |
michael@0 | 866 | PKIX_LISTGETITEMFAILED); |
michael@0 | 867 | |
michael@0 | 868 | PKIX_CHECK(PKIX_List_AppendItem(newList, object, plContext), |
michael@0 | 869 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 870 | |
michael@0 | 871 | PKIX_DECREF(object); |
michael@0 | 872 | } |
michael@0 | 873 | |
michael@0 | 874 | *pMutableCopy = newList; |
michael@0 | 875 | newList = NULL; |
michael@0 | 876 | |
michael@0 | 877 | cleanup: |
michael@0 | 878 | PKIX_DECREF(newList); |
michael@0 | 879 | PKIX_DECREF(object); |
michael@0 | 880 | |
michael@0 | 881 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 882 | } |
michael@0 | 883 | |
michael@0 | 884 | /* |
michael@0 | 885 | * FUNCTION: pkix_PolicyChecker_MakeSingleton |
michael@0 | 886 | * DESCRIPTION: |
michael@0 | 887 | * |
michael@0 | 888 | * Creates a new List containing the Object pointed to by "listItem", using |
michael@0 | 889 | * the Boolean value of "immutability" to determine whether to set the List |
michael@0 | 890 | * immutable, and stores the address at "pList". |
michael@0 | 891 | * |
michael@0 | 892 | * PARAMETERS: |
michael@0 | 893 | * "listItem" |
michael@0 | 894 | * Address of Object to be inserted into the new List. Must be non-NULL. |
michael@0 | 895 | * "immutability" |
michael@0 | 896 | * Boolean value indicating whether new List is to be immutable |
michael@0 | 897 | * "pList" |
michael@0 | 898 | * Address where List will be stored. Must be non-NULL. |
michael@0 | 899 | * "plContext" |
michael@0 | 900 | * Platform-specific context pointer. |
michael@0 | 901 | * THREAD SAFETY: |
michael@0 | 902 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 903 | * RETURNS: |
michael@0 | 904 | * Returns NULL if the function succeeds |
michael@0 | 905 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 906 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 907 | */ |
michael@0 | 908 | static PKIX_Error * |
michael@0 | 909 | pkix_PolicyChecker_MakeSingleton( |
michael@0 | 910 | PKIX_PL_Object *listItem, |
michael@0 | 911 | PKIX_Boolean immutability, |
michael@0 | 912 | PKIX_List **pList, |
michael@0 | 913 | void *plContext) |
michael@0 | 914 | { |
michael@0 | 915 | PKIX_List *newList = NULL; |
michael@0 | 916 | |
michael@0 | 917 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeSingleton"); |
michael@0 | 918 | PKIX_NULLCHECK_TWO(listItem, pList); |
michael@0 | 919 | |
michael@0 | 920 | PKIX_CHECK(PKIX_List_Create(&newList, plContext), |
michael@0 | 921 | PKIX_LISTCREATEFAILED); |
michael@0 | 922 | |
michael@0 | 923 | PKIX_CHECK(PKIX_List_AppendItem |
michael@0 | 924 | (newList, (PKIX_PL_Object *)listItem, plContext), |
michael@0 | 925 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 926 | |
michael@0 | 927 | if (immutability) { |
michael@0 | 928 | PKIX_CHECK(PKIX_List_SetImmutable(newList, plContext), |
michael@0 | 929 | PKIX_LISTSETIMMUTABLEFAILED); |
michael@0 | 930 | } |
michael@0 | 931 | |
michael@0 | 932 | *pList = newList; |
michael@0 | 933 | |
michael@0 | 934 | cleanup: |
michael@0 | 935 | if (PKIX_ERROR_RECEIVED) { |
michael@0 | 936 | PKIX_DECREF(newList); |
michael@0 | 937 | } |
michael@0 | 938 | |
michael@0 | 939 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 940 | } |
michael@0 | 941 | |
michael@0 | 942 | /* |
michael@0 | 943 | * FUNCTION: pkix_PolicyChecker_Spawn |
michael@0 | 944 | * DESCRIPTION: |
michael@0 | 945 | * |
michael@0 | 946 | * Creates a new childNode for the parent pointed to by "parent", using |
michael@0 | 947 | * the OID pointed to by "policyOID", the List of CertPolicyQualifiers |
michael@0 | 948 | * pointed to by "qualifiers", the List of OIDs pointed to by |
michael@0 | 949 | * "subjectDomainPolicies", and the PolicyCheckerState pointed to by |
michael@0 | 950 | * "state". The new node will be added to "parent". |
michael@0 | 951 | * |
michael@0 | 952 | * The validPolicy of the new node is set from the OID pointed to by |
michael@0 | 953 | * "policyOID". The policy qualifiers for the new node is set from the |
michael@0 | 954 | * List of qualifiers pointed to by "qualifiers", and may be NULL or |
michael@0 | 955 | * empty if the argument provided was NULL or empty. The criticality is |
michael@0 | 956 | * set according to the criticality obtained from the PolicyCheckerState. |
michael@0 | 957 | * If "subjectDomainPolicies" is NULL, the expectedPolicySet of the |
michael@0 | 958 | * child is set to contain the same policy as the validPolicy. If |
michael@0 | 959 | * "subjectDomainPolicies" is not NULL, it is used as the value for |
michael@0 | 960 | * the expectedPolicySet. |
michael@0 | 961 | * |
michael@0 | 962 | * The PolicyCheckerState also contains a constant, anyPolicy, which is |
michael@0 | 963 | * compared to "policyOID". If they match, the address of the childNode |
michael@0 | 964 | * is saved in the state's newAnyPolicyNode. |
michael@0 | 965 | * |
michael@0 | 966 | * PARAMETERS: |
michael@0 | 967 | * "parent" |
michael@0 | 968 | * Address of PolicyNode to which the child will be linked. Must be |
michael@0 | 969 | * non-NULL. |
michael@0 | 970 | * "policyOID" |
michael@0 | 971 | * Address of OID of the new child's validPolicy and also, if |
michael@0 | 972 | * subjectDomainPolicies is NULL, of the new child's expectedPolicySet. |
michael@0 | 973 | * Must be non-NULL. |
michael@0 | 974 | * "qualifiers" |
michael@0 | 975 | * Address of List of CertPolicyQualifiers. May be NULL or empty. |
michael@0 | 976 | * "subjectDomainPolicies" |
michael@0 | 977 | * Address of List of OIDs indicating the policies to which "policy" is |
michael@0 | 978 | * mapped. May be empty or NULL. |
michael@0 | 979 | * "state" |
michael@0 | 980 | * Address of the current PKIX_PolicyCheckerState. Must be non-NULL.. |
michael@0 | 981 | * "plContext" |
michael@0 | 982 | * Platform-specific context pointer. |
michael@0 | 983 | * THREAD SAFETY: |
michael@0 | 984 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 985 | * RETURNS: |
michael@0 | 986 | * Returns NULL if the function succeeds |
michael@0 | 987 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 988 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 989 | */ |
michael@0 | 990 | static PKIX_Error * |
michael@0 | 991 | pkix_PolicyChecker_Spawn( |
michael@0 | 992 | PKIX_PolicyNode *parent, |
michael@0 | 993 | PKIX_PL_OID *policyOID, |
michael@0 | 994 | PKIX_List *qualifiers, /* CertPolicyQualifiers */ |
michael@0 | 995 | PKIX_List *subjectDomainPolicies, |
michael@0 | 996 | PKIX_PolicyCheckerState *state, |
michael@0 | 997 | void *plContext) |
michael@0 | 998 | { |
michael@0 | 999 | PKIX_List *expectedSet = NULL; /* OIDs */ |
michael@0 | 1000 | PKIX_PolicyNode *childNode = NULL; |
michael@0 | 1001 | PKIX_Boolean match = PKIX_FALSE; |
michael@0 | 1002 | |
michael@0 | 1003 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Spawn"); |
michael@0 | 1004 | PKIX_NULLCHECK_THREE(policyOID, parent, state); |
michael@0 | 1005 | |
michael@0 | 1006 | if (subjectDomainPolicies) { |
michael@0 | 1007 | |
michael@0 | 1008 | PKIX_INCREF(subjectDomainPolicies); |
michael@0 | 1009 | expectedSet = subjectDomainPolicies; |
michael@0 | 1010 | |
michael@0 | 1011 | } else { |
michael@0 | 1012 | /* Create the child's ExpectedPolicy Set */ |
michael@0 | 1013 | PKIX_CHECK(pkix_PolicyChecker_MakeSingleton |
michael@0 | 1014 | ((PKIX_PL_Object *)policyOID, |
michael@0 | 1015 | PKIX_TRUE, /* make expectedPolicySet immutable */ |
michael@0 | 1016 | &expectedSet, |
michael@0 | 1017 | plContext), |
michael@0 | 1018 | PKIX_POLICYCHECKERMAKESINGLETONFAILED); |
michael@0 | 1019 | } |
michael@0 | 1020 | |
michael@0 | 1021 | PKIX_CHECK(pkix_PolicyNode_Create |
michael@0 | 1022 | (policyOID, |
michael@0 | 1023 | qualifiers, |
michael@0 | 1024 | state->certPoliciesCritical, |
michael@0 | 1025 | expectedSet, |
michael@0 | 1026 | &childNode, |
michael@0 | 1027 | plContext), |
michael@0 | 1028 | PKIX_POLICYNODECREATEFAILED); |
michael@0 | 1029 | |
michael@0 | 1030 | /* |
michael@0 | 1031 | * If we had a non-empty mapping, we know the new node could not |
michael@0 | 1032 | * have been created with a validPolicy of anyPolicy. Otherwise, |
michael@0 | 1033 | * check whether we just created a new node with anyPolicy, because |
michael@0 | 1034 | * in that case we want to save the child pointer in newAnyPolicyNode. |
michael@0 | 1035 | */ |
michael@0 | 1036 | if (!subjectDomainPolicies) { |
michael@0 | 1037 | PKIX_EQUALS(policyOID, state->anyPolicyOID, &match, plContext, |
michael@0 | 1038 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 1039 | |
michael@0 | 1040 | if (match) { |
michael@0 | 1041 | PKIX_DECREF(state->newAnyPolicyNode); |
michael@0 | 1042 | PKIX_INCREF(childNode); |
michael@0 | 1043 | state->newAnyPolicyNode = childNode; |
michael@0 | 1044 | } |
michael@0 | 1045 | } |
michael@0 | 1046 | |
michael@0 | 1047 | PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, childNode, plContext), |
michael@0 | 1048 | PKIX_POLICYNODEADDTOPARENTFAILED); |
michael@0 | 1049 | |
michael@0 | 1050 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 1051 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 1052 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 1053 | |
michael@0 | 1054 | cleanup: |
michael@0 | 1055 | PKIX_DECREF(childNode); |
michael@0 | 1056 | PKIX_DECREF(expectedSet); |
michael@0 | 1057 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 1058 | } |
michael@0 | 1059 | |
michael@0 | 1060 | /* |
michael@0 | 1061 | * FUNCTION: pkix_PolicyChecker_CheckPolicyRecursive |
michael@0 | 1062 | * DESCRIPTION: |
michael@0 | 1063 | * |
michael@0 | 1064 | * Performs policy processing for the policy whose OID is pointed to by |
michael@0 | 1065 | * "policyOID" and whose List of CertPolicyQualifiers is pointed to by |
michael@0 | 1066 | * "policyQualifiers", using the List of policy OIDs pointed to by |
michael@0 | 1067 | * "subjectDomainPolicies" and the PolicyNode pointed to by "currentNode", |
michael@0 | 1068 | * in accordance with the current PolicyCheckerState pointed to by "state", |
michael@0 | 1069 | * and setting "pChildNodeCreated" to TRUE if a new childNode is created. |
michael@0 | 1070 | * Note: "pChildNodeCreated" is not set to FALSE if no childNode is created. |
michael@0 | 1071 | * The intent of the design is that the caller can set a variable to FALSE |
michael@0 | 1072 | * initially, prior to a recursive set of calls. At the end, the variable |
michael@0 | 1073 | * can be tested to see whether *any* of the calls created a child node. |
michael@0 | 1074 | * |
michael@0 | 1075 | * If the currentNode is not at the bottom of the tree, this function |
michael@0 | 1076 | * calls itself recursively for each child of currentNode. At the bottom of |
michael@0 | 1077 | * the tree, it creates new child nodes as appropriate. This function will |
michael@0 | 1078 | * never be called with policy = anyPolicy. |
michael@0 | 1079 | * |
michael@0 | 1080 | * This function implements the processing described in RFC3280 |
michael@0 | 1081 | * Section 6.1.3(d)(1)(i). |
michael@0 | 1082 | * |
michael@0 | 1083 | * PARAMETERS: |
michael@0 | 1084 | * "policyOID" |
michael@0 | 1085 | * Address of OID of the policy to be checked for. Must be non-NULL. |
michael@0 | 1086 | * "policyQualifiers" |
michael@0 | 1087 | * Address of List of CertPolicyQualifiers of the policy to be checked for. |
michael@0 | 1088 | * May be empty or NULL. |
michael@0 | 1089 | * "subjectDomainPolicies" |
michael@0 | 1090 | * Address of List of OIDs indicating the policies to which "policy" is |
michael@0 | 1091 | * mapped. May be empty or NULL. |
michael@0 | 1092 | * "currentNode" |
michael@0 | 1093 | * Address of PolicyNode whose descendants will be checked, if not at the |
michael@0 | 1094 | * bottom of the tree; or whose expectedPolicySet will be compared to |
michael@0 | 1095 | * "policy", if at the bottom. Must be non-NULL. |
michael@0 | 1096 | * "state" |
michael@0 | 1097 | * Address of PolicyCheckerState of the current PolicyChecker. Must be |
michael@0 | 1098 | * non-NULL. |
michael@0 | 1099 | * "pChildNodeCreated" |
michael@0 | 1100 | * Address of the Boolean that will be set TRUE if this function |
michael@0 | 1101 | * creates a child node. Must be non-NULL. |
michael@0 | 1102 | * "plContext" |
michael@0 | 1103 | * Platform-specific context pointer. |
michael@0 | 1104 | * THREAD SAFETY: |
michael@0 | 1105 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 1106 | * RETURNS: |
michael@0 | 1107 | * Returns NULL if the function succeeds |
michael@0 | 1108 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 1109 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 1110 | */ |
michael@0 | 1111 | static PKIX_Error * |
michael@0 | 1112 | pkix_PolicyChecker_CheckPolicyRecursive( |
michael@0 | 1113 | PKIX_PL_OID *policyOID, |
michael@0 | 1114 | PKIX_List *policyQualifiers, |
michael@0 | 1115 | PKIX_List *subjectDomainPolicies, |
michael@0 | 1116 | PKIX_PolicyNode *currentNode, |
michael@0 | 1117 | PKIX_PolicyCheckerState *state, |
michael@0 | 1118 | PKIX_Boolean *pChildNodeCreated, |
michael@0 | 1119 | void *plContext) |
michael@0 | 1120 | { |
michael@0 | 1121 | PKIX_UInt32 depth = 0; |
michael@0 | 1122 | PKIX_UInt32 numChildren = 0; |
michael@0 | 1123 | PKIX_UInt32 childIx = 0; |
michael@0 | 1124 | PKIX_Boolean isIncluded = PKIX_FALSE; |
michael@0 | 1125 | PKIX_List *children = NULL; /* PolicyNodes */ |
michael@0 | 1126 | PKIX_PolicyNode *childNode = NULL; |
michael@0 | 1127 | PKIX_List *expectedPolicies = NULL; /* OIDs */ |
michael@0 | 1128 | |
michael@0 | 1129 | PKIX_ENTER |
michael@0 | 1130 | (CERTCHAINCHECKER, |
michael@0 | 1131 | "pkix_PolicyChecker_CheckPolicyRecursive"); |
michael@0 | 1132 | PKIX_NULLCHECK_FOUR(policyOID, currentNode, state, pChildNodeCreated); |
michael@0 | 1133 | |
michael@0 | 1134 | /* if not at the bottom of the tree */ |
michael@0 | 1135 | PKIX_CHECK(PKIX_PolicyNode_GetDepth |
michael@0 | 1136 | (currentNode, &depth, plContext), |
michael@0 | 1137 | PKIX_POLICYNODEGETDEPTHFAILED); |
michael@0 | 1138 | |
michael@0 | 1139 | if (depth < (state->certsProcessed)) { |
michael@0 | 1140 | PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable |
michael@0 | 1141 | (currentNode, &children, plContext), |
michael@0 | 1142 | PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); |
michael@0 | 1143 | |
michael@0 | 1144 | if (children) { |
michael@0 | 1145 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1146 | (children, &numChildren, plContext), |
michael@0 | 1147 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1148 | } |
michael@0 | 1149 | |
michael@0 | 1150 | for (childIx = 0; childIx < numChildren; childIx++) { |
michael@0 | 1151 | |
michael@0 | 1152 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1153 | (children, |
michael@0 | 1154 | childIx, |
michael@0 | 1155 | (PKIX_PL_Object **)&childNode, |
michael@0 | 1156 | plContext), |
michael@0 | 1157 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1158 | |
michael@0 | 1159 | PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive |
michael@0 | 1160 | (policyOID, |
michael@0 | 1161 | policyQualifiers, |
michael@0 | 1162 | subjectDomainPolicies, |
michael@0 | 1163 | childNode, |
michael@0 | 1164 | state, |
michael@0 | 1165 | pChildNodeCreated, |
michael@0 | 1166 | plContext), |
michael@0 | 1167 | PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED); |
michael@0 | 1168 | |
michael@0 | 1169 | PKIX_DECREF(childNode); |
michael@0 | 1170 | } |
michael@0 | 1171 | } else { /* if at the bottom of the tree */ |
michael@0 | 1172 | |
michael@0 | 1173 | /* Check whether policy is in this node's expectedPolicySet */ |
michael@0 | 1174 | PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies |
michael@0 | 1175 | (currentNode, &expectedPolicies, plContext), |
michael@0 | 1176 | PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED); |
michael@0 | 1177 | |
michael@0 | 1178 | PKIX_NULLCHECK_ONE(expectedPolicies); |
michael@0 | 1179 | |
michael@0 | 1180 | PKIX_CHECK(pkix_List_Contains |
michael@0 | 1181 | (expectedPolicies, |
michael@0 | 1182 | (PKIX_PL_Object *)policyOID, |
michael@0 | 1183 | &isIncluded, |
michael@0 | 1184 | plContext), |
michael@0 | 1185 | PKIX_LISTCONTAINSFAILED); |
michael@0 | 1186 | |
michael@0 | 1187 | if (isIncluded) { |
michael@0 | 1188 | PKIX_CHECK(pkix_PolicyChecker_Spawn |
michael@0 | 1189 | (currentNode, |
michael@0 | 1190 | policyOID, |
michael@0 | 1191 | policyQualifiers, |
michael@0 | 1192 | subjectDomainPolicies, |
michael@0 | 1193 | state, |
michael@0 | 1194 | plContext), |
michael@0 | 1195 | PKIX_POLICYCHECKERSPAWNFAILED); |
michael@0 | 1196 | |
michael@0 | 1197 | *pChildNodeCreated = PKIX_TRUE; |
michael@0 | 1198 | } |
michael@0 | 1199 | } |
michael@0 | 1200 | |
michael@0 | 1201 | cleanup: |
michael@0 | 1202 | |
michael@0 | 1203 | PKIX_DECREF(children); |
michael@0 | 1204 | PKIX_DECREF(childNode); |
michael@0 | 1205 | PKIX_DECREF(expectedPolicies); |
michael@0 | 1206 | |
michael@0 | 1207 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 1208 | } |
michael@0 | 1209 | |
michael@0 | 1210 | /* |
michael@0 | 1211 | * FUNCTION: pkix_PolicyChecker_CheckPolicy |
michael@0 | 1212 | * DESCRIPTION: |
michael@0 | 1213 | * |
michael@0 | 1214 | * Performs the non-recursive portion of the policy processing for the policy |
michael@0 | 1215 | * whose OID is pointed to by "policyOID" and whose List of |
michael@0 | 1216 | * CertPolicyQualifiers is pointed to by "policyQualifiers", for the |
michael@0 | 1217 | * Certificate pointed to by "cert" with the List of CertPolicyMaps pointed |
michael@0 | 1218 | * to by "maps", in accordance with the current PolicyCheckerState pointed |
michael@0 | 1219 | * to by "state". |
michael@0 | 1220 | * |
michael@0 | 1221 | * This function implements the processing described in RFC3280 |
michael@0 | 1222 | * Section 6.1.3(d)(1)(i). |
michael@0 | 1223 | * |
michael@0 | 1224 | * PARAMETERS: |
michael@0 | 1225 | * "policyOID" |
michael@0 | 1226 | * Address of OID of the policy to be checked for. Must be non-NULL. |
michael@0 | 1227 | * "policyQualifiers" |
michael@0 | 1228 | * Address of List of CertPolicyQualifiers of the policy to be checked for. |
michael@0 | 1229 | * May be empty or NULL. |
michael@0 | 1230 | * "cert" |
michael@0 | 1231 | * Address of the current certificate. Must be non-NULL. |
michael@0 | 1232 | * "maps" |
michael@0 | 1233 | * Address of List of CertPolicyMaps for the current certificate |
michael@0 | 1234 | * "state" |
michael@0 | 1235 | * Address of PolicyCheckerState of the current PolicyChecker. Must be |
michael@0 | 1236 | * non-NULL. |
michael@0 | 1237 | * "plContext" |
michael@0 | 1238 | * Platform-specific context pointer. |
michael@0 | 1239 | * THREAD SAFETY: |
michael@0 | 1240 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 1241 | * RETURNS: |
michael@0 | 1242 | * Returns NULL if the function succeeds |
michael@0 | 1243 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 1244 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 1245 | */ |
michael@0 | 1246 | static PKIX_Error * |
michael@0 | 1247 | pkix_PolicyChecker_CheckPolicy( |
michael@0 | 1248 | PKIX_PL_OID *policyOID, |
michael@0 | 1249 | PKIX_List *policyQualifiers, |
michael@0 | 1250 | PKIX_PL_Cert *cert, |
michael@0 | 1251 | PKIX_List *maps, |
michael@0 | 1252 | PKIX_PolicyCheckerState *state, |
michael@0 | 1253 | void *plContext) |
michael@0 | 1254 | { |
michael@0 | 1255 | PKIX_Boolean childNodeCreated = PKIX_FALSE; |
michael@0 | 1256 | PKIX_Boolean okToSpawn = PKIX_FALSE; |
michael@0 | 1257 | PKIX_Boolean found = PKIX_FALSE; |
michael@0 | 1258 | PKIX_List *subjectDomainPolicies = NULL; |
michael@0 | 1259 | |
michael@0 | 1260 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckPolicy"); |
michael@0 | 1261 | PKIX_NULLCHECK_THREE(policyOID, cert, state); |
michael@0 | 1262 | |
michael@0 | 1263 | /* |
michael@0 | 1264 | * If this is not the last certificate, get the set of |
michael@0 | 1265 | * subjectDomainPolicies that "policy" maps to, according to the |
michael@0 | 1266 | * current cert's policy mapping extension. That set will be NULL |
michael@0 | 1267 | * if the current cert does not have a policy mapping extension, |
michael@0 | 1268 | * or if the current policy is not mapped. |
michael@0 | 1269 | */ |
michael@0 | 1270 | if (state->certsProcessed != (state->numCerts - 1)) { |
michael@0 | 1271 | PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies |
michael@0 | 1272 | (maps, policyOID, &subjectDomainPolicies, plContext), |
michael@0 | 1273 | PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); |
michael@0 | 1274 | } |
michael@0 | 1275 | |
michael@0 | 1276 | /* |
michael@0 | 1277 | * Section 6.1.4(b)(2) tells us that if policyMapping is zero, we |
michael@0 | 1278 | * will have to delete any nodes created with validPolicies equal to |
michael@0 | 1279 | * policies that appear as issuerDomainPolicies in a policy mapping |
michael@0 | 1280 | * extension. Let's avoid creating any such nodes. |
michael@0 | 1281 | */ |
michael@0 | 1282 | if ((state->policyMapping) == 0) { |
michael@0 | 1283 | if (subjectDomainPolicies) { |
michael@0 | 1284 | goto cleanup; |
michael@0 | 1285 | } |
michael@0 | 1286 | } |
michael@0 | 1287 | |
michael@0 | 1288 | PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive |
michael@0 | 1289 | (policyOID, |
michael@0 | 1290 | policyQualifiers, |
michael@0 | 1291 | subjectDomainPolicies, |
michael@0 | 1292 | state->validPolicyTree, |
michael@0 | 1293 | state, |
michael@0 | 1294 | &childNodeCreated, |
michael@0 | 1295 | plContext), |
michael@0 | 1296 | PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED); |
michael@0 | 1297 | |
michael@0 | 1298 | if (!childNodeCreated) { |
michael@0 | 1299 | /* |
michael@0 | 1300 | * Section 6.1.3(d)(1)(ii) |
michael@0 | 1301 | * There was no match. If there was a node at |
michael@0 | 1302 | * depth i-1 with valid policy anyPolicy, |
michael@0 | 1303 | * generate a node subordinate to that. |
michael@0 | 1304 | * |
michael@0 | 1305 | * But that means this created node would be in |
michael@0 | 1306 | * the valid-policy-node-set, and will be |
michael@0 | 1307 | * pruned in 6.1.5(g)(iii)(2) unless it is in |
michael@0 | 1308 | * the user-initial-policy-set or the user- |
michael@0 | 1309 | * initial-policy-set is {anyPolicy}. So check, |
michael@0 | 1310 | * and don't create it if it will be pruned. |
michael@0 | 1311 | */ |
michael@0 | 1312 | if (state->anyPolicyNodeAtBottom) { |
michael@0 | 1313 | if (state->initialIsAnyPolicy) { |
michael@0 | 1314 | okToSpawn = PKIX_TRUE; |
michael@0 | 1315 | } else { |
michael@0 | 1316 | PKIX_CHECK(pkix_List_Contains |
michael@0 | 1317 | (state->mappedUserInitialPolicySet, |
michael@0 | 1318 | (PKIX_PL_Object *)policyOID, |
michael@0 | 1319 | &okToSpawn, |
michael@0 | 1320 | plContext), |
michael@0 | 1321 | PKIX_LISTCONTAINSFAILED); |
michael@0 | 1322 | } |
michael@0 | 1323 | if (okToSpawn) { |
michael@0 | 1324 | PKIX_CHECK(pkix_PolicyChecker_Spawn |
michael@0 | 1325 | (state->anyPolicyNodeAtBottom, |
michael@0 | 1326 | policyOID, |
michael@0 | 1327 | policyQualifiers, |
michael@0 | 1328 | subjectDomainPolicies, |
michael@0 | 1329 | state, |
michael@0 | 1330 | plContext), |
michael@0 | 1331 | PKIX_POLICYCHECKERSPAWNFAILED); |
michael@0 | 1332 | childNodeCreated = PKIX_TRUE; |
michael@0 | 1333 | } |
michael@0 | 1334 | } |
michael@0 | 1335 | } |
michael@0 | 1336 | |
michael@0 | 1337 | if (childNodeCreated) { |
michael@0 | 1338 | /* |
michael@0 | 1339 | * If this policy had qualifiers, and the certificate policies |
michael@0 | 1340 | * extension was marked critical, and the user cannot deal with |
michael@0 | 1341 | * policy qualifiers, throw an error. |
michael@0 | 1342 | */ |
michael@0 | 1343 | if (policyQualifiers && |
michael@0 | 1344 | state->certPoliciesCritical && |
michael@0 | 1345 | state->policyQualifiersRejected) { |
michael@0 | 1346 | PKIX_ERROR |
michael@0 | 1347 | (PKIX_QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION); |
michael@0 | 1348 | } |
michael@0 | 1349 | /* |
michael@0 | 1350 | * If the policy we just propagated was in the list of mapped |
michael@0 | 1351 | * policies, remove it from the list. That list is used, at the |
michael@0 | 1352 | * end, to determine policies that have not been propagated. |
michael@0 | 1353 | */ |
michael@0 | 1354 | if (state->mappedPolicyOIDs) { |
michael@0 | 1355 | PKIX_CHECK(pkix_List_Contains |
michael@0 | 1356 | (state->mappedPolicyOIDs, |
michael@0 | 1357 | (PKIX_PL_Object *)policyOID, |
michael@0 | 1358 | &found, |
michael@0 | 1359 | plContext), |
michael@0 | 1360 | PKIX_LISTCONTAINSFAILED); |
michael@0 | 1361 | if (found) { |
michael@0 | 1362 | PKIX_CHECK(pkix_List_Remove |
michael@0 | 1363 | (state->mappedPolicyOIDs, |
michael@0 | 1364 | (PKIX_PL_Object *)policyOID, |
michael@0 | 1365 | plContext), |
michael@0 | 1366 | PKIX_LISTREMOVEFAILED); |
michael@0 | 1367 | } |
michael@0 | 1368 | } |
michael@0 | 1369 | } |
michael@0 | 1370 | |
michael@0 | 1371 | cleanup: |
michael@0 | 1372 | |
michael@0 | 1373 | PKIX_DECREF(subjectDomainPolicies); |
michael@0 | 1374 | |
michael@0 | 1375 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 1376 | } |
michael@0 | 1377 | |
michael@0 | 1378 | /* |
michael@0 | 1379 | * FUNCTION: pkix_PolicyChecker_CheckAny |
michael@0 | 1380 | * DESCRIPTION: |
michael@0 | 1381 | * Performs the creation of PolicyNodes, for the PolicyNode pointed to by |
michael@0 | 1382 | * "currentNode" and PolicyNodes subordinate to it, using the List of |
michael@0 | 1383 | * qualifiers pointed to by "qualsOfAny", in accordance with the current |
michael@0 | 1384 | * certificate's PolicyMaps pointed to by "policyMaps" and the current |
michael@0 | 1385 | * PolicyCheckerState pointed to by "state". |
michael@0 | 1386 | * |
michael@0 | 1387 | * If the currentNode is not just above the bottom of the validPolicyTree, this |
michael@0 | 1388 | * function calls itself recursively for each child of currentNode. At the |
michael@0 | 1389 | * level just above the bottom, for each policy in the currentNode's |
michael@0 | 1390 | * expectedPolicySet not already present in a child node, it creates a new |
michael@0 | 1391 | * child node. The validPolicy of the child created, and its expectedPolicySet, |
michael@0 | 1392 | * will be the policy from the currentNode's expectedPolicySet. The policy |
michael@0 | 1393 | * qualifiers will be the qualifiers from the current certificate's anyPolicy, |
michael@0 | 1394 | * the "qualsOfAny" parameter. If the currentNode's expectedSet includes |
michael@0 | 1395 | * anyPolicy, a childNode will be created with a policy of anyPolicy. This is |
michael@0 | 1396 | * the only way such a node can be created. |
michael@0 | 1397 | * |
michael@0 | 1398 | * This function is called only when anyPolicy is one of the current |
michael@0 | 1399 | * certificate's policies. This function implements the processing described |
michael@0 | 1400 | * in RFC3280 Section 6.1.3(d)(2). |
michael@0 | 1401 | * |
michael@0 | 1402 | * PARAMETERS: |
michael@0 | 1403 | * "currentNode" |
michael@0 | 1404 | * Address of PolicyNode whose descendants will be checked, if not at the |
michael@0 | 1405 | * bottom of the tree; or whose expectedPolicySet will be compared to those |
michael@0 | 1406 | * in "alreadyPresent", if at the bottom. Must be non-NULL. |
michael@0 | 1407 | * "qualsOfAny" |
michael@0 | 1408 | * Address of List of qualifiers of the anyPolicy in the current |
michael@0 | 1409 | * certificate. May be empty or NULL. |
michael@0 | 1410 | * "policyMaps" |
michael@0 | 1411 | * Address of the List of PolicyMaps of the current certificate. May be |
michael@0 | 1412 | * empty or NULL. |
michael@0 | 1413 | * "state" |
michael@0 | 1414 | * Address of the current state of the PKIX_PolicyChecker. |
michael@0 | 1415 | * Must be non-NULL. |
michael@0 | 1416 | * "plContext" |
michael@0 | 1417 | * Platform-specific context pointer. |
michael@0 | 1418 | * THREAD SAFETY: |
michael@0 | 1419 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 1420 | * RETURNS: |
michael@0 | 1421 | * Returns NULL if the function succeeds |
michael@0 | 1422 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 1423 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 1424 | */ |
michael@0 | 1425 | static PKIX_Error * |
michael@0 | 1426 | pkix_PolicyChecker_CheckAny( |
michael@0 | 1427 | PKIX_PolicyNode *currentNode, |
michael@0 | 1428 | PKIX_List *qualsOfAny, /* CertPolicyQualifiers */ |
michael@0 | 1429 | PKIX_List *policyMaps, /* CertPolicyMaps */ |
michael@0 | 1430 | PKIX_PolicyCheckerState *state, |
michael@0 | 1431 | void *plContext) |
michael@0 | 1432 | { |
michael@0 | 1433 | PKIX_UInt32 depth = 0; |
michael@0 | 1434 | PKIX_UInt32 numChildren = 0; |
michael@0 | 1435 | PKIX_UInt32 childIx = 0; |
michael@0 | 1436 | PKIX_UInt32 numPolicies = 0; |
michael@0 | 1437 | PKIX_UInt32 polx = 0; |
michael@0 | 1438 | PKIX_Boolean isIncluded = PKIX_FALSE; |
michael@0 | 1439 | PKIX_List *children = NULL; /* PolicyNodes */ |
michael@0 | 1440 | PKIX_PolicyNode *childNode = NULL; |
michael@0 | 1441 | PKIX_List *expectedPolicies = NULL; /* OIDs */ |
michael@0 | 1442 | PKIX_PL_OID *policyOID = NULL; |
michael@0 | 1443 | PKIX_PL_OID *childPolicy = NULL; |
michael@0 | 1444 | PKIX_List *subjectDomainPolicies = NULL; /* OIDs */ |
michael@0 | 1445 | |
michael@0 | 1446 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckAny"); |
michael@0 | 1447 | PKIX_NULLCHECK_TWO(currentNode, state); |
michael@0 | 1448 | |
michael@0 | 1449 | PKIX_CHECK(PKIX_PolicyNode_GetDepth |
michael@0 | 1450 | (currentNode, &depth, plContext), |
michael@0 | 1451 | PKIX_POLICYNODEGETDEPTHFAILED); |
michael@0 | 1452 | |
michael@0 | 1453 | PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable |
michael@0 | 1454 | (currentNode, &children, plContext), |
michael@0 | 1455 | PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); |
michael@0 | 1456 | |
michael@0 | 1457 | if (children) { |
michael@0 | 1458 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1459 | (children, &numChildren, plContext), |
michael@0 | 1460 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1461 | } |
michael@0 | 1462 | |
michael@0 | 1463 | if (depth < (state->certsProcessed)) { |
michael@0 | 1464 | for (childIx = 0; childIx < numChildren; childIx++) { |
michael@0 | 1465 | |
michael@0 | 1466 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1467 | (children, |
michael@0 | 1468 | childIx, |
michael@0 | 1469 | (PKIX_PL_Object **)&childNode, |
michael@0 | 1470 | plContext), |
michael@0 | 1471 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1472 | |
michael@0 | 1473 | PKIX_NULLCHECK_ONE(childNode); |
michael@0 | 1474 | PKIX_CHECK(pkix_PolicyChecker_CheckAny |
michael@0 | 1475 | (childNode, |
michael@0 | 1476 | qualsOfAny, |
michael@0 | 1477 | policyMaps, |
michael@0 | 1478 | state, |
michael@0 | 1479 | plContext), |
michael@0 | 1480 | PKIX_POLICYCHECKERCHECKANYFAILED); |
michael@0 | 1481 | |
michael@0 | 1482 | PKIX_DECREF(childNode); |
michael@0 | 1483 | } |
michael@0 | 1484 | } else { /* if at the bottom of the tree */ |
michael@0 | 1485 | |
michael@0 | 1486 | PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies |
michael@0 | 1487 | (currentNode, &expectedPolicies, plContext), |
michael@0 | 1488 | PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED); |
michael@0 | 1489 | |
michael@0 | 1490 | /* Expected Policy Set is not allowed to be NULL */ |
michael@0 | 1491 | PKIX_NULLCHECK_ONE(expectedPolicies); |
michael@0 | 1492 | |
michael@0 | 1493 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1494 | (expectedPolicies, &numPolicies, plContext), |
michael@0 | 1495 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1496 | |
michael@0 | 1497 | for (polx = 0; polx < numPolicies; polx++) { |
michael@0 | 1498 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1499 | (expectedPolicies, |
michael@0 | 1500 | polx, |
michael@0 | 1501 | (PKIX_PL_Object **)&policyOID, |
michael@0 | 1502 | plContext), |
michael@0 | 1503 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1504 | |
michael@0 | 1505 | PKIX_NULLCHECK_ONE(policyOID); |
michael@0 | 1506 | |
michael@0 | 1507 | isIncluded = PKIX_FALSE; |
michael@0 | 1508 | |
michael@0 | 1509 | for (childIx = 0; |
michael@0 | 1510 | (!isIncluded && (childIx < numChildren)); |
michael@0 | 1511 | childIx++) { |
michael@0 | 1512 | |
michael@0 | 1513 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1514 | (children, |
michael@0 | 1515 | childIx, |
michael@0 | 1516 | (PKIX_PL_Object **)&childNode, |
michael@0 | 1517 | plContext), |
michael@0 | 1518 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1519 | |
michael@0 | 1520 | PKIX_NULLCHECK_ONE(childNode); |
michael@0 | 1521 | |
michael@0 | 1522 | PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy |
michael@0 | 1523 | (childNode, &childPolicy, plContext), |
michael@0 | 1524 | PKIX_POLICYNODEGETVALIDPOLICYFAILED); |
michael@0 | 1525 | |
michael@0 | 1526 | PKIX_NULLCHECK_ONE(childPolicy); |
michael@0 | 1527 | |
michael@0 | 1528 | PKIX_EQUALS(policyOID, childPolicy, &isIncluded, plContext, |
michael@0 | 1529 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 1530 | |
michael@0 | 1531 | PKIX_DECREF(childNode); |
michael@0 | 1532 | PKIX_DECREF(childPolicy); |
michael@0 | 1533 | } |
michael@0 | 1534 | |
michael@0 | 1535 | if (!isIncluded) { |
michael@0 | 1536 | if (policyMaps) { |
michael@0 | 1537 | PKIX_CHECK |
michael@0 | 1538 | (pkix_PolicyChecker_MapGetSubjectDomainPolicies |
michael@0 | 1539 | (policyMaps, |
michael@0 | 1540 | policyOID, |
michael@0 | 1541 | &subjectDomainPolicies, |
michael@0 | 1542 | plContext), |
michael@0 | 1543 | PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); |
michael@0 | 1544 | } |
michael@0 | 1545 | PKIX_CHECK(pkix_PolicyChecker_Spawn |
michael@0 | 1546 | (currentNode, |
michael@0 | 1547 | policyOID, |
michael@0 | 1548 | qualsOfAny, |
michael@0 | 1549 | subjectDomainPolicies, |
michael@0 | 1550 | state, |
michael@0 | 1551 | plContext), |
michael@0 | 1552 | PKIX_POLICYCHECKERSPAWNFAILED); |
michael@0 | 1553 | PKIX_DECREF(subjectDomainPolicies); |
michael@0 | 1554 | } |
michael@0 | 1555 | |
michael@0 | 1556 | PKIX_DECREF(policyOID); |
michael@0 | 1557 | } |
michael@0 | 1558 | } |
michael@0 | 1559 | |
michael@0 | 1560 | cleanup: |
michael@0 | 1561 | |
michael@0 | 1562 | PKIX_DECREF(children); |
michael@0 | 1563 | PKIX_DECREF(childNode); |
michael@0 | 1564 | PKIX_DECREF(expectedPolicies); |
michael@0 | 1565 | PKIX_DECREF(policyOID); |
michael@0 | 1566 | PKIX_DECREF(childPolicy); |
michael@0 | 1567 | PKIX_DECREF(subjectDomainPolicies); |
michael@0 | 1568 | |
michael@0 | 1569 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 1570 | |
michael@0 | 1571 | } |
michael@0 | 1572 | |
michael@0 | 1573 | /* |
michael@0 | 1574 | * FUNCTION: pkix_PolicyChecker_CalculateIntersection |
michael@0 | 1575 | * DESCRIPTION: |
michael@0 | 1576 | * |
michael@0 | 1577 | * Processes the PolicyNode pointed to by "currentNode", and its descendants, |
michael@0 | 1578 | * using the PolicyCheckerState pointed to by "state", using the List at |
michael@0 | 1579 | * the address pointed to by "nominees" the OIDs of policies that are in the |
michael@0 | 1580 | * user-initial-policy-set but are not represented among the nodes at the |
michael@0 | 1581 | * bottom of the tree, and storing at "pShouldBePruned" the value TRUE if |
michael@0 | 1582 | * currentNode is childless at the end of this processing, FALSE if it has |
michael@0 | 1583 | * children or is at the bottom of the tree. |
michael@0 | 1584 | * |
michael@0 | 1585 | * When this function is called at the top level, "nominees" should be the List |
michael@0 | 1586 | * of all policies in the user-initial-policy-set. Policies that are |
michael@0 | 1587 | * represented in the valid-policy-node-set are removed from this List. As a |
michael@0 | 1588 | * result when nodes are created according to 6.1.5.(g)(iii)(3)(b), a node will |
michael@0 | 1589 | * be created for each policy remaining in this List. |
michael@0 | 1590 | * |
michael@0 | 1591 | * This function implements the calculation of the intersection of the |
michael@0 | 1592 | * validPolicyTree with the user-initial-policy-set, as described in |
michael@0 | 1593 | * RFC 3280 6.1.5(g)(iii). |
michael@0 | 1594 | * |
michael@0 | 1595 | * PARAMETERS: |
michael@0 | 1596 | * "currentNode" |
michael@0 | 1597 | * Address of PolicyNode whose descendants will be processed as described. |
michael@0 | 1598 | * Must be non-NULL. |
michael@0 | 1599 | * "state" |
michael@0 | 1600 | * Address of the current state of the PKIX_PolicyChecker. Must be non-NULL |
michael@0 | 1601 | * "nominees" |
michael@0 | 1602 | * Address of List of the OIDs for which nodes should be created to replace |
michael@0 | 1603 | * anyPolicy nodes. Must be non-NULL but may be empty. |
michael@0 | 1604 | * "pShouldBePruned" |
michael@0 | 1605 | * Address where Boolean return value, set to TRUE if this PolicyNode |
michael@0 | 1606 | * should be deleted, is stored. Must be non-NULL. |
michael@0 | 1607 | * "plContext" |
michael@0 | 1608 | * Platform-specific context pointer. |
michael@0 | 1609 | * THREAD SAFETY: |
michael@0 | 1610 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 1611 | * RETURNS: |
michael@0 | 1612 | * Returns NULL if the function succeeds |
michael@0 | 1613 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 1614 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 1615 | */ |
michael@0 | 1616 | static PKIX_Error * |
michael@0 | 1617 | pkix_PolicyChecker_CalculateIntersection( |
michael@0 | 1618 | PKIX_PolicyNode *currentNode, |
michael@0 | 1619 | PKIX_PolicyCheckerState *state, |
michael@0 | 1620 | PKIX_List *nominees, /* OIDs */ |
michael@0 | 1621 | PKIX_Boolean *pShouldBePruned, |
michael@0 | 1622 | void *plContext) |
michael@0 | 1623 | { |
michael@0 | 1624 | PKIX_Boolean currentPolicyIsAny = PKIX_FALSE; |
michael@0 | 1625 | PKIX_Boolean parentPolicyIsAny = PKIX_FALSE; |
michael@0 | 1626 | PKIX_Boolean currentPolicyIsValid = PKIX_FALSE; |
michael@0 | 1627 | PKIX_Boolean shouldBePruned = PKIX_FALSE; |
michael@0 | 1628 | PKIX_Boolean priorCriticality = PKIX_FALSE; |
michael@0 | 1629 | PKIX_UInt32 depth = 0; |
michael@0 | 1630 | PKIX_UInt32 numChildren = 0; |
michael@0 | 1631 | PKIX_UInt32 childIndex = 0; |
michael@0 | 1632 | PKIX_UInt32 numNominees = 0; |
michael@0 | 1633 | PKIX_UInt32 polIx = 0; |
michael@0 | 1634 | PKIX_PL_OID *currentPolicy = NULL; |
michael@0 | 1635 | PKIX_PL_OID *parentPolicy = NULL; |
michael@0 | 1636 | PKIX_PL_OID *substPolicy = NULL; |
michael@0 | 1637 | PKIX_PolicyNode *parent = NULL; |
michael@0 | 1638 | PKIX_PolicyNode *child = NULL; |
michael@0 | 1639 | PKIX_List *children = NULL; /* PolicyNodes */ |
michael@0 | 1640 | PKIX_List *policyQualifiers = NULL; |
michael@0 | 1641 | |
michael@0 | 1642 | PKIX_ENTER |
michael@0 | 1643 | (CERTCHAINCHECKER, |
michael@0 | 1644 | "pkix_PolicyChecker_CalculateIntersection"); |
michael@0 | 1645 | |
michael@0 | 1646 | /* |
michael@0 | 1647 | * We call this function if the valid_policy_tree is not NULL and |
michael@0 | 1648 | * the user-initial-policy-set is not any-policy. |
michael@0 | 1649 | */ |
michael@0 | 1650 | if (!state->validPolicyTree || state->initialIsAnyPolicy) { |
michael@0 | 1651 | PKIX_ERROR(PKIX_PRECONDITIONFAILED); |
michael@0 | 1652 | } |
michael@0 | 1653 | |
michael@0 | 1654 | PKIX_NULLCHECK_FOUR(currentNode, state, nominees, pShouldBePruned); |
michael@0 | 1655 | |
michael@0 | 1656 | PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy |
michael@0 | 1657 | (currentNode, ¤tPolicy, plContext), |
michael@0 | 1658 | PKIX_POLICYNODEGETVALIDPOLICYFAILED); |
michael@0 | 1659 | |
michael@0 | 1660 | PKIX_NULLCHECK_TWO(state->anyPolicyOID, currentPolicy); |
michael@0 | 1661 | |
michael@0 | 1662 | PKIX_EQUALS |
michael@0 | 1663 | (state->anyPolicyOID, |
michael@0 | 1664 | currentPolicy, |
michael@0 | 1665 | ¤tPolicyIsAny, |
michael@0 | 1666 | plContext, |
michael@0 | 1667 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 1668 | |
michael@0 | 1669 | PKIX_CHECK(PKIX_PolicyNode_GetParent(currentNode, &parent, plContext), |
michael@0 | 1670 | PKIX_POLICYNODEGETPARENTFAILED); |
michael@0 | 1671 | |
michael@0 | 1672 | if (currentPolicyIsAny == PKIX_FALSE) { |
michael@0 | 1673 | |
michael@0 | 1674 | /* |
michael@0 | 1675 | * If we are at the top of the tree, or if our |
michael@0 | 1676 | * parent's validPolicy is anyPolicy, we are in |
michael@0 | 1677 | * the valid policy node set. |
michael@0 | 1678 | */ |
michael@0 | 1679 | if (parent) { |
michael@0 | 1680 | PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy |
michael@0 | 1681 | (parent, &parentPolicy, plContext), |
michael@0 | 1682 | PKIX_POLICYNODEGETVALIDPOLICYFAILED); |
michael@0 | 1683 | |
michael@0 | 1684 | PKIX_NULLCHECK_ONE(parentPolicy); |
michael@0 | 1685 | |
michael@0 | 1686 | PKIX_EQUALS |
michael@0 | 1687 | (state->anyPolicyOID, |
michael@0 | 1688 | parentPolicy, |
michael@0 | 1689 | &parentPolicyIsAny, |
michael@0 | 1690 | plContext, |
michael@0 | 1691 | PKIX_OBJECTEQUALSFAILED); |
michael@0 | 1692 | } |
michael@0 | 1693 | |
michael@0 | 1694 | /* |
michael@0 | 1695 | * Section 6.1.5(g)(iii)(2) |
michael@0 | 1696 | * If this node's policy is not in the user-initial-policy-set, |
michael@0 | 1697 | * it is not in the intersection. Prune it. |
michael@0 | 1698 | */ |
michael@0 | 1699 | if (!parent || parentPolicyIsAny) { |
michael@0 | 1700 | PKIX_CHECK(pkix_List_Contains |
michael@0 | 1701 | (state->userInitialPolicySet, |
michael@0 | 1702 | (PKIX_PL_Object *)currentPolicy, |
michael@0 | 1703 | ¤tPolicyIsValid, |
michael@0 | 1704 | plContext), |
michael@0 | 1705 | PKIX_LISTCONTAINSFAILED); |
michael@0 | 1706 | if (!currentPolicyIsValid) { |
michael@0 | 1707 | *pShouldBePruned = PKIX_TRUE; |
michael@0 | 1708 | goto cleanup; |
michael@0 | 1709 | } |
michael@0 | 1710 | |
michael@0 | 1711 | /* |
michael@0 | 1712 | * If this node's policy is in the user-initial-policy- |
michael@0 | 1713 | * set, it will propagate that policy into the next |
michael@0 | 1714 | * level of the tree. Remove the policy from the list |
michael@0 | 1715 | * of policies that an anyPolicy will spawn. |
michael@0 | 1716 | */ |
michael@0 | 1717 | PKIX_CHECK(pkix_List_Remove |
michael@0 | 1718 | (nominees, |
michael@0 | 1719 | (PKIX_PL_Object *)currentPolicy, |
michael@0 | 1720 | plContext), |
michael@0 | 1721 | PKIX_LISTREMOVEFAILED); |
michael@0 | 1722 | } |
michael@0 | 1723 | } |
michael@0 | 1724 | |
michael@0 | 1725 | |
michael@0 | 1726 | /* Are we at the bottom of the tree? */ |
michael@0 | 1727 | |
michael@0 | 1728 | PKIX_CHECK(PKIX_PolicyNode_GetDepth |
michael@0 | 1729 | (currentNode, &depth, plContext), |
michael@0 | 1730 | PKIX_POLICYNODEGETDEPTHFAILED); |
michael@0 | 1731 | |
michael@0 | 1732 | if (depth == (state->numCerts)) { |
michael@0 | 1733 | /* |
michael@0 | 1734 | * Section 6.1.5(g)(iii)(3) |
michael@0 | 1735 | * Replace anyPolicy nodes... |
michael@0 | 1736 | */ |
michael@0 | 1737 | if (currentPolicyIsAny == PKIX_TRUE) { |
michael@0 | 1738 | |
michael@0 | 1739 | /* replace this node */ |
michael@0 | 1740 | |
michael@0 | 1741 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1742 | (nominees, &numNominees, plContext), |
michael@0 | 1743 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1744 | |
michael@0 | 1745 | if (numNominees) { |
michael@0 | 1746 | |
michael@0 | 1747 | PKIX_CHECK(PKIX_PolicyNode_GetPolicyQualifiers |
michael@0 | 1748 | (currentNode, |
michael@0 | 1749 | &policyQualifiers, |
michael@0 | 1750 | plContext), |
michael@0 | 1751 | PKIX_POLICYNODEGETPOLICYQUALIFIERSFAILED); |
michael@0 | 1752 | |
michael@0 | 1753 | PKIX_CHECK(PKIX_PolicyNode_IsCritical |
michael@0 | 1754 | (currentNode, &priorCriticality, plContext), |
michael@0 | 1755 | PKIX_POLICYNODEISCRITICALFAILED); |
michael@0 | 1756 | } |
michael@0 | 1757 | |
michael@0 | 1758 | PKIX_NULLCHECK_ONE(parent); |
michael@0 | 1759 | |
michael@0 | 1760 | for (polIx = 0; polIx < numNominees; polIx++) { |
michael@0 | 1761 | |
michael@0 | 1762 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1763 | (nominees, |
michael@0 | 1764 | polIx, |
michael@0 | 1765 | (PKIX_PL_Object **)&substPolicy, |
michael@0 | 1766 | plContext), |
michael@0 | 1767 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1768 | |
michael@0 | 1769 | PKIX_CHECK(pkix_PolicyChecker_Spawn |
michael@0 | 1770 | (parent, |
michael@0 | 1771 | substPolicy, |
michael@0 | 1772 | policyQualifiers, |
michael@0 | 1773 | NULL, |
michael@0 | 1774 | state, |
michael@0 | 1775 | plContext), |
michael@0 | 1776 | PKIX_POLICYCHECKERSPAWNFAILED); |
michael@0 | 1777 | |
michael@0 | 1778 | PKIX_DECREF(substPolicy); |
michael@0 | 1779 | |
michael@0 | 1780 | } |
michael@0 | 1781 | /* remove currentNode from parent */ |
michael@0 | 1782 | *pShouldBePruned = PKIX_TRUE; |
michael@0 | 1783 | /* |
michael@0 | 1784 | * We can get away with augmenting the parent's List |
michael@0 | 1785 | * of children because we started at the end and went |
michael@0 | 1786 | * toward the beginning. New nodes are added at the end. |
michael@0 | 1787 | */ |
michael@0 | 1788 | } |
michael@0 | 1789 | } else { |
michael@0 | 1790 | /* |
michael@0 | 1791 | * Section 6.1.5(g)(iii)(4) |
michael@0 | 1792 | * Prune any childless nodes above the bottom level |
michael@0 | 1793 | */ |
michael@0 | 1794 | PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable |
michael@0 | 1795 | (currentNode, &children, plContext), |
michael@0 | 1796 | PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); |
michael@0 | 1797 | |
michael@0 | 1798 | /* CurrentNode should have been pruned if childless. */ |
michael@0 | 1799 | PKIX_NULLCHECK_ONE(children); |
michael@0 | 1800 | |
michael@0 | 1801 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1802 | (children, &numChildren, plContext), |
michael@0 | 1803 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1804 | |
michael@0 | 1805 | for (childIndex = numChildren; childIndex > 0; childIndex--) { |
michael@0 | 1806 | |
michael@0 | 1807 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1808 | (children, |
michael@0 | 1809 | childIndex - 1, |
michael@0 | 1810 | (PKIX_PL_Object **)&child, |
michael@0 | 1811 | plContext), |
michael@0 | 1812 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1813 | |
michael@0 | 1814 | PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection |
michael@0 | 1815 | (child, state, nominees, &shouldBePruned, plContext), |
michael@0 | 1816 | PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED); |
michael@0 | 1817 | |
michael@0 | 1818 | if (PKIX_TRUE == shouldBePruned) { |
michael@0 | 1819 | |
michael@0 | 1820 | PKIX_CHECK(PKIX_List_DeleteItem |
michael@0 | 1821 | (children, childIndex - 1, plContext), |
michael@0 | 1822 | PKIX_LISTDELETEITEMFAILED); |
michael@0 | 1823 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 1824 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 1825 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 1826 | } |
michael@0 | 1827 | |
michael@0 | 1828 | PKIX_DECREF(child); |
michael@0 | 1829 | } |
michael@0 | 1830 | |
michael@0 | 1831 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1832 | (children, &numChildren, plContext), |
michael@0 | 1833 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1834 | |
michael@0 | 1835 | if (numChildren == 0) { |
michael@0 | 1836 | *pShouldBePruned = PKIX_TRUE; |
michael@0 | 1837 | } |
michael@0 | 1838 | } |
michael@0 | 1839 | cleanup: |
michael@0 | 1840 | PKIX_DECREF(currentPolicy); |
michael@0 | 1841 | PKIX_DECREF(parentPolicy); |
michael@0 | 1842 | PKIX_DECREF(substPolicy); |
michael@0 | 1843 | PKIX_DECREF(parent); |
michael@0 | 1844 | PKIX_DECREF(child); |
michael@0 | 1845 | PKIX_DECREF(children); |
michael@0 | 1846 | PKIX_DECREF(policyQualifiers); |
michael@0 | 1847 | |
michael@0 | 1848 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 1849 | |
michael@0 | 1850 | } |
michael@0 | 1851 | |
michael@0 | 1852 | /* |
michael@0 | 1853 | * FUNCTION: pkix_PolicyChecker_PolicyMapProcessing |
michael@0 | 1854 | * DESCRIPTION: |
michael@0 | 1855 | * |
michael@0 | 1856 | * Performs the processing of Policies in the List of CertPolicyMaps pointed |
michael@0 | 1857 | * to by "policyMaps", using and updating the PolicyCheckerState pointed to by |
michael@0 | 1858 | * "state". |
michael@0 | 1859 | * |
michael@0 | 1860 | * This function implements the policyMap processing described in RFC3280 |
michael@0 | 1861 | * Section 6.1.4(b)(1), after certificate i has been processed, in preparation |
michael@0 | 1862 | * for certificate i+1. Section references are to that document. |
michael@0 | 1863 | * |
michael@0 | 1864 | * PARAMETERS: |
michael@0 | 1865 | * "policyMaps" |
michael@0 | 1866 | * Address of the List of CertPolicyMaps presented by certificate i. |
michael@0 | 1867 | * Must be non-NULL. |
michael@0 | 1868 | * "certPoliciesIncludeAny" |
michael@0 | 1869 | * Boolean value which is PKIX_TRUE if the current certificate asserts |
michael@0 | 1870 | * anyPolicy, PKIX_FALSE otherwise. |
michael@0 | 1871 | * "qualsOfAny" |
michael@0 | 1872 | * Address of List of qualifiers of the anyPolicy in the current |
michael@0 | 1873 | * certificate. May be empty or NULL. |
michael@0 | 1874 | * "state" |
michael@0 | 1875 | * Address of the current state of the PKIX_PolicyChecker. |
michael@0 | 1876 | * Must be non-NULL. |
michael@0 | 1877 | * "plContext" |
michael@0 | 1878 | * Platform-specific context pointer. |
michael@0 | 1879 | * THREAD SAFETY: |
michael@0 | 1880 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 1881 | * RETURNS: |
michael@0 | 1882 | * Returns NULL if the function succeeds |
michael@0 | 1883 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 1884 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 1885 | */ |
michael@0 | 1886 | static PKIX_Error * |
michael@0 | 1887 | pkix_PolicyChecker_PolicyMapProcessing( |
michael@0 | 1888 | PKIX_List *policyMaps, /* CertPolicyMaps */ |
michael@0 | 1889 | PKIX_Boolean certPoliciesIncludeAny, |
michael@0 | 1890 | PKIX_List *qualsOfAny, |
michael@0 | 1891 | PKIX_PolicyCheckerState *state, |
michael@0 | 1892 | void *plContext) |
michael@0 | 1893 | { |
michael@0 | 1894 | PKIX_UInt32 numPolicies = 0; |
michael@0 | 1895 | PKIX_UInt32 polX = 0; |
michael@0 | 1896 | PKIX_PL_OID *policyOID = NULL; |
michael@0 | 1897 | PKIX_List *newMappedPolicies = NULL; /* OIDs */ |
michael@0 | 1898 | PKIX_List *subjectDomainPolicies = NULL; /* OIDs */ |
michael@0 | 1899 | |
michael@0 | 1900 | PKIX_ENTER |
michael@0 | 1901 | (CERTCHAINCHECKER, |
michael@0 | 1902 | "pkix_PolicyChecker_PolicyMapProcessing"); |
michael@0 | 1903 | PKIX_NULLCHECK_THREE |
michael@0 | 1904 | (policyMaps, |
michael@0 | 1905 | state, |
michael@0 | 1906 | state->mappedUserInitialPolicySet); |
michael@0 | 1907 | |
michael@0 | 1908 | /* |
michael@0 | 1909 | * For each policy in mappedUserInitialPolicySet, if it is not mapped, |
michael@0 | 1910 | * append it to new policySet; if it is mapped, append its |
michael@0 | 1911 | * subjectDomainPolicies to new policySet. When done, this new |
michael@0 | 1912 | * policySet will replace mappedUserInitialPolicySet. |
michael@0 | 1913 | */ |
michael@0 | 1914 | PKIX_CHECK(PKIX_List_Create |
michael@0 | 1915 | (&newMappedPolicies, plContext), |
michael@0 | 1916 | PKIX_LISTCREATEFAILED); |
michael@0 | 1917 | |
michael@0 | 1918 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1919 | (state->mappedUserInitialPolicySet, |
michael@0 | 1920 | &numPolicies, |
michael@0 | 1921 | plContext), |
michael@0 | 1922 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1923 | |
michael@0 | 1924 | for (polX = 0; polX < numPolicies; polX++) { |
michael@0 | 1925 | |
michael@0 | 1926 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1927 | (state->mappedUserInitialPolicySet, |
michael@0 | 1928 | polX, |
michael@0 | 1929 | (PKIX_PL_Object **)&policyOID, |
michael@0 | 1930 | plContext), |
michael@0 | 1931 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1932 | |
michael@0 | 1933 | PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies |
michael@0 | 1934 | (policyMaps, |
michael@0 | 1935 | policyOID, |
michael@0 | 1936 | &subjectDomainPolicies, |
michael@0 | 1937 | plContext), |
michael@0 | 1938 | PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); |
michael@0 | 1939 | |
michael@0 | 1940 | if (subjectDomainPolicies) { |
michael@0 | 1941 | |
michael@0 | 1942 | PKIX_CHECK(pkix_List_AppendUnique |
michael@0 | 1943 | (newMappedPolicies, |
michael@0 | 1944 | subjectDomainPolicies, |
michael@0 | 1945 | plContext), |
michael@0 | 1946 | PKIX_LISTAPPENDUNIQUEFAILED); |
michael@0 | 1947 | |
michael@0 | 1948 | PKIX_DECREF(subjectDomainPolicies); |
michael@0 | 1949 | |
michael@0 | 1950 | } else { |
michael@0 | 1951 | PKIX_CHECK(PKIX_List_AppendItem |
michael@0 | 1952 | (newMappedPolicies, |
michael@0 | 1953 | (PKIX_PL_Object *)policyOID, |
michael@0 | 1954 | plContext), |
michael@0 | 1955 | PKIX_LISTAPPENDITEMFAILED); |
michael@0 | 1956 | } |
michael@0 | 1957 | PKIX_DECREF(policyOID); |
michael@0 | 1958 | } |
michael@0 | 1959 | |
michael@0 | 1960 | /* |
michael@0 | 1961 | * For each policy ID-P remaining in mappedPolicyOIDs, it has not been |
michael@0 | 1962 | * propagated to the bottom of the tree (depth i). If policyMapping |
michael@0 | 1963 | * is greater than zero and this cert contains anyPolicy and the tree |
michael@0 | 1964 | * contains an anyPolicy node at depth i-1, then we must create a node |
michael@0 | 1965 | * with validPolicy ID-P, the policy qualifiers of anyPolicy in |
michael@0 | 1966 | * this certificate, and expectedPolicySet the subjectDomainPolicies |
michael@0 | 1967 | * that ID-P maps to. We also then add those subjectDomainPolicies to |
michael@0 | 1968 | * the list of policies that will be accepted in the next certificate, |
michael@0 | 1969 | * the mappedUserInitialPolicySet. |
michael@0 | 1970 | */ |
michael@0 | 1971 | |
michael@0 | 1972 | if ((state->policyMapping > 0) && (certPoliciesIncludeAny) && |
michael@0 | 1973 | (state->anyPolicyNodeAtBottom) && (state->mappedPolicyOIDs)) { |
michael@0 | 1974 | |
michael@0 | 1975 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 1976 | (state->mappedPolicyOIDs, |
michael@0 | 1977 | &numPolicies, |
michael@0 | 1978 | plContext), |
michael@0 | 1979 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 1980 | |
michael@0 | 1981 | for (polX = 0; polX < numPolicies; polX++) { |
michael@0 | 1982 | |
michael@0 | 1983 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 1984 | (state->mappedPolicyOIDs, |
michael@0 | 1985 | polX, |
michael@0 | 1986 | (PKIX_PL_Object **)&policyOID, |
michael@0 | 1987 | plContext), |
michael@0 | 1988 | PKIX_LISTGETITEMFAILED); |
michael@0 | 1989 | |
michael@0 | 1990 | PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies |
michael@0 | 1991 | (policyMaps, |
michael@0 | 1992 | policyOID, |
michael@0 | 1993 | &subjectDomainPolicies, |
michael@0 | 1994 | plContext), |
michael@0 | 1995 | PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); |
michael@0 | 1996 | |
michael@0 | 1997 | PKIX_CHECK(pkix_PolicyChecker_Spawn |
michael@0 | 1998 | (state->anyPolicyNodeAtBottom, |
michael@0 | 1999 | policyOID, |
michael@0 | 2000 | qualsOfAny, |
michael@0 | 2001 | subjectDomainPolicies, |
michael@0 | 2002 | state, |
michael@0 | 2003 | plContext), |
michael@0 | 2004 | PKIX_POLICYCHECKERSPAWNFAILED); |
michael@0 | 2005 | |
michael@0 | 2006 | PKIX_CHECK(pkix_List_AppendUnique |
michael@0 | 2007 | (newMappedPolicies, |
michael@0 | 2008 | subjectDomainPolicies, |
michael@0 | 2009 | plContext), |
michael@0 | 2010 | PKIX_LISTAPPENDUNIQUEFAILED); |
michael@0 | 2011 | |
michael@0 | 2012 | PKIX_DECREF(subjectDomainPolicies); |
michael@0 | 2013 | PKIX_DECREF(policyOID); |
michael@0 | 2014 | } |
michael@0 | 2015 | } |
michael@0 | 2016 | |
michael@0 | 2017 | PKIX_CHECK(PKIX_List_SetImmutable(newMappedPolicies, plContext), |
michael@0 | 2018 | PKIX_LISTSETIMMUTABLEFAILED); |
michael@0 | 2019 | |
michael@0 | 2020 | PKIX_DECREF(state->mappedUserInitialPolicySet); |
michael@0 | 2021 | PKIX_INCREF(newMappedPolicies); |
michael@0 | 2022 | |
michael@0 | 2023 | state->mappedUserInitialPolicySet = newMappedPolicies; |
michael@0 | 2024 | |
michael@0 | 2025 | cleanup: |
michael@0 | 2026 | |
michael@0 | 2027 | PKIX_DECREF(policyOID); |
michael@0 | 2028 | PKIX_DECREF(newMappedPolicies); |
michael@0 | 2029 | PKIX_DECREF(subjectDomainPolicies); |
michael@0 | 2030 | |
michael@0 | 2031 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 2032 | } |
michael@0 | 2033 | |
michael@0 | 2034 | /* |
michael@0 | 2035 | * FUNCTION: pkix_PolicyChecker_WrapUpProcessing |
michael@0 | 2036 | * DESCRIPTION: |
michael@0 | 2037 | * |
michael@0 | 2038 | * Performs the wrap-up processing for the Cert pointed to by "cert", |
michael@0 | 2039 | * using and updating the PolicyCheckerState pointed to by "state". |
michael@0 | 2040 | * |
michael@0 | 2041 | * This function implements the wrap-up processing described in RFC3280 |
michael@0 | 2042 | * Section 6.1.5, after the final certificate has been processed. Section |
michael@0 | 2043 | * references in the comments are to that document. |
michael@0 | 2044 | * |
michael@0 | 2045 | * PARAMETERS: |
michael@0 | 2046 | * "cert" |
michael@0 | 2047 | * Address of the current (presumably the end entity) certificate. |
michael@0 | 2048 | * Must be non-NULL. |
michael@0 | 2049 | * "state" |
michael@0 | 2050 | * Address of the current state of the PKIX_PolicyChecker. |
michael@0 | 2051 | * Must be non-NULL. |
michael@0 | 2052 | * "plContext" |
michael@0 | 2053 | * Platform-specific context pointer. |
michael@0 | 2054 | * THREAD SAFETY: |
michael@0 | 2055 | * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 2056 | * RETURNS: |
michael@0 | 2057 | * Returns NULL if the function succeeds |
michael@0 | 2058 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 2059 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 2060 | */ |
michael@0 | 2061 | static PKIX_Error * |
michael@0 | 2062 | pkix_PolicyChecker_WrapUpProcessing( |
michael@0 | 2063 | PKIX_PL_Cert *cert, |
michael@0 | 2064 | PKIX_PolicyCheckerState *state, |
michael@0 | 2065 | void *plContext) |
michael@0 | 2066 | { |
michael@0 | 2067 | PKIX_Int32 explicitPolicySkipCerts = 0; |
michael@0 | 2068 | PKIX_Boolean isSelfIssued = PKIX_FALSE; |
michael@0 | 2069 | PKIX_Boolean shouldBePruned = PKIX_FALSE; |
michael@0 | 2070 | PKIX_List *nominees = NULL; /* OIDs */ |
michael@0 | 2071 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2072 | PKIX_PL_String *stateString = NULL; |
michael@0 | 2073 | char *stateAscii = NULL; |
michael@0 | 2074 | PKIX_UInt32 length; |
michael@0 | 2075 | #endif |
michael@0 | 2076 | |
michael@0 | 2077 | PKIX_ENTER |
michael@0 | 2078 | (CERTCHAINCHECKER, |
michael@0 | 2079 | "pkix_PolicyChecker_WrapUpProcessing"); |
michael@0 | 2080 | PKIX_NULLCHECK_THREE(cert, state, state->userInitialPolicySet); |
michael@0 | 2081 | |
michael@0 | 2082 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2083 | PKIX_CHECK(PKIX_PL_Object_ToString |
michael@0 | 2084 | ((PKIX_PL_Object*)state, &stateString, plContext), |
michael@0 | 2085 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 2086 | |
michael@0 | 2087 | PKIX_CHECK(PKIX_PL_String_GetEncoded |
michael@0 | 2088 | (stateString, |
michael@0 | 2089 | PKIX_ESCASCII, |
michael@0 | 2090 | (void **)&stateAscii, |
michael@0 | 2091 | &length, |
michael@0 | 2092 | plContext), |
michael@0 | 2093 | PKIX_STRINGGETENCODEDFAILED); |
michael@0 | 2094 | |
michael@0 | 2095 | PKIX_DEBUG_ARG("%s\n", stateAscii); |
michael@0 | 2096 | |
michael@0 | 2097 | PKIX_FREE(stateAscii); |
michael@0 | 2098 | PKIX_DECREF(stateString); |
michael@0 | 2099 | #endif |
michael@0 | 2100 | |
michael@0 | 2101 | /* Section 6.1.5(a) ... */ |
michael@0 | 2102 | PKIX_CHECK(pkix_IsCertSelfIssued |
michael@0 | 2103 | (cert, &isSelfIssued, plContext), |
michael@0 | 2104 | PKIX_ISCERTSELFISSUEDFAILED); |
michael@0 | 2105 | |
michael@0 | 2106 | if (!isSelfIssued) { |
michael@0 | 2107 | if (state->explicitPolicy > 0) { |
michael@0 | 2108 | |
michael@0 | 2109 | state->explicitPolicy--; |
michael@0 | 2110 | |
michael@0 | 2111 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2112 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 2113 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2114 | } |
michael@0 | 2115 | } |
michael@0 | 2116 | |
michael@0 | 2117 | /* Section 6.1.5(b) ... */ |
michael@0 | 2118 | PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy |
michael@0 | 2119 | (cert, &explicitPolicySkipCerts, plContext), |
michael@0 | 2120 | PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); |
michael@0 | 2121 | |
michael@0 | 2122 | if (explicitPolicySkipCerts == 0) { |
michael@0 | 2123 | state->explicitPolicy = 0; |
michael@0 | 2124 | } |
michael@0 | 2125 | |
michael@0 | 2126 | /* Section 6.1.5(g)(i) ... */ |
michael@0 | 2127 | |
michael@0 | 2128 | if (!(state->validPolicyTree)) { |
michael@0 | 2129 | goto cleanup; |
michael@0 | 2130 | } |
michael@0 | 2131 | |
michael@0 | 2132 | /* Section 6.1.5(g)(ii) ... */ |
michael@0 | 2133 | |
michael@0 | 2134 | if (state->initialIsAnyPolicy) { |
michael@0 | 2135 | goto cleanup; |
michael@0 | 2136 | } |
michael@0 | 2137 | |
michael@0 | 2138 | /* |
michael@0 | 2139 | * Section 6.1.5(g)(iii) ... |
michael@0 | 2140 | * Create a list of policies which could be substituted for anyPolicy. |
michael@0 | 2141 | * Start with a (mutable) copy of user-initial-policy-set. |
michael@0 | 2142 | */ |
michael@0 | 2143 | PKIX_CHECK(pkix_PolicyChecker_MakeMutableCopy |
michael@0 | 2144 | (state->userInitialPolicySet, &nominees, plContext), |
michael@0 | 2145 | PKIX_POLICYCHECKERMAKEMUTABLECOPYFAILED); |
michael@0 | 2146 | |
michael@0 | 2147 | PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection |
michael@0 | 2148 | (state->validPolicyTree, /* node at top of tree */ |
michael@0 | 2149 | state, |
michael@0 | 2150 | nominees, |
michael@0 | 2151 | &shouldBePruned, |
michael@0 | 2152 | plContext), |
michael@0 | 2153 | PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED); |
michael@0 | 2154 | |
michael@0 | 2155 | if (PKIX_TRUE == shouldBePruned) { |
michael@0 | 2156 | PKIX_DECREF(state->validPolicyTree); |
michael@0 | 2157 | } |
michael@0 | 2158 | |
michael@0 | 2159 | if (state->validPolicyTree) { |
michael@0 | 2160 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2161 | ((PKIX_PL_Object *)state->validPolicyTree, plContext), |
michael@0 | 2162 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2163 | } |
michael@0 | 2164 | |
michael@0 | 2165 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2166 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 2167 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2168 | |
michael@0 | 2169 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2170 | if (state->validPolicyTree) { |
michael@0 | 2171 | PKIX_CHECK(PKIX_PL_Object_ToString |
michael@0 | 2172 | ((PKIX_PL_Object*)state, &stateString, plContext), |
michael@0 | 2173 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 2174 | |
michael@0 | 2175 | PKIX_CHECK(PKIX_PL_String_GetEncoded |
michael@0 | 2176 | (stateString, |
michael@0 | 2177 | PKIX_ESCASCII, |
michael@0 | 2178 | (void **)&stateAscii, |
michael@0 | 2179 | &length, |
michael@0 | 2180 | plContext), |
michael@0 | 2181 | PKIX_STRINGGETENCODEDFAILED); |
michael@0 | 2182 | |
michael@0 | 2183 | PKIX_DEBUG_ARG |
michael@0 | 2184 | ("After CalculateIntersection:\n%s\n", stateAscii); |
michael@0 | 2185 | |
michael@0 | 2186 | PKIX_FREE(stateAscii); |
michael@0 | 2187 | PKIX_DECREF(stateString); |
michael@0 | 2188 | } else { |
michael@0 | 2189 | PKIX_DEBUG("validPolicyTree is NULL\n"); |
michael@0 | 2190 | } |
michael@0 | 2191 | #endif |
michael@0 | 2192 | |
michael@0 | 2193 | /* Section 6.1.5(g)(iii)(4) ... */ |
michael@0 | 2194 | |
michael@0 | 2195 | if (state->validPolicyTree) { |
michael@0 | 2196 | |
michael@0 | 2197 | PKIX_CHECK(pkix_PolicyNode_Prune |
michael@0 | 2198 | (state->validPolicyTree, |
michael@0 | 2199 | state->numCerts, |
michael@0 | 2200 | &shouldBePruned, |
michael@0 | 2201 | plContext), |
michael@0 | 2202 | PKIX_POLICYNODEPRUNEFAILED); |
michael@0 | 2203 | |
michael@0 | 2204 | if (shouldBePruned) { |
michael@0 | 2205 | PKIX_DECREF(state->validPolicyTree); |
michael@0 | 2206 | } |
michael@0 | 2207 | } |
michael@0 | 2208 | |
michael@0 | 2209 | if (state->validPolicyTree) { |
michael@0 | 2210 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2211 | ((PKIX_PL_Object *)state->validPolicyTree, plContext), |
michael@0 | 2212 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2213 | } |
michael@0 | 2214 | |
michael@0 | 2215 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2216 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 2217 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2218 | |
michael@0 | 2219 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2220 | PKIX_CHECK(PKIX_PL_Object_ToString |
michael@0 | 2221 | ((PKIX_PL_Object*)state, &stateString, plContext), |
michael@0 | 2222 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 2223 | PKIX_CHECK(PKIX_PL_String_GetEncoded |
michael@0 | 2224 | (stateString, |
michael@0 | 2225 | PKIX_ESCASCII, |
michael@0 | 2226 | (void **)&stateAscii, |
michael@0 | 2227 | &length, |
michael@0 | 2228 | plContext), |
michael@0 | 2229 | PKIX_STRINGGETENCODEDFAILED); |
michael@0 | 2230 | PKIX_DEBUG_ARG("%s\n", stateAscii); |
michael@0 | 2231 | |
michael@0 | 2232 | PKIX_FREE(stateAscii); |
michael@0 | 2233 | PKIX_DECREF(stateString); |
michael@0 | 2234 | #endif |
michael@0 | 2235 | |
michael@0 | 2236 | cleanup: |
michael@0 | 2237 | |
michael@0 | 2238 | PKIX_DECREF(nominees); |
michael@0 | 2239 | |
michael@0 | 2240 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 2241 | } |
michael@0 | 2242 | |
michael@0 | 2243 | |
michael@0 | 2244 | /* |
michael@0 | 2245 | * FUNCTION: pkix_PolicyChecker_Check |
michael@0 | 2246 | * (see comments in pkix_checker.h for PKIX_CertChainChecker_CheckCallback) |
michael@0 | 2247 | * |
michael@0 | 2248 | * Labels referring to sections, such as "Section 6.1.3(d)", refer to |
michael@0 | 2249 | * sections of RFC3280, Section 6.1.3 Basic Certificate Processing. |
michael@0 | 2250 | * |
michael@0 | 2251 | * If a non-fatal error occurs, it is unlikely that policy processing can |
michael@0 | 2252 | * continue. But it is still possible that chain validation could succeed if |
michael@0 | 2253 | * policy processing is non-critical. So if this function receives a non-fatal |
michael@0 | 2254 | * error from a lower level routine, it aborts policy processing by setting |
michael@0 | 2255 | * the validPolicyTree to NULL and tries to continue. |
michael@0 | 2256 | * |
michael@0 | 2257 | */ |
michael@0 | 2258 | static PKIX_Error * |
michael@0 | 2259 | pkix_PolicyChecker_Check( |
michael@0 | 2260 | PKIX_CertChainChecker *checker, |
michael@0 | 2261 | PKIX_PL_Cert *cert, |
michael@0 | 2262 | PKIX_List *unresolvedCriticals, /* OIDs */ |
michael@0 | 2263 | void **pNBIOContext, |
michael@0 | 2264 | void *plContext) |
michael@0 | 2265 | { |
michael@0 | 2266 | PKIX_UInt32 numPolicies = 0; |
michael@0 | 2267 | PKIX_UInt32 polX = 0; |
michael@0 | 2268 | PKIX_Boolean result = PKIX_FALSE; |
michael@0 | 2269 | PKIX_Int32 inhibitMappingSkipCerts = 0; |
michael@0 | 2270 | PKIX_Int32 explicitPolicySkipCerts = 0; |
michael@0 | 2271 | PKIX_Int32 inhibitAnyPolicySkipCerts = 0; |
michael@0 | 2272 | PKIX_Boolean shouldBePruned = PKIX_FALSE; |
michael@0 | 2273 | PKIX_Boolean isSelfIssued = PKIX_FALSE; |
michael@0 | 2274 | PKIX_Boolean certPoliciesIncludeAny = PKIX_FALSE; |
michael@0 | 2275 | PKIX_Boolean doAnyPolicyProcessing = PKIX_FALSE; |
michael@0 | 2276 | |
michael@0 | 2277 | PKIX_PolicyCheckerState *state = NULL; |
michael@0 | 2278 | PKIX_List *certPolicyInfos = NULL; /* CertPolicyInfos */ |
michael@0 | 2279 | PKIX_PL_CertPolicyInfo *policy = NULL; |
michael@0 | 2280 | PKIX_PL_OID *policyOID = NULL; |
michael@0 | 2281 | PKIX_List *qualsOfAny = NULL; /* CertPolicyQualifiers */ |
michael@0 | 2282 | PKIX_List *policyQualifiers = NULL; /* CertPolicyQualifiers */ |
michael@0 | 2283 | PKIX_List *policyMaps = NULL; /* CertPolicyMaps */ |
michael@0 | 2284 | PKIX_List *mappedPolicies = NULL; /* OIDs */ |
michael@0 | 2285 | PKIX_Error *subroutineErr = NULL; |
michael@0 | 2286 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2287 | PKIX_PL_String *stateString = NULL; |
michael@0 | 2288 | char *stateAscii = NULL; |
michael@0 | 2289 | PKIX_PL_String *certString = NULL; |
michael@0 | 2290 | char *certAscii = NULL; |
michael@0 | 2291 | PKIX_UInt32 length; |
michael@0 | 2292 | #endif |
michael@0 | 2293 | |
michael@0 | 2294 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Check"); |
michael@0 | 2295 | PKIX_NULLCHECK_FOUR(checker, cert, unresolvedCriticals, pNBIOContext); |
michael@0 | 2296 | |
michael@0 | 2297 | *pNBIOContext = NULL; /* we never block on pending I/O */ |
michael@0 | 2298 | |
michael@0 | 2299 | PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState |
michael@0 | 2300 | (checker, (PKIX_PL_Object **)&state, plContext), |
michael@0 | 2301 | PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); |
michael@0 | 2302 | |
michael@0 | 2303 | PKIX_NULLCHECK_TWO(state, state->certPoliciesExtension); |
michael@0 | 2304 | |
michael@0 | 2305 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2306 | PKIX_CHECK(PKIX_PL_Object_ToString |
michael@0 | 2307 | ((PKIX_PL_Object*)state, &stateString, plContext), |
michael@0 | 2308 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 2309 | PKIX_CHECK(PKIX_PL_String_GetEncoded |
michael@0 | 2310 | (stateString, |
michael@0 | 2311 | PKIX_ESCASCII, |
michael@0 | 2312 | (void **)&stateAscii, |
michael@0 | 2313 | &length, |
michael@0 | 2314 | plContext), |
michael@0 | 2315 | PKIX_STRINGGETENCODEDFAILED); |
michael@0 | 2316 | PKIX_DEBUG_ARG("On entry %s\n", stateAscii); |
michael@0 | 2317 | PKIX_FREE(stateAscii); |
michael@0 | 2318 | PKIX_DECREF(stateString); |
michael@0 | 2319 | #endif |
michael@0 | 2320 | |
michael@0 | 2321 | /* |
michael@0 | 2322 | * Section 6.1.4(a) |
michael@0 | 2323 | * If this is not the last certificate, and if |
michael@0 | 2324 | * policyMapping extension is present, check that no |
michael@0 | 2325 | * issuerDomainPolicy or subjectDomainPolicy is equal to the |
michael@0 | 2326 | * special policy anyPolicy. |
michael@0 | 2327 | */ |
michael@0 | 2328 | if (state->certsProcessed != (state->numCerts - 1)) { |
michael@0 | 2329 | PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings |
michael@0 | 2330 | (cert, &policyMaps, plContext), |
michael@0 | 2331 | PKIX_CERTGETPOLICYMAPPINGSFAILED); |
michael@0 | 2332 | } |
michael@0 | 2333 | |
michael@0 | 2334 | if (policyMaps) { |
michael@0 | 2335 | |
michael@0 | 2336 | PKIX_CHECK(pkix_PolicyChecker_MapContains |
michael@0 | 2337 | (policyMaps, state->anyPolicyOID, &result, plContext), |
michael@0 | 2338 | PKIX_POLICYCHECKERMAPCONTAINSFAILED); |
michael@0 | 2339 | |
michael@0 | 2340 | if (result) { |
michael@0 | 2341 | PKIX_ERROR(PKIX_INVALIDPOLICYMAPPINGINCLUDESANYPOLICY); |
michael@0 | 2342 | } |
michael@0 | 2343 | |
michael@0 | 2344 | PKIX_CHECK(pkix_PolicyChecker_MapGetMappedPolicies |
michael@0 | 2345 | (policyMaps, &mappedPolicies, plContext), |
michael@0 | 2346 | PKIX_POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED); |
michael@0 | 2347 | |
michael@0 | 2348 | PKIX_DECREF(state->mappedPolicyOIDs); |
michael@0 | 2349 | PKIX_INCREF(mappedPolicies); |
michael@0 | 2350 | state->mappedPolicyOIDs = mappedPolicies; |
michael@0 | 2351 | } |
michael@0 | 2352 | |
michael@0 | 2353 | /* Section 6.1.3(d) */ |
michael@0 | 2354 | if (state->validPolicyTree) { |
michael@0 | 2355 | |
michael@0 | 2356 | PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation |
michael@0 | 2357 | (cert, &certPolicyInfos, plContext), |
michael@0 | 2358 | PKIX_CERTGETPOLICYINFORMATIONFAILED); |
michael@0 | 2359 | |
michael@0 | 2360 | if (certPolicyInfos) { |
michael@0 | 2361 | PKIX_CHECK(PKIX_List_GetLength |
michael@0 | 2362 | (certPolicyInfos, &numPolicies, plContext), |
michael@0 | 2363 | PKIX_LISTGETLENGTHFAILED); |
michael@0 | 2364 | } |
michael@0 | 2365 | |
michael@0 | 2366 | if (numPolicies > 0) { |
michael@0 | 2367 | |
michael@0 | 2368 | PKIX_CHECK(PKIX_PL_Cert_AreCertPoliciesCritical |
michael@0 | 2369 | (cert, &(state->certPoliciesCritical), plContext), |
michael@0 | 2370 | PKIX_CERTARECERTPOLICIESCRITICALFAILED); |
michael@0 | 2371 | |
michael@0 | 2372 | /* Section 6.1.3(d)(1) For each policy not equal to anyPolicy */ |
michael@0 | 2373 | for (polX = 0; polX < numPolicies; polX++) { |
michael@0 | 2374 | |
michael@0 | 2375 | PKIX_CHECK(PKIX_List_GetItem |
michael@0 | 2376 | (certPolicyInfos, |
michael@0 | 2377 | polX, |
michael@0 | 2378 | (PKIX_PL_Object **)&policy, |
michael@0 | 2379 | plContext), |
michael@0 | 2380 | PKIX_LISTGETITEMFAILED); |
michael@0 | 2381 | |
michael@0 | 2382 | PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId |
michael@0 | 2383 | (policy, &policyOID, plContext), |
michael@0 | 2384 | PKIX_CERTPOLICYINFOGETPOLICYIDFAILED); |
michael@0 | 2385 | |
michael@0 | 2386 | PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolQualifiers |
michael@0 | 2387 | (policy, &policyQualifiers, plContext), |
michael@0 | 2388 | PKIX_CERTPOLICYINFOGETPOLQUALIFIERSFAILED); |
michael@0 | 2389 | |
michael@0 | 2390 | PKIX_EQUALS |
michael@0 | 2391 | (state->anyPolicyOID, |
michael@0 | 2392 | policyOID, |
michael@0 | 2393 | &result, |
michael@0 | 2394 | plContext, |
michael@0 | 2395 | PKIX_OIDEQUALFAILED); |
michael@0 | 2396 | |
michael@0 | 2397 | if (result == PKIX_FALSE) { |
michael@0 | 2398 | |
michael@0 | 2399 | /* Section 6.1.3(d)(1)(i) */ |
michael@0 | 2400 | subroutineErr = pkix_PolicyChecker_CheckPolicy |
michael@0 | 2401 | (policyOID, |
michael@0 | 2402 | policyQualifiers, |
michael@0 | 2403 | cert, |
michael@0 | 2404 | policyMaps, |
michael@0 | 2405 | state, |
michael@0 | 2406 | plContext); |
michael@0 | 2407 | if (subroutineErr) { |
michael@0 | 2408 | goto subrErrorCleanup; |
michael@0 | 2409 | } |
michael@0 | 2410 | |
michael@0 | 2411 | } else { |
michael@0 | 2412 | /* |
michael@0 | 2413 | * No descent (yet) for anyPolicy, but we will need |
michael@0 | 2414 | * the policyQualifiers for anyPolicy in 6.1.3(d)(2) |
michael@0 | 2415 | */ |
michael@0 | 2416 | PKIX_DECREF(qualsOfAny); |
michael@0 | 2417 | PKIX_INCREF(policyQualifiers); |
michael@0 | 2418 | qualsOfAny = policyQualifiers; |
michael@0 | 2419 | certPoliciesIncludeAny = PKIX_TRUE; |
michael@0 | 2420 | } |
michael@0 | 2421 | PKIX_DECREF(policy); |
michael@0 | 2422 | PKIX_DECREF(policyOID); |
michael@0 | 2423 | PKIX_DECREF(policyQualifiers); |
michael@0 | 2424 | } |
michael@0 | 2425 | |
michael@0 | 2426 | /* Section 6.1.3(d)(2) */ |
michael@0 | 2427 | if (certPoliciesIncludeAny == PKIX_TRUE) { |
michael@0 | 2428 | if (state->inhibitAnyPolicy > 0) { |
michael@0 | 2429 | doAnyPolicyProcessing = PKIX_TRUE; |
michael@0 | 2430 | } else { |
michael@0 | 2431 | /* We haven't yet counted the current cert */ |
michael@0 | 2432 | if (((state->certsProcessed) + 1) < |
michael@0 | 2433 | (state->numCerts)) { |
michael@0 | 2434 | |
michael@0 | 2435 | PKIX_CHECK(pkix_IsCertSelfIssued |
michael@0 | 2436 | (cert, |
michael@0 | 2437 | &doAnyPolicyProcessing, |
michael@0 | 2438 | plContext), |
michael@0 | 2439 | PKIX_ISCERTSELFISSUEDFAILED); |
michael@0 | 2440 | } |
michael@0 | 2441 | } |
michael@0 | 2442 | if (doAnyPolicyProcessing) { |
michael@0 | 2443 | subroutineErr = pkix_PolicyChecker_CheckAny |
michael@0 | 2444 | (state->validPolicyTree, |
michael@0 | 2445 | qualsOfAny, |
michael@0 | 2446 | policyMaps, |
michael@0 | 2447 | state, |
michael@0 | 2448 | plContext); |
michael@0 | 2449 | if (subroutineErr) { |
michael@0 | 2450 | goto subrErrorCleanup; |
michael@0 | 2451 | } |
michael@0 | 2452 | } |
michael@0 | 2453 | } |
michael@0 | 2454 | |
michael@0 | 2455 | /* Section 6.1.3(d)(3) */ |
michael@0 | 2456 | if (state->validPolicyTree) { |
michael@0 | 2457 | subroutineErr = pkix_PolicyNode_Prune |
michael@0 | 2458 | (state->validPolicyTree, |
michael@0 | 2459 | state->certsProcessed + 1, |
michael@0 | 2460 | &shouldBePruned, |
michael@0 | 2461 | plContext); |
michael@0 | 2462 | if (subroutineErr) { |
michael@0 | 2463 | goto subrErrorCleanup; |
michael@0 | 2464 | } |
michael@0 | 2465 | if (shouldBePruned) { |
michael@0 | 2466 | PKIX_DECREF(state->validPolicyTree); |
michael@0 | 2467 | PKIX_DECREF(state->anyPolicyNodeAtBottom); |
michael@0 | 2468 | } |
michael@0 | 2469 | } |
michael@0 | 2470 | |
michael@0 | 2471 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2472 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 2473 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2474 | |
michael@0 | 2475 | } else { |
michael@0 | 2476 | /* Section 6.1.3(e) */ |
michael@0 | 2477 | PKIX_DECREF(state->validPolicyTree); |
michael@0 | 2478 | PKIX_DECREF(state->anyPolicyNodeAtBottom); |
michael@0 | 2479 | PKIX_DECREF(state->newAnyPolicyNode); |
michael@0 | 2480 | |
michael@0 | 2481 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2482 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 2483 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2484 | } |
michael@0 | 2485 | } |
michael@0 | 2486 | |
michael@0 | 2487 | /* Section 6.1.3(f) */ |
michael@0 | 2488 | if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) { |
michael@0 | 2489 | PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); |
michael@0 | 2490 | } |
michael@0 | 2491 | |
michael@0 | 2492 | /* |
michael@0 | 2493 | * Remove Policy OIDs from list of unresolved critical |
michael@0 | 2494 | * extensions, if present. |
michael@0 | 2495 | */ |
michael@0 | 2496 | PKIX_CHECK(pkix_List_Remove |
michael@0 | 2497 | (unresolvedCriticals, |
michael@0 | 2498 | (PKIX_PL_Object *)state->certPoliciesExtension, |
michael@0 | 2499 | plContext), |
michael@0 | 2500 | PKIX_LISTREMOVEFAILED); |
michael@0 | 2501 | |
michael@0 | 2502 | PKIX_CHECK(pkix_List_Remove |
michael@0 | 2503 | (unresolvedCriticals, |
michael@0 | 2504 | (PKIX_PL_Object *)state->policyMappingsExtension, |
michael@0 | 2505 | plContext), |
michael@0 | 2506 | PKIX_LISTREMOVEFAILED); |
michael@0 | 2507 | |
michael@0 | 2508 | PKIX_CHECK(pkix_List_Remove |
michael@0 | 2509 | (unresolvedCriticals, |
michael@0 | 2510 | (PKIX_PL_Object *)state->policyConstraintsExtension, |
michael@0 | 2511 | plContext), |
michael@0 | 2512 | PKIX_LISTREMOVEFAILED); |
michael@0 | 2513 | |
michael@0 | 2514 | PKIX_CHECK(pkix_List_Remove |
michael@0 | 2515 | (unresolvedCriticals, |
michael@0 | 2516 | (PKIX_PL_Object *)state->inhibitAnyPolicyExtension, |
michael@0 | 2517 | plContext), |
michael@0 | 2518 | PKIX_LISTREMOVEFAILED); |
michael@0 | 2519 | |
michael@0 | 2520 | state->certsProcessed++; |
michael@0 | 2521 | |
michael@0 | 2522 | /* If this was not the last certificate, do next-cert preparation */ |
michael@0 | 2523 | if (state->certsProcessed != state->numCerts) { |
michael@0 | 2524 | |
michael@0 | 2525 | if (policyMaps) { |
michael@0 | 2526 | subroutineErr = pkix_PolicyChecker_PolicyMapProcessing |
michael@0 | 2527 | (policyMaps, |
michael@0 | 2528 | certPoliciesIncludeAny, |
michael@0 | 2529 | qualsOfAny, |
michael@0 | 2530 | state, |
michael@0 | 2531 | plContext); |
michael@0 | 2532 | if (subroutineErr) { |
michael@0 | 2533 | goto subrErrorCleanup; |
michael@0 | 2534 | } |
michael@0 | 2535 | } |
michael@0 | 2536 | |
michael@0 | 2537 | /* update anyPolicyNodeAtBottom pointer */ |
michael@0 | 2538 | PKIX_DECREF(state->anyPolicyNodeAtBottom); |
michael@0 | 2539 | state->anyPolicyNodeAtBottom = state->newAnyPolicyNode; |
michael@0 | 2540 | state->newAnyPolicyNode = NULL; |
michael@0 | 2541 | |
michael@0 | 2542 | /* Section 6.1.4(h) */ |
michael@0 | 2543 | PKIX_CHECK(pkix_IsCertSelfIssued |
michael@0 | 2544 | (cert, &isSelfIssued, plContext), |
michael@0 | 2545 | PKIX_ISCERTSELFISSUEDFAILED); |
michael@0 | 2546 | |
michael@0 | 2547 | if (!isSelfIssued) { |
michael@0 | 2548 | if (state->explicitPolicy > 0) { |
michael@0 | 2549 | state->explicitPolicy--; |
michael@0 | 2550 | } |
michael@0 | 2551 | if (state->policyMapping > 0) { |
michael@0 | 2552 | state->policyMapping--; |
michael@0 | 2553 | } |
michael@0 | 2554 | if (state->inhibitAnyPolicy > 0) { |
michael@0 | 2555 | state->inhibitAnyPolicy--; |
michael@0 | 2556 | } |
michael@0 | 2557 | } |
michael@0 | 2558 | |
michael@0 | 2559 | /* Section 6.1.4(i) */ |
michael@0 | 2560 | PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy |
michael@0 | 2561 | (cert, &explicitPolicySkipCerts, plContext), |
michael@0 | 2562 | PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); |
michael@0 | 2563 | |
michael@0 | 2564 | if (explicitPolicySkipCerts != -1) { |
michael@0 | 2565 | if (((PKIX_UInt32)explicitPolicySkipCerts) < |
michael@0 | 2566 | (state->explicitPolicy)) { |
michael@0 | 2567 | state->explicitPolicy = |
michael@0 | 2568 | ((PKIX_UInt32) explicitPolicySkipCerts); |
michael@0 | 2569 | } |
michael@0 | 2570 | } |
michael@0 | 2571 | |
michael@0 | 2572 | PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited |
michael@0 | 2573 | (cert, &inhibitMappingSkipCerts, plContext), |
michael@0 | 2574 | PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); |
michael@0 | 2575 | |
michael@0 | 2576 | if (inhibitMappingSkipCerts != -1) { |
michael@0 | 2577 | if (((PKIX_UInt32)inhibitMappingSkipCerts) < |
michael@0 | 2578 | (state->policyMapping)) { |
michael@0 | 2579 | state->policyMapping = |
michael@0 | 2580 | ((PKIX_UInt32)inhibitMappingSkipCerts); |
michael@0 | 2581 | } |
michael@0 | 2582 | } |
michael@0 | 2583 | |
michael@0 | 2584 | PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy |
michael@0 | 2585 | (cert, &inhibitAnyPolicySkipCerts, plContext), |
michael@0 | 2586 | PKIX_CERTGETINHIBITANYPOLICYFAILED); |
michael@0 | 2587 | |
michael@0 | 2588 | if (inhibitAnyPolicySkipCerts != -1) { |
michael@0 | 2589 | if (((PKIX_UInt32)inhibitAnyPolicySkipCerts) < |
michael@0 | 2590 | (state->inhibitAnyPolicy)) { |
michael@0 | 2591 | state->inhibitAnyPolicy = |
michael@0 | 2592 | ((PKIX_UInt32)inhibitAnyPolicySkipCerts); |
michael@0 | 2593 | } |
michael@0 | 2594 | } |
michael@0 | 2595 | |
michael@0 | 2596 | PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
michael@0 | 2597 | ((PKIX_PL_Object *)state, plContext), |
michael@0 | 2598 | PKIX_OBJECTINVALIDATECACHEFAILED); |
michael@0 | 2599 | |
michael@0 | 2600 | } else { /* If this was the last certificate, do wrap-up processing */ |
michael@0 | 2601 | |
michael@0 | 2602 | /* Section 6.1.5 */ |
michael@0 | 2603 | subroutineErr = pkix_PolicyChecker_WrapUpProcessing |
michael@0 | 2604 | (cert, state, plContext); |
michael@0 | 2605 | if (subroutineErr) { |
michael@0 | 2606 | goto subrErrorCleanup; |
michael@0 | 2607 | } |
michael@0 | 2608 | |
michael@0 | 2609 | if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) { |
michael@0 | 2610 | PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); |
michael@0 | 2611 | } |
michael@0 | 2612 | |
michael@0 | 2613 | PKIX_DECREF(state->anyPolicyNodeAtBottom); |
michael@0 | 2614 | PKIX_DECREF(state->newAnyPolicyNode); |
michael@0 | 2615 | } |
michael@0 | 2616 | |
michael@0 | 2617 | |
michael@0 | 2618 | if (subroutineErr) { |
michael@0 | 2619 | |
michael@0 | 2620 | subrErrorCleanup: |
michael@0 | 2621 | /* We had an error. Was it a fatal error? */ |
michael@0 | 2622 | pkixErrorClass = subroutineErr->errClass; |
michael@0 | 2623 | if (pkixErrorClass == PKIX_FATAL_ERROR) { |
michael@0 | 2624 | pkixErrorResult = subroutineErr; |
michael@0 | 2625 | subroutineErr = NULL; |
michael@0 | 2626 | goto cleanup; |
michael@0 | 2627 | } |
michael@0 | 2628 | /* |
michael@0 | 2629 | * Abort policy processing, and then determine whether |
michael@0 | 2630 | * we can continue without policy processing. |
michael@0 | 2631 | */ |
michael@0 | 2632 | PKIX_DECREF(state->validPolicyTree); |
michael@0 | 2633 | PKIX_DECREF(state->anyPolicyNodeAtBottom); |
michael@0 | 2634 | PKIX_DECREF(state->newAnyPolicyNode); |
michael@0 | 2635 | if (state->explicitPolicy == 0) { |
michael@0 | 2636 | PKIX_ERROR |
michael@0 | 2637 | (PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); |
michael@0 | 2638 | } |
michael@0 | 2639 | } |
michael@0 | 2640 | |
michael@0 | 2641 | /* Checking is complete. Save state for the next certificate. */ |
michael@0 | 2642 | PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState |
michael@0 | 2643 | (checker, (PKIX_PL_Object *)state, plContext), |
michael@0 | 2644 | PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); |
michael@0 | 2645 | |
michael@0 | 2646 | cleanup: |
michael@0 | 2647 | |
michael@0 | 2648 | #if PKIX_CERTPOLICYCHECKERSTATEDEBUG |
michael@0 | 2649 | if (cert) { |
michael@0 | 2650 | PKIX_CHECK(PKIX_PL_Object_ToString |
michael@0 | 2651 | ((PKIX_PL_Object*)cert, &certString, plContext), |
michael@0 | 2652 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 2653 | PKIX_CHECK(PKIX_PL_String_GetEncoded |
michael@0 | 2654 | (certString, |
michael@0 | 2655 | PKIX_ESCASCII, |
michael@0 | 2656 | (void **)&certAscii, |
michael@0 | 2657 | &length, |
michael@0 | 2658 | plContext), |
michael@0 | 2659 | PKIX_STRINGGETENCODEDFAILED); |
michael@0 | 2660 | PKIX_DEBUG_ARG("Cert was %s\n", certAscii); |
michael@0 | 2661 | PKIX_FREE(certAscii); |
michael@0 | 2662 | PKIX_DECREF(certString); |
michael@0 | 2663 | } |
michael@0 | 2664 | if (state) { |
michael@0 | 2665 | PKIX_CHECK(PKIX_PL_Object_ToString |
michael@0 | 2666 | ((PKIX_PL_Object*)state, &stateString, plContext), |
michael@0 | 2667 | PKIX_OBJECTTOSTRINGFAILED); |
michael@0 | 2668 | PKIX_CHECK(PKIX_PL_String_GetEncoded |
michael@0 | 2669 | (stateString, |
michael@0 | 2670 | PKIX_ESCASCII, |
michael@0 | 2671 | (void **)&stateAscii, |
michael@0 | 2672 | &length, |
michael@0 | 2673 | plContext), |
michael@0 | 2674 | PKIX_STRINGGETENCODEDFAILED); |
michael@0 | 2675 | PKIX_DEBUG_ARG("On exit %s\n", stateAscii); |
michael@0 | 2676 | PKIX_FREE(stateAscii); |
michael@0 | 2677 | PKIX_DECREF(stateString); |
michael@0 | 2678 | } |
michael@0 | 2679 | #endif |
michael@0 | 2680 | |
michael@0 | 2681 | PKIX_DECREF(state); |
michael@0 | 2682 | PKIX_DECREF(certPolicyInfos); |
michael@0 | 2683 | PKIX_DECREF(policy); |
michael@0 | 2684 | PKIX_DECREF(qualsOfAny); |
michael@0 | 2685 | PKIX_DECREF(policyQualifiers); |
michael@0 | 2686 | PKIX_DECREF(policyOID); |
michael@0 | 2687 | PKIX_DECREF(subroutineErr); |
michael@0 | 2688 | PKIX_DECREF(policyMaps); |
michael@0 | 2689 | PKIX_DECREF(mappedPolicies); |
michael@0 | 2690 | |
michael@0 | 2691 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 2692 | } |
michael@0 | 2693 | |
michael@0 | 2694 | /* |
michael@0 | 2695 | * FUNCTION: pkix_PolicyChecker_Initialize |
michael@0 | 2696 | * DESCRIPTION: |
michael@0 | 2697 | * |
michael@0 | 2698 | * Creates and initializes a PolicyChecker, using the List pointed to |
michael@0 | 2699 | * by "initialPolicies" for the user-initial-policy-set, the Boolean value |
michael@0 | 2700 | * of "policyQualifiersRejected" for the policyQualifiersRejected parameter, |
michael@0 | 2701 | * the Boolean value of "initialPolicyMappingInhibit" for the |
michael@0 | 2702 | * inhibitPolicyMappings parameter, the Boolean value of |
michael@0 | 2703 | * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the |
michael@0 | 2704 | * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy |
michael@0 | 2705 | * parameter, and the UInt32 value of "numCerts" as the number of |
michael@0 | 2706 | * certificates in the chain; and stores the Checker at "pChecker". |
michael@0 | 2707 | * |
michael@0 | 2708 | * PARAMETERS: |
michael@0 | 2709 | * "initialPolicies" |
michael@0 | 2710 | * Address of List of OIDs comprising the user-initial-policy-set; the List |
michael@0 | 2711 | * may be empty or NULL |
michael@0 | 2712 | * "policyQualifiersRejected" |
michael@0 | 2713 | * Boolean value of the policyQualifiersRejected parameter |
michael@0 | 2714 | * "initialPolicyMappingInhibit" |
michael@0 | 2715 | * Boolean value of the inhibitPolicyMappings parameter |
michael@0 | 2716 | * "initialExplicitPolicy" |
michael@0 | 2717 | * Boolean value of the initialExplicitPolicy parameter |
michael@0 | 2718 | * "initialAnyPolicyInhibit" |
michael@0 | 2719 | * Boolean value of the inhibitAnyPolicy parameter |
michael@0 | 2720 | * "numCerts" |
michael@0 | 2721 | * Number of certificates in the chain to be validated |
michael@0 | 2722 | * "pChecker" |
michael@0 | 2723 | * Address to store the created PolicyChecker. Must be non-NULL. |
michael@0 | 2724 | * "plContext" |
michael@0 | 2725 | * Platform-specific context pointer. |
michael@0 | 2726 | * THREAD SAFETY: |
michael@0 | 2727 | * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
michael@0 | 2728 | * RETURNS: |
michael@0 | 2729 | * Returns NULL if the function succeeds |
michael@0 | 2730 | * Returns a CertChainChecker Error if the functions fails in a non-fatal way |
michael@0 | 2731 | * Returns a Fatal Error if the function fails in an unrecoverable way |
michael@0 | 2732 | */ |
michael@0 | 2733 | PKIX_Error * |
michael@0 | 2734 | pkix_PolicyChecker_Initialize( |
michael@0 | 2735 | PKIX_List *initialPolicies, |
michael@0 | 2736 | PKIX_Boolean policyQualifiersRejected, |
michael@0 | 2737 | PKIX_Boolean initialPolicyMappingInhibit, |
michael@0 | 2738 | PKIX_Boolean initialExplicitPolicy, |
michael@0 | 2739 | PKIX_Boolean initialAnyPolicyInhibit, |
michael@0 | 2740 | PKIX_UInt32 numCerts, |
michael@0 | 2741 | PKIX_CertChainChecker **pChecker, |
michael@0 | 2742 | void *plContext) |
michael@0 | 2743 | { |
michael@0 | 2744 | PKIX_PolicyCheckerState *polCheckerState = NULL; |
michael@0 | 2745 | PKIX_List *policyExtensions = NULL; /* OIDs */ |
michael@0 | 2746 | PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Initialize"); |
michael@0 | 2747 | PKIX_NULLCHECK_ONE(pChecker); |
michael@0 | 2748 | |
michael@0 | 2749 | PKIX_CHECK(pkix_PolicyCheckerState_Create |
michael@0 | 2750 | (initialPolicies, |
michael@0 | 2751 | policyQualifiersRejected, |
michael@0 | 2752 | initialPolicyMappingInhibit, |
michael@0 | 2753 | initialExplicitPolicy, |
michael@0 | 2754 | initialAnyPolicyInhibit, |
michael@0 | 2755 | numCerts, |
michael@0 | 2756 | &polCheckerState, |
michael@0 | 2757 | plContext), |
michael@0 | 2758 | PKIX_POLICYCHECKERSTATECREATEFAILED); |
michael@0 | 2759 | |
michael@0 | 2760 | /* Create the list of extensions that we handle */ |
michael@0 | 2761 | PKIX_CHECK(pkix_PolicyChecker_MakeSingleton |
michael@0 | 2762 | ((PKIX_PL_Object *)(polCheckerState->certPoliciesExtension), |
michael@0 | 2763 | PKIX_TRUE, |
michael@0 | 2764 | &policyExtensions, |
michael@0 | 2765 | plContext), |
michael@0 | 2766 | PKIX_POLICYCHECKERMAKESINGLETONFAILED); |
michael@0 | 2767 | |
michael@0 | 2768 | PKIX_CHECK(PKIX_CertChainChecker_Create |
michael@0 | 2769 | (pkix_PolicyChecker_Check, |
michael@0 | 2770 | PKIX_FALSE, /* forwardCheckingSupported */ |
michael@0 | 2771 | PKIX_FALSE, |
michael@0 | 2772 | policyExtensions, |
michael@0 | 2773 | (PKIX_PL_Object *)polCheckerState, |
michael@0 | 2774 | pChecker, |
michael@0 | 2775 | plContext), |
michael@0 | 2776 | PKIX_CERTCHAINCHECKERCREATEFAILED); |
michael@0 | 2777 | |
michael@0 | 2778 | cleanup: |
michael@0 | 2779 | PKIX_DECREF(polCheckerState); |
michael@0 | 2780 | PKIX_DECREF(policyExtensions); |
michael@0 | 2781 | PKIX_RETURN(CERTCHAINCHECKER); |
michael@0 | 2782 | |
michael@0 | 2783 | } |