andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: /* andre@0: * pkix_policychecker.c andre@0: * andre@0: * Functions for Policy Checker andre@0: * andre@0: */ andre@0: #include "pkix_policychecker.h" andre@0: andre@0: /* --Forward declarations----------------------------------------------- */ andre@0: andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_MakeSingleton( andre@0: PKIX_PL_Object *listItem, andre@0: PKIX_Boolean immutability, andre@0: PKIX_List **pList, andre@0: void *plContext); andre@0: andre@0: /* --Private-PolicyCheckerState-Functions---------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION:pkix_PolicyCheckerState_Destroy andre@0: * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyCheckerState_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PolicyCheckerState *checkerState = NULL; andre@0: andre@0: PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: PKIX_CHECK(pkix_CheckType andre@0: (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext), andre@0: PKIX_OBJECTNOTPOLICYCHECKERSTATE); andre@0: andre@0: checkerState = (PKIX_PolicyCheckerState *)object; andre@0: andre@0: PKIX_DECREF(checkerState->certPoliciesExtension); andre@0: PKIX_DECREF(checkerState->policyMappingsExtension); andre@0: PKIX_DECREF(checkerState->policyConstraintsExtension); andre@0: PKIX_DECREF(checkerState->inhibitAnyPolicyExtension); andre@0: PKIX_DECREF(checkerState->anyPolicyOID); andre@0: PKIX_DECREF(checkerState->validPolicyTree); andre@0: PKIX_DECREF(checkerState->userInitialPolicySet); andre@0: PKIX_DECREF(checkerState->mappedUserInitialPolicySet); andre@0: andre@0: checkerState->policyQualifiersRejected = PKIX_FALSE; andre@0: checkerState->explicitPolicy = 0; andre@0: checkerState->inhibitAnyPolicy = 0; andre@0: checkerState->policyMapping = 0; andre@0: checkerState->numCerts = 0; andre@0: checkerState->certsProcessed = 0; andre@0: checkerState->certPoliciesCritical = PKIX_FALSE; andre@0: andre@0: PKIX_DECREF(checkerState->anyPolicyNodeAtBottom); andre@0: PKIX_DECREF(checkerState->newAnyPolicyNode); andre@0: PKIX_DECREF(checkerState->mappedPolicyOIDs); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(CERTPOLICYCHECKERSTATE); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyCheckerState_ToString andre@0: * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyCheckerState_ToString( andre@0: PKIX_PL_Object *object, andre@0: PKIX_PL_String **pCheckerStateString, andre@0: void *plContext) andre@0: { andre@0: PKIX_PolicyCheckerState *state = NULL; andre@0: PKIX_PL_String *resultString = NULL; andre@0: PKIX_PL_String *policiesExtOIDString = NULL; andre@0: PKIX_PL_String *policyMapOIDString = NULL; andre@0: PKIX_PL_String *policyConstrOIDString = NULL; andre@0: PKIX_PL_String *inhAnyPolOIDString = NULL; andre@0: PKIX_PL_String *anyPolicyOIDString = NULL; andre@0: PKIX_PL_String *validPolicyTreeString = NULL; andre@0: PKIX_PL_String *userInitialPolicySetString = NULL; andre@0: PKIX_PL_String *mappedUserPolicySetString = NULL; andre@0: PKIX_PL_String *mappedPolicyOIDsString = NULL; andre@0: PKIX_PL_String *anyAtBottomString = NULL; andre@0: PKIX_PL_String *newAnyPolicyString = NULL; andre@0: PKIX_PL_String *formatString = NULL; andre@0: PKIX_PL_String *trueString = NULL; andre@0: PKIX_PL_String *falseString = NULL; andre@0: PKIX_PL_String *nullString = NULL; andre@0: PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; andre@0: PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; andre@0: PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; andre@0: PKIX_Boolean initialIsAnyPolicy = PKIX_FALSE; andre@0: PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; andre@0: PKIX_Boolean certPoliciesCritical = PKIX_FALSE; andre@0: char *asciiFormat = andre@0: "{\n" andre@0: "\tcertPoliciesExtension: \t%s\n" andre@0: "\tpolicyMappingsExtension: \t%s\n" andre@0: "\tpolicyConstraintsExtension:\t%s\n" andre@0: "\tinhibitAnyPolicyExtension:\t%s\n" andre@0: "\tanyPolicyOID: \t%s\n" andre@0: "\tinitialIsAnyPolicy: \t%s\n" andre@0: "\tvalidPolicyTree: \t%s\n" andre@0: "\tuserInitialPolicySet: \t%s\n" andre@0: "\tmappedUserPolicySet: \t%s\n" andre@0: "\tpolicyQualifiersRejected: \t%s\n" andre@0: "\tinitialPolMappingInhibit: \t%s\n" andre@0: "\tinitialExplicitPolicy: \t%s\n" andre@0: "\tinitialAnyPolicyInhibit: \t%s\n" andre@0: "\texplicitPolicy: \t%d\n" andre@0: "\tinhibitAnyPolicy: \t%d\n" andre@0: "\tpolicyMapping: \t%d\n" andre@0: "\tnumCerts: \t%d\n" andre@0: "\tcertsProcessed: \t%d\n" andre@0: "\tanyPolicyNodeAtBottom: \t%s\n" andre@0: "\tnewAnyPolicyNode: \t%s\n" andre@0: "\tcertPoliciesCritical: \t%s\n" andre@0: "\tmappedPolicyOIDs: \t%s\n" andre@0: "}"; andre@0: andre@0: PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_ToString"); andre@0: andre@0: PKIX_NULLCHECK_TWO(object, pCheckerStateString); andre@0: andre@0: PKIX_CHECK(pkix_CheckType andre@0: (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext), andre@0: PKIX_OBJECTNOTPOLICYCHECKERSTATE); andre@0: andre@0: state = (PKIX_PolicyCheckerState *)object; andre@0: PKIX_NULLCHECK_THREE andre@0: (state->certPoliciesExtension, andre@0: state->policyMappingsExtension, andre@0: state->policyConstraintsExtension); andre@0: PKIX_NULLCHECK_THREE andre@0: (state->inhibitAnyPolicyExtension, andre@0: state->anyPolicyOID, andre@0: state->userInitialPolicySet); andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: /* andre@0: * Create TRUE, FALSE, and "NULL" PKIX_PL_Strings. But creating a andre@0: * PKIX_PL_String is complicated enough, it's worth checking, for andre@0: * each, to make sure the string is needed. andre@0: */ andre@0: initialPolicyMappingInhibit = state->initialPolicyMappingInhibit; andre@0: initialExplicitPolicy = state->initialExplicitPolicy; andre@0: initialAnyPolicyInhibit = state->initialAnyPolicyInhibit; andre@0: initialIsAnyPolicy = state->initialIsAnyPolicy; andre@0: policyQualifiersRejected = state->policyQualifiersRejected; andre@0: certPoliciesCritical = state->certPoliciesCritical; andre@0: andre@0: if (initialPolicyMappingInhibit || initialExplicitPolicy || andre@0: initialAnyPolicyInhibit || initialIsAnyPolicy || andre@0: policyQualifiersRejected || certPoliciesCritical) { andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, "TRUE", 0, &trueString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: } andre@0: if (!initialPolicyMappingInhibit || !initialExplicitPolicy || andre@0: !initialAnyPolicyInhibit || !initialIsAnyPolicy || andre@0: !policyQualifiersRejected || !certPoliciesCritical) { andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, "FALSE", 0, &falseString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: } andre@0: if (!(state->anyPolicyNodeAtBottom) || !(state->newAnyPolicyNode)) { andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, "(null)", 0, &nullString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: } andre@0: andre@0: PKIX_TOSTRING andre@0: (state->certPoliciesExtension, &policiesExtOIDString, plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING andre@0: (state->policyMappingsExtension, andre@0: &policyMapOIDString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING andre@0: (state->policyConstraintsExtension, andre@0: &policyConstrOIDString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING andre@0: (state->inhibitAnyPolicyExtension, andre@0: &inhAnyPolOIDString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING(state->anyPolicyOID, &anyPolicyOIDString, plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING(state->validPolicyTree, &validPolicyTreeString, plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING andre@0: (state->userInitialPolicySet, andre@0: &userInitialPolicySetString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_TOSTRING andre@0: (state->mappedUserInitialPolicySet, andre@0: &mappedUserPolicySetString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: if (state->anyPolicyNodeAtBottom) { andre@0: PKIX_CHECK(pkix_SinglePolicyNode_ToString andre@0: (state->anyPolicyNodeAtBottom, andre@0: &anyAtBottomString, andre@0: plContext), andre@0: PKIX_SINGLEPOLICYNODETOSTRINGFAILED); andre@0: } else { andre@0: PKIX_INCREF(nullString); andre@0: anyAtBottomString = nullString; andre@0: } andre@0: andre@0: if (state->newAnyPolicyNode) { andre@0: PKIX_CHECK(pkix_SinglePolicyNode_ToString andre@0: (state->newAnyPolicyNode, andre@0: &newAnyPolicyString, andre@0: plContext), andre@0: PKIX_SINGLEPOLICYNODETOSTRINGFAILED); andre@0: } else { andre@0: PKIX_INCREF(nullString); andre@0: newAnyPolicyString = nullString; andre@0: } andre@0: andre@0: PKIX_TOSTRING andre@0: (state->mappedPolicyOIDs, andre@0: &mappedPolicyOIDsString, andre@0: plContext, andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Sprintf andre@0: (&resultString, andre@0: plContext, andre@0: formatString, andre@0: policiesExtOIDString, andre@0: policyMapOIDString, andre@0: policyConstrOIDString, andre@0: inhAnyPolOIDString, andre@0: anyPolicyOIDString, andre@0: initialIsAnyPolicy?trueString:falseString, andre@0: validPolicyTreeString, andre@0: userInitialPolicySetString, andre@0: mappedUserPolicySetString, andre@0: policyQualifiersRejected?trueString:falseString, andre@0: initialPolicyMappingInhibit?trueString:falseString, andre@0: initialExplicitPolicy?trueString:falseString, andre@0: initialAnyPolicyInhibit?trueString:falseString, andre@0: state->explicitPolicy, andre@0: state->inhibitAnyPolicy, andre@0: state->policyMapping, andre@0: state->numCerts, andre@0: state->certsProcessed, andre@0: anyAtBottomString, andre@0: newAnyPolicyString, andre@0: certPoliciesCritical?trueString:falseString, andre@0: mappedPolicyOIDsString), andre@0: PKIX_SPRINTFFAILED); andre@0: andre@0: *pCheckerStateString = resultString; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(policiesExtOIDString); andre@0: PKIX_DECREF(policyMapOIDString); andre@0: PKIX_DECREF(policyConstrOIDString); andre@0: PKIX_DECREF(inhAnyPolOIDString); andre@0: PKIX_DECREF(anyPolicyOIDString); andre@0: PKIX_DECREF(validPolicyTreeString); andre@0: PKIX_DECREF(userInitialPolicySetString); andre@0: PKIX_DECREF(mappedUserPolicySetString); andre@0: PKIX_DECREF(anyAtBottomString); andre@0: PKIX_DECREF(newAnyPolicyString); andre@0: PKIX_DECREF(mappedPolicyOIDsString); andre@0: PKIX_DECREF(formatString); andre@0: PKIX_DECREF(trueString); andre@0: PKIX_DECREF(falseString); andre@0: PKIX_DECREF(nullString); andre@0: andre@0: PKIX_RETURN(CERTPOLICYCHECKERSTATE); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyCheckerState_RegisterSelf andre@0: * DESCRIPTION: andre@0: * andre@0: * Registers PKIX_POLICYCHECKERSTATE_TYPE and its related functions andre@0: * with systemClasses[] andre@0: * andre@0: * PARAMETERS: andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe - for performance and complexity reasons andre@0: * andre@0: * Since this function is only called by PKIX_PL_Initialize, which should andre@0: * only be called once, it is acceptable that this function is not andre@0: * thread-safe. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_PolicyCheckerState_RegisterSelf(void *plContext) andre@0: { andre@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: pkix_ClassTable_Entry entry; andre@0: andre@0: PKIX_ENTER andre@0: (CERTPOLICYCHECKERSTATE, andre@0: "pkix_PolicyCheckerState_RegisterSelf"); andre@0: andre@0: entry.description = "PolicyCheckerState"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(PKIX_PolicyCheckerState); andre@0: entry.destructor = pkix_PolicyCheckerState_Destroy; andre@0: entry.equalsFunction = NULL; andre@0: entry.hashcodeFunction = NULL; andre@0: entry.toStringFunction = pkix_PolicyCheckerState_ToString; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = NULL; andre@0: andre@0: systemClasses[PKIX_CERTPOLICYCHECKERSTATE_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(CERTPOLICYCHECKERSTATE); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION:pkix_PolicyCheckerState_Create andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a PolicyCheckerState Object, using the List pointed to andre@0: * by "initialPolicies" for the user-initial-policy-set, the Boolean value andre@0: * of "policyQualifiersRejected" for the policyQualifiersRejected parameter, andre@0: * the Boolean value of "initialPolicyMappingInhibit" for the andre@0: * inhibitPolicyMappings parameter, the Boolean value of andre@0: * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the andre@0: * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy andre@0: * parameter, and the UInt32 value of "numCerts" as the number of andre@0: * certificates in the chain; and stores the Object at "pCheckerState". andre@0: * andre@0: * PARAMETERS: andre@0: * "initialPolicies" andre@0: * Address of List of OIDs comprising the user-initial-policy-set; the List andre@0: * may be empty, but must be non-NULL andre@0: * "policyQualifiersRejected" andre@0: * Boolean value of the policyQualifiersRejected parameter andre@0: * "initialPolicyMappingInhibit" andre@0: * Boolean value of the inhibitPolicyMappings parameter andre@0: * "initialExplicitPolicy" andre@0: * Boolean value of the initialExplicitPolicy parameter andre@0: * "initialAnyPolicyInhibit" andre@0: * Boolean value of the inhibitAnyPolicy parameter andre@0: * "numCerts" andre@0: * Number of certificates in the chain to be validated andre@0: * "pCheckerState" andre@0: * Address where PolicyCheckerState will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertPolicyCheckerState Error if the functions fails in a andre@0: * non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyCheckerState_Create( andre@0: PKIX_List *initialPolicies, andre@0: PKIX_Boolean policyQualifiersRejected, andre@0: PKIX_Boolean initialPolicyMappingInhibit, andre@0: PKIX_Boolean initialExplicitPolicy, andre@0: PKIX_Boolean initialAnyPolicyInhibit, andre@0: PKIX_UInt32 numCerts, andre@0: PKIX_PolicyCheckerState **pCheckerState, andre@0: void *plContext) andre@0: { andre@0: PKIX_PolicyCheckerState *checkerState = NULL; andre@0: PKIX_PolicyNode *policyNode = NULL; andre@0: PKIX_List *anyPolicyList = NULL; andre@0: PKIX_Boolean initialPoliciesIsEmpty = PKIX_FALSE; andre@0: andre@0: PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Create"); andre@0: PKIX_NULLCHECK_TWO(initialPolicies, pCheckerState); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_CERTPOLICYCHECKERSTATE_TYPE, andre@0: sizeof (PKIX_PolicyCheckerState), andre@0: (PKIX_PL_Object **)&checkerState, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEPOLICYCHECKERSTATEOBJECT); andre@0: andre@0: /* Create constant PKIX_PL_OIDs: */ andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_Create andre@0: (PKIX_CERTIFICATEPOLICIES_OID, andre@0: &(checkerState->certPoliciesExtension), andre@0: plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_Create andre@0: (PKIX_POLICYMAPPINGS_OID, andre@0: &(checkerState->policyMappingsExtension), andre@0: plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_Create andre@0: (PKIX_POLICYCONSTRAINTS_OID, andre@0: &(checkerState->policyConstraintsExtension), andre@0: plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_Create andre@0: (PKIX_INHIBITANYPOLICY_OID, andre@0: &(checkerState->inhibitAnyPolicyExtension), andre@0: plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_Create andre@0: (PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID, andre@0: &(checkerState->anyPolicyOID), andre@0: plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: /* Create an initial policy set from argument supplied */ andre@0: PKIX_INCREF(initialPolicies); andre@0: checkerState->userInitialPolicySet = initialPolicies; andre@0: PKIX_INCREF(initialPolicies); andre@0: checkerState->mappedUserInitialPolicySet = initialPolicies; andre@0: andre@0: PKIX_CHECK(PKIX_List_IsEmpty andre@0: (initialPolicies, andre@0: &initialPoliciesIsEmpty, andre@0: plContext), andre@0: PKIX_LISTISEMPTYFAILED); andre@0: if (initialPoliciesIsEmpty) { andre@0: checkerState->initialIsAnyPolicy = PKIX_TRUE; andre@0: } else { andre@0: PKIX_CHECK(pkix_List_Contains andre@0: (initialPolicies, andre@0: (PKIX_PL_Object *)(checkerState->anyPolicyOID), andre@0: &(checkerState->initialIsAnyPolicy), andre@0: plContext), andre@0: PKIX_LISTCONTAINSFAILED); andre@0: } andre@0: andre@0: checkerState->policyQualifiersRejected = andre@0: policyQualifiersRejected; andre@0: checkerState->initialExplicitPolicy = initialExplicitPolicy; andre@0: checkerState->explicitPolicy = andre@0: (initialExplicitPolicy? 0: numCerts + 1); andre@0: checkerState->initialAnyPolicyInhibit = initialAnyPolicyInhibit; andre@0: checkerState->inhibitAnyPolicy = andre@0: (initialAnyPolicyInhibit? 0: numCerts + 1); andre@0: checkerState->initialPolicyMappingInhibit = initialPolicyMappingInhibit; andre@0: checkerState->policyMapping = andre@0: (initialPolicyMappingInhibit? 0: numCerts + 1); andre@0: ; andre@0: checkerState->numCerts = numCerts; andre@0: checkerState->certsProcessed = 0; andre@0: checkerState->certPoliciesCritical = PKIX_FALSE; andre@0: andre@0: /* Create a valid_policy_tree as in RFC3280 6.1.2(a) */ andre@0: PKIX_CHECK(pkix_PolicyChecker_MakeSingleton andre@0: ((PKIX_PL_Object *)(checkerState->anyPolicyOID), andre@0: PKIX_TRUE, andre@0: &anyPolicyList, andre@0: plContext), andre@0: PKIX_POLICYCHECKERMAKESINGLETONFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyNode_Create andre@0: (checkerState->anyPolicyOID, /* validPolicy */ andre@0: NULL, /* qualifier set */ andre@0: PKIX_FALSE, /* criticality */ andre@0: anyPolicyList, /* expectedPolicySet */ andre@0: &policyNode, andre@0: plContext), andre@0: PKIX_POLICYNODECREATEFAILED); andre@0: checkerState->validPolicyTree = policyNode; andre@0: andre@0: /* andre@0: * Since the initial validPolicyTree specifies andre@0: * ANY_POLICY, begin with a pointer to the root node. andre@0: */ andre@0: PKIX_INCREF(policyNode); andre@0: checkerState->anyPolicyNodeAtBottom = policyNode; andre@0: andre@0: checkerState->newAnyPolicyNode = NULL; andre@0: andre@0: checkerState->mappedPolicyOIDs = NULL; andre@0: andre@0: *pCheckerState = checkerState; andre@0: checkerState = NULL; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(checkerState); andre@0: andre@0: PKIX_DECREF(anyPolicyList); andre@0: andre@0: PKIX_RETURN(CERTPOLICYCHECKERSTATE); andre@0: } andre@0: andre@0: /* --Private-PolicyChecker-Functions--------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_MapContains andre@0: * DESCRIPTION: andre@0: * andre@0: * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to andre@0: * determine whether the OID pointed to by "policy" is among the andre@0: * issuerDomainPolicies or subjectDomainPolicies of "certPolicyMaps", and andre@0: * stores the result in "pFound". andre@0: * andre@0: * This function is intended to allow an efficient check that the proscription andre@0: * against anyPolicy being mapped, described in RFC3280 Section 6.1.4(a), is andre@0: * not violated. andre@0: * andre@0: * PARAMETERS: andre@0: * "certPolicyMaps" andre@0: * Address of List of CertPolicyMaps to be searched. May be empty, but andre@0: * must be non-NULL andre@0: * "policy" andre@0: * Address of OID to be checked for. Must be non-NULL andre@0: * "pFound" andre@0: * Address where the result of the search will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * platform-specific context pointer andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: PKIX_Error * andre@0: pkix_PolicyChecker_MapContains( andre@0: PKIX_List *certPolicyMaps, andre@0: PKIX_PL_OID *policy, andre@0: PKIX_Boolean *pFound, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertPolicyMap *map = NULL; andre@0: PKIX_UInt32 numEntries = 0; andre@0: PKIX_UInt32 index = 0; andre@0: PKIX_Boolean match = PKIX_FALSE; andre@0: PKIX_PL_OID *issuerDomainPolicy = NULL; andre@0: PKIX_PL_OID *subjectDomainPolicy = NULL; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MapContains"); andre@0: PKIX_NULLCHECK_THREE(certPolicyMaps, policy, pFound); andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (index = 0; (!match) && (index < numEntries); index++) { andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(map); andre@0: andre@0: PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy andre@0: (map, &issuerDomainPolicy, plContext), andre@0: PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); andre@0: andre@0: PKIX_EQUALS andre@0: (policy, issuerDomainPolicy, &match, plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: if (!match) { andre@0: PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy andre@0: (map, &subjectDomainPolicy, plContext), andre@0: PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED); andre@0: andre@0: PKIX_EQUALS andre@0: (policy, subjectDomainPolicy, &match, plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: } andre@0: andre@0: PKIX_DECREF(map); andre@0: PKIX_DECREF(issuerDomainPolicy); andre@0: PKIX_DECREF(subjectDomainPolicy); andre@0: } andre@0: andre@0: *pFound = match; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(map); andre@0: PKIX_DECREF(issuerDomainPolicy); andre@0: PKIX_DECREF(subjectDomainPolicy); andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_MapGetSubjectDomainPolicies andre@0: * DESCRIPTION: andre@0: * andre@0: * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to create andre@0: * a list of all SubjectDomainPolicies for which the IssuerDomainPolicy is the andre@0: * policy pointed to by "policy", and stores the result in andre@0: * "pSubjectDomainPolicies". andre@0: * andre@0: * If the List of CertPolicyMaps provided in "certPolicyMaps" is NULL, the andre@0: * resulting List will be NULL. If there are CertPolicyMaps, but none that andre@0: * include "policy" as an IssuerDomainPolicy, the returned List pointer will andre@0: * be NULL. Otherwise, the returned List will contain the SubjectDomainPolicies andre@0: * of all CertPolicyMaps for which "policy" is the IssuerDomainPolicy. If a andre@0: * List is returned it will be immutable. andre@0: * andre@0: * PARAMETERS: andre@0: * "certPolicyMaps" andre@0: * Address of List of CertPolicyMaps to be searched. May be empty or NULL. andre@0: * "policy" andre@0: * Address of OID to be checked for. Must be non-NULL andre@0: * "pSubjectDomainPolicies" andre@0: * Address where the result of the search will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * platform-specific context pointer andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: PKIX_Error * andre@0: pkix_PolicyChecker_MapGetSubjectDomainPolicies( andre@0: PKIX_List *certPolicyMaps, andre@0: PKIX_PL_OID *policy, andre@0: PKIX_List **pSubjectDomainPolicies, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertPolicyMap *map = NULL; andre@0: PKIX_List *subjectList = NULL; andre@0: PKIX_UInt32 numEntries = 0; andre@0: PKIX_UInt32 index = 0; andre@0: PKIX_Boolean match = PKIX_FALSE; andre@0: PKIX_PL_OID *issuerDomainPolicy = NULL; andre@0: PKIX_PL_OID *subjectDomainPolicy = NULL; andre@0: andre@0: PKIX_ENTER andre@0: (CERTCHAINCHECKER, andre@0: "pkix_PolicyChecker_MapGetSubjectDomainPolicies"); andre@0: PKIX_NULLCHECK_TWO(policy, pSubjectDomainPolicies); andre@0: andre@0: if (certPolicyMaps) { andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (certPolicyMaps, andre@0: &numEntries, andre@0: plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: } andre@0: andre@0: for (index = 0; index < numEntries; index++) { andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(map); andre@0: andre@0: PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy andre@0: (map, &issuerDomainPolicy, plContext), andre@0: PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); andre@0: andre@0: PKIX_EQUALS andre@0: (policy, issuerDomainPolicy, &match, plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: if (match) { andre@0: if (!subjectList) { andre@0: PKIX_CHECK(PKIX_List_Create(&subjectList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy andre@0: (map, &subjectDomainPolicy, plContext), andre@0: PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (subjectList, andre@0: (PKIX_PL_Object *)subjectDomainPolicy, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: } andre@0: andre@0: PKIX_DECREF(map); andre@0: PKIX_DECREF(issuerDomainPolicy); andre@0: PKIX_DECREF(subjectDomainPolicy); andre@0: } andre@0: andre@0: if (subjectList) { andre@0: PKIX_CHECK(PKIX_List_SetImmutable(subjectList, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: } andre@0: andre@0: *pSubjectDomainPolicies = subjectList; andre@0: andre@0: cleanup: andre@0: andre@0: if (PKIX_ERROR_RECEIVED) { andre@0: PKIX_DECREF(subjectList); andre@0: } andre@0: andre@0: PKIX_DECREF(map); andre@0: PKIX_DECREF(issuerDomainPolicy); andre@0: PKIX_DECREF(subjectDomainPolicy); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_MapGetMappedPolicies andre@0: * DESCRIPTION: andre@0: * andre@0: * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps" to create a andre@0: * List of all IssuerDomainPolicies, and stores the result in andre@0: * "pMappedPolicies". andre@0: * andre@0: * The caller may not rely on the IssuerDomainPolicies to be in any particular andre@0: * order. IssuerDomainPolicies that appear in more than one CertPolicyMap will andre@0: * only appear once in "pMappedPolicies". If "certPolicyMaps" is empty the andre@0: * result will be an empty List. The created List is mutable. andre@0: * andre@0: * PARAMETERS: andre@0: * "certPolicyMaps" andre@0: * Address of List of CertPolicyMaps to be searched. May be empty, but andre@0: * must be non-NULL. andre@0: * "pMappedPolicies" andre@0: * Address where the result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * platform-specific context pointer andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: PKIX_Error * andre@0: pkix_PolicyChecker_MapGetMappedPolicies( andre@0: PKIX_List *certPolicyMaps, andre@0: PKIX_List **pMappedPolicies, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_CertPolicyMap *map = NULL; andre@0: PKIX_List *mappedList = NULL; andre@0: PKIX_UInt32 numEntries = 0; andre@0: PKIX_UInt32 index = 0; andre@0: PKIX_Boolean isContained = PKIX_FALSE; andre@0: PKIX_PL_OID *issuerDomainPolicy = NULL; andre@0: andre@0: PKIX_ENTER andre@0: (CERTCHAINCHECKER, "pkix_PolicyChecker_MapGetMappedPolicies"); andre@0: PKIX_NULLCHECK_TWO(certPolicyMaps, pMappedPolicies); andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&mappedList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (index = 0; index < numEntries; index++) { andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(map); andre@0: andre@0: PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy andre@0: (map, &issuerDomainPolicy, plContext), andre@0: PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED); andre@0: andre@0: PKIX_CHECK(pkix_List_Contains andre@0: (mappedList, andre@0: (PKIX_PL_Object *)issuerDomainPolicy, andre@0: &isContained, andre@0: plContext), andre@0: PKIX_LISTCONTAINSFAILED); andre@0: andre@0: if (isContained == PKIX_FALSE) { andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (mappedList, andre@0: (PKIX_PL_Object *)issuerDomainPolicy, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: } andre@0: andre@0: PKIX_DECREF(map); andre@0: PKIX_DECREF(issuerDomainPolicy); andre@0: } andre@0: andre@0: *pMappedPolicies = mappedList; andre@0: andre@0: cleanup: andre@0: andre@0: if (PKIX_ERROR_RECEIVED) { andre@0: PKIX_DECREF(mappedList); andre@0: } andre@0: andre@0: PKIX_DECREF(map); andre@0: PKIX_DECREF(issuerDomainPolicy); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_MakeMutableCopy andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a mutable copy of the List pointed to by "list", which may or may andre@0: * not be immutable, and stores the address at "pMutableCopy". andre@0: * andre@0: * PARAMETERS: andre@0: * "list" andre@0: * Address of List to be copied. Must be non-NULL. andre@0: * "pMutableCopy" andre@0: * Address where mutable copy will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_MakeMutableCopy( andre@0: PKIX_List *list, andre@0: PKIX_List **pMutableCopy, andre@0: void *plContext) andre@0: { andre@0: PKIX_List *newList = NULL; andre@0: PKIX_UInt32 listLen = 0; andre@0: PKIX_UInt32 listIx = 0; andre@0: PKIX_PL_Object *object = NULL; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeMutableCopy"); andre@0: PKIX_NULLCHECK_TWO(list, pMutableCopy); andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&newList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength(list, &listLen, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (listIx = 0; listIx < listLen; listIx++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem(list, listIx, &object, plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem(newList, object, plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: PKIX_DECREF(object); andre@0: } andre@0: andre@0: *pMutableCopy = newList; andre@0: newList = NULL; andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(newList); andre@0: PKIX_DECREF(object); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_MakeSingleton andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a new List containing the Object pointed to by "listItem", using andre@0: * the Boolean value of "immutability" to determine whether to set the List andre@0: * immutable, and stores the address at "pList". andre@0: * andre@0: * PARAMETERS: andre@0: * "listItem" andre@0: * Address of Object to be inserted into the new List. Must be non-NULL. andre@0: * "immutability" andre@0: * Boolean value indicating whether new List is to be immutable andre@0: * "pList" andre@0: * Address where List will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_MakeSingleton( andre@0: PKIX_PL_Object *listItem, andre@0: PKIX_Boolean immutability, andre@0: PKIX_List **pList, andre@0: void *plContext) andre@0: { andre@0: PKIX_List *newList = NULL; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeSingleton"); andre@0: PKIX_NULLCHECK_TWO(listItem, pList); andre@0: andre@0: PKIX_CHECK(PKIX_List_Create(&newList, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (newList, (PKIX_PL_Object *)listItem, plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: andre@0: if (immutability) { andre@0: PKIX_CHECK(PKIX_List_SetImmutable(newList, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: } andre@0: andre@0: *pList = newList; andre@0: andre@0: cleanup: andre@0: if (PKIX_ERROR_RECEIVED) { andre@0: PKIX_DECREF(newList); andre@0: } andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_Spawn andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates a new childNode for the parent pointed to by "parent", using andre@0: * the OID pointed to by "policyOID", the List of CertPolicyQualifiers andre@0: * pointed to by "qualifiers", the List of OIDs pointed to by andre@0: * "subjectDomainPolicies", and the PolicyCheckerState pointed to by andre@0: * "state". The new node will be added to "parent". andre@0: * andre@0: * The validPolicy of the new node is set from the OID pointed to by andre@0: * "policyOID". The policy qualifiers for the new node is set from the andre@0: * List of qualifiers pointed to by "qualifiers", and may be NULL or andre@0: * empty if the argument provided was NULL or empty. The criticality is andre@0: * set according to the criticality obtained from the PolicyCheckerState. andre@0: * If "subjectDomainPolicies" is NULL, the expectedPolicySet of the andre@0: * child is set to contain the same policy as the validPolicy. If andre@0: * "subjectDomainPolicies" is not NULL, it is used as the value for andre@0: * the expectedPolicySet. andre@0: * andre@0: * The PolicyCheckerState also contains a constant, anyPolicy, which is andre@0: * compared to "policyOID". If they match, the address of the childNode andre@0: * is saved in the state's newAnyPolicyNode. andre@0: * andre@0: * PARAMETERS: andre@0: * "parent" andre@0: * Address of PolicyNode to which the child will be linked. Must be andre@0: * non-NULL. andre@0: * "policyOID" andre@0: * Address of OID of the new child's validPolicy and also, if andre@0: * subjectDomainPolicies is NULL, of the new child's expectedPolicySet. andre@0: * Must be non-NULL. andre@0: * "qualifiers" andre@0: * Address of List of CertPolicyQualifiers. May be NULL or empty. andre@0: * "subjectDomainPolicies" andre@0: * Address of List of OIDs indicating the policies to which "policy" is andre@0: * mapped. May be empty or NULL. andre@0: * "state" andre@0: * Address of the current PKIX_PolicyCheckerState. Must be non-NULL.. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_Spawn( andre@0: PKIX_PolicyNode *parent, andre@0: PKIX_PL_OID *policyOID, andre@0: PKIX_List *qualifiers, /* CertPolicyQualifiers */ andre@0: PKIX_List *subjectDomainPolicies, andre@0: PKIX_PolicyCheckerState *state, andre@0: void *plContext) andre@0: { andre@0: PKIX_List *expectedSet = NULL; /* OIDs */ andre@0: PKIX_PolicyNode *childNode = NULL; andre@0: PKIX_Boolean match = PKIX_FALSE; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Spawn"); andre@0: PKIX_NULLCHECK_THREE(policyOID, parent, state); andre@0: andre@0: if (subjectDomainPolicies) { andre@0: andre@0: PKIX_INCREF(subjectDomainPolicies); andre@0: expectedSet = subjectDomainPolicies; andre@0: andre@0: } else { andre@0: /* Create the child's ExpectedPolicy Set */ andre@0: PKIX_CHECK(pkix_PolicyChecker_MakeSingleton andre@0: ((PKIX_PL_Object *)policyOID, andre@0: PKIX_TRUE, /* make expectedPolicySet immutable */ andre@0: &expectedSet, andre@0: plContext), andre@0: PKIX_POLICYCHECKERMAKESINGLETONFAILED); andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_PolicyNode_Create andre@0: (policyOID, andre@0: qualifiers, andre@0: state->certPoliciesCritical, andre@0: expectedSet, andre@0: &childNode, andre@0: plContext), andre@0: PKIX_POLICYNODECREATEFAILED); andre@0: andre@0: /* andre@0: * If we had a non-empty mapping, we know the new node could not andre@0: * have been created with a validPolicy of anyPolicy. Otherwise, andre@0: * check whether we just created a new node with anyPolicy, because andre@0: * in that case we want to save the child pointer in newAnyPolicyNode. andre@0: */ andre@0: if (!subjectDomainPolicies) { andre@0: PKIX_EQUALS(policyOID, state->anyPolicyOID, &match, plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: if (match) { andre@0: PKIX_DECREF(state->newAnyPolicyNode); andre@0: PKIX_INCREF(childNode); andre@0: state->newAnyPolicyNode = childNode; andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, childNode, plContext), andre@0: PKIX_POLICYNODEADDTOPARENTFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(childNode); andre@0: PKIX_DECREF(expectedSet); andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_CheckPolicyRecursive andre@0: * DESCRIPTION: andre@0: * andre@0: * Performs policy processing for the policy whose OID is pointed to by andre@0: * "policyOID" and whose List of CertPolicyQualifiers is pointed to by andre@0: * "policyQualifiers", using the List of policy OIDs pointed to by andre@0: * "subjectDomainPolicies" and the PolicyNode pointed to by "currentNode", andre@0: * in accordance with the current PolicyCheckerState pointed to by "state", andre@0: * and setting "pChildNodeCreated" to TRUE if a new childNode is created. andre@0: * Note: "pChildNodeCreated" is not set to FALSE if no childNode is created. andre@0: * The intent of the design is that the caller can set a variable to FALSE andre@0: * initially, prior to a recursive set of calls. At the end, the variable andre@0: * can be tested to see whether *any* of the calls created a child node. andre@0: * andre@0: * If the currentNode is not at the bottom of the tree, this function andre@0: * calls itself recursively for each child of currentNode. At the bottom of andre@0: * the tree, it creates new child nodes as appropriate. This function will andre@0: * never be called with policy = anyPolicy. andre@0: * andre@0: * This function implements the processing described in RFC3280 andre@0: * Section 6.1.3(d)(1)(i). andre@0: * andre@0: * PARAMETERS: andre@0: * "policyOID" andre@0: * Address of OID of the policy to be checked for. Must be non-NULL. andre@0: * "policyQualifiers" andre@0: * Address of List of CertPolicyQualifiers of the policy to be checked for. andre@0: * May be empty or NULL. andre@0: * "subjectDomainPolicies" andre@0: * Address of List of OIDs indicating the policies to which "policy" is andre@0: * mapped. May be empty or NULL. andre@0: * "currentNode" andre@0: * Address of PolicyNode whose descendants will be checked, if not at the andre@0: * bottom of the tree; or whose expectedPolicySet will be compared to andre@0: * "policy", if at the bottom. Must be non-NULL. andre@0: * "state" andre@0: * Address of PolicyCheckerState of the current PolicyChecker. Must be andre@0: * non-NULL. andre@0: * "pChildNodeCreated" andre@0: * Address of the Boolean that will be set TRUE if this function andre@0: * creates a child node. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_CheckPolicyRecursive( andre@0: PKIX_PL_OID *policyOID, andre@0: PKIX_List *policyQualifiers, andre@0: PKIX_List *subjectDomainPolicies, andre@0: PKIX_PolicyNode *currentNode, andre@0: PKIX_PolicyCheckerState *state, andre@0: PKIX_Boolean *pChildNodeCreated, andre@0: void *plContext) andre@0: { andre@0: PKIX_UInt32 depth = 0; andre@0: PKIX_UInt32 numChildren = 0; andre@0: PKIX_UInt32 childIx = 0; andre@0: PKIX_Boolean isIncluded = PKIX_FALSE; andre@0: PKIX_List *children = NULL; /* PolicyNodes */ andre@0: PKIX_PolicyNode *childNode = NULL; andre@0: PKIX_List *expectedPolicies = NULL; /* OIDs */ andre@0: andre@0: PKIX_ENTER andre@0: (CERTCHAINCHECKER, andre@0: "pkix_PolicyChecker_CheckPolicyRecursive"); andre@0: PKIX_NULLCHECK_FOUR(policyOID, currentNode, state, pChildNodeCreated); andre@0: andre@0: /* if not at the bottom of the tree */ andre@0: PKIX_CHECK(PKIX_PolicyNode_GetDepth andre@0: (currentNode, &depth, plContext), andre@0: PKIX_POLICYNODEGETDEPTHFAILED); andre@0: andre@0: if (depth < (state->certsProcessed)) { andre@0: PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable andre@0: (currentNode, &children, plContext), andre@0: PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); andre@0: andre@0: if (children) { andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (children, &numChildren, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: } andre@0: andre@0: for (childIx = 0; childIx < numChildren; childIx++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (children, andre@0: childIx, andre@0: (PKIX_PL_Object **)&childNode, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive andre@0: (policyOID, andre@0: policyQualifiers, andre@0: subjectDomainPolicies, andre@0: childNode, andre@0: state, andre@0: pChildNodeCreated, andre@0: plContext), andre@0: PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED); andre@0: andre@0: PKIX_DECREF(childNode); andre@0: } andre@0: } else { /* if at the bottom of the tree */ andre@0: andre@0: /* Check whether policy is in this node's expectedPolicySet */ andre@0: PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies andre@0: (currentNode, &expectedPolicies, plContext), andre@0: PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(expectedPolicies); andre@0: andre@0: PKIX_CHECK(pkix_List_Contains andre@0: (expectedPolicies, andre@0: (PKIX_PL_Object *)policyOID, andre@0: &isIncluded, andre@0: plContext), andre@0: PKIX_LISTCONTAINSFAILED); andre@0: andre@0: if (isIncluded) { andre@0: PKIX_CHECK(pkix_PolicyChecker_Spawn andre@0: (currentNode, andre@0: policyOID, andre@0: policyQualifiers, andre@0: subjectDomainPolicies, andre@0: state, andre@0: plContext), andre@0: PKIX_POLICYCHECKERSPAWNFAILED); andre@0: andre@0: *pChildNodeCreated = PKIX_TRUE; andre@0: } andre@0: } andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(children); andre@0: PKIX_DECREF(childNode); andre@0: PKIX_DECREF(expectedPolicies); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_CheckPolicy andre@0: * DESCRIPTION: andre@0: * andre@0: * Performs the non-recursive portion of the policy processing for the policy andre@0: * whose OID is pointed to by "policyOID" and whose List of andre@0: * CertPolicyQualifiers is pointed to by "policyQualifiers", for the andre@0: * Certificate pointed to by "cert" with the List of CertPolicyMaps pointed andre@0: * to by "maps", in accordance with the current PolicyCheckerState pointed andre@0: * to by "state". andre@0: * andre@0: * This function implements the processing described in RFC3280 andre@0: * Section 6.1.3(d)(1)(i). andre@0: * andre@0: * PARAMETERS: andre@0: * "policyOID" andre@0: * Address of OID of the policy to be checked for. Must be non-NULL. andre@0: * "policyQualifiers" andre@0: * Address of List of CertPolicyQualifiers of the policy to be checked for. andre@0: * May be empty or NULL. andre@0: * "cert" andre@0: * Address of the current certificate. Must be non-NULL. andre@0: * "maps" andre@0: * Address of List of CertPolicyMaps for the current certificate andre@0: * "state" andre@0: * Address of PolicyCheckerState of the current PolicyChecker. Must be andre@0: * non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_CheckPolicy( andre@0: PKIX_PL_OID *policyOID, andre@0: PKIX_List *policyQualifiers, andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List *maps, andre@0: PKIX_PolicyCheckerState *state, andre@0: void *plContext) andre@0: { andre@0: PKIX_Boolean childNodeCreated = PKIX_FALSE; andre@0: PKIX_Boolean okToSpawn = PKIX_FALSE; andre@0: PKIX_Boolean found = PKIX_FALSE; andre@0: PKIX_List *subjectDomainPolicies = NULL; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckPolicy"); andre@0: PKIX_NULLCHECK_THREE(policyOID, cert, state); andre@0: andre@0: /* andre@0: * If this is not the last certificate, get the set of andre@0: * subjectDomainPolicies that "policy" maps to, according to the andre@0: * current cert's policy mapping extension. That set will be NULL andre@0: * if the current cert does not have a policy mapping extension, andre@0: * or if the current policy is not mapped. andre@0: */ andre@0: if (state->certsProcessed != (state->numCerts - 1)) { andre@0: PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies andre@0: (maps, policyOID, &subjectDomainPolicies, plContext), andre@0: PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); andre@0: } andre@0: andre@0: /* andre@0: * Section 6.1.4(b)(2) tells us that if policyMapping is zero, we andre@0: * will have to delete any nodes created with validPolicies equal to andre@0: * policies that appear as issuerDomainPolicies in a policy mapping andre@0: * extension. Let's avoid creating any such nodes. andre@0: */ andre@0: if ((state->policyMapping) == 0) { andre@0: if (subjectDomainPolicies) { andre@0: goto cleanup; andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive andre@0: (policyOID, andre@0: policyQualifiers, andre@0: subjectDomainPolicies, andre@0: state->validPolicyTree, andre@0: state, andre@0: &childNodeCreated, andre@0: plContext), andre@0: PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED); andre@0: andre@0: if (!childNodeCreated) { andre@0: /* andre@0: * Section 6.1.3(d)(1)(ii) andre@0: * There was no match. If there was a node at andre@0: * depth i-1 with valid policy anyPolicy, andre@0: * generate a node subordinate to that. andre@0: * andre@0: * But that means this created node would be in andre@0: * the valid-policy-node-set, and will be andre@0: * pruned in 6.1.5(g)(iii)(2) unless it is in andre@0: * the user-initial-policy-set or the user- andre@0: * initial-policy-set is {anyPolicy}. So check, andre@0: * and don't create it if it will be pruned. andre@0: */ andre@0: if (state->anyPolicyNodeAtBottom) { andre@0: if (state->initialIsAnyPolicy) { andre@0: okToSpawn = PKIX_TRUE; andre@0: } else { andre@0: PKIX_CHECK(pkix_List_Contains andre@0: (state->mappedUserInitialPolicySet, andre@0: (PKIX_PL_Object *)policyOID, andre@0: &okToSpawn, andre@0: plContext), andre@0: PKIX_LISTCONTAINSFAILED); andre@0: } andre@0: if (okToSpawn) { andre@0: PKIX_CHECK(pkix_PolicyChecker_Spawn andre@0: (state->anyPolicyNodeAtBottom, andre@0: policyOID, andre@0: policyQualifiers, andre@0: subjectDomainPolicies, andre@0: state, andre@0: plContext), andre@0: PKIX_POLICYCHECKERSPAWNFAILED); andre@0: childNodeCreated = PKIX_TRUE; andre@0: } andre@0: } andre@0: } andre@0: andre@0: if (childNodeCreated) { andre@0: /* andre@0: * If this policy had qualifiers, and the certificate policies andre@0: * extension was marked critical, and the user cannot deal with andre@0: * policy qualifiers, throw an error. andre@0: */ andre@0: if (policyQualifiers && andre@0: state->certPoliciesCritical && andre@0: state->policyQualifiersRejected) { andre@0: PKIX_ERROR andre@0: (PKIX_QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION); andre@0: } andre@0: /* andre@0: * If the policy we just propagated was in the list of mapped andre@0: * policies, remove it from the list. That list is used, at the andre@0: * end, to determine policies that have not been propagated. andre@0: */ andre@0: if (state->mappedPolicyOIDs) { andre@0: PKIX_CHECK(pkix_List_Contains andre@0: (state->mappedPolicyOIDs, andre@0: (PKIX_PL_Object *)policyOID, andre@0: &found, andre@0: plContext), andre@0: PKIX_LISTCONTAINSFAILED); andre@0: if (found) { andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (state->mappedPolicyOIDs, andre@0: (PKIX_PL_Object *)policyOID, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: } andre@0: } andre@0: } andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(subjectDomainPolicies); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_CheckAny andre@0: * DESCRIPTION: andre@0: * Performs the creation of PolicyNodes, for the PolicyNode pointed to by andre@0: * "currentNode" and PolicyNodes subordinate to it, using the List of andre@0: * qualifiers pointed to by "qualsOfAny", in accordance with the current andre@0: * certificate's PolicyMaps pointed to by "policyMaps" and the current andre@0: * PolicyCheckerState pointed to by "state". andre@0: * andre@0: * If the currentNode is not just above the bottom of the validPolicyTree, this andre@0: * function calls itself recursively for each child of currentNode. At the andre@0: * level just above the bottom, for each policy in the currentNode's andre@0: * expectedPolicySet not already present in a child node, it creates a new andre@0: * child node. The validPolicy of the child created, and its expectedPolicySet, andre@0: * will be the policy from the currentNode's expectedPolicySet. The policy andre@0: * qualifiers will be the qualifiers from the current certificate's anyPolicy, andre@0: * the "qualsOfAny" parameter. If the currentNode's expectedSet includes andre@0: * anyPolicy, a childNode will be created with a policy of anyPolicy. This is andre@0: * the only way such a node can be created. andre@0: * andre@0: * This function is called only when anyPolicy is one of the current andre@0: * certificate's policies. This function implements the processing described andre@0: * in RFC3280 Section 6.1.3(d)(2). andre@0: * andre@0: * PARAMETERS: andre@0: * "currentNode" andre@0: * Address of PolicyNode whose descendants will be checked, if not at the andre@0: * bottom of the tree; or whose expectedPolicySet will be compared to those andre@0: * in "alreadyPresent", if at the bottom. Must be non-NULL. andre@0: * "qualsOfAny" andre@0: * Address of List of qualifiers of the anyPolicy in the current andre@0: * certificate. May be empty or NULL. andre@0: * "policyMaps" andre@0: * Address of the List of PolicyMaps of the current certificate. May be andre@0: * empty or NULL. andre@0: * "state" andre@0: * Address of the current state of the PKIX_PolicyChecker. andre@0: * Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_CheckAny( andre@0: PKIX_PolicyNode *currentNode, andre@0: PKIX_List *qualsOfAny, /* CertPolicyQualifiers */ andre@0: PKIX_List *policyMaps, /* CertPolicyMaps */ andre@0: PKIX_PolicyCheckerState *state, andre@0: void *plContext) andre@0: { andre@0: PKIX_UInt32 depth = 0; andre@0: PKIX_UInt32 numChildren = 0; andre@0: PKIX_UInt32 childIx = 0; andre@0: PKIX_UInt32 numPolicies = 0; andre@0: PKIX_UInt32 polx = 0; andre@0: PKIX_Boolean isIncluded = PKIX_FALSE; andre@0: PKIX_List *children = NULL; /* PolicyNodes */ andre@0: PKIX_PolicyNode *childNode = NULL; andre@0: PKIX_List *expectedPolicies = NULL; /* OIDs */ andre@0: PKIX_PL_OID *policyOID = NULL; andre@0: PKIX_PL_OID *childPolicy = NULL; andre@0: PKIX_List *subjectDomainPolicies = NULL; /* OIDs */ andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckAny"); andre@0: PKIX_NULLCHECK_TWO(currentNode, state); andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetDepth andre@0: (currentNode, &depth, plContext), andre@0: PKIX_POLICYNODEGETDEPTHFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable andre@0: (currentNode, &children, plContext), andre@0: PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); andre@0: andre@0: if (children) { andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (children, &numChildren, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: } andre@0: andre@0: if (depth < (state->certsProcessed)) { andre@0: for (childIx = 0; childIx < numChildren; childIx++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (children, andre@0: childIx, andre@0: (PKIX_PL_Object **)&childNode, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(childNode); andre@0: PKIX_CHECK(pkix_PolicyChecker_CheckAny andre@0: (childNode, andre@0: qualsOfAny, andre@0: policyMaps, andre@0: state, andre@0: plContext), andre@0: PKIX_POLICYCHECKERCHECKANYFAILED); andre@0: andre@0: PKIX_DECREF(childNode); andre@0: } andre@0: } else { /* if at the bottom of the tree */ andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies andre@0: (currentNode, &expectedPolicies, plContext), andre@0: PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED); andre@0: andre@0: /* Expected Policy Set is not allowed to be NULL */ andre@0: PKIX_NULLCHECK_ONE(expectedPolicies); andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (expectedPolicies, &numPolicies, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (polx = 0; polx < numPolicies; polx++) { andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (expectedPolicies, andre@0: polx, andre@0: (PKIX_PL_Object **)&policyOID, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(policyOID); andre@0: andre@0: isIncluded = PKIX_FALSE; andre@0: andre@0: for (childIx = 0; andre@0: (!isIncluded && (childIx < numChildren)); andre@0: childIx++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (children, andre@0: childIx, andre@0: (PKIX_PL_Object **)&childNode, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(childNode); andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy andre@0: (childNode, &childPolicy, plContext), andre@0: PKIX_POLICYNODEGETVALIDPOLICYFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(childPolicy); andre@0: andre@0: PKIX_EQUALS(policyOID, childPolicy, &isIncluded, plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: PKIX_DECREF(childNode); andre@0: PKIX_DECREF(childPolicy); andre@0: } andre@0: andre@0: if (!isIncluded) { andre@0: if (policyMaps) { andre@0: PKIX_CHECK andre@0: (pkix_PolicyChecker_MapGetSubjectDomainPolicies andre@0: (policyMaps, andre@0: policyOID, andre@0: &subjectDomainPolicies, andre@0: plContext), andre@0: PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); andre@0: } andre@0: PKIX_CHECK(pkix_PolicyChecker_Spawn andre@0: (currentNode, andre@0: policyOID, andre@0: qualsOfAny, andre@0: subjectDomainPolicies, andre@0: state, andre@0: plContext), andre@0: PKIX_POLICYCHECKERSPAWNFAILED); andre@0: PKIX_DECREF(subjectDomainPolicies); andre@0: } andre@0: andre@0: PKIX_DECREF(policyOID); andre@0: } andre@0: } andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(children); andre@0: PKIX_DECREF(childNode); andre@0: PKIX_DECREF(expectedPolicies); andre@0: PKIX_DECREF(policyOID); andre@0: PKIX_DECREF(childPolicy); andre@0: PKIX_DECREF(subjectDomainPolicies); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_CalculateIntersection andre@0: * DESCRIPTION: andre@0: * andre@0: * Processes the PolicyNode pointed to by "currentNode", and its descendants, andre@0: * using the PolicyCheckerState pointed to by "state", using the List at andre@0: * the address pointed to by "nominees" the OIDs of policies that are in the andre@0: * user-initial-policy-set but are not represented among the nodes at the andre@0: * bottom of the tree, and storing at "pShouldBePruned" the value TRUE if andre@0: * currentNode is childless at the end of this processing, FALSE if it has andre@0: * children or is at the bottom of the tree. andre@0: * andre@0: * When this function is called at the top level, "nominees" should be the List andre@0: * of all policies in the user-initial-policy-set. Policies that are andre@0: * represented in the valid-policy-node-set are removed from this List. As a andre@0: * result when nodes are created according to 6.1.5.(g)(iii)(3)(b), a node will andre@0: * be created for each policy remaining in this List. andre@0: * andre@0: * This function implements the calculation of the intersection of the andre@0: * validPolicyTree with the user-initial-policy-set, as described in andre@0: * RFC 3280 6.1.5(g)(iii). andre@0: * andre@0: * PARAMETERS: andre@0: * "currentNode" andre@0: * Address of PolicyNode whose descendants will be processed as described. andre@0: * Must be non-NULL. andre@0: * "state" andre@0: * Address of the current state of the PKIX_PolicyChecker. Must be non-NULL andre@0: * "nominees" andre@0: * Address of List of the OIDs for which nodes should be created to replace andre@0: * anyPolicy nodes. Must be non-NULL but may be empty. andre@0: * "pShouldBePruned" andre@0: * Address where Boolean return value, set to TRUE if this PolicyNode andre@0: * should be deleted, is stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_CalculateIntersection( andre@0: PKIX_PolicyNode *currentNode, andre@0: PKIX_PolicyCheckerState *state, andre@0: PKIX_List *nominees, /* OIDs */ andre@0: PKIX_Boolean *pShouldBePruned, andre@0: void *plContext) andre@0: { andre@0: PKIX_Boolean currentPolicyIsAny = PKIX_FALSE; andre@0: PKIX_Boolean parentPolicyIsAny = PKIX_FALSE; andre@0: PKIX_Boolean currentPolicyIsValid = PKIX_FALSE; andre@0: PKIX_Boolean shouldBePruned = PKIX_FALSE; andre@0: PKIX_Boolean priorCriticality = PKIX_FALSE; andre@0: PKIX_UInt32 depth = 0; andre@0: PKIX_UInt32 numChildren = 0; andre@0: PKIX_UInt32 childIndex = 0; andre@0: PKIX_UInt32 numNominees = 0; andre@0: PKIX_UInt32 polIx = 0; andre@0: PKIX_PL_OID *currentPolicy = NULL; andre@0: PKIX_PL_OID *parentPolicy = NULL; andre@0: PKIX_PL_OID *substPolicy = NULL; andre@0: PKIX_PolicyNode *parent = NULL; andre@0: PKIX_PolicyNode *child = NULL; andre@0: PKIX_List *children = NULL; /* PolicyNodes */ andre@0: PKIX_List *policyQualifiers = NULL; andre@0: andre@0: PKIX_ENTER andre@0: (CERTCHAINCHECKER, andre@0: "pkix_PolicyChecker_CalculateIntersection"); andre@0: andre@0: /* andre@0: * We call this function if the valid_policy_tree is not NULL and andre@0: * the user-initial-policy-set is not any-policy. andre@0: */ andre@0: if (!state->validPolicyTree || state->initialIsAnyPolicy) { andre@0: PKIX_ERROR(PKIX_PRECONDITIONFAILED); andre@0: } andre@0: andre@0: PKIX_NULLCHECK_FOUR(currentNode, state, nominees, pShouldBePruned); andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy andre@0: (currentNode, ¤tPolicy, plContext), andre@0: PKIX_POLICYNODEGETVALIDPOLICYFAILED); andre@0: andre@0: PKIX_NULLCHECK_TWO(state->anyPolicyOID, currentPolicy); andre@0: andre@0: PKIX_EQUALS andre@0: (state->anyPolicyOID, andre@0: currentPolicy, andre@0: ¤tPolicyIsAny, andre@0: plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetParent(currentNode, &parent, plContext), andre@0: PKIX_POLICYNODEGETPARENTFAILED); andre@0: andre@0: if (currentPolicyIsAny == PKIX_FALSE) { andre@0: andre@0: /* andre@0: * If we are at the top of the tree, or if our andre@0: * parent's validPolicy is anyPolicy, we are in andre@0: * the valid policy node set. andre@0: */ andre@0: if (parent) { andre@0: PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy andre@0: (parent, &parentPolicy, plContext), andre@0: PKIX_POLICYNODEGETVALIDPOLICYFAILED); andre@0: andre@0: PKIX_NULLCHECK_ONE(parentPolicy); andre@0: andre@0: PKIX_EQUALS andre@0: (state->anyPolicyOID, andre@0: parentPolicy, andre@0: &parentPolicyIsAny, andre@0: plContext, andre@0: PKIX_OBJECTEQUALSFAILED); andre@0: } andre@0: andre@0: /* andre@0: * Section 6.1.5(g)(iii)(2) andre@0: * If this node's policy is not in the user-initial-policy-set, andre@0: * it is not in the intersection. Prune it. andre@0: */ andre@0: if (!parent || parentPolicyIsAny) { andre@0: PKIX_CHECK(pkix_List_Contains andre@0: (state->userInitialPolicySet, andre@0: (PKIX_PL_Object *)currentPolicy, andre@0: ¤tPolicyIsValid, andre@0: plContext), andre@0: PKIX_LISTCONTAINSFAILED); andre@0: if (!currentPolicyIsValid) { andre@0: *pShouldBePruned = PKIX_TRUE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* andre@0: * If this node's policy is in the user-initial-policy- andre@0: * set, it will propagate that policy into the next andre@0: * level of the tree. Remove the policy from the list andre@0: * of policies that an anyPolicy will spawn. andre@0: */ andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (nominees, andre@0: (PKIX_PL_Object *)currentPolicy, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: } andre@0: } andre@0: andre@0: andre@0: /* Are we at the bottom of the tree? */ andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetDepth andre@0: (currentNode, &depth, plContext), andre@0: PKIX_POLICYNODEGETDEPTHFAILED); andre@0: andre@0: if (depth == (state->numCerts)) { andre@0: /* andre@0: * Section 6.1.5(g)(iii)(3) andre@0: * Replace anyPolicy nodes... andre@0: */ andre@0: if (currentPolicyIsAny == PKIX_TRUE) { andre@0: andre@0: /* replace this node */ andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (nominees, &numNominees, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: if (numNominees) { andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_GetPolicyQualifiers andre@0: (currentNode, andre@0: &policyQualifiers, andre@0: plContext), andre@0: PKIX_POLICYNODEGETPOLICYQUALIFIERSFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PolicyNode_IsCritical andre@0: (currentNode, &priorCriticality, plContext), andre@0: PKIX_POLICYNODEISCRITICALFAILED); andre@0: } andre@0: andre@0: PKIX_NULLCHECK_ONE(parent); andre@0: andre@0: for (polIx = 0; polIx < numNominees; polIx++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (nominees, andre@0: polIx, andre@0: (PKIX_PL_Object **)&substPolicy, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_Spawn andre@0: (parent, andre@0: substPolicy, andre@0: policyQualifiers, andre@0: NULL, andre@0: state, andre@0: plContext), andre@0: PKIX_POLICYCHECKERSPAWNFAILED); andre@0: andre@0: PKIX_DECREF(substPolicy); andre@0: andre@0: } andre@0: /* remove currentNode from parent */ andre@0: *pShouldBePruned = PKIX_TRUE; andre@0: /* andre@0: * We can get away with augmenting the parent's List andre@0: * of children because we started at the end and went andre@0: * toward the beginning. New nodes are added at the end. andre@0: */ andre@0: } andre@0: } else { andre@0: /* andre@0: * Section 6.1.5(g)(iii)(4) andre@0: * Prune any childless nodes above the bottom level andre@0: */ andre@0: PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable andre@0: (currentNode, &children, plContext), andre@0: PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED); andre@0: andre@0: /* CurrentNode should have been pruned if childless. */ andre@0: PKIX_NULLCHECK_ONE(children); andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (children, &numChildren, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (childIndex = numChildren; childIndex > 0; childIndex--) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (children, andre@0: childIndex - 1, andre@0: (PKIX_PL_Object **)&child, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection andre@0: (child, state, nominees, &shouldBePruned, plContext), andre@0: PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED); andre@0: andre@0: if (PKIX_TRUE == shouldBePruned) { andre@0: andre@0: PKIX_CHECK(PKIX_List_DeleteItem andre@0: (children, childIndex - 1, plContext), andre@0: PKIX_LISTDELETEITEMFAILED); andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: } andre@0: andre@0: PKIX_DECREF(child); andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (children, &numChildren, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: if (numChildren == 0) { andre@0: *pShouldBePruned = PKIX_TRUE; andre@0: } andre@0: } andre@0: cleanup: andre@0: PKIX_DECREF(currentPolicy); andre@0: PKIX_DECREF(parentPolicy); andre@0: PKIX_DECREF(substPolicy); andre@0: PKIX_DECREF(parent); andre@0: PKIX_DECREF(child); andre@0: PKIX_DECREF(children); andre@0: PKIX_DECREF(policyQualifiers); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_PolicyMapProcessing andre@0: * DESCRIPTION: andre@0: * andre@0: * Performs the processing of Policies in the List of CertPolicyMaps pointed andre@0: * to by "policyMaps", using and updating the PolicyCheckerState pointed to by andre@0: * "state". andre@0: * andre@0: * This function implements the policyMap processing described in RFC3280 andre@0: * Section 6.1.4(b)(1), after certificate i has been processed, in preparation andre@0: * for certificate i+1. Section references are to that document. andre@0: * andre@0: * PARAMETERS: andre@0: * "policyMaps" andre@0: * Address of the List of CertPolicyMaps presented by certificate i. andre@0: * Must be non-NULL. andre@0: * "certPoliciesIncludeAny" andre@0: * Boolean value which is PKIX_TRUE if the current certificate asserts andre@0: * anyPolicy, PKIX_FALSE otherwise. andre@0: * "qualsOfAny" andre@0: * Address of List of qualifiers of the anyPolicy in the current andre@0: * certificate. May be empty or NULL. andre@0: * "state" andre@0: * Address of the current state of the PKIX_PolicyChecker. andre@0: * Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_PolicyMapProcessing( andre@0: PKIX_List *policyMaps, /* CertPolicyMaps */ andre@0: PKIX_Boolean certPoliciesIncludeAny, andre@0: PKIX_List *qualsOfAny, andre@0: PKIX_PolicyCheckerState *state, andre@0: void *plContext) andre@0: { andre@0: PKIX_UInt32 numPolicies = 0; andre@0: PKIX_UInt32 polX = 0; andre@0: PKIX_PL_OID *policyOID = NULL; andre@0: PKIX_List *newMappedPolicies = NULL; /* OIDs */ andre@0: PKIX_List *subjectDomainPolicies = NULL; /* OIDs */ andre@0: andre@0: PKIX_ENTER andre@0: (CERTCHAINCHECKER, andre@0: "pkix_PolicyChecker_PolicyMapProcessing"); andre@0: PKIX_NULLCHECK_THREE andre@0: (policyMaps, andre@0: state, andre@0: state->mappedUserInitialPolicySet); andre@0: andre@0: /* andre@0: * For each policy in mappedUserInitialPolicySet, if it is not mapped, andre@0: * append it to new policySet; if it is mapped, append its andre@0: * subjectDomainPolicies to new policySet. When done, this new andre@0: * policySet will replace mappedUserInitialPolicySet. andre@0: */ andre@0: PKIX_CHECK(PKIX_List_Create andre@0: (&newMappedPolicies, plContext), andre@0: PKIX_LISTCREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (state->mappedUserInitialPolicySet, andre@0: &numPolicies, andre@0: plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (polX = 0; polX < numPolicies; polX++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (state->mappedUserInitialPolicySet, andre@0: polX, andre@0: (PKIX_PL_Object **)&policyOID, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies andre@0: (policyMaps, andre@0: policyOID, andre@0: &subjectDomainPolicies, andre@0: plContext), andre@0: PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); andre@0: andre@0: if (subjectDomainPolicies) { andre@0: andre@0: PKIX_CHECK(pkix_List_AppendUnique andre@0: (newMappedPolicies, andre@0: subjectDomainPolicies, andre@0: plContext), andre@0: PKIX_LISTAPPENDUNIQUEFAILED); andre@0: andre@0: PKIX_DECREF(subjectDomainPolicies); andre@0: andre@0: } else { andre@0: PKIX_CHECK(PKIX_List_AppendItem andre@0: (newMappedPolicies, andre@0: (PKIX_PL_Object *)policyOID, andre@0: plContext), andre@0: PKIX_LISTAPPENDITEMFAILED); andre@0: } andre@0: PKIX_DECREF(policyOID); andre@0: } andre@0: andre@0: /* andre@0: * For each policy ID-P remaining in mappedPolicyOIDs, it has not been andre@0: * propagated to the bottom of the tree (depth i). If policyMapping andre@0: * is greater than zero and this cert contains anyPolicy and the tree andre@0: * contains an anyPolicy node at depth i-1, then we must create a node andre@0: * with validPolicy ID-P, the policy qualifiers of anyPolicy in andre@0: * this certificate, and expectedPolicySet the subjectDomainPolicies andre@0: * that ID-P maps to. We also then add those subjectDomainPolicies to andre@0: * the list of policies that will be accepted in the next certificate, andre@0: * the mappedUserInitialPolicySet. andre@0: */ andre@0: andre@0: if ((state->policyMapping > 0) && (certPoliciesIncludeAny) && andre@0: (state->anyPolicyNodeAtBottom) && (state->mappedPolicyOIDs)) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (state->mappedPolicyOIDs, andre@0: &numPolicies, andre@0: plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: andre@0: for (polX = 0; polX < numPolicies; polX++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (state->mappedPolicyOIDs, andre@0: polX, andre@0: (PKIX_PL_Object **)&policyOID, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies andre@0: (policyMaps, andre@0: policyOID, andre@0: &subjectDomainPolicies, andre@0: plContext), andre@0: PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_Spawn andre@0: (state->anyPolicyNodeAtBottom, andre@0: policyOID, andre@0: qualsOfAny, andre@0: subjectDomainPolicies, andre@0: state, andre@0: plContext), andre@0: PKIX_POLICYCHECKERSPAWNFAILED); andre@0: andre@0: PKIX_CHECK(pkix_List_AppendUnique andre@0: (newMappedPolicies, andre@0: subjectDomainPolicies, andre@0: plContext), andre@0: PKIX_LISTAPPENDUNIQUEFAILED); andre@0: andre@0: PKIX_DECREF(subjectDomainPolicies); andre@0: PKIX_DECREF(policyOID); andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_List_SetImmutable(newMappedPolicies, plContext), andre@0: PKIX_LISTSETIMMUTABLEFAILED); andre@0: andre@0: PKIX_DECREF(state->mappedUserInitialPolicySet); andre@0: PKIX_INCREF(newMappedPolicies); andre@0: andre@0: state->mappedUserInitialPolicySet = newMappedPolicies; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(policyOID); andre@0: PKIX_DECREF(newMappedPolicies); andre@0: PKIX_DECREF(subjectDomainPolicies); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_WrapUpProcessing andre@0: * DESCRIPTION: andre@0: * andre@0: * Performs the wrap-up processing for the Cert pointed to by "cert", andre@0: * using and updating the PolicyCheckerState pointed to by "state". andre@0: * andre@0: * This function implements the wrap-up processing described in RFC3280 andre@0: * Section 6.1.5, after the final certificate has been processed. Section andre@0: * references in the comments are to that document. andre@0: * andre@0: * PARAMETERS: andre@0: * "cert" andre@0: * Address of the current (presumably the end entity) certificate. andre@0: * Must be non-NULL. andre@0: * "state" andre@0: * Address of the current state of the PKIX_PolicyChecker. andre@0: * Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_WrapUpProcessing( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PolicyCheckerState *state, andre@0: void *plContext) andre@0: { andre@0: PKIX_Int32 explicitPolicySkipCerts = 0; andre@0: PKIX_Boolean isSelfIssued = PKIX_FALSE; andre@0: PKIX_Boolean shouldBePruned = PKIX_FALSE; andre@0: PKIX_List *nominees = NULL; /* OIDs */ andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: PKIX_PL_String *stateString = NULL; andre@0: char *stateAscii = NULL; andre@0: PKIX_UInt32 length; andre@0: #endif andre@0: andre@0: PKIX_ENTER andre@0: (CERTCHAINCHECKER, andre@0: "pkix_PolicyChecker_WrapUpProcessing"); andre@0: PKIX_NULLCHECK_THREE(cert, state, state->userInitialPolicySet); andre@0: andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object*)state, &stateString, plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (stateString, andre@0: PKIX_ESCASCII, andre@0: (void **)&stateAscii, andre@0: &length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: andre@0: PKIX_DEBUG_ARG("%s\n", stateAscii); andre@0: andre@0: PKIX_FREE(stateAscii); andre@0: PKIX_DECREF(stateString); andre@0: #endif andre@0: andre@0: /* Section 6.1.5(a) ... */ andre@0: PKIX_CHECK(pkix_IsCertSelfIssued andre@0: (cert, &isSelfIssued, plContext), andre@0: PKIX_ISCERTSELFISSUEDFAILED); andre@0: andre@0: if (!isSelfIssued) { andre@0: if (state->explicitPolicy > 0) { andre@0: andre@0: state->explicitPolicy--; andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: } andre@0: } andre@0: andre@0: /* Section 6.1.5(b) ... */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy andre@0: (cert, &explicitPolicySkipCerts, plContext), andre@0: PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); andre@0: andre@0: if (explicitPolicySkipCerts == 0) { andre@0: state->explicitPolicy = 0; andre@0: } andre@0: andre@0: /* Section 6.1.5(g)(i) ... */ andre@0: andre@0: if (!(state->validPolicyTree)) { andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* Section 6.1.5(g)(ii) ... */ andre@0: andre@0: if (state->initialIsAnyPolicy) { andre@0: goto cleanup; andre@0: } andre@0: andre@0: /* andre@0: * Section 6.1.5(g)(iii) ... andre@0: * Create a list of policies which could be substituted for anyPolicy. andre@0: * Start with a (mutable) copy of user-initial-policy-set. andre@0: */ andre@0: PKIX_CHECK(pkix_PolicyChecker_MakeMutableCopy andre@0: (state->userInitialPolicySet, &nominees, plContext), andre@0: PKIX_POLICYCHECKERMAKEMUTABLECOPYFAILED); andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection andre@0: (state->validPolicyTree, /* node at top of tree */ andre@0: state, andre@0: nominees, andre@0: &shouldBePruned, andre@0: plContext), andre@0: PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED); andre@0: andre@0: if (PKIX_TRUE == shouldBePruned) { andre@0: PKIX_DECREF(state->validPolicyTree); andre@0: } andre@0: andre@0: if (state->validPolicyTree) { andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state->validPolicyTree, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: if (state->validPolicyTree) { andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object*)state, &stateString, plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (stateString, andre@0: PKIX_ESCASCII, andre@0: (void **)&stateAscii, andre@0: &length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: andre@0: PKIX_DEBUG_ARG andre@0: ("After CalculateIntersection:\n%s\n", stateAscii); andre@0: andre@0: PKIX_FREE(stateAscii); andre@0: PKIX_DECREF(stateString); andre@0: } else { andre@0: PKIX_DEBUG("validPolicyTree is NULL\n"); andre@0: } andre@0: #endif andre@0: andre@0: /* Section 6.1.5(g)(iii)(4) ... */ andre@0: andre@0: if (state->validPolicyTree) { andre@0: andre@0: PKIX_CHECK(pkix_PolicyNode_Prune andre@0: (state->validPolicyTree, andre@0: state->numCerts, andre@0: &shouldBePruned, andre@0: plContext), andre@0: PKIX_POLICYNODEPRUNEFAILED); andre@0: andre@0: if (shouldBePruned) { andre@0: PKIX_DECREF(state->validPolicyTree); andre@0: } andre@0: } andre@0: andre@0: if (state->validPolicyTree) { andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state->validPolicyTree, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object*)state, &stateString, plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (stateString, andre@0: PKIX_ESCASCII, andre@0: (void **)&stateAscii, andre@0: &length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: PKIX_DEBUG_ARG("%s\n", stateAscii); andre@0: andre@0: PKIX_FREE(stateAscii); andre@0: PKIX_DECREF(stateString); andre@0: #endif andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(nominees); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_Check andre@0: * (see comments in pkix_checker.h for PKIX_CertChainChecker_CheckCallback) andre@0: * andre@0: * Labels referring to sections, such as "Section 6.1.3(d)", refer to andre@0: * sections of RFC3280, Section 6.1.3 Basic Certificate Processing. andre@0: * andre@0: * If a non-fatal error occurs, it is unlikely that policy processing can andre@0: * continue. But it is still possible that chain validation could succeed if andre@0: * policy processing is non-critical. So if this function receives a non-fatal andre@0: * error from a lower level routine, it aborts policy processing by setting andre@0: * the validPolicyTree to NULL and tries to continue. andre@0: * andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_PolicyChecker_Check( andre@0: PKIX_CertChainChecker *checker, andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List *unresolvedCriticals, /* OIDs */ andre@0: void **pNBIOContext, andre@0: void *plContext) andre@0: { andre@0: PKIX_UInt32 numPolicies = 0; andre@0: PKIX_UInt32 polX = 0; andre@0: PKIX_Boolean result = PKIX_FALSE; andre@0: PKIX_Int32 inhibitMappingSkipCerts = 0; andre@0: PKIX_Int32 explicitPolicySkipCerts = 0; andre@0: PKIX_Int32 inhibitAnyPolicySkipCerts = 0; andre@0: PKIX_Boolean shouldBePruned = PKIX_FALSE; andre@0: PKIX_Boolean isSelfIssued = PKIX_FALSE; andre@0: PKIX_Boolean certPoliciesIncludeAny = PKIX_FALSE; andre@0: PKIX_Boolean doAnyPolicyProcessing = PKIX_FALSE; andre@0: andre@0: PKIX_PolicyCheckerState *state = NULL; andre@0: PKIX_List *certPolicyInfos = NULL; /* CertPolicyInfos */ andre@0: PKIX_PL_CertPolicyInfo *policy = NULL; andre@0: PKIX_PL_OID *policyOID = NULL; andre@0: PKIX_List *qualsOfAny = NULL; /* CertPolicyQualifiers */ andre@0: PKIX_List *policyQualifiers = NULL; /* CertPolicyQualifiers */ andre@0: PKIX_List *policyMaps = NULL; /* CertPolicyMaps */ andre@0: PKIX_List *mappedPolicies = NULL; /* OIDs */ andre@0: PKIX_Error *subroutineErr = NULL; andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: PKIX_PL_String *stateString = NULL; andre@0: char *stateAscii = NULL; andre@0: PKIX_PL_String *certString = NULL; andre@0: char *certAscii = NULL; andre@0: PKIX_UInt32 length; andre@0: #endif andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Check"); andre@0: PKIX_NULLCHECK_FOUR(checker, cert, unresolvedCriticals, pNBIOContext); andre@0: andre@0: *pNBIOContext = NULL; /* we never block on pending I/O */ andre@0: andre@0: PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState andre@0: (checker, (PKIX_PL_Object **)&state, plContext), andre@0: PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); andre@0: andre@0: PKIX_NULLCHECK_TWO(state, state->certPoliciesExtension); andre@0: andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object*)state, &stateString, plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (stateString, andre@0: PKIX_ESCASCII, andre@0: (void **)&stateAscii, andre@0: &length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: PKIX_DEBUG_ARG("On entry %s\n", stateAscii); andre@0: PKIX_FREE(stateAscii); andre@0: PKIX_DECREF(stateString); andre@0: #endif andre@0: andre@0: /* andre@0: * Section 6.1.4(a) andre@0: * If this is not the last certificate, and if andre@0: * policyMapping extension is present, check that no andre@0: * issuerDomainPolicy or subjectDomainPolicy is equal to the andre@0: * special policy anyPolicy. andre@0: */ andre@0: if (state->certsProcessed != (state->numCerts - 1)) { andre@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings andre@0: (cert, &policyMaps, plContext), andre@0: PKIX_CERTGETPOLICYMAPPINGSFAILED); andre@0: } andre@0: andre@0: if (policyMaps) { andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_MapContains andre@0: (policyMaps, state->anyPolicyOID, &result, plContext), andre@0: PKIX_POLICYCHECKERMAPCONTAINSFAILED); andre@0: andre@0: if (result) { andre@0: PKIX_ERROR(PKIX_INVALIDPOLICYMAPPINGINCLUDESANYPOLICY); andre@0: } andre@0: andre@0: PKIX_CHECK(pkix_PolicyChecker_MapGetMappedPolicies andre@0: (policyMaps, &mappedPolicies, plContext), andre@0: PKIX_POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED); andre@0: andre@0: PKIX_DECREF(state->mappedPolicyOIDs); andre@0: PKIX_INCREF(mappedPolicies); andre@0: state->mappedPolicyOIDs = mappedPolicies; andre@0: } andre@0: andre@0: /* Section 6.1.3(d) */ andre@0: if (state->validPolicyTree) { andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation andre@0: (cert, &certPolicyInfos, plContext), andre@0: PKIX_CERTGETPOLICYINFORMATIONFAILED); andre@0: andre@0: if (certPolicyInfos) { andre@0: PKIX_CHECK(PKIX_List_GetLength andre@0: (certPolicyInfos, &numPolicies, plContext), andre@0: PKIX_LISTGETLENGTHFAILED); andre@0: } andre@0: andre@0: if (numPolicies > 0) { andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_AreCertPoliciesCritical andre@0: (cert, &(state->certPoliciesCritical), plContext), andre@0: PKIX_CERTARECERTPOLICIESCRITICALFAILED); andre@0: andre@0: /* Section 6.1.3(d)(1) For each policy not equal to anyPolicy */ andre@0: for (polX = 0; polX < numPolicies; polX++) { andre@0: andre@0: PKIX_CHECK(PKIX_List_GetItem andre@0: (certPolicyInfos, andre@0: polX, andre@0: (PKIX_PL_Object **)&policy, andre@0: plContext), andre@0: PKIX_LISTGETITEMFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId andre@0: (policy, &policyOID, plContext), andre@0: PKIX_CERTPOLICYINFOGETPOLICYIDFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolQualifiers andre@0: (policy, &policyQualifiers, plContext), andre@0: PKIX_CERTPOLICYINFOGETPOLQUALIFIERSFAILED); andre@0: andre@0: PKIX_EQUALS andre@0: (state->anyPolicyOID, andre@0: policyOID, andre@0: &result, andre@0: plContext, andre@0: PKIX_OIDEQUALFAILED); andre@0: andre@0: if (result == PKIX_FALSE) { andre@0: andre@0: /* Section 6.1.3(d)(1)(i) */ andre@0: subroutineErr = pkix_PolicyChecker_CheckPolicy andre@0: (policyOID, andre@0: policyQualifiers, andre@0: cert, andre@0: policyMaps, andre@0: state, andre@0: plContext); andre@0: if (subroutineErr) { andre@0: goto subrErrorCleanup; andre@0: } andre@0: andre@0: } else { andre@0: /* andre@0: * No descent (yet) for anyPolicy, but we will need andre@0: * the policyQualifiers for anyPolicy in 6.1.3(d)(2) andre@0: */ andre@0: PKIX_DECREF(qualsOfAny); andre@0: PKIX_INCREF(policyQualifiers); andre@0: qualsOfAny = policyQualifiers; andre@0: certPoliciesIncludeAny = PKIX_TRUE; andre@0: } andre@0: PKIX_DECREF(policy); andre@0: PKIX_DECREF(policyOID); andre@0: PKIX_DECREF(policyQualifiers); andre@0: } andre@0: andre@0: /* Section 6.1.3(d)(2) */ andre@0: if (certPoliciesIncludeAny == PKIX_TRUE) { andre@0: if (state->inhibitAnyPolicy > 0) { andre@0: doAnyPolicyProcessing = PKIX_TRUE; andre@0: } else { andre@0: /* We haven't yet counted the current cert */ andre@0: if (((state->certsProcessed) + 1) < andre@0: (state->numCerts)) { andre@0: andre@0: PKIX_CHECK(pkix_IsCertSelfIssued andre@0: (cert, andre@0: &doAnyPolicyProcessing, andre@0: plContext), andre@0: PKIX_ISCERTSELFISSUEDFAILED); andre@0: } andre@0: } andre@0: if (doAnyPolicyProcessing) { andre@0: subroutineErr = pkix_PolicyChecker_CheckAny andre@0: (state->validPolicyTree, andre@0: qualsOfAny, andre@0: policyMaps, andre@0: state, andre@0: plContext); andre@0: if (subroutineErr) { andre@0: goto subrErrorCleanup; andre@0: } andre@0: } andre@0: } andre@0: andre@0: /* Section 6.1.3(d)(3) */ andre@0: if (state->validPolicyTree) { andre@0: subroutineErr = pkix_PolicyNode_Prune andre@0: (state->validPolicyTree, andre@0: state->certsProcessed + 1, andre@0: &shouldBePruned, andre@0: plContext); andre@0: if (subroutineErr) { andre@0: goto subrErrorCleanup; andre@0: } andre@0: if (shouldBePruned) { andre@0: PKIX_DECREF(state->validPolicyTree); andre@0: PKIX_DECREF(state->anyPolicyNodeAtBottom); andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: andre@0: } else { andre@0: /* Section 6.1.3(e) */ andre@0: PKIX_DECREF(state->validPolicyTree); andre@0: PKIX_DECREF(state->anyPolicyNodeAtBottom); andre@0: PKIX_DECREF(state->newAnyPolicyNode); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: } andre@0: } andre@0: andre@0: /* Section 6.1.3(f) */ andre@0: if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) { andre@0: PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); andre@0: } andre@0: andre@0: /* andre@0: * Remove Policy OIDs from list of unresolved critical andre@0: * extensions, if present. andre@0: */ andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (unresolvedCriticals, andre@0: (PKIX_PL_Object *)state->certPoliciesExtension, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (unresolvedCriticals, andre@0: (PKIX_PL_Object *)state->policyMappingsExtension, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (unresolvedCriticals, andre@0: (PKIX_PL_Object *)state->policyConstraintsExtension, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (unresolvedCriticals, andre@0: (PKIX_PL_Object *)state->inhibitAnyPolicyExtension, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: andre@0: state->certsProcessed++; andre@0: andre@0: /* If this was not the last certificate, do next-cert preparation */ andre@0: if (state->certsProcessed != state->numCerts) { andre@0: andre@0: if (policyMaps) { andre@0: subroutineErr = pkix_PolicyChecker_PolicyMapProcessing andre@0: (policyMaps, andre@0: certPoliciesIncludeAny, andre@0: qualsOfAny, andre@0: state, andre@0: plContext); andre@0: if (subroutineErr) { andre@0: goto subrErrorCleanup; andre@0: } andre@0: } andre@0: andre@0: /* update anyPolicyNodeAtBottom pointer */ andre@0: PKIX_DECREF(state->anyPolicyNodeAtBottom); andre@0: state->anyPolicyNodeAtBottom = state->newAnyPolicyNode; andre@0: state->newAnyPolicyNode = NULL; andre@0: andre@0: /* Section 6.1.4(h) */ andre@0: PKIX_CHECK(pkix_IsCertSelfIssued andre@0: (cert, &isSelfIssued, plContext), andre@0: PKIX_ISCERTSELFISSUEDFAILED); andre@0: andre@0: if (!isSelfIssued) { andre@0: if (state->explicitPolicy > 0) { andre@0: state->explicitPolicy--; andre@0: } andre@0: if (state->policyMapping > 0) { andre@0: state->policyMapping--; andre@0: } andre@0: if (state->inhibitAnyPolicy > 0) { andre@0: state->inhibitAnyPolicy--; andre@0: } andre@0: } andre@0: andre@0: /* Section 6.1.4(i) */ andre@0: PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy andre@0: (cert, &explicitPolicySkipCerts, plContext), andre@0: PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); andre@0: andre@0: if (explicitPolicySkipCerts != -1) { andre@0: if (((PKIX_UInt32)explicitPolicySkipCerts) < andre@0: (state->explicitPolicy)) { andre@0: state->explicitPolicy = andre@0: ((PKIX_UInt32) explicitPolicySkipCerts); andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited andre@0: (cert, &inhibitMappingSkipCerts, plContext), andre@0: PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); andre@0: andre@0: if (inhibitMappingSkipCerts != -1) { andre@0: if (((PKIX_UInt32)inhibitMappingSkipCerts) < andre@0: (state->policyMapping)) { andre@0: state->policyMapping = andre@0: ((PKIX_UInt32)inhibitMappingSkipCerts); andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy andre@0: (cert, &inhibitAnyPolicySkipCerts, plContext), andre@0: PKIX_CERTGETINHIBITANYPOLICYFAILED); andre@0: andre@0: if (inhibitAnyPolicySkipCerts != -1) { andre@0: if (((PKIX_UInt32)inhibitAnyPolicySkipCerts) < andre@0: (state->inhibitAnyPolicy)) { andre@0: state->inhibitAnyPolicy = andre@0: ((PKIX_UInt32)inhibitAnyPolicySkipCerts); andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache andre@0: ((PKIX_PL_Object *)state, plContext), andre@0: PKIX_OBJECTINVALIDATECACHEFAILED); andre@0: andre@0: } else { /* If this was the last certificate, do wrap-up processing */ andre@0: andre@0: /* Section 6.1.5 */ andre@0: subroutineErr = pkix_PolicyChecker_WrapUpProcessing andre@0: (cert, state, plContext); andre@0: if (subroutineErr) { andre@0: goto subrErrorCleanup; andre@0: } andre@0: andre@0: if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) { andre@0: PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); andre@0: } andre@0: andre@0: PKIX_DECREF(state->anyPolicyNodeAtBottom); andre@0: PKIX_DECREF(state->newAnyPolicyNode); andre@0: } andre@0: andre@0: andre@0: if (subroutineErr) { andre@0: andre@0: subrErrorCleanup: andre@0: /* We had an error. Was it a fatal error? */ andre@0: pkixErrorClass = subroutineErr->errClass; andre@0: if (pkixErrorClass == PKIX_FATAL_ERROR) { andre@0: pkixErrorResult = subroutineErr; andre@0: subroutineErr = NULL; andre@0: goto cleanup; andre@0: } andre@0: /* andre@0: * Abort policy processing, and then determine whether andre@0: * we can continue without policy processing. andre@0: */ andre@0: PKIX_DECREF(state->validPolicyTree); andre@0: PKIX_DECREF(state->anyPolicyNodeAtBottom); andre@0: PKIX_DECREF(state->newAnyPolicyNode); andre@0: if (state->explicitPolicy == 0) { andre@0: PKIX_ERROR andre@0: (PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION); andre@0: } andre@0: } andre@0: andre@0: /* Checking is complete. Save state for the next certificate. */ andre@0: PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState andre@0: (checker, (PKIX_PL_Object *)state, plContext), andre@0: PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); andre@0: andre@0: cleanup: andre@0: andre@0: #if PKIX_CERTPOLICYCHECKERSTATEDEBUG andre@0: if (cert) { andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object*)cert, &certString, plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (certString, andre@0: PKIX_ESCASCII, andre@0: (void **)&certAscii, andre@0: &length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: PKIX_DEBUG_ARG("Cert was %s\n", certAscii); andre@0: PKIX_FREE(certAscii); andre@0: PKIX_DECREF(certString); andre@0: } andre@0: if (state) { andre@0: PKIX_CHECK(PKIX_PL_Object_ToString andre@0: ((PKIX_PL_Object*)state, &stateString, plContext), andre@0: PKIX_OBJECTTOSTRINGFAILED); andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (stateString, andre@0: PKIX_ESCASCII, andre@0: (void **)&stateAscii, andre@0: &length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: PKIX_DEBUG_ARG("On exit %s\n", stateAscii); andre@0: PKIX_FREE(stateAscii); andre@0: PKIX_DECREF(stateString); andre@0: } andre@0: #endif andre@0: andre@0: PKIX_DECREF(state); andre@0: PKIX_DECREF(certPolicyInfos); andre@0: PKIX_DECREF(policy); andre@0: PKIX_DECREF(qualsOfAny); andre@0: PKIX_DECREF(policyQualifiers); andre@0: PKIX_DECREF(policyOID); andre@0: PKIX_DECREF(subroutineErr); andre@0: PKIX_DECREF(policyMaps); andre@0: PKIX_DECREF(mappedPolicies); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_PolicyChecker_Initialize andre@0: * DESCRIPTION: andre@0: * andre@0: * Creates and initializes a PolicyChecker, using the List pointed to andre@0: * by "initialPolicies" for the user-initial-policy-set, the Boolean value andre@0: * of "policyQualifiersRejected" for the policyQualifiersRejected parameter, andre@0: * the Boolean value of "initialPolicyMappingInhibit" for the andre@0: * inhibitPolicyMappings parameter, the Boolean value of andre@0: * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the andre@0: * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy andre@0: * parameter, and the UInt32 value of "numCerts" as the number of andre@0: * certificates in the chain; and stores the Checker at "pChecker". andre@0: * andre@0: * PARAMETERS: andre@0: * "initialPolicies" andre@0: * Address of List of OIDs comprising the user-initial-policy-set; the List andre@0: * may be empty or NULL andre@0: * "policyQualifiersRejected" andre@0: * Boolean value of the policyQualifiersRejected parameter andre@0: * "initialPolicyMappingInhibit" andre@0: * Boolean value of the inhibitPolicyMappings parameter andre@0: * "initialExplicitPolicy" andre@0: * Boolean value of the initialExplicitPolicy parameter andre@0: * "initialAnyPolicyInhibit" andre@0: * Boolean value of the inhibitAnyPolicy parameter andre@0: * "numCerts" andre@0: * Number of certificates in the chain to be validated andre@0: * "pChecker" andre@0: * Address to store the created PolicyChecker. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds andre@0: * Returns a CertChainChecker Error if the functions fails in a non-fatal way andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way andre@0: */ andre@0: PKIX_Error * andre@0: pkix_PolicyChecker_Initialize( andre@0: PKIX_List *initialPolicies, andre@0: PKIX_Boolean policyQualifiersRejected, andre@0: PKIX_Boolean initialPolicyMappingInhibit, andre@0: PKIX_Boolean initialExplicitPolicy, andre@0: PKIX_Boolean initialAnyPolicyInhibit, andre@0: PKIX_UInt32 numCerts, andre@0: PKIX_CertChainChecker **pChecker, andre@0: void *plContext) andre@0: { andre@0: PKIX_PolicyCheckerState *polCheckerState = NULL; andre@0: PKIX_List *policyExtensions = NULL; /* OIDs */ andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Initialize"); andre@0: PKIX_NULLCHECK_ONE(pChecker); andre@0: andre@0: PKIX_CHECK(pkix_PolicyCheckerState_Create andre@0: (initialPolicies, andre@0: policyQualifiersRejected, andre@0: initialPolicyMappingInhibit, andre@0: initialExplicitPolicy, andre@0: initialAnyPolicyInhibit, andre@0: numCerts, andre@0: &polCheckerState, andre@0: plContext), andre@0: PKIX_POLICYCHECKERSTATECREATEFAILED); andre@0: andre@0: /* Create the list of extensions that we handle */ andre@0: PKIX_CHECK(pkix_PolicyChecker_MakeSingleton andre@0: ((PKIX_PL_Object *)(polCheckerState->certPoliciesExtension), andre@0: PKIX_TRUE, andre@0: &policyExtensions, andre@0: plContext), andre@0: PKIX_POLICYCHECKERMAKESINGLETONFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_CertChainChecker_Create andre@0: (pkix_PolicyChecker_Check, andre@0: PKIX_FALSE, /* forwardCheckingSupported */ andre@0: PKIX_FALSE, andre@0: policyExtensions, andre@0: (PKIX_PL_Object *)polCheckerState, andre@0: pChecker, andre@0: plContext), andre@0: PKIX_CERTCHAINCHECKERCREATEFAILED); andre@0: andre@0: cleanup: andre@0: PKIX_DECREF(polCheckerState); andre@0: PKIX_DECREF(policyExtensions); andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: andre@0: }