diff options
Diffstat (limited to 'security/nss/lib/libpkix/pkix/results')
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/Makefile | 46 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/exports.gyp | 28 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/manifest.mn | 24 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_buildresult.c | 362 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_buildresult.h | 40 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_policynode.c | 1377 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_policynode.h | 74 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_valresult.c | 442 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_valresult.h | 43 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_verifynode.c | 1182 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/pkix_verifynode.h | 75 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/results/results.gyp | 26 |
12 files changed, 3719 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/results/Makefile b/security/nss/lib/libpkix/pkix/results/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/Makefile @@ -0,0 +1,46 @@ +#! gmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + + diff --git a/security/nss/lib/libpkix/pkix/results/exports.gyp b/security/nss/lib/libpkix/pkix/results/exports.gyp new file mode 100644 index 0000000000..dfff689033 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/exports.gyp @@ -0,0 +1,28 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'lib_libpkix_pkix_results_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_buildresult.h', + 'pkix_policynode.h', + 'pkix_valresult.h', + 'pkix_verifynode.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/results/manifest.mn b/security/nss/lib/libpkix/pkix/results/manifest.mn new file mode 100644 index 0000000000..bec0270fb6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/manifest.mn @@ -0,0 +1,24 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +CORE_DEPTH = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_buildresult.h \ + pkix_policynode.h \ + pkix_valresult.h \ + pkix_verifynode.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_buildresult.c \ + pkix_policynode.c \ + pkix_valresult.c \ + pkix_verifynode.c \ + $(NULL) + +LIBRARY_NAME = pkixresults +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c new file mode 100644 index 0000000000..7d35119bcb --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c @@ -0,0 +1,362 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_buildresult.c + * + * BuildResult Object Functions + * + */ + +#include "pkix_buildresult.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_BuildResult_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_BuildResult *result = NULL; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a build result object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_OBJECTNOTBUILDRESULT); + + result = (PKIX_BuildResult *)object; + + PKIX_DECREF(result->valResult); + PKIX_DECREF(result->certChain); + +cleanup: + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_BuildResult *firstBuildResult = NULL; + PKIX_BuildResult *secondBuildResult = NULL; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_FIRSTOBJECTNOTBUILDRESULT); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_BUILDRESULT_TYPE) goto cleanup; + + firstBuildResult = (PKIX_BuildResult *)first; + secondBuildResult = (PKIX_BuildResult *)second; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstBuildResult->valResult, + (PKIX_PL_Object *)secondBuildResult->valResult, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstBuildResult->certChain, + (PKIX_PL_Object *)secondBuildResult->certChain, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + /* + * The remaining case is that both are null, + * which we consider equality. + * cmpResult = PKIX_TRUE; + */ + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_BuildResult *buildResult = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 valResultHash = 0; + PKIX_UInt32 certChainHash = 0; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_OBJECTNOTBUILDRESULT); + + buildResult = (PKIX_BuildResult*)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)buildResult->valResult, + &valResultHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)buildResult->certChain, + &certChainHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + hash = 31*(31 * valResultHash + certChainHash); + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_BuildResult_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_BuildResult *buildResult = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *buildResultString = NULL; + + PKIX_ValidateResult *valResult = NULL; + PKIX_List *certChain = NULL; + + PKIX_PL_String *valResultString = NULL; + PKIX_PL_String *certChainString = NULL; + + char *asciiFormat = + "[\n" + "\tValidateResult: \t\t%s" + "\tCertChain: \t\t%s\n" + "]\n"; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext), + PKIX_OBJECTNOTBUILDRESULT); + + buildResult = (PKIX_BuildResult*)object; + + valResult = buildResult->valResult; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)valResult, &valResultString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + certChain = buildResult->certChain; + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)certChain, &certChainString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&buildResultString, + plContext, + formatString, + valResultString, + certChainString), + PKIX_SPRINTFFAILED); + + *pString = buildResultString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(valResultString); + PKIX_DECREF(certChainString); + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_RegisterSelf + * DESCRIPTION: + * Registers PKIX_BUILDRESULT_TYPE and its related functions with + * systemClasses[] + * THREAD SAFETY: + * Not Thread Safe - for performance and complexity reasons + * + * Since this function is only called by PKIX_PL_Initialize, which should + * only be called once, it is acceptable that this function is not + * thread-safe. + */ +PKIX_Error * +pkix_BuildResult_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_RegisterSelf"); + + entry.description = "BuildResult"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_BuildResult); + entry.destructor = pkix_BuildResult_Destroy; + entry.equalsFunction = pkix_BuildResult_Equals; + entry.hashcodeFunction = pkix_BuildResult_Hashcode; + entry.toStringFunction = pkix_BuildResult_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_BUILDRESULT_TYPE] = entry; + + PKIX_RETURN(BUILDRESULT); +} + +/* + * FUNCTION: pkix_BuildResult_Create + * DESCRIPTION: + * + * Creates a new BuildResult Object using the ValidateResult pointed to by + * "valResult" and the List pointed to by "certChain", and stores it at + * "pResult". + * + * PARAMETERS + * "valResult" + * Address of ValidateResult component. Must be non-NULL. + * "certChain + * Address of List component. Must be non-NULL. + * "pResult" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_BuildResult_Create( + PKIX_ValidateResult *valResult, + PKIX_List *certChain, + PKIX_BuildResult **pResult, + void *plContext) +{ + PKIX_BuildResult *result = NULL; + + PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Create"); + PKIX_NULLCHECK_THREE(valResult, certChain, pResult); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_BUILDRESULT_TYPE, + sizeof (PKIX_BuildResult), + (PKIX_PL_Object **)&result, + plContext), + PKIX_COULDNOTCREATEBUILDRESULTOBJECT); + + /* initialize fields */ + + PKIX_INCREF(valResult); + result->valResult = valResult; + + PKIX_INCREF(certChain); + result->certChain = certChain; + + PKIX_CHECK(PKIX_List_SetImmutable(result->certChain, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pResult = result; + result = NULL; + +cleanup: + + PKIX_DECREF(result); + + PKIX_RETURN(BUILDRESULT); + +} + +/* --Public-Functions--------------------------------------------- */ + + +/* + * FUNCTION: PKIX_BuildResult_GetValidateResult + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_BuildResult_GetValidateResult( + PKIX_BuildResult *result, + PKIX_ValidateResult **pResult, + void *plContext) +{ + PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetValidateResult"); + PKIX_NULLCHECK_TWO(result, pResult); + + PKIX_INCREF(result->valResult); + *pResult = result->valResult; + +cleanup: + PKIX_RETURN(BUILDRESULT); +} + + + +/* + * FUNCTION: PKIX_BuildResult_GetCertChain + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_BuildResult_GetCertChain( + PKIX_BuildResult *result, + PKIX_List **pChain, + void *plContext) +{ + PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetCertChain"); + PKIX_NULLCHECK_TWO(result, pChain); + + PKIX_INCREF(result->certChain); + *pChain = result->certChain; + +cleanup: + PKIX_RETURN(BUILDRESULT); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h new file mode 100644 index 0000000000..b43f12ba14 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_buildresult.h + * + * BuildResult Object Type Definition + * + */ + +#ifndef _PKIX_BUILDRESULT_H +#define _PKIX_BUILDRESULT_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_BuildResultStruct { + PKIX_ValidateResult *valResult; + PKIX_List *certChain; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_BuildResult_Create( + PKIX_ValidateResult *valResult, + PKIX_List *certChain, + PKIX_BuildResult **pResult, + void *plContext); + +PKIX_Error *pkix_BuildResult_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_BUILDRESULT_H */ diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.c b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c new file mode 100644 index 0000000000..fd8cee982b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c @@ -0,0 +1,1377 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_policynode.c + * + * Policy Node Object Type Definition + * + */ + +#include "pkix_policynode.h" + +/* --Private-PolicyNode-Functions---------------------------------- */ + +/* + * FUNCTION: pkix_PolicyNode_GetChildrenMutable + * DESCRIPTION: + * + * Retrieves the List of PolicyNodes representing the child nodes of the + * Policy Node pointed to by "node" and stores it at "pChildren". If "node" + * has no List of child nodes, this function stores NULL at "pChildren". + * + * Note that the List returned by this function may be mutable. This function + * differs from the public function PKIX_PolicyNode_GetChildren in that + * respect. (It also differs in that the public function creates an empty + * List, if necessary, rather than storing NULL.) + * + * During certificate processing, children Lists are created and modified. + * Once the list is accessed using the public call, the List is set immutable. + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose child nodes are to be stored. + * Must be non-NULL. + * "pChildren" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_PolicyNode_GetChildrenMutable( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* list of PKIX_PolicyNode */ + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_GetChildrenMutable"); + + PKIX_NULLCHECK_TWO(node, pChildren); + + PKIX_INCREF(node->children); + + *pChildren = node->children; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Create + * DESCRIPTION: + * + * Creates a new PolicyNode using the OID pointed to by "validPolicy", the List + * of CertPolicyQualifiers pointed to by "qualifierSet", the criticality + * indicated by the Boolean value of "criticality", and the List of OIDs + * pointed to by "expectedPolicySet", and stores the result at "pObject". The + * criticality should be derived from whether the certificate policy extension + * was marked as critical in the certificate that led to creation of this + * PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made + * immutable. The PolicyNode pointers to parent and to children are initialized + * to NULL, and the depth is set to zero; those values should be set by using + * the pkix_PolicyNode_AddToParent function. + * + * PARAMETERS + * "validPolicy" + * Address of OID of the valid policy for the path. Must be non-NULL + * "qualifierSet" + * Address of List of CertPolicyQualifiers associated with the validpolicy. + * May be NULL + * "criticality" + * Boolean indicator of whether the criticality should be set in this + * PolicyNode + * "expectedPolicySet" + * Address of List of OIDs that would satisfy this policy in the next + * certificate. Must be non-NULL + * "pObject" + * Address where the PolicyNode pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_PolicyNode_Create( + PKIX_PL_OID *validPolicy, + PKIX_List *qualifierSet, + PKIX_Boolean criticality, + PKIX_List *expectedPolicySet, + PKIX_PolicyNode **pObject, + void *plContext) +{ + PKIX_PolicyNode *node = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Create"); + + PKIX_NULLCHECK_THREE(validPolicy, expectedPolicySet, pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTPOLICYNODE_TYPE, + sizeof (PKIX_PolicyNode), + (PKIX_PL_Object **)&node, + plContext), + PKIX_COULDNOTCREATEPOLICYNODEOBJECT); + + PKIX_INCREF(validPolicy); + node->validPolicy = validPolicy; + + PKIX_INCREF(qualifierSet); + node->qualifierSet = qualifierSet; + if (qualifierSet) { + PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + } + + node->criticality = criticality; + + PKIX_INCREF(expectedPolicySet); + node->expectedPolicySet = expectedPolicySet; + PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + node->parent = NULL; + node->children = NULL; + node->depth = 0; + + *pObject = node; + node = NULL; + +cleanup: + + PKIX_DECREF(node); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_AddToParent + * DESCRIPTION: + * + * Adds the PolicyNode pointed to by "child" to the List of children of + * the PolicyNode pointed to by "parentNode". If "parentNode" had a + * NULL pointer for the List of children, a new List is created containing + * "child". Otherwise "child" is appended to the existing List. The + * parent field in "child" is set to "parent", and the depth field is + * set to one more than the corresponding value in "parent". + * + * Depth, in this context, means distance from the root node, which + * is at depth zero. + * + * PARAMETERS: + * "parentNode" + * Address of PolicyNode whose List of child PolicyNodes is to be + * created or appended to. Must be non-NULL. + * "child" + * Address of PolicyNode to be added to parentNode's List. Must be + * non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_PolicyNode_AddToParent( + PKIX_PolicyNode *parentNode, + PKIX_PolicyNode *child, + void *plContext) +{ + PKIX_List *listOfChildren = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_AddToParent"); + + PKIX_NULLCHECK_TWO(parentNode, child); + + listOfChildren = parentNode->children; + if (listOfChildren == NULL) { + PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), + PKIX_LISTCREATEFAILED); + parentNode->children = listOfChildren; + } + + /* + * Note: this link is not reference-counted. The link from parent + * to child is counted (actually, the parent "owns" a List which + * "owns" children), but the children do not "own" the parent. + * Otherwise, there would be loops. + */ + child->parent = parentNode; + + child->depth = 1 + (parentNode->depth); + + PKIX_CHECK(PKIX_List_AppendItem + (listOfChildren, (PKIX_PL_Object *)child, plContext), + PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)parentNode, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)child, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Prune + * DESCRIPTION: + * + * Prunes a tree below the PolicyNode whose address is pointed to by "node", + * using the UInt32 value of "height" as the distance from the leaf level, + * and storing at "pDelete" the Boolean value of whether this PolicyNode is, + * after pruning, childless and should be pruned. + * + * Any PolicyNode at height 0 is allowed to survive. If the height is greater + * than zero, pkix_PolicyNode_Prune is called recursively for each child of + * the current PolicyNode. After this process, a node with no children + * stores PKIX_TRUE in "pDelete" to indicate that it should be deleted. + * + * PARAMETERS: + * "node" + * Address of the PolicyNode to be pruned. Must be non-NULL. + * "height" + * UInt32 value for the distance from the leaf level + * "pDelete" + * Address to store the Boolean return value of PKIX_TRUE if this node + * should be pruned, or PKIX_FALSE if there remains at least one + * branch of the required height. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_PolicyNode_Prune( + PKIX_PolicyNode *node, + PKIX_UInt32 height, + PKIX_Boolean *pDelete, + void *plContext) +{ + PKIX_Boolean childless = PKIX_FALSE; + PKIX_Boolean shouldBePruned = PKIX_FALSE; + PKIX_UInt32 listSize = 0; + PKIX_UInt32 listIndex = 0; + PKIX_PolicyNode *candidate = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Prune"); + + PKIX_NULLCHECK_TWO(node, pDelete); + + /* Don't prune at the leaf */ + if (height == 0) { + goto cleanup; + } + + /* Above the bottom level, childless nodes get pruned */ + if (!(node->children)) { + childless = PKIX_TRUE; + goto cleanup; + } + + /* + * This node has children. If they are leaf nodes, + * we know they will live. Otherwise, check them out. + */ + if (height > 1) { + PKIX_CHECK(PKIX_List_GetLength + (node->children, &listSize, plContext), + PKIX_LISTGETLENGTHFAILED); + /* + * By working backwards from the end of the list, + * we avoid having to worry about possible + * decreases in the size of the list, as we + * delete items. The only nuisance is that since the + * index is UInt32, we can't check for it to reach -1; + * we have to use the 1-based index, rather than the + * 0-based index that PKIX_List functions require. + */ + for (listIndex = listSize; listIndex > 0; listIndex--) { + PKIX_CHECK(PKIX_List_GetItem + (node->children, + (listIndex - 1), + (PKIX_PL_Object **)&candidate, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyNode_Prune + (candidate, + height - 1, + &shouldBePruned, + plContext), + PKIX_POLICYNODEPRUNEFAILED); + + if (shouldBePruned == PKIX_TRUE) { + PKIX_CHECK(PKIX_List_DeleteItem + (node->children, + (listIndex - 1), + plContext), + PKIX_LISTDELETEITEMFAILED); + } + + PKIX_DECREF(candidate); + } + } + + /* Prune if this node has *become* childless */ + PKIX_CHECK(PKIX_List_GetLength + (node->children, &listSize, plContext), + PKIX_LISTGETLENGTHFAILED); + if (listSize == 0) { + childless = PKIX_TRUE; + } + + /* + * Even if we did not change this node, or any of its children, + * maybe a [great-]*grandchild was pruned. + */ + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)node, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + *pDelete = childless; + + PKIX_DECREF(candidate); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_SinglePolicyNode_ToString + * DESCRIPTION: + * + * Creates a String representation of the attributes of the PolicyNode + * pointed to by "node", other than its parents or children, and + * stores the result at "pString". + * + * PARAMETERS: + * "node" + * Address of PolicyNode to be described by the string. Must be non-NULL. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +PKIX_Error * +pkix_SinglePolicyNode_ToString( + PKIX_PolicyNode *node, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *fmtString = NULL; + PKIX_PL_String *validString = NULL; + PKIX_PL_String *qualifierString = NULL; + PKIX_PL_String *criticalityString = NULL; + PKIX_PL_String *expectedString = NULL; + PKIX_PL_String *outString = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_ToString"); + PKIX_NULLCHECK_TWO(node, pString); + PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "{%s,%s,%s,%s,%d}", + 0, + &fmtString, + plContext), + PKIX_CANTCREATESTRING); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)(node->validPolicy), + &validString, + plContext), + PKIX_OIDTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)(node->expectedPolicySet), + &expectedString, + plContext), + PKIX_LISTTOSTRINGFAILED); + + if (node->qualifierSet) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)(node->qualifierSet), + &qualifierString, + plContext), + PKIX_LISTTOSTRINGFAILED); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "{}", + 0, + &qualifierString, + plContext), + PKIX_CANTCREATESTRING); + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (node->criticality)?"Critical":"Not Critical", + 0, + &criticalityString, + plContext), + PKIX_CANTCREATESTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, + plContext, + fmtString, + validString, + qualifierString, + criticalityString, + expectedString, + node->depth), + PKIX_SPRINTFFAILED); + + *pString = outString; + +cleanup: + + PKIX_DECREF(fmtString); + PKIX_DECREF(validString); + PKIX_DECREF(qualifierString); + PKIX_DECREF(criticalityString); + PKIX_DECREF(expectedString); + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_ToString_Helper + * DESCRIPTION: + * + * Produces a String representation of a PolicyNode tree below the PolicyNode + * pointed to by "rootNode", with each line of output prefixed by the String + * pointed to by "indent", and stores the result at "pTreeString". It is + * called recursively, with ever-increasing indentation, for successively + * lower nodes on the tree. + * + * PARAMETERS: + * "rootNode" + * Address of PolicyNode subtree. Must be non-NULL. + * "indent" + * Address of String to be prefixed to each line of output. May be NULL + * if no indentation is desired + * "pTreeString" + * Address where the resulting String will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_PolicyNode_ToString_Helper( + PKIX_PolicyNode *rootNode, + PKIX_PL_String *indent, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_PL_String *nextIndentFormat = NULL; + PKIX_PL_String *thisNodeFormat = NULL; + PKIX_PL_String *childrenFormat = NULL; + PKIX_PL_String *nextIndentString = NULL; + PKIX_PL_String *resultString = NULL; + PKIX_PL_String *thisItemString = NULL; + PKIX_PL_String *childString = NULL; + PKIX_PolicyNode *childNode = NULL; + PKIX_UInt32 numberOfChildren = 0; + PKIX_UInt32 childIndex = 0; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString_Helper"); + + PKIX_NULLCHECK_TWO(rootNode, pTreeString); + + /* Create a string for this node */ + PKIX_CHECK(pkix_SinglePolicyNode_ToString + (rootNode, &thisItemString, plContext), + PKIX_ERRORINSINGLEPOLICYNODETOSTRING); + + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + indent, + thisItemString), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + thisItemString), + PKIX_ERRORINSPRINTF); + } + + PKIX_DECREF(thisItemString); + thisItemString = resultString; + + /* if no children, we are done */ + if (rootNode->children) { + PKIX_CHECK(PKIX_List_GetLength + (rootNode->children, &numberOfChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + if (numberOfChildren != 0) { + /* + * We create a string for each child in turn, + * concatenating them to thisItemString. + */ + + /* Prepare an indent string for each child */ + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s. ", + 0, + &nextIndentFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&nextIndentString, + plContext, + nextIndentFormat, + indent), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + ". ", + 0, + &nextIndentString, + plContext), + PKIX_ERRORCREATINGINDENTSTRING); + } + + /* Prepare the format for concatenation. */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s\n%s", + 0, + &childrenFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + for (childIndex = 0; + childIndex < numberOfChildren; + childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (rootNode->children, + childIndex, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyNode_ToString_Helper + (childNode, + nextIndentString, + &childString, + plContext), + PKIX_ERRORCREATINGCHILDSTRING); + + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + childrenFormat, + thisItemString, + childString), + PKIX_ERRORINSPRINTF); + + PKIX_DECREF(childNode); + PKIX_DECREF(childString); + PKIX_DECREF(thisItemString); + + thisItemString = resultString; + } + } + + *pTreeString = thisItemString; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(thisItemString); + } + + PKIX_DECREF(nextIndentFormat); + PKIX_DECREF(thisNodeFormat); + PKIX_DECREF(childrenFormat); + PKIX_DECREF(nextIndentString); + PKIX_DECREF(childString); + PKIX_DECREF(childNode); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_PolicyNode *rootNode = NULL; + PKIX_PL_String *resultString = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString"); + + PKIX_NULLCHECK_TWO(object, pTreeString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + rootNode = (PKIX_PolicyNode *)object; + + PKIX_CHECK(pkix_PolicyNode_ToString_Helper + (rootNode, NULL, &resultString, plContext), + PKIX_ERRORCREATINGSUBTREESTRING); + + *pTreeString = resultString; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PolicyNode *node = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + node = (PKIX_PolicyNode*)object; + + node->criticality = PKIX_FALSE; + PKIX_DECREF(node->validPolicy); + PKIX_DECREF(node->qualifierSet); + PKIX_DECREF(node->expectedPolicySet); + PKIX_DECREF(node->children); + + /* + * Note: the link to parent is not reference-counted. See comment + * in pkix_PolicyNode_AddToParent for more details. + */ + node->parent = NULL; + node->depth = 0; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_SinglePolicyNode_Hashcode + * DESCRIPTION: + * + * Computes the hashcode of the attributes of the PolicyNode pointed to by + * "node", other than its parents and children, and stores the result at + * "pHashcode". + * + * PARAMETERS: + * "node" + * Address of PolicyNode to be hashcoded; must be non-NULL + * "pHashcode" + * Address where UInt32 result will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SinglePolicyNode_Hashcode( + PKIX_PolicyNode *node, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 componentHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Hashcode"); + PKIX_NULLCHECK_TWO(node, pHashcode); + PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet); + + PKIX_HASHCODE + (node->qualifierSet, + &nodeHash, + plContext, + PKIX_FAILUREHASHINGLISTQUALIFIERSET); + + if (PKIX_TRUE == (node->criticality)) { + nodeHash = 31*nodeHash + 0xff; + } else { + nodeHash = 31*nodeHash + 0x00; + } + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)node->validPolicy, + &componentHash, + plContext), + PKIX_FAILUREHASHINGOIDVALIDPOLICY); + + nodeHash = 31*nodeHash + componentHash; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)node->expectedPolicySet, + &componentHash, + plContext), + PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET); + + nodeHash = 31*nodeHash + componentHash; + + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PolicyNode *node = NULL; + PKIX_UInt32 childrenHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + node = (PKIX_PolicyNode *)object; + + PKIX_CHECK(pkix_SinglePolicyNode_Hashcode + (node, &nodeHash, plContext), + PKIX_SINGLEPOLICYNODEHASHCODEFAILED); + + nodeHash = 31*nodeHash + (PKIX_UInt32)((char *)node->parent - (char *)NULL); + + PKIX_HASHCODE + (node->children, + &childrenHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + nodeHash = 31*nodeHash + childrenHash; + + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_SinglePolicyNode_Equals + * DESCRIPTION: + * + * Compares for equality the components of the PolicyNode pointed to by + * "firstPN", other than its parents and children, with those of the + * PolicyNode pointed to by "secondPN" and stores the result at "pResult" + * (PKIX_TRUE if equal; PKIX_FALSE if not). + * + * PARAMETERS: + * "firstPN" + * Address of first of the PolicyNodes to be compared; must be non-NULL + * "secondPN" + * Address of second of the PolicyNodes to be compared; must be non-NULL + * "pResult" + * Address where Boolean will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SinglePolicyNode_Equals( + PKIX_PolicyNode *firstPN, + PKIX_PolicyNode *secondPN, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Equals"); + PKIX_NULLCHECK_THREE(firstPN, secondPN, pResult); + + /* If both references are identical, they must be equal */ + if (firstPN == secondPN) { + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * It seems we have to do the comparisons. Do + * the easiest ones first. + */ + if ((firstPN->criticality) != (secondPN->criticality)) { + goto cleanup; + } + if ((firstPN->depth) != (secondPN->depth)) { + goto cleanup; + } + + PKIX_EQUALS + (firstPN->qualifierSet, + secondPN->qualifierSet, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + /* These fields must be non-NULL */ + PKIX_NULLCHECK_TWO(firstPN->validPolicy, secondPN->validPolicy); + + PKIX_EQUALS + (firstPN->validPolicy, + secondPN->validPolicy, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + /* These fields must be non-NULL */ + PKIX_NULLCHECK_TWO + (firstPN->expectedPolicySet, secondPN->expectedPolicySet); + + PKIX_EQUALS + (firstPN->expectedPolicySet, + secondPN->expectedPolicySet, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PolicyNode *firstPN = NULL; + PKIX_PolicyNode *secondPN = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a PolicyNode */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_FIRSTOBJECTNOTPOLICYNODE); + + /* + * Since we know firstObject is a PolicyNode, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a PolicyNode, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_CERTPOLICYNODE_TYPE) { + goto cleanup; + } + + /* + * Oh, well, we have to do the comparisons. Do + * the easiest ones first. + */ + firstPN = (PKIX_PolicyNode *)firstObject; + secondPN = (PKIX_PolicyNode *)secondObject; + + /* + * We don't require the parents to be identical. In the + * course of traversing the tree, we will have checked the + * attributes of the parent nodes, and checking the lists + * of children will determine whether they match. + */ + + PKIX_EQUALS + (firstPN->children, + secondPN->children, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILEDONCHILDREN); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + PKIX_CHECK(pkix_SinglePolicyNode_Equals + (firstPN, secondPN, &compResult, plContext), + PKIX_SINGLEPOLICYNODEEQUALSFAILED); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_DuplicateHelper + * DESCRIPTION: + * + * Duplicates the PolicyNode whose address is pointed to by "original", + * and stores the result at "pNewNode", if a non-NULL pointer is provided + * for "pNewNode". In addition, the created PolicyNode is added as a child + * to "parent", if a non-NULL pointer is provided for "parent". Then this + * function is called recursively to duplicate each of the children of + * "original". At the top level this function is called with a null + * "parent" and a non-NULL "pNewNode". Below the top level "parent" will + * be non-NULL and "pNewNode" will be NULL. + * + * PARAMETERS: + * "original" + * Address of PolicyNode to be copied; must be non-NULL + * "parent" + * Address of PolicyNode to which the created node is to be added as a + * child; NULL for the top-level call and non-NULL below the top level + * "pNewNode" + * Address to store the node created; should be NULL if "parent" is + * non-NULL and vice versa + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a PolicyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_PolicyNode_DuplicateHelper( + PKIX_PolicyNode *original, + PKIX_PolicyNode *parent, + PKIX_PolicyNode **pNewNode, + void *plContext) +{ + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIndex = 0; + PKIX_List *children = NULL; /* List of PKIX_PolicyNode */ + PKIX_PolicyNode *copy = NULL; + PKIX_PolicyNode *child = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper"); + + PKIX_NULLCHECK_THREE + (original, original->validPolicy, original->expectedPolicySet); + + /* + * These components are immutable, so copying the pointers + * is sufficient. The create function increments the reference + * counts as it stores the pointers into the new object. + */ + PKIX_CHECK(pkix_PolicyNode_Create + (original->validPolicy, + original->qualifierSet, + original->criticality, + original->expectedPolicySet, + ©, + plContext), + PKIX_POLICYNODECREATEFAILED); + + if (parent) { + PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext), + PKIX_POLICYNODEADDTOPARENTFAILED); + } + + /* Are there any children to duplicate? */ + children = original->children; + + if (children) { + PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (childIndex = 0; childIndex < numChildren; childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (children, + childIndex, + (PKIX_PL_Object **)&child, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_PolicyNode_DuplicateHelper + (child, copy, NULL, plContext), + PKIX_POLICYNODEDUPLICATEHELPERFAILED); + + PKIX_DECREF(child); + } + + if (pNewNode) { + *pNewNode = copy; + copy = NULL; /* no DecRef if we give our handle away */ + } + +cleanup: + PKIX_DECREF(copy); + PKIX_DECREF(child); + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_PolicyNode_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_PolicyNode *original = NULL; + PKIX_PolicyNode *copy = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate"); + + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYNODE_TYPE, plContext), + PKIX_OBJECTNOTPOLICYNODE); + + original = (PKIX_PolicyNode *)object; + + PKIX_CHECK(pkix_PolicyNode_DuplicateHelper + (original, NULL, ©, plContext), + PKIX_POLICYNODEDUPLICATEHELPERFAILED); + + *pNewObject = (PKIX_PL_Object *)copy; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: pkix_PolicyNode_RegisterSelf + * DESCRIPTION: + * + * Registers PKIX_CERTPOLICYNODE_TYPE and its related + * functions with systemClasses[] + * + * THREAD SAFETY: + * Not Thread Safe - for performance and complexity reasons + * + * Since this function is only called by PKIX_PL_Initialize, + * which should only be called once, it is acceptable that + * this function is not thread-safe. + */ +PKIX_Error * +pkix_PolicyNode_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_RegisterSelf"); + + entry.description = "PolicyNode"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PolicyNode); + entry.destructor = pkix_PolicyNode_Destroy; + entry.equalsFunction = pkix_PolicyNode_Equals; + entry.hashcodeFunction = pkix_PolicyNode_Hashcode; + entry.toStringFunction = pkix_PolicyNode_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_PolicyNode_Duplicate; + + systemClasses[PKIX_CERTPOLICYNODE_TYPE] = entry; + + PKIX_RETURN(CERTPOLICYNODE); +} + + +/* --Public-PolicyNode-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_PolicyNode_GetChildren + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetChildren( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* list of PKIX_PolicyNode */ + void *plContext) +{ + PKIX_List *children = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetChildren"); + + PKIX_NULLCHECK_TWO(node, pChildren); + + PKIX_INCREF(node->children); + children = node->children; + + if (!children) { + PKIX_CHECK(PKIX_List_Create(&children, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_SetImmutable(children, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pChildren = children; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(children); + } + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetParent + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetParent( + PKIX_PolicyNode *node, + PKIX_PolicyNode **pParent, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetParent"); + + PKIX_NULLCHECK_TWO(node, pParent); + + PKIX_INCREF(node->parent); + *pParent = node->parent; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetValidPolicy + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetValidPolicy( + PKIX_PolicyNode *node, + PKIX_PL_OID **pValidPolicy, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetValidPolicy"); + + PKIX_NULLCHECK_TWO(node, pValidPolicy); + + PKIX_INCREF(node->validPolicy); + *pValidPolicy = node->validPolicy; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetPolicyQualifiers( + PKIX_PolicyNode *node, + PKIX_List **pQualifiers, /* list of PKIX_PL_CertPolicyQualifier */ + void *plContext) +{ + PKIX_List *qualifiers = NULL; + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetPolicyQualifiers"); + + PKIX_NULLCHECK_TWO(node, pQualifiers); + + PKIX_INCREF(node->qualifierSet); + qualifiers = node->qualifierSet; + + if (!qualifiers) { + PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_SetImmutable(qualifiers, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pQualifiers = qualifiers; + +cleanup: + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetExpectedPolicies( + PKIX_PolicyNode *node, + PKIX_List **pExpPolicies, /* list of PKIX_PL_OID */ + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetExpectedPolicies"); + + PKIX_NULLCHECK_TWO(node, pExpPolicies); + + PKIX_INCREF(node->expectedPolicySet); + *pExpPolicies = node->expectedPolicySet; + +cleanup: + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_IsCritical + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_IsCritical( + PKIX_PolicyNode *node, + PKIX_Boolean *pCritical, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_IsCritical"); + + PKIX_NULLCHECK_TWO(node, pCritical); + + *pCritical = node->criticality; + + PKIX_RETURN(CERTPOLICYNODE); +} + +/* + * FUNCTION: PKIX_PolicyNode_GetDepth + * (see description of this function in pkix_results.h) + */ +PKIX_Error * +PKIX_PolicyNode_GetDepth( + PKIX_PolicyNode *node, + PKIX_UInt32 *pDepth, + void *plContext) +{ + + PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetDepth"); + + PKIX_NULLCHECK_TWO(node, pDepth); + + *pDepth = node->depth; + + PKIX_RETURN(CERTPOLICYNODE); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.h b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h new file mode 100644 index 0000000000..799b7a60aa --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h @@ -0,0 +1,74 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_policynode.h + * + * PolicyNode Type Definitions + * + */ + +#ifndef _PKIX_POLICYNODE_H +#define _PKIX_POLICYNODE_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This structure reflects the contents of a policy node... + */ +struct PKIX_PolicyNodeStruct { + PKIX_PL_OID *validPolicy; + PKIX_List *qualifierSet; /* CertPolicyQualifiers */ + PKIX_Boolean criticality; + PKIX_List *expectedPolicySet; /* OIDs */ + PKIX_PolicyNode *parent; + PKIX_List *children; /* PolicyNodes */ + PKIX_UInt32 depth; +}; + +PKIX_Error * +pkix_SinglePolicyNode_ToString( + PKIX_PolicyNode *node, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_GetChildrenMutable( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* PolicyNodes */ + void *plContext); + +PKIX_Error * +pkix_PolicyNode_Create( + PKIX_PL_OID *validPolicy, + PKIX_List *qualifierSet, /* CertPolicyQualifiers */ + PKIX_Boolean criticality, + PKIX_List *expectedPolicySet, /* OIDs */ + PKIX_PolicyNode **pObject, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_AddToParent( + PKIX_PolicyNode *parentNode, + PKIX_PolicyNode *child, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_Prune( + PKIX_PolicyNode *node, + PKIX_UInt32 depth, + PKIX_Boolean *pDelete, + void *plContext); + +PKIX_Error * +pkix_PolicyNode_RegisterSelf( + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_POLICYNODE_H */ diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.c b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c new file mode 100644 index 0000000000..25b69e59c3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c @@ -0,0 +1,442 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_valresult.c + * + * ValidateResult Object Functions + * + */ + +#include "pkix_valresult.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_ValidateResult_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ValidateResult *result = NULL; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a validate result object */ + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_OBJECTNOTVALIDATERESULT); + + result = (PKIX_ValidateResult *)object; + + PKIX_DECREF(result->anchor); + PKIX_DECREF(result->pubKey); + PKIX_DECREF(result->policyTree); + +cleanup: + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_ValidateResult *firstValResult = NULL; + PKIX_ValidateResult *secondValResult = NULL; + PKIX_TrustAnchor *firstAnchor = NULL; + PKIX_TrustAnchor *secondAnchor = NULL; + PKIX_PolicyNode *firstTree = NULL; + PKIX_PolicyNode *secondTree = NULL; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_FIRSTOBJECTNOTVALIDATERESULT); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_VALIDATERESULT_TYPE) goto cleanup; + + firstValResult = (PKIX_ValidateResult *)first; + secondValResult = (PKIX_ValidateResult *)second; + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstValResult->pubKey, + (PKIX_PL_Object *)secondValResult->pubKey, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + if (!cmpResult) goto cleanup; + + firstAnchor = firstValResult->anchor; + secondAnchor = secondValResult->anchor; + + if ((firstAnchor != NULL) && (secondAnchor != NULL)) { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstAnchor, + (PKIX_PL_Object *)secondAnchor, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + } else { + cmpResult = (firstAnchor == secondAnchor); + } + + if (!cmpResult) goto cleanup; + + firstTree = firstValResult->policyTree; + secondTree = secondValResult->policyTree; + + if ((firstTree != NULL) && (secondTree != NULL)) { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstTree, + (PKIX_PL_Object *)secondTree, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + } else { + cmpResult = (firstTree == secondTree); + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_ValidateResult *valResult = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 pubKeyHash = 0; + PKIX_UInt32 anchorHash = 0; + PKIX_UInt32 policyTreeHash = 0; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_OBJECTNOTVALIDATERESULT); + + valResult = (PKIX_ValidateResult*)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valResult->pubKey, &pubKeyHash, plContext), + PKIX_OBJECTHASHCODEFAILED); + + if (valResult->anchor) { + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valResult->anchor, + &anchorHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + } + + if (valResult->policyTree) { + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)valResult->policyTree, + &policyTreeHash, + plContext), + PKIX_OBJECTHASHCODEFAILED); + } + + hash = 31*(31 * pubKeyHash + anchorHash) + policyTreeHash; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_ValidateResult_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ValidateResult *valResult = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *valResultString = NULL; + + PKIX_TrustAnchor *anchor = NULL; + PKIX_PL_PublicKey *pubKey = NULL; + PKIX_PolicyNode *policyTree = NULL; + + PKIX_PL_String *anchorString = NULL; + PKIX_PL_String *pubKeyString = NULL; + PKIX_PL_String *treeString = NULL; + char *asciiNullString = "(null)"; + char *asciiFormat = + "[\n" + "\tTrustAnchor: \t\t%s" + "\tPubKey: \t\t%s\n" + "\tPolicyTree: \t\t%s\n" + "]\n"; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext), + PKIX_OBJECTNOTVALIDATERESULT); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + valResult = (PKIX_ValidateResult*)object; + + anchor = valResult->anchor; + + if (anchor) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)anchor, &anchorString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiNullString, + 0, + &anchorString, + plContext), + PKIX_STRINGCREATEFAILED); + } + + pubKey = valResult->pubKey; + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)pubKey, &pubKeyString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + + policyTree = valResult->policyTree; + + if (policyTree) { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)policyTree, &treeString, plContext), + PKIX_OBJECTTOSTRINGFAILED); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiNullString, + 0, + &treeString, + plContext), + PKIX_STRINGCREATEFAILED); + } + + PKIX_CHECK(PKIX_PL_Sprintf + (&valResultString, + plContext, + formatString, + anchorString, + pubKeyString, + treeString), + PKIX_SPRINTFFAILED); + + *pString = valResultString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(anchorString); + PKIX_DECREF(pubKeyString); + PKIX_DECREF(treeString); + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_RegisterSelf + * DESCRIPTION: + * Registers PKIX_VALIDATERESULT_TYPE and its related functions with + * systemClasses[] + * THREAD SAFETY: + * Not Thread Safe - for performance and complexity reasons + * + * Since this function is only called by PKIX_PL_Initialize, which should + * only be called once, it is acceptable that this function is not + * thread-safe. + */ +PKIX_Error * +pkix_ValidateResult_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_RegisterSelf"); + + entry.description = "ValidateResult"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_ValidateResult); + entry.destructor = pkix_ValidateResult_Destroy; + entry.equalsFunction = pkix_ValidateResult_Equals; + entry.hashcodeFunction = pkix_ValidateResult_Hashcode; + entry.toStringFunction = pkix_ValidateResult_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_VALIDATERESULT_TYPE] = entry; + + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: pkix_ValidateResult_Create + * DESCRIPTION: + * + * Creates a new ValidateResult Object using the PublicKey pointed to by + * "pubKey", the TrustAnchor pointed to by "anchor", and the PolicyNode + * pointed to by "policyTree", and stores it at "pResult". + * + * PARAMETERS + * "pubKey" + * PublicKey of the desired ValidateResult. Must be non-NULL. + * "anchor" + * TrustAnchor of the desired Validateresult. May be NULL. + * "policyTree" + * PolicyNode of the desired ValidateResult; may be NULL + * "pResult" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_ValidateResult_Create( + PKIX_PL_PublicKey *pubKey, + PKIX_TrustAnchor *anchor, + PKIX_PolicyNode *policyTree, + PKIX_ValidateResult **pResult, + void *plContext) +{ + PKIX_ValidateResult *result = NULL; + + PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Create"); + PKIX_NULLCHECK_TWO(pubKey, pResult); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_VALIDATERESULT_TYPE, + sizeof (PKIX_ValidateResult), + (PKIX_PL_Object **)&result, + plContext), + PKIX_COULDNOTCREATEVALIDATERESULTOBJECT); + + /* initialize fields */ + + PKIX_INCREF(pubKey); + result->pubKey = pubKey; + + PKIX_INCREF(anchor); + result->anchor = anchor; + + PKIX_INCREF(policyTree); + result->policyTree = policyTree; + + *pResult = result; + result = NULL; + +cleanup: + + PKIX_DECREF(result); + + PKIX_RETURN(VALIDATERESULT); + +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_ValidateResult_GetPublicKey + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_ValidateResult_GetPublicKey( + PKIX_ValidateResult *result, + PKIX_PL_PublicKey **pPublicKey, + void *plContext) +{ + PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPublicKey"); + PKIX_NULLCHECK_TWO(result, pPublicKey); + + PKIX_INCREF(result->pubKey); + *pPublicKey = result->pubKey; + +cleanup: + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: PKIX_ValidateResult_GetTrustAnchor + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_ValidateResult_GetTrustAnchor( + PKIX_ValidateResult *result, + PKIX_TrustAnchor **pTrustAnchor, + void *plContext) +{ + PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetTrustAnchor"); + PKIX_NULLCHECK_TWO(result, pTrustAnchor); + + PKIX_INCREF(result->anchor); + *pTrustAnchor = result->anchor; + +cleanup: + PKIX_RETURN(VALIDATERESULT); +} + +/* + * FUNCTION: PKIX_ValidateResult_GetPolicyTree + * (see comments in pkix_result.h) + */ +PKIX_Error * +PKIX_ValidateResult_GetPolicyTree( + PKIX_ValidateResult *result, + PKIX_PolicyNode **pPolicyTree, + void *plContext) +{ + PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPolicyTree"); + PKIX_NULLCHECK_TWO(result, pPolicyTree); + + PKIX_INCREF(result->policyTree); + (*pPolicyTree) = result->policyTree; + +cleanup: + PKIX_RETURN(VALIDATERESULT); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.h b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h new file mode 100644 index 0000000000..8011ae8c8f --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_valresult.h + * + * ValidateResult Object Type Definition + * + */ + +#ifndef _PKIX_VALIDATERESULT_H +#define _PKIX_VALIDATERESULT_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ValidateResultStruct { + PKIX_PL_PublicKey *pubKey; + PKIX_TrustAnchor *anchor; + PKIX_PolicyNode *policyTree; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_ValidateResult_Create( + PKIX_PL_PublicKey *pubKey, + PKIX_TrustAnchor *anchor, + PKIX_PolicyNode *policyTree, + PKIX_ValidateResult **pResult, + void *plContext); + +PKIX_Error *pkix_ValidateResult_RegisterSelf(void *plContext); + + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_VALIDATERESULT_H */ diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c new file mode 100644 index 0000000000..b52f83fcab --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c @@ -0,0 +1,1182 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_verifynode.c + * + * Verify Node Object Type Definition + * + */ + +#include "pkix_verifynode.h" + +/* --Private-VerifyNode-Functions---------------------------------- */ + +/* + * FUNCTION: pkix_VerifyNode_Create + * DESCRIPTION: + * + * This function creates a VerifyNode using the Cert pointed to by "cert", + * the depth given by "depth", and the Error pointed to by "error", storing + * the result at "pObject". + * + * PARAMETERS + * "cert" + * Address of Cert for the node. Must be non-NULL + * "depth" + * UInt32 value of the depth for this node. + * "error" + * Address of Error for the node. + * "pObject" + * Address where the VerifyNode pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_Create( + PKIX_PL_Cert *cert, + PKIX_UInt32 depth, + PKIX_Error *error, + PKIX_VerifyNode **pObject, + void *plContext) +{ + PKIX_VerifyNode *node = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create"); + PKIX_NULLCHECK_TWO(cert, pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_VERIFYNODE_TYPE, + sizeof (PKIX_VerifyNode), + (PKIX_PL_Object **)&node, + plContext), + PKIX_COULDNOTCREATEVERIFYNODEOBJECT); + + PKIX_INCREF(cert); + node->verifyCert = cert; + + PKIX_INCREF(error); + node->error = error; + + node->depth = depth; + + node->children = NULL; + + *pObject = node; + node = NULL; + +cleanup: + + PKIX_DECREF(node); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_AddToChain + * DESCRIPTION: + * + * Adds the VerifyNode pointed to by "child", at the appropriate depth, to the + * List of children of the VerifyNode pointed to by "parentNode". The chain of + * VerifyNodes is traversed until a VerifyNode is found at a depth one less + * than that specified in "child". An Error is returned if there is no parent + * at a suitable depth. + * + * If "parentNode" has a NULL pointer for the List of children, a new List is + * created containing "child". Otherwise "child" is appended to the existing + * List. + * + * Depth, in this context, means distance from the root node, which + * is at depth zero. + * + * PARAMETERS: + * "parentNode" + * Address of VerifyNode whose List of child VerifyNodes is to be + * created or appended to. Must be non-NULL. + * "child" + * Address of VerifyNode to be added to parentNode's List. Must be + * non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_AddToChain( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext) +{ + PKIX_VerifyNode *successor = NULL; + PKIX_List *listOfChildren = NULL; + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 parentDepth = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain"); + PKIX_NULLCHECK_TWO(parentNode, child); + + parentDepth = parentNode->depth; + listOfChildren = parentNode->children; + if (listOfChildren == NULL) { + + if (parentDepth != (child->depth - 1)) { + PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN); + } + + PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (listOfChildren, (PKIX_PL_Object *)child, plContext), + PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST); + + parentNode->children = listOfChildren; + } else { + /* get number of children */ + PKIX_CHECK(PKIX_List_GetLength + (listOfChildren, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numChildren != 1) { + PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE); + } + + /* successor = listOfChildren[0] */ + PKIX_CHECK(PKIX_List_GetItem + (listOfChildren, + 0, + (PKIX_PL_Object **)&successor, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_VerifyNode_AddToChain + (successor, child, plContext), + PKIX_VERIFYNODEADDTOCHAINFAILED); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)parentNode, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + PKIX_DECREF(successor); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_SetDepth + * DESCRIPTION: + * + * The function sets the depth field of each VerifyNode in the List "children" + * to the value given by "depth", and recursively sets the depth of any + * successive generations to the successive values. + * + * PARAMETERS: + * "children" + * The List of VerifyNodes. Must be non-NULL. + * "depth" + * The value of the depth field to be set in members of the List. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_VerifyNode_SetDepth(PKIX_List *children, + PKIX_UInt32 depth, + void *plContext) +{ + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 chIx = 0; + PKIX_VerifyNode *child = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth"); + PKIX_NULLCHECK_ONE(children); + + PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (chIx = 0; chIx < numChildren; chIx++) { + PKIX_CHECK(PKIX_List_GetItem + (children, chIx, (PKIX_PL_Object **)&child, plContext), + PKIX_LISTGETITEMFAILED); + + child->depth = depth; + + if (child->children != NULL) { + PKIX_CHECK(pkix_VerifyNode_SetDepth + (child->children, depth + 1, plContext), + PKIX_VERIFYNODESETDEPTHFAILED); + } + + PKIX_DECREF(child); + } + +cleanup: + + PKIX_DECREF(child); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_AddToTree + * DESCRIPTION: + * + * Adds the VerifyNode pointed to by "child" to the List of children of the + * VerifyNode pointed to by "parentNode". If "parentNode" has a NULL pointer + * for the List of children, a new List is created containing "child". + * Otherwise "child" is appended to the existing List. The depth field of + * "child" is set to one more than the corresponding value in "parent", and + * if the "child" itself has child nodes, their depth fields are updated + * accordingly. + * + * Depth, in this context, means distance from the root node, which + * is at depth zero. + * + * PARAMETERS: + * "parentNode" + * Address of VerifyNode whose List of child VerifyNodes is to be + * created or appended to. Must be non-NULL. + * "child" + * Address of VerifyNode to be added to parentNode's List. Must be + * non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_AddToTree( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext) +{ + PKIX_List *listOfChildren = NULL; + PKIX_UInt32 parentDepth = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree"); + PKIX_NULLCHECK_TWO(parentNode, child); + + parentDepth = parentNode->depth; + listOfChildren = parentNode->children; + if (listOfChildren == NULL) { + + PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), + PKIX_LISTCREATEFAILED); + + parentNode->children = listOfChildren; + } + + child->depth = parentDepth + 1; + + PKIX_CHECK(PKIX_List_AppendItem + (parentNode->children, (PKIX_PL_Object *)child, plContext), + PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST); + + if (child->children != NULL) { + PKIX_CHECK(pkix_VerifyNode_SetDepth + (child->children, child->depth + 1, plContext), + PKIX_VERIFYNODESETDEPTHFAILED); + } + + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_SingleVerifyNode_ToString + * DESCRIPTION: + * + * Creates a String representation of the attributes of the VerifyNode pointed + * to by "node", other than its children, and stores the result at "pString". + * + * PARAMETERS: + * "node" + * Address of VerifyNode to be described by the string. Must be non-NULL. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +PKIX_Error * +pkix_SingleVerifyNode_ToString( + PKIX_VerifyNode *node, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *fmtString = NULL; + PKIX_PL_String *errorString = NULL; + PKIX_PL_String *outString = NULL; + + PKIX_PL_X500Name *issuerName = NULL; + PKIX_PL_X500Name *subjectName = NULL; + PKIX_PL_String *issuerString = NULL; + PKIX_PL_String *subjectString = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString"); + PKIX_NULLCHECK_THREE(node, pString, node->verifyCert); + + PKIX_TOSTRING(node->error, &errorString, plContext, + PKIX_ERRORTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetIssuer + (node->verifyCert, &issuerName, plContext), + PKIX_CERTGETISSUERFAILED); + + PKIX_TOSTRING(issuerName, &issuerString, plContext, + PKIX_X500NAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetSubject + (node->verifyCert, &subjectName, plContext), + PKIX_CERTGETSUBJECTFAILED); + + PKIX_TOSTRING(subjectName, &subjectString, plContext, + PKIX_X500NAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s", + 0, + &fmtString, + plContext), + PKIX_CANTCREATESTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, + plContext, + fmtString, + issuerString, + subjectString, + node->depth, + errorString), + PKIX_SPRINTFFAILED); + + *pString = outString; + +cleanup: + + PKIX_DECREF(fmtString); + PKIX_DECREF(errorString); + PKIX_DECREF(issuerName); + PKIX_DECREF(subjectName); + PKIX_DECREF(issuerString); + PKIX_DECREF(subjectString); + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_ToString_Helper + * DESCRIPTION: + * + * Produces a String representation of a VerifyNode tree below the VerifyNode + * pointed to by "rootNode", with each line of output prefixed by the String + * pointed to by "indent", and stores the result at "pTreeString". It is + * called recursively, with ever-increasing indentation, for successively + * lower nodes on the tree. + * + * PARAMETERS: + * "rootNode" + * Address of VerifyNode subtree. Must be non-NULL. + * "indent" + * Address of String to be prefixed to each line of output. May be NULL + * if no indentation is desired + * "pTreeString" + * Address where the resulting String will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_VerifyNode_ToString_Helper( + PKIX_VerifyNode *rootNode, + PKIX_PL_String *indent, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_PL_String *nextIndentFormat = NULL; + PKIX_PL_String *thisNodeFormat = NULL; + PKIX_PL_String *childrenFormat = NULL; + PKIX_PL_String *nextIndentString = NULL; + PKIX_PL_String *resultString = NULL; + PKIX_PL_String *thisItemString = NULL; + PKIX_PL_String *childString = NULL; + PKIX_VerifyNode *childNode = NULL; + PKIX_UInt32 numberOfChildren = 0; + PKIX_UInt32 childIndex = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper"); + + PKIX_NULLCHECK_TWO(rootNode, pTreeString); + + /* Create a string for this node */ + PKIX_CHECK(pkix_SingleVerifyNode_ToString + (rootNode, &thisItemString, plContext), + PKIX_ERRORINSINGLEVERIFYNODETOSTRING); + + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + indent, + thisItemString), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s", + 0, + &thisNodeFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + thisNodeFormat, + thisItemString), + PKIX_ERRORINSPRINTF); + } + + PKIX_DECREF(thisItemString); + thisItemString = resultString; + + /* if no children, we are done */ + if (rootNode->children) { + PKIX_CHECK(PKIX_List_GetLength + (rootNode->children, &numberOfChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + if (numberOfChildren != 0) { + /* + * We create a string for each child in turn, + * concatenating them to thisItemString. + */ + + /* Prepare an indent string for each child */ + if (indent) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s. ", + 0, + &nextIndentFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + PKIX_CHECK(PKIX_PL_Sprintf + (&nextIndentString, + plContext, + nextIndentFormat, + indent), + PKIX_ERRORINSPRINTF); + } else { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + ". ", + 0, + &nextIndentString, + plContext), + PKIX_ERRORCREATINGINDENTSTRING); + } + + /* Prepare the format for concatenation. */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s\n%s", + 0, + &childrenFormat, + plContext), + PKIX_ERRORCREATINGFORMATSTRING); + + for (childIndex = 0; + childIndex < numberOfChildren; + childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (rootNode->children, + childIndex, + (PKIX_PL_Object **)&childNode, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_VerifyNode_ToString_Helper + (childNode, + nextIndentString, + &childString, + plContext), + PKIX_ERRORCREATINGCHILDSTRING); + + + PKIX_CHECK(PKIX_PL_Sprintf + (&resultString, + plContext, + childrenFormat, + thisItemString, + childString), + PKIX_ERRORINSPRINTF); + + PKIX_DECREF(childNode); + PKIX_DECREF(childString); + PKIX_DECREF(thisItemString); + + thisItemString = resultString; + } + } + + *pTreeString = thisItemString; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(thisItemString); + } + + PKIX_DECREF(nextIndentFormat); + PKIX_DECREF(thisNodeFormat); + PKIX_DECREF(childrenFormat); + PKIX_DECREF(nextIndentString); + PKIX_DECREF(childString); + PKIX_DECREF(childNode); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pTreeString, + void *plContext) +{ + PKIX_VerifyNode *rootNode = NULL; + PKIX_PL_String *resultString = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString"); + + PKIX_NULLCHECK_TWO(object, pTreeString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + rootNode = (PKIX_VerifyNode *)object; + + PKIX_CHECK(pkix_VerifyNode_ToString_Helper + (rootNode, NULL, &resultString, plContext), + PKIX_ERRORCREATINGSUBTREESTRING); + + *pTreeString = resultString; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_VerifyNode *node = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + node = (PKIX_VerifyNode*)object; + + PKIX_DECREF(node->verifyCert); + PKIX_DECREF(node->children); + PKIX_DECREF(node->error); + + node->depth = 0; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_SingleVerifyNode_Hashcode + * DESCRIPTION: + * + * Computes the hashcode of the attributes of the VerifyNode pointed to by + * "node", other than its parents and children, and stores the result at + * "pHashcode". + * + * PARAMETERS: + * "node" + * Address of VerifyNode to be hashcoded; must be non-NULL + * "pHashcode" + * Address where UInt32 result will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SingleVerifyNode_Hashcode( + PKIX_VerifyNode *node, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 errorHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode"); + PKIX_NULLCHECK_TWO(node, pHashcode); + + PKIX_HASHCODE + (node->verifyCert, + &nodeHash, + plContext, + PKIX_FAILUREHASHINGCERT); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)node->error, + &errorHash, + plContext), + PKIX_FAILUREHASHINGERROR); + + nodeHash = 31*nodeHash + errorHash; + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_VerifyNode *node = NULL; + PKIX_UInt32 childrenHash = 0; + PKIX_UInt32 nodeHash = 0; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + node = (PKIX_VerifyNode *)object; + + PKIX_CHECK(pkix_SingleVerifyNode_Hashcode + (node, &nodeHash, plContext), + PKIX_SINGLEVERIFYNODEHASHCODEFAILED); + + PKIX_HASHCODE + (node->children, + &childrenHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + nodeHash = 31*nodeHash + childrenHash; + + *pHashcode = nodeHash; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_SingleVerifyNode_Equals + * DESCRIPTION: + * + * Compares for equality the components of the VerifyNode pointed to by + * "firstPN", other than its parents and children, with those of the + * VerifyNode pointed to by "secondPN" and stores the result at "pResult" + * (PKIX_TRUE if equal; PKIX_FALSE if not). + * + * PARAMETERS: + * "firstPN" + * Address of first of the VerifyNodes to be compared; must be non-NULL + * "secondPN" + * Address of second of the VerifyNodes to be compared; must be non-NULL + * "pResult" + * Address where Boolean will be stored; must be non-NULL + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_SingleVerifyNode_Equals( + PKIX_VerifyNode *firstVN, + PKIX_VerifyNode *secondVN, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals"); + PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult); + + /* If both references are identical, they must be equal */ + if (firstVN == secondVN) { + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * It seems we have to do the comparisons. Do + * the easiest ones first. + */ + if ((firstVN->depth) != (secondVN->depth)) { + goto cleanup; + } + + /* These fields must be non-NULL */ + PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert); + + PKIX_EQUALS + (firstVN->verifyCert, + secondVN->verifyCert, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + PKIX_EQUALS + (firstVN->error, + secondVN->error, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_VerifyNode *firstVN = NULL; + PKIX_VerifyNode *secondVN = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a VerifyNode */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_FIRSTOBJECTNOTVERIFYNODE); + + /* + * Since we know firstObject is a VerifyNode, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + compResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a VerifyNode, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_VERIFYNODE_TYPE) { + goto cleanup; + } + + /* + * Oh, well, we have to do the comparisons. Do + * the easiest ones first. + */ + firstVN = (PKIX_VerifyNode *)firstObject; + secondVN = (PKIX_VerifyNode *)secondObject; + + PKIX_CHECK(pkix_SingleVerifyNode_Equals + (firstVN, secondVN, &compResult, plContext), + PKIX_SINGLEVERIFYNODEEQUALSFAILED); + + if (compResult == PKIX_FALSE) { + goto cleanup; + } + + PKIX_EQUALS + (firstVN->children, + secondVN->children, + &compResult, + plContext, + PKIX_OBJECTEQUALSFAILEDONCHILDREN); + +cleanup: + + *pResult = compResult; + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_DuplicateHelper + * DESCRIPTION: + * + * Duplicates the VerifyNode whose address is pointed to by "original", + * and stores the result at "pNewNode", if a non-NULL pointer is provided + * for "pNewNode". In addition, the created VerifyNode is added as a child + * to "parent", if a non-NULL pointer is provided for "parent". Then this + * function is called recursively to duplicate each of the children of + * "original". At the top level this function is called with a null + * "parent" and a non-NULL "pNewNode". Below the top level "parent" will + * be non-NULL and "pNewNode" will be NULL. + * + * PARAMETERS: + * "original" + * Address of VerifyNode to be copied; must be non-NULL + * "parent" + * Address of VerifyNode to which the created node is to be added as a + * child; NULL for the top-level call and non-NULL below the top level + * "pNewNode" + * Address to store the node created; should be NULL if "parent" is + * non-NULL and vice versa + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if function succeeds + * Returns a VerifyNode Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in a fatal way + */ +static PKIX_Error * +pkix_VerifyNode_DuplicateHelper( + PKIX_VerifyNode *original, + PKIX_VerifyNode *parent, + PKIX_VerifyNode **pNewNode, + void *plContext) +{ + PKIX_UInt32 numChildren = 0; + PKIX_UInt32 childIndex = 0; + PKIX_List *children = NULL; /* List of PKIX_VerifyNode */ + PKIX_VerifyNode *copy = NULL; + PKIX_VerifyNode *child = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper"); + + PKIX_NULLCHECK_TWO + (original, original->verifyCert); + + /* + * These components are immutable, so copying the pointers + * is sufficient. The create function increments the reference + * counts as it stores the pointers into the new object. + */ + PKIX_CHECK(pkix_VerifyNode_Create + (original->verifyCert, + original->depth, + original->error, + ©, + plContext), + PKIX_VERIFYNODECREATEFAILED); + + /* Are there any children to duplicate? */ + children = original->children; + + if (children) { + PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (childIndex = 0; childIndex < numChildren; childIndex++) { + PKIX_CHECK(PKIX_List_GetItem + (children, + childIndex, + (PKIX_PL_Object **)&child, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_VerifyNode_DuplicateHelper + (child, copy, NULL, plContext), + PKIX_VERIFYNODEDUPLICATEHELPERFAILED); + + PKIX_DECREF(child); + } + + if (pNewNode) { + *pNewNode = copy; + copy = NULL; /* no DecRef if we give our handle away */ + } + +cleanup: + PKIX_DECREF(copy); + PKIX_DECREF(child); + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_VerifyNode_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_VerifyNode *original = NULL; + PKIX_VerifyNode *copy = NULL; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate"); + + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_VERIFYNODE_TYPE, plContext), + PKIX_OBJECTNOTVERIFYNODE); + + original = (PKIX_VerifyNode *)object; + + PKIX_CHECK(pkix_VerifyNode_DuplicateHelper + (original, NULL, ©, plContext), + PKIX_VERIFYNODEDUPLICATEHELPERFAILED); + + *pNewObject = (PKIX_PL_Object *)copy; + +cleanup: + + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: pkix_VerifyNode_RegisterSelf + * DESCRIPTION: + * + * Registers PKIX_VERIFYNODE_TYPE and its related + * functions with systemClasses[] + * + * THREAD SAFETY: + * Not Thread Safe - for performance and complexity reasons + * + * Since this function is only called by PKIX_PL_Initialize, + * which should only be called once, it is acceptable that + * this function is not thread-safe. + */ +PKIX_Error * +pkix_VerifyNode_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf"); + + entry.description = "VerifyNode"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_VerifyNode); + entry.destructor = pkix_VerifyNode_Destroy; + entry.equalsFunction = pkix_VerifyNode_Equals; + entry.hashcodeFunction = pkix_VerifyNode_Hashcode; + entry.toStringFunction = pkix_VerifyNode_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_VerifyNode_Duplicate; + + systemClasses[PKIX_VERIFYNODE_TYPE] = entry; + + PKIX_RETURN(VERIFYNODE); +} + +/* --Public-VerifyNode-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_VerifyNode_SetError + * DESCRIPTION: + * + * This function sets the Error field of the VerifyNode pointed to by "node" + * to contain the Error pointed to by "error". + * + * PARAMETERS: + * "node" + * The address of the VerifyNode to be modified. Must be non-NULL. + * "error" + * The address of the Error to be stored. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_SetError( + PKIX_VerifyNode *node, + PKIX_Error *error, + void *plContext) +{ + + PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError"); + + PKIX_NULLCHECK_TWO(node, error); + + PKIX_DECREF(node->error); /* should have been NULL */ + PKIX_INCREF(error); + node->error = error; + +cleanup: + PKIX_RETURN(VERIFYNODE); +} + +/* + * FUNCTION: PKIX_VerifyNode_FindError + * DESCRIPTION: + * + * Finds meaningful error in the log. For now, just returns the first + * error it finds in. In the future the function should be changed to + * return a top priority error. + * + * PARAMETERS: + * "node" + * The address of the VerifyNode to be modified. Must be non-NULL. + * "error" + * The address of a pointer the error will be returned to. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_VerifyNode_FindError( + PKIX_VerifyNode *node, + PKIX_Error **error, + void *plContext) +{ + PKIX_VerifyNode *childNode = NULL; + + PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError"); + + /* Make sure the return address is initialized with NULL */ + PKIX_DECREF(*error); + + if (!node) + goto cleanup; + + /* First, try to get error from lowest level. */ + if (node->children) { + PKIX_UInt32 length = 0; + PKIX_UInt32 index = 0; + + PKIX_CHECK( + PKIX_List_GetLength(node->children, &length, + plContext), + PKIX_LISTGETLENGTHFAILED); + for (index = 0;index < length;index++) { + PKIX_CHECK( + PKIX_List_GetItem(node->children, index, + (PKIX_PL_Object**)&childNode, plContext), + PKIX_LISTGETITEMFAILED); + if (!childNode) + continue; + PKIX_CHECK( + pkix_VerifyNode_FindError(childNode, error, + plContext), + PKIX_VERIFYNODEFINDERRORFAILED); + PKIX_DECREF(childNode); + if (*error) { + goto cleanup; + } + } + } + + if (node->error && node->error->plErr) { + PKIX_INCREF(node->error); + *error = node->error; + } + +cleanup: + PKIX_DECREF(childNode); + + PKIX_RETURN(VERIFYNODE); +} diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h new file mode 100644 index 0000000000..c943ae4ddc --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h @@ -0,0 +1,75 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * pkix_verifynode.h + * + * VerifyNode Type Definitions + * + */ + +#ifndef _PKIX_VERIFYNODE_H +#define _PKIX_VERIFYNODE_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This structure reflects the contents of a verify node... + */ +struct PKIX_VerifyNodeStruct { + PKIX_PL_Cert *verifyCert; + PKIX_List *children; /* VerifyNodes */ + PKIX_UInt32 depth; + PKIX_Error *error; +}; + +PKIX_Error * +pkix_SingleVerifyNode_ToString( + PKIX_VerifyNode *node, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_Create( + PKIX_PL_Cert *verifyCert, + PKIX_UInt32 depth, + PKIX_Error *error, + PKIX_VerifyNode **pObject, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_AddToChain( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_AddToTree( + PKIX_VerifyNode *parentNode, + PKIX_VerifyNode *child, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_SetError( + PKIX_VerifyNode *node, + PKIX_Error *error, + void *plContext); + +PKIX_Error * +pkix_VerifyNode_RegisterSelf( + void *plContext); + +PKIX_Error * +pkix_VerifyNode_FindError( + PKIX_VerifyNode *node, + PKIX_Error **error, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_VERIFYNODE_H */ diff --git a/security/nss/lib/libpkix/pkix/results/results.gyp b/security/nss/lib/libpkix/pkix/results/results.gyp new file mode 100644 index 0000000000..962fdb9481 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/results/results.gyp @@ -0,0 +1,26 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'pkixresults', + 'type': 'static_library', + 'sources': [ + 'pkix_buildresult.c', + 'pkix_policynode.c', + 'pkix_valresult.c', + 'pkix_verifynode.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file |