security/nss/lib/libpkix/pkix/results/pkix_policynode.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1377 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * pkix_policynode.c
     1.9 + *
    1.10 + * Policy Node Object Type Definition
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +#include "pkix_policynode.h"
    1.15 +
    1.16 +/* --Private-PolicyNode-Functions---------------------------------- */
    1.17 +
    1.18 +/*
    1.19 + * FUNCTION: pkix_PolicyNode_GetChildrenMutable
    1.20 + * DESCRIPTION:
    1.21 + *
    1.22 + *  Retrieves the List of PolicyNodes representing the child nodes of the
    1.23 + *  Policy Node pointed to by "node" and stores it at "pChildren". If "node"
    1.24 + *  has no List of child nodes, this function stores NULL at "pChildren".
    1.25 + *
    1.26 + *  Note that the List returned by this function may be mutable. This function
    1.27 + *  differs from the public function PKIX_PolicyNode_GetChildren in that
    1.28 + *  respect. (It also differs in that the public function creates an empty
    1.29 + *  List, if necessary, rather than storing NULL.)
    1.30 + *
    1.31 + *  During certificate processing, children Lists are created and modified.
    1.32 + *  Once the list is accessed using the public call, the List is set immutable.
    1.33 + *
    1.34 + * PARAMETERS:
    1.35 + *  "node"
    1.36 + *      Address of PolicyNode whose child nodes are to be stored.
    1.37 + *      Must be non-NULL.
    1.38 + *  "pChildren"
    1.39 + *      Address where object pointer will be stored. Must be non-NULL.
    1.40 + *  "plContext"
    1.41 + *      Platform-specific context pointer.
    1.42 + * THREAD SAFETY:
    1.43 + *  Conditionally Thread Safe
    1.44 + *  (see Thread Safety Definitions in Programmer's Guide)
    1.45 + * RETURNS:
    1.46 + *  Returns NULL if the function succeeds.
    1.47 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    1.48 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
    1.49 + */
    1.50 +PKIX_Error *
    1.51 +pkix_PolicyNode_GetChildrenMutable(
    1.52 +        PKIX_PolicyNode *node,
    1.53 +        PKIX_List **pChildren,  /* list of PKIX_PolicyNode */
    1.54 +        void *plContext)
    1.55 +{
    1.56 +
    1.57 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_GetChildrenMutable");
    1.58 +
    1.59 +        PKIX_NULLCHECK_TWO(node, pChildren);
    1.60 +
    1.61 +        PKIX_INCREF(node->children);
    1.62 +
    1.63 +        *pChildren = node->children;
    1.64 +
    1.65 +cleanup:
    1.66 +        PKIX_RETURN(CERTPOLICYNODE);
    1.67 +}
    1.68 +
    1.69 +/*
    1.70 + * FUNCTION: pkix_PolicyNode_Create
    1.71 + * DESCRIPTION:
    1.72 + *
    1.73 + *  Creates a new PolicyNode using the OID pointed to by "validPolicy", the List
    1.74 + *  of CertPolicyQualifiers pointed to by "qualifierSet", the criticality
    1.75 + *  indicated by the Boolean value of "criticality", and the List of OIDs
    1.76 + *  pointed to by "expectedPolicySet", and stores the result at "pObject". The
    1.77 + *  criticality should be derived from whether the certificate policy extension
    1.78 + *  was marked as critical in the certificate that led to creation of this
    1.79 + *  PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made
    1.80 + *  immutable. The PolicyNode pointers to parent and to children are initialized
    1.81 + *  to NULL, and the depth is set to zero; those values should be set by using
    1.82 + *  the pkix_PolicyNode_AddToParent function.
    1.83 + *
    1.84 + * PARAMETERS
    1.85 + *  "validPolicy"
    1.86 + *      Address of OID of the valid policy for the path. Must be non-NULL
    1.87 + *  "qualifierSet"
    1.88 + *      Address of List of CertPolicyQualifiers associated with the validpolicy.
    1.89 + *      May be NULL
    1.90 + *  "criticality"
    1.91 + *      Boolean indicator of whether the criticality should be set in this
    1.92 + *      PolicyNode
    1.93 + *  "expectedPolicySet"
    1.94 + *      Address of List of OIDs that would satisfy this policy in the next
    1.95 + *      certificate. Must be non-NULL
    1.96 + *  "pObject"
    1.97 + *      Address where the PolicyNode pointer will be stored. Must be non-NULL.
    1.98 + *  "plContext"
    1.99 + *      Platform-specific context pointer.
   1.100 + * THREAD SAFETY:
   1.101 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.102 + * RETURNS:
   1.103 + *  Returns NULL if the function succeeds.
   1.104 + *  Returns a PolicyNode Error if the function fails  in a non-fatal way.
   1.105 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.106 + */
   1.107 +PKIX_Error *
   1.108 +pkix_PolicyNode_Create(
   1.109 +        PKIX_PL_OID *validPolicy,
   1.110 +        PKIX_List *qualifierSet,
   1.111 +        PKIX_Boolean criticality,
   1.112 +        PKIX_List *expectedPolicySet,
   1.113 +        PKIX_PolicyNode **pObject,
   1.114 +        void *plContext)
   1.115 +{
   1.116 +        PKIX_PolicyNode *node = NULL;
   1.117 +
   1.118 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Create");
   1.119 +
   1.120 +        PKIX_NULLCHECK_THREE(validPolicy, expectedPolicySet, pObject);
   1.121 +
   1.122 +        PKIX_CHECK(PKIX_PL_Object_Alloc
   1.123 +                (PKIX_CERTPOLICYNODE_TYPE,
   1.124 +                sizeof (PKIX_PolicyNode),
   1.125 +                (PKIX_PL_Object **)&node,
   1.126 +                plContext),
   1.127 +                PKIX_COULDNOTCREATEPOLICYNODEOBJECT);
   1.128 +
   1.129 +        PKIX_INCREF(validPolicy);
   1.130 +        node->validPolicy = validPolicy;
   1.131 +
   1.132 +        PKIX_INCREF(qualifierSet);
   1.133 +        node->qualifierSet = qualifierSet;
   1.134 +        if (qualifierSet) {
   1.135 +                PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet, plContext),
   1.136 +                        PKIX_LISTSETIMMUTABLEFAILED);
   1.137 +        }
   1.138 +
   1.139 +        node->criticality = criticality;
   1.140 +
   1.141 +        PKIX_INCREF(expectedPolicySet);
   1.142 +        node->expectedPolicySet = expectedPolicySet;
   1.143 +        PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet, plContext),
   1.144 +                PKIX_LISTSETIMMUTABLEFAILED);
   1.145 +
   1.146 +        node->parent = NULL;
   1.147 +        node->children = NULL;
   1.148 +        node->depth = 0;
   1.149 +
   1.150 +        *pObject = node;
   1.151 +        node = NULL;
   1.152 +
   1.153 +cleanup:
   1.154 +
   1.155 +        PKIX_DECREF(node);
   1.156 +
   1.157 +        PKIX_RETURN(CERTPOLICYNODE);
   1.158 +}
   1.159 +
   1.160 +/*
   1.161 + * FUNCTION: pkix_PolicyNode_AddToParent
   1.162 + * DESCRIPTION:
   1.163 + *
   1.164 + *  Adds the PolicyNode pointed to by "child" to the List of children of
   1.165 + *  the PolicyNode pointed to by "parentNode". If "parentNode" had a
   1.166 + *  NULL pointer for the List of children, a new List is created containing
   1.167 + *  "child". Otherwise "child" is appended to the existing List. The
   1.168 + *  parent field in "child" is set to "parent", and the depth field is
   1.169 + *  set to one more than the corresponding value in "parent".
   1.170 + *
   1.171 + *  Depth, in this context, means distance from the root node, which
   1.172 + *  is at depth zero.
   1.173 + *
   1.174 + * PARAMETERS:
   1.175 + *  "parentNode"
   1.176 + *      Address of PolicyNode whose List of child PolicyNodes is to be
   1.177 + *      created or appended to. Must be non-NULL.
   1.178 + *  "child"
   1.179 + *      Address of PolicyNode to be added to parentNode's List. Must be
   1.180 + *      non-NULL.
   1.181 + *  "plContext"
   1.182 + *      Platform-specific context pointer.
   1.183 + * THREAD SAFETY:
   1.184 + *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.185 + * RETURNS:
   1.186 + *  Returns NULL if the function succeeds.
   1.187 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1.188 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.189 + */
   1.190 +PKIX_Error *
   1.191 +pkix_PolicyNode_AddToParent(
   1.192 +        PKIX_PolicyNode *parentNode,
   1.193 +        PKIX_PolicyNode *child,
   1.194 +        void *plContext)
   1.195 +{
   1.196 +        PKIX_List *listOfChildren = NULL;
   1.197 +
   1.198 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_AddToParent");
   1.199 +
   1.200 +        PKIX_NULLCHECK_TWO(parentNode, child);
   1.201 +
   1.202 +        listOfChildren = parentNode->children;
   1.203 +        if (listOfChildren == NULL) {
   1.204 +                PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
   1.205 +                        PKIX_LISTCREATEFAILED);
   1.206 +                parentNode->children = listOfChildren;
   1.207 +        }
   1.208 +
   1.209 +        /*
   1.210 +         * Note: this link is not reference-counted. The link from parent
   1.211 +         * to child is counted (actually, the parent "owns" a List which
   1.212 +         * "owns" children), but the children do not "own" the parent.
   1.213 +         * Otherwise, there would be loops.
   1.214 +         */
   1.215 +        child->parent = parentNode;
   1.216 +
   1.217 +        child->depth = 1 + (parentNode->depth);
   1.218 +
   1.219 +        PKIX_CHECK(PKIX_List_AppendItem
   1.220 +                (listOfChildren, (PKIX_PL_Object *)child, plContext),
   1.221 +                PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST);
   1.222 +
   1.223 +        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1.224 +                ((PKIX_PL_Object *)parentNode, plContext),
   1.225 +                PKIX_OBJECTINVALIDATECACHEFAILED);
   1.226 +
   1.227 +        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1.228 +                ((PKIX_PL_Object *)child, plContext),
   1.229 +                PKIX_OBJECTINVALIDATECACHEFAILED);
   1.230 +
   1.231 +cleanup:
   1.232 +
   1.233 +        PKIX_RETURN(CERTPOLICYNODE);
   1.234 +}
   1.235 +
   1.236 +/*
   1.237 + * FUNCTION: pkix_PolicyNode_Prune
   1.238 + * DESCRIPTION:
   1.239 + *
   1.240 + *  Prunes a tree below the PolicyNode whose address is pointed to by "node",
   1.241 + *  using the UInt32 value of "height" as the distance from the leaf level,
   1.242 + *  and storing at "pDelete" the Boolean value of whether this PolicyNode is,
   1.243 + *  after pruning, childless and should be pruned.
   1.244 + *
   1.245 + *  Any PolicyNode at height 0 is allowed to survive. If the height is greater
   1.246 + *  than zero, pkix_PolicyNode_Prune is called recursively for each child of
   1.247 + *  the current PolicyNode. After this process, a node with no children
   1.248 + *  stores PKIX_TRUE in "pDelete" to indicate that it should be deleted.
   1.249 + *
   1.250 + * PARAMETERS:
   1.251 + *  "node"
   1.252 + *      Address of the PolicyNode to be pruned. Must be non-NULL.
   1.253 + *  "height"
   1.254 + *      UInt32 value for the distance from the leaf level
   1.255 + *  "pDelete"
   1.256 + *      Address to store the Boolean return value of PKIX_TRUE if this node
   1.257 + *      should be pruned, or PKIX_FALSE if there remains at least one
   1.258 + *      branch of the required height. Must be non-NULL.
   1.259 + *  "plContext"
   1.260 + *      Platform-specific context pointer.
   1.261 + * THREAD SAFETY:
   1.262 + *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.263 + * RETURNS:
   1.264 + *  Returns NULL if the function succeeds.
   1.265 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1.266 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.267 + */
   1.268 +PKIX_Error *
   1.269 +pkix_PolicyNode_Prune(
   1.270 +        PKIX_PolicyNode *node,
   1.271 +        PKIX_UInt32 height,
   1.272 +        PKIX_Boolean *pDelete,
   1.273 +        void *plContext)
   1.274 +{
   1.275 +        PKIX_Boolean childless = PKIX_FALSE;
   1.276 +        PKIX_Boolean shouldBePruned = PKIX_FALSE;
   1.277 +        PKIX_UInt32 listSize = 0;
   1.278 +        PKIX_UInt32 listIndex = 0;
   1.279 +        PKIX_PolicyNode *candidate = NULL;
   1.280 +
   1.281 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Prune");
   1.282 +
   1.283 +        PKIX_NULLCHECK_TWO(node, pDelete);
   1.284 +
   1.285 +        /* Don't prune at the leaf */
   1.286 +        if (height == 0) {
   1.287 +                goto cleanup;
   1.288 +        }
   1.289 +
   1.290 +        /* Above the bottom level, childless nodes get pruned */
   1.291 +        if (!(node->children)) {
   1.292 +                childless = PKIX_TRUE;
   1.293 +                goto cleanup;
   1.294 +        }
   1.295 +
   1.296 +        /*
   1.297 +         * This node has children. If they are leaf nodes,
   1.298 +         * we know they will live. Otherwise, check them out.
   1.299 +         */
   1.300 +        if (height > 1) {
   1.301 +                PKIX_CHECK(PKIX_List_GetLength
   1.302 +                        (node->children, &listSize, plContext),
   1.303 +                        PKIX_LISTGETLENGTHFAILED);
   1.304 +                /*
   1.305 +                 * By working backwards from the end of the list,
   1.306 +                 * we avoid having to worry about possible
   1.307 +                 * decreases in the size of the list, as we
   1.308 +                 * delete items. The only nuisance is that since the
   1.309 +                 * index is UInt32, we can't check for it to reach -1;
   1.310 +                 * we have to use the 1-based index, rather than the
   1.311 +                 * 0-based index that PKIX_List functions require.
   1.312 +                 */
   1.313 +                for (listIndex = listSize; listIndex > 0; listIndex--) {
   1.314 +                        PKIX_CHECK(PKIX_List_GetItem
   1.315 +                                (node->children,
   1.316 +                                (listIndex - 1),
   1.317 +                                (PKIX_PL_Object **)&candidate,
   1.318 +                                plContext),
   1.319 +                                PKIX_LISTGETITEMFAILED);
   1.320 +
   1.321 +                        PKIX_CHECK(pkix_PolicyNode_Prune
   1.322 +                                (candidate,
   1.323 +                                height - 1,
   1.324 +                                &shouldBePruned,
   1.325 +                                plContext),
   1.326 +                                PKIX_POLICYNODEPRUNEFAILED);
   1.327 +
   1.328 +                        if (shouldBePruned == PKIX_TRUE) {
   1.329 +                                PKIX_CHECK(PKIX_List_DeleteItem
   1.330 +                                        (node->children,
   1.331 +                                        (listIndex - 1),
   1.332 +                                        plContext),
   1.333 +                                        PKIX_LISTDELETEITEMFAILED);
   1.334 +                        }
   1.335 +
   1.336 +                        PKIX_DECREF(candidate);
   1.337 +                }
   1.338 +        }
   1.339 +
   1.340 +        /* Prune if this node has *become* childless */
   1.341 +        PKIX_CHECK(PKIX_List_GetLength
   1.342 +                (node->children, &listSize, plContext),
   1.343 +                PKIX_LISTGETLENGTHFAILED);
   1.344 +        if (listSize == 0) {
   1.345 +                childless = PKIX_TRUE;
   1.346 +        }
   1.347 +
   1.348 +        /*
   1.349 +         * Even if we did not change this node, or any of its children,
   1.350 +         * maybe a [great-]*grandchild was pruned.
   1.351 +         */
   1.352 +        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1.353 +                ((PKIX_PL_Object *)node, plContext),
   1.354 +                PKIX_OBJECTINVALIDATECACHEFAILED);
   1.355 +
   1.356 +cleanup:
   1.357 +        *pDelete = childless;
   1.358 +
   1.359 +        PKIX_DECREF(candidate);
   1.360 +
   1.361 +        PKIX_RETURN(CERTPOLICYNODE);
   1.362 +}
   1.363 +
   1.364 +/*
   1.365 + * FUNCTION: pkix_SinglePolicyNode_ToString
   1.366 + * DESCRIPTION:
   1.367 + *
   1.368 + *  Creates a String representation of the attributes of the PolicyNode
   1.369 + *  pointed to by "node", other than its parents or children, and
   1.370 + *  stores the result at "pString".
   1.371 + *
   1.372 + * PARAMETERS:
   1.373 + *  "node"
   1.374 + *      Address of PolicyNode to be described by the string. Must be non-NULL.
   1.375 + *  "pString"
   1.376 + *      Address where object pointer will be stored. Must be non-NULL.
   1.377 + *  "plContext"
   1.378 + *      Platform-specific context pointer.
   1.379 + * THREAD SAFETY:
   1.380 + *  Conditionally Thread Safe
   1.381 + *  (see Thread Safety Definitions in Programmer's Guide)
   1.382 + * RETURNS:
   1.383 + *  Returns NULL if function succeeds
   1.384 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1.385 + *  Returns a Fatal Error if the function fails in a fatal way
   1.386 + */
   1.387 +PKIX_Error *
   1.388 +pkix_SinglePolicyNode_ToString(
   1.389 +        PKIX_PolicyNode *node,
   1.390 +        PKIX_PL_String **pString,
   1.391 +        void *plContext)
   1.392 +{
   1.393 +        PKIX_PL_String *fmtString = NULL;
   1.394 +        PKIX_PL_String *validString = NULL;
   1.395 +        PKIX_PL_String *qualifierString = NULL;
   1.396 +        PKIX_PL_String *criticalityString = NULL;
   1.397 +        PKIX_PL_String *expectedString = NULL;
   1.398 +        PKIX_PL_String *outString = NULL;
   1.399 +
   1.400 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_ToString");
   1.401 +        PKIX_NULLCHECK_TWO(node, pString);
   1.402 +        PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
   1.403 +
   1.404 +        PKIX_CHECK(PKIX_PL_String_Create
   1.405 +                (PKIX_ESCASCII,
   1.406 +                "{%s,%s,%s,%s,%d}",
   1.407 +                0,
   1.408 +                &fmtString,
   1.409 +                plContext),
   1.410 +                PKIX_CANTCREATESTRING);
   1.411 +
   1.412 +        PKIX_CHECK(PKIX_PL_Object_ToString
   1.413 +                ((PKIX_PL_Object *)(node->validPolicy),
   1.414 +                &validString,
   1.415 +                plContext),
   1.416 +                PKIX_OIDTOSTRINGFAILED);
   1.417 +
   1.418 +        PKIX_CHECK(PKIX_PL_Object_ToString
   1.419 +                ((PKIX_PL_Object *)(node->expectedPolicySet),
   1.420 +                &expectedString,
   1.421 +                plContext),
   1.422 +                PKIX_LISTTOSTRINGFAILED);
   1.423 +
   1.424 +        if (node->qualifierSet) {
   1.425 +                PKIX_CHECK(PKIX_PL_Object_ToString
   1.426 +                        ((PKIX_PL_Object *)(node->qualifierSet),
   1.427 +                        &qualifierString,
   1.428 +                        plContext),
   1.429 +                        PKIX_LISTTOSTRINGFAILED);
   1.430 +        } else {
   1.431 +                PKIX_CHECK(PKIX_PL_String_Create
   1.432 +                        (PKIX_ESCASCII,
   1.433 +                        "{}",
   1.434 +                        0,
   1.435 +                        &qualifierString,
   1.436 +                        plContext),
   1.437 +                        PKIX_CANTCREATESTRING);
   1.438 +        }
   1.439 +
   1.440 +        PKIX_CHECK(PKIX_PL_String_Create
   1.441 +                (PKIX_ESCASCII,
   1.442 +                (node->criticality)?"Critical":"Not Critical",
   1.443 +                0,
   1.444 +                &criticalityString,
   1.445 +                plContext),
   1.446 +                PKIX_CANTCREATESTRING);
   1.447 +
   1.448 +        PKIX_CHECK(PKIX_PL_Sprintf
   1.449 +                (&outString,
   1.450 +                plContext,
   1.451 +                fmtString,
   1.452 +                validString,
   1.453 +                qualifierString,
   1.454 +                criticalityString,
   1.455 +                expectedString,
   1.456 +                node->depth),
   1.457 +                PKIX_SPRINTFFAILED);
   1.458 +
   1.459 +        *pString = outString;
   1.460 +
   1.461 +cleanup:
   1.462 +
   1.463 +        PKIX_DECREF(fmtString);
   1.464 +        PKIX_DECREF(validString);
   1.465 +        PKIX_DECREF(qualifierString);
   1.466 +        PKIX_DECREF(criticalityString);
   1.467 +        PKIX_DECREF(expectedString);
   1.468 +        PKIX_RETURN(CERTPOLICYNODE);
   1.469 +}
   1.470 +
   1.471 +/*
   1.472 + * FUNCTION: pkix_PolicyNode_ToString_Helper
   1.473 + * DESCRIPTION:
   1.474 + *
   1.475 + *  Produces a String representation of a PolicyNode tree below the PolicyNode
   1.476 + *  pointed to by "rootNode", with each line of output prefixed by the String
   1.477 + *  pointed to by "indent", and stores the result at "pTreeString". It is
   1.478 + *  called recursively, with ever-increasing indentation, for successively
   1.479 + *  lower nodes on the tree.
   1.480 + *
   1.481 + * PARAMETERS:
   1.482 + *  "rootNode"
   1.483 + *      Address of PolicyNode subtree. Must be non-NULL.
   1.484 + *  "indent"
   1.485 + *      Address of String to be prefixed to each line of output. May be NULL
   1.486 + *      if no indentation is desired
   1.487 + *  "pTreeString"
   1.488 + *      Address where the resulting String will be stored; must be non-NULL
   1.489 + *  "plContext"
   1.490 + *      Platform-specific context pointer.
   1.491 + * THREAD SAFETY:
   1.492 + *  Conditionally Thread Safe
   1.493 + *  (see Thread Safety Definitions in Programmer's Guide)
   1.494 + * RETURNS:
   1.495 + *  Returns NULL if the function succeeds.
   1.496 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1.497 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.498 + */
   1.499 +static PKIX_Error *
   1.500 +pkix_PolicyNode_ToString_Helper(
   1.501 +        PKIX_PolicyNode *rootNode,
   1.502 +        PKIX_PL_String *indent,
   1.503 +        PKIX_PL_String **pTreeString,
   1.504 +        void *plContext)
   1.505 +{
   1.506 +        PKIX_PL_String *nextIndentFormat = NULL;
   1.507 +        PKIX_PL_String *thisNodeFormat = NULL;
   1.508 +        PKIX_PL_String *childrenFormat = NULL;
   1.509 +        PKIX_PL_String *nextIndentString = NULL;
   1.510 +        PKIX_PL_String *resultString = NULL;
   1.511 +        PKIX_PL_String *thisItemString = NULL;
   1.512 +        PKIX_PL_String *childString = NULL;
   1.513 +        PKIX_PolicyNode *childNode = NULL;
   1.514 +        PKIX_UInt32 numberOfChildren = 0;
   1.515 +        PKIX_UInt32 childIndex = 0;
   1.516 +
   1.517 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString_Helper");
   1.518 +
   1.519 +        PKIX_NULLCHECK_TWO(rootNode, pTreeString);
   1.520 +
   1.521 +        /* Create a string for this node */
   1.522 +        PKIX_CHECK(pkix_SinglePolicyNode_ToString
   1.523 +                (rootNode, &thisItemString, plContext),
   1.524 +                PKIX_ERRORINSINGLEPOLICYNODETOSTRING);
   1.525 +
   1.526 +        if (indent) {
   1.527 +                PKIX_CHECK(PKIX_PL_String_Create
   1.528 +                        (PKIX_ESCASCII,
   1.529 +                        "%s%s",
   1.530 +                        0,
   1.531 +                        &thisNodeFormat,
   1.532 +                        plContext),
   1.533 +                        PKIX_ERRORCREATINGFORMATSTRING);
   1.534 +
   1.535 +                PKIX_CHECK(PKIX_PL_Sprintf
   1.536 +                        (&resultString,
   1.537 +                        plContext,
   1.538 +                        thisNodeFormat,
   1.539 +                        indent,
   1.540 +                        thisItemString),
   1.541 +                        PKIX_ERRORINSPRINTF);
   1.542 +        } else {
   1.543 +                PKIX_CHECK(PKIX_PL_String_Create
   1.544 +                        (PKIX_ESCASCII,
   1.545 +                        "%s",
   1.546 +                        0,
   1.547 +                        &thisNodeFormat,
   1.548 +                        plContext),
   1.549 +                        PKIX_ERRORCREATINGFORMATSTRING);
   1.550 +
   1.551 +                PKIX_CHECK(PKIX_PL_Sprintf
   1.552 +                        (&resultString,
   1.553 +                        plContext,
   1.554 +                        thisNodeFormat,
   1.555 +                        thisItemString),
   1.556 +                        PKIX_ERRORINSPRINTF);
   1.557 +        }
   1.558 +
   1.559 +        PKIX_DECREF(thisItemString);
   1.560 +        thisItemString = resultString;
   1.561 +
   1.562 +        /* if no children, we are done */
   1.563 +        if (rootNode->children) {
   1.564 +                PKIX_CHECK(PKIX_List_GetLength
   1.565 +                        (rootNode->children, &numberOfChildren, plContext),
   1.566 +                        PKIX_LISTGETLENGTHFAILED);
   1.567 +        }
   1.568 +
   1.569 +        if (numberOfChildren != 0) {
   1.570 +                /*
   1.571 +                 * We create a string for each child in turn,
   1.572 +                 * concatenating them to thisItemString.
   1.573 +                 */
   1.574 +
   1.575 +                /* Prepare an indent string for each child */
   1.576 +                if (indent) {
   1.577 +                        PKIX_CHECK(PKIX_PL_String_Create
   1.578 +                                (PKIX_ESCASCII,
   1.579 +                                "%s. ",
   1.580 +                                0,
   1.581 +                                &nextIndentFormat,
   1.582 +                                plContext),
   1.583 +                                PKIX_ERRORCREATINGFORMATSTRING);
   1.584 +
   1.585 +                        PKIX_CHECK(PKIX_PL_Sprintf
   1.586 +                                (&nextIndentString,
   1.587 +                                plContext,
   1.588 +                                nextIndentFormat,
   1.589 +                                indent),
   1.590 +                                PKIX_ERRORINSPRINTF);
   1.591 +                } else {
   1.592 +                        PKIX_CHECK(PKIX_PL_String_Create
   1.593 +                                (PKIX_ESCASCII,
   1.594 +                                ". ",
   1.595 +                                0,
   1.596 +                                &nextIndentString,
   1.597 +                                plContext),
   1.598 +                                PKIX_ERRORCREATINGINDENTSTRING);
   1.599 +                }
   1.600 +
   1.601 +                /* Prepare the format for concatenation. */
   1.602 +                PKIX_CHECK(PKIX_PL_String_Create
   1.603 +                        (PKIX_ESCASCII,
   1.604 +                        "%s\n%s",
   1.605 +                        0,
   1.606 +                        &childrenFormat,
   1.607 +                        plContext),
   1.608 +                        PKIX_ERRORCREATINGFORMATSTRING);
   1.609 +
   1.610 +                for (childIndex = 0;
   1.611 +                        childIndex < numberOfChildren;
   1.612 +                        childIndex++) {
   1.613 +                        PKIX_CHECK(PKIX_List_GetItem
   1.614 +                                (rootNode->children,
   1.615 +                                childIndex,
   1.616 +                                (PKIX_PL_Object **)&childNode,
   1.617 +                                plContext),
   1.618 +                                PKIX_LISTGETITEMFAILED);
   1.619 +
   1.620 +                        PKIX_CHECK(pkix_PolicyNode_ToString_Helper
   1.621 +                                (childNode,
   1.622 +                                nextIndentString,
   1.623 +                                &childString,
   1.624 +                                plContext),
   1.625 +                                PKIX_ERRORCREATINGCHILDSTRING);
   1.626 +
   1.627 +
   1.628 +                        PKIX_CHECK(PKIX_PL_Sprintf
   1.629 +                                (&resultString,
   1.630 +                                plContext,
   1.631 +                                childrenFormat,
   1.632 +                                thisItemString,
   1.633 +                                childString),
   1.634 +                        PKIX_ERRORINSPRINTF);
   1.635 +
   1.636 +                        PKIX_DECREF(childNode);
   1.637 +                        PKIX_DECREF(childString);
   1.638 +                        PKIX_DECREF(thisItemString);
   1.639 +
   1.640 +                        thisItemString = resultString;
   1.641 +                }
   1.642 +        }
   1.643 +
   1.644 +        *pTreeString = thisItemString;
   1.645 +
   1.646 +cleanup:
   1.647 +        if (PKIX_ERROR_RECEIVED) {
   1.648 +                PKIX_DECREF(thisItemString);
   1.649 +        }
   1.650 +
   1.651 +        PKIX_DECREF(nextIndentFormat);
   1.652 +        PKIX_DECREF(thisNodeFormat);
   1.653 +        PKIX_DECREF(childrenFormat);
   1.654 +        PKIX_DECREF(nextIndentString);
   1.655 +        PKIX_DECREF(childString);
   1.656 +        PKIX_DECREF(childNode);
   1.657 +
   1.658 +        PKIX_RETURN(CERTPOLICYNODE);
   1.659 +}
   1.660 +
   1.661 +/*
   1.662 + * FUNCTION: pkix_PolicyNode_ToString
   1.663 + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
   1.664 + */
   1.665 +static PKIX_Error *
   1.666 +pkix_PolicyNode_ToString(
   1.667 +        PKIX_PL_Object *object,
   1.668 +        PKIX_PL_String **pTreeString,
   1.669 +        void *plContext)
   1.670 +{
   1.671 +        PKIX_PolicyNode *rootNode = NULL;
   1.672 +        PKIX_PL_String *resultString = NULL;
   1.673 +
   1.674 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString");
   1.675 +
   1.676 +        PKIX_NULLCHECK_TWO(object, pTreeString);
   1.677 +
   1.678 +        PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
   1.679 +                PKIX_OBJECTNOTPOLICYNODE);
   1.680 +
   1.681 +        rootNode = (PKIX_PolicyNode *)object;
   1.682 +
   1.683 +        PKIX_CHECK(pkix_PolicyNode_ToString_Helper
   1.684 +                (rootNode, NULL, &resultString, plContext),
   1.685 +                PKIX_ERRORCREATINGSUBTREESTRING);
   1.686 +
   1.687 +        *pTreeString = resultString;
   1.688 +
   1.689 +cleanup:
   1.690 +
   1.691 +        PKIX_RETURN(CERTPOLICYNODE);
   1.692 +}
   1.693 +
   1.694 +/*
   1.695 + * FUNCTION: pkix_PolicyNode_Destroy
   1.696 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
   1.697 + */
   1.698 +static PKIX_Error *
   1.699 +pkix_PolicyNode_Destroy(
   1.700 +        PKIX_PL_Object *object,
   1.701 +        void *plContext)
   1.702 +{
   1.703 +        PKIX_PolicyNode *node = NULL;
   1.704 +
   1.705 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Destroy");
   1.706 +
   1.707 +        PKIX_NULLCHECK_ONE(object);
   1.708 +
   1.709 +        PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
   1.710 +                PKIX_OBJECTNOTPOLICYNODE);
   1.711 +
   1.712 +        node = (PKIX_PolicyNode*)object;
   1.713 +
   1.714 +        node->criticality = PKIX_FALSE;
   1.715 +        PKIX_DECREF(node->validPolicy);
   1.716 +        PKIX_DECREF(node->qualifierSet);
   1.717 +        PKIX_DECREF(node->expectedPolicySet);
   1.718 +        PKIX_DECREF(node->children);
   1.719 +
   1.720 +        /*
   1.721 +         * Note: the link to parent is not reference-counted. See comment
   1.722 +         * in pkix_PolicyNode_AddToParent for more details.
   1.723 +         */
   1.724 +        node->parent = NULL;
   1.725 +        node->depth = 0;
   1.726 +
   1.727 +cleanup:
   1.728 +
   1.729 +        PKIX_RETURN(CERTPOLICYNODE);
   1.730 +}
   1.731 +
   1.732 +/*
   1.733 + * FUNCTION: pkix_SinglePolicyNode_Hashcode
   1.734 + * DESCRIPTION:
   1.735 + *
   1.736 + *  Computes the hashcode of the attributes of the PolicyNode pointed to by
   1.737 + *  "node", other than its parents and children, and stores the result at
   1.738 + *  "pHashcode".
   1.739 + *
   1.740 + * PARAMETERS:
   1.741 + *  "node"
   1.742 + *      Address of PolicyNode to be hashcoded; must be non-NULL
   1.743 + *  "pHashcode"
   1.744 + *      Address where UInt32 result will be stored; must be non-NULL
   1.745 + *  "plContext"
   1.746 + *      Platform-specific context pointer.
   1.747 + * THREAD SAFETY:
   1.748 + *  Conditionally Thread Safe
   1.749 + *  (see Thread Safety Definitions in Programmer's Guide)
   1.750 + * RETURNS:
   1.751 + *  Returns NULL if function succeeds
   1.752 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1.753 + *  Returns a Fatal Error if the function fails in a fatal way
   1.754 + */
   1.755 +static PKIX_Error *
   1.756 +pkix_SinglePolicyNode_Hashcode(
   1.757 +        PKIX_PolicyNode *node,
   1.758 +        PKIX_UInt32 *pHashcode,
   1.759 +        void *plContext)
   1.760 +{
   1.761 +        PKIX_UInt32 componentHash = 0;
   1.762 +        PKIX_UInt32 nodeHash = 0;
   1.763 +
   1.764 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Hashcode");
   1.765 +        PKIX_NULLCHECK_TWO(node, pHashcode);
   1.766 +        PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
   1.767 +
   1.768 +        PKIX_HASHCODE
   1.769 +                (node->qualifierSet,
   1.770 +                &nodeHash,
   1.771 +                plContext,
   1.772 +                PKIX_FAILUREHASHINGLISTQUALIFIERSET);
   1.773 +
   1.774 +        if (PKIX_TRUE == (node->criticality)) {
   1.775 +                nodeHash = 31*nodeHash + 0xff;
   1.776 +        } else {
   1.777 +                nodeHash = 31*nodeHash + 0x00;
   1.778 +        }
   1.779 +
   1.780 +        PKIX_CHECK(PKIX_PL_Object_Hashcode
   1.781 +                ((PKIX_PL_Object *)node->validPolicy,
   1.782 +                &componentHash,
   1.783 +                plContext),
   1.784 +                PKIX_FAILUREHASHINGOIDVALIDPOLICY);
   1.785 +
   1.786 +        nodeHash = 31*nodeHash + componentHash;
   1.787 +
   1.788 +        PKIX_CHECK(PKIX_PL_Object_Hashcode
   1.789 +                ((PKIX_PL_Object *)node->expectedPolicySet,
   1.790 +                &componentHash,
   1.791 +                plContext),
   1.792 +                PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET);
   1.793 +
   1.794 +        nodeHash = 31*nodeHash + componentHash;
   1.795 +
   1.796 +        *pHashcode = nodeHash;
   1.797 +
   1.798 +cleanup:
   1.799 +
   1.800 +        PKIX_RETURN(CERTPOLICYNODE);
   1.801 +}
   1.802 +
   1.803 +/*
   1.804 + * FUNCTION: pkix_PolicyNode_Hashcode
   1.805 + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
   1.806 + */
   1.807 +static PKIX_Error *
   1.808 +pkix_PolicyNode_Hashcode(
   1.809 +        PKIX_PL_Object *object,
   1.810 +        PKIX_UInt32 *pHashcode,
   1.811 +        void *plContext)
   1.812 +{
   1.813 +        PKIX_PolicyNode *node = NULL;
   1.814 +        PKIX_UInt32 childrenHash = 0;
   1.815 +        PKIX_UInt32 nodeHash = 0;
   1.816 +
   1.817 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode");
   1.818 +        PKIX_NULLCHECK_TWO(object, pHashcode);
   1.819 +
   1.820 +        PKIX_CHECK(pkix_CheckType
   1.821 +                (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
   1.822 +                PKIX_OBJECTNOTPOLICYNODE);
   1.823 +
   1.824 +        node = (PKIX_PolicyNode *)object;
   1.825 +
   1.826 +        PKIX_CHECK(pkix_SinglePolicyNode_Hashcode
   1.827 +                (node, &nodeHash, plContext),
   1.828 +                PKIX_SINGLEPOLICYNODEHASHCODEFAILED);
   1.829 +
   1.830 +        nodeHash = 31*nodeHash + (PKIX_UInt32)(node->parent);
   1.831 +
   1.832 +        PKIX_HASHCODE
   1.833 +                (node->children,
   1.834 +                &childrenHash,
   1.835 +                plContext,
   1.836 +                PKIX_OBJECTHASHCODEFAILED);
   1.837 +
   1.838 +        nodeHash = 31*nodeHash + childrenHash;
   1.839 +
   1.840 +        *pHashcode = nodeHash;
   1.841 +
   1.842 +cleanup:
   1.843 +
   1.844 +        PKIX_RETURN(CERTPOLICYNODE);
   1.845 +}
   1.846 +
   1.847 +/*
   1.848 + * FUNCTION: pkix_SinglePolicyNode_Equals
   1.849 + * DESCRIPTION:
   1.850 + *
   1.851 + *  Compares for equality the components of the PolicyNode pointed to by
   1.852 + *  "firstPN", other than its parents and children, with those of the
   1.853 + *  PolicyNode pointed to by "secondPN" and stores the result at "pResult"
   1.854 + *  (PKIX_TRUE if equal; PKIX_FALSE if not).
   1.855 + *
   1.856 + * PARAMETERS:
   1.857 + *  "firstPN"
   1.858 + *      Address of first of the PolicyNodes to be compared; must be non-NULL
   1.859 + *  "secondPN"
   1.860 + *      Address of second of the PolicyNodes to be compared; must be non-NULL
   1.861 + *  "pResult"
   1.862 + *      Address where Boolean will be stored; must be non-NULL
   1.863 + *  "plContext"
   1.864 + *      Platform-specific context pointer.
   1.865 + * THREAD SAFETY:
   1.866 + *  Conditionally Thread Safe
   1.867 + *  (see Thread Safety Definitions in Programmer's Guide)
   1.868 + * RETURNS:
   1.869 + *  Returns NULL if function succeeds
   1.870 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1.871 + *  Returns a Fatal Error if the function fails in a fatal way
   1.872 + */
   1.873 +static PKIX_Error *
   1.874 +pkix_SinglePolicyNode_Equals(
   1.875 +        PKIX_PolicyNode *firstPN,
   1.876 +        PKIX_PolicyNode *secondPN,
   1.877 +        PKIX_Boolean *pResult,
   1.878 +        void *plContext)
   1.879 +{
   1.880 +        PKIX_Boolean compResult = PKIX_FALSE;
   1.881 +
   1.882 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Equals");
   1.883 +        PKIX_NULLCHECK_THREE(firstPN, secondPN, pResult);
   1.884 +
   1.885 +        /* If both references are identical, they must be equal */
   1.886 +        if (firstPN == secondPN) {
   1.887 +                compResult = PKIX_TRUE;
   1.888 +                goto cleanup;
   1.889 +        }
   1.890 +
   1.891 +        /*
   1.892 +         * It seems we have to do the comparisons. Do
   1.893 +         * the easiest ones first.
   1.894 +         */
   1.895 +        if ((firstPN->criticality) != (secondPN->criticality)) {
   1.896 +                goto cleanup;
   1.897 +        }
   1.898 +        if ((firstPN->depth) != (secondPN->depth)) {
   1.899 +                goto cleanup;
   1.900 +        }
   1.901 +
   1.902 +        PKIX_EQUALS
   1.903 +                (firstPN->qualifierSet,
   1.904 +                secondPN->qualifierSet,
   1.905 +                &compResult,
   1.906 +                plContext,
   1.907 +                PKIX_OBJECTEQUALSFAILED);
   1.908 +
   1.909 +        if (compResult == PKIX_FALSE) {
   1.910 +                goto cleanup;
   1.911 +        }
   1.912 +
   1.913 +        /* These fields must be non-NULL */
   1.914 +        PKIX_NULLCHECK_TWO(firstPN->validPolicy, secondPN->validPolicy);
   1.915 +
   1.916 +        PKIX_EQUALS
   1.917 +                (firstPN->validPolicy,
   1.918 +                secondPN->validPolicy,
   1.919 +                &compResult,
   1.920 +                plContext,
   1.921 +                PKIX_OBJECTEQUALSFAILED);
   1.922 +
   1.923 +        if (compResult == PKIX_FALSE) {
   1.924 +                goto cleanup;
   1.925 +        }
   1.926 +
   1.927 +        /* These fields must be non-NULL */
   1.928 +        PKIX_NULLCHECK_TWO
   1.929 +                (firstPN->expectedPolicySet, secondPN->expectedPolicySet);
   1.930 +
   1.931 +        PKIX_EQUALS
   1.932 +                (firstPN->expectedPolicySet,
   1.933 +                secondPN->expectedPolicySet,
   1.934 +                &compResult,
   1.935 +                plContext,
   1.936 +                PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS);
   1.937 +
   1.938 +cleanup:
   1.939 +
   1.940 +        *pResult = compResult;
   1.941 +
   1.942 +        PKIX_RETURN(CERTPOLICYNODE);
   1.943 +}
   1.944 +
   1.945 +/*
   1.946 + * FUNCTION: pkix_PolicyNode_Equals
   1.947 + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
   1.948 + */
   1.949 +static PKIX_Error *
   1.950 +pkix_PolicyNode_Equals(
   1.951 +        PKIX_PL_Object *firstObject,
   1.952 +        PKIX_PL_Object *secondObject,
   1.953 +        PKIX_Boolean *pResult,
   1.954 +        void *plContext)
   1.955 +{
   1.956 +        PKIX_PolicyNode *firstPN = NULL;
   1.957 +        PKIX_PolicyNode *secondPN = NULL;
   1.958 +        PKIX_UInt32 secondType;
   1.959 +        PKIX_Boolean compResult = PKIX_FALSE;
   1.960 +
   1.961 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Equals");
   1.962 +        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
   1.963 +
   1.964 +        /* test that firstObject is a PolicyNode */
   1.965 +        PKIX_CHECK(pkix_CheckType
   1.966 +                (firstObject, PKIX_CERTPOLICYNODE_TYPE, plContext),
   1.967 +                PKIX_FIRSTOBJECTNOTPOLICYNODE);
   1.968 +
   1.969 +        /*
   1.970 +         * Since we know firstObject is a PolicyNode,
   1.971 +         * if both references are identical, they must be equal
   1.972 +         */
   1.973 +        if (firstObject == secondObject){
   1.974 +                compResult = PKIX_TRUE;
   1.975 +                goto cleanup;
   1.976 +        }
   1.977 +
   1.978 +        /*
   1.979 +         * If secondObject isn't a PolicyNode, we
   1.980 +         * don't throw an error. We simply return FALSE.
   1.981 +         */
   1.982 +        PKIX_CHECK(PKIX_PL_Object_GetType
   1.983 +                    (secondObject, &secondType, plContext),
   1.984 +                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
   1.985 +
   1.986 +        if (secondType != PKIX_CERTPOLICYNODE_TYPE) {
   1.987 +                goto cleanup;
   1.988 +        }
   1.989 +
   1.990 +        /*
   1.991 +         * Oh, well, we have to do the comparisons. Do
   1.992 +         * the easiest ones first.
   1.993 +         */
   1.994 +        firstPN = (PKIX_PolicyNode *)firstObject;
   1.995 +        secondPN = (PKIX_PolicyNode *)secondObject;
   1.996 +
   1.997 +        /*
   1.998 +         * We don't require the parents to be identical. In the
   1.999 +         * course of traversing the tree, we will have checked the
  1.1000 +         * attributes of the parent nodes, and checking the lists
  1.1001 +         * of children will determine whether they match.
  1.1002 +         */
  1.1003 +
  1.1004 +        PKIX_EQUALS
  1.1005 +                (firstPN->children,
  1.1006 +                secondPN->children,
  1.1007 +                &compResult,
  1.1008 +                plContext,
  1.1009 +                PKIX_OBJECTEQUALSFAILEDONCHILDREN);
  1.1010 +
  1.1011 +        if (compResult == PKIX_FALSE) {
  1.1012 +                goto cleanup;
  1.1013 +        }
  1.1014 +
  1.1015 +        PKIX_CHECK(pkix_SinglePolicyNode_Equals
  1.1016 +                (firstPN, secondPN, &compResult, plContext),
  1.1017 +                PKIX_SINGLEPOLICYNODEEQUALSFAILED);
  1.1018 +
  1.1019 +cleanup:
  1.1020 +
  1.1021 +        *pResult = compResult;
  1.1022 +
  1.1023 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1024 +}
  1.1025 +
  1.1026 +/*
  1.1027 + * FUNCTION: pkix_PolicyNode_DuplicateHelper
  1.1028 + * DESCRIPTION:
  1.1029 + *
  1.1030 + *  Duplicates the PolicyNode whose address is pointed to by "original",
  1.1031 + *  and stores the result at "pNewNode", if a non-NULL pointer is provided
  1.1032 + *  for "pNewNode". In addition, the created PolicyNode is added as a child
  1.1033 + *  to "parent", if a non-NULL pointer is provided for "parent". Then this
  1.1034 + *  function is called recursively to duplicate each of the children of
  1.1035 + *  "original". At the top level this function is called with a null
  1.1036 + *  "parent" and a non-NULL "pNewNode". Below the top level "parent" will
  1.1037 + *  be non-NULL and "pNewNode" will be NULL.
  1.1038 + *
  1.1039 + * PARAMETERS:
  1.1040 + *  "original"
  1.1041 + *      Address of PolicyNode to be copied; must be non-NULL
  1.1042 + *  "parent"
  1.1043 + *      Address of PolicyNode to which the created node is to be added as a
  1.1044 + *      child; NULL for the top-level call and non-NULL below the top level
  1.1045 + *  "pNewNode"
  1.1046 + *      Address to store the node created; should be NULL if "parent" is
  1.1047 + *      non-NULL and vice versa
  1.1048 + *  "plContext"
  1.1049 + *      Platform-specific context pointer.
  1.1050 + * THREAD SAFETY:
  1.1051 + *  Conditionally Thread Safe
  1.1052 + *  (see Thread Safety Definitions in Programmer's Guide)
  1.1053 + * RETURNS:
  1.1054 + *  Returns NULL if function succeeds
  1.1055 + *  Returns a PolicyNode Error if the function fails in a non-fatal way.
  1.1056 + *  Returns a Fatal Error if the function fails in a fatal way
  1.1057 + */
  1.1058 +static PKIX_Error *
  1.1059 +pkix_PolicyNode_DuplicateHelper(
  1.1060 +        PKIX_PolicyNode *original,
  1.1061 +        PKIX_PolicyNode *parent,
  1.1062 +        PKIX_PolicyNode **pNewNode,
  1.1063 +        void *plContext)
  1.1064 +{
  1.1065 +        PKIX_UInt32 numChildren = 0;
  1.1066 +        PKIX_UInt32 childIndex = 0;
  1.1067 +        PKIX_List *children = NULL; /* List of PKIX_PolicyNode */
  1.1068 +        PKIX_PolicyNode *copy = NULL;
  1.1069 +        PKIX_PolicyNode *child = NULL;
  1.1070 +
  1.1071 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper");
  1.1072 +
  1.1073 +        PKIX_NULLCHECK_THREE
  1.1074 +                (original, original->validPolicy, original->expectedPolicySet);
  1.1075 +
  1.1076 +        /*
  1.1077 +         * These components are immutable, so copying the pointers
  1.1078 +         * is sufficient. The create function increments the reference
  1.1079 +         * counts as it stores the pointers into the new object.
  1.1080 +         */
  1.1081 +        PKIX_CHECK(pkix_PolicyNode_Create
  1.1082 +                (original->validPolicy,
  1.1083 +                original->qualifierSet,
  1.1084 +                original->criticality,
  1.1085 +                original->expectedPolicySet,
  1.1086 +                &copy,
  1.1087 +                plContext),
  1.1088 +                PKIX_POLICYNODECREATEFAILED);
  1.1089 +
  1.1090 +        if (parent) {
  1.1091 +                PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext),
  1.1092 +                        PKIX_POLICYNODEADDTOPARENTFAILED);
  1.1093 +        }
  1.1094 +
  1.1095 +        /* Are there any children to duplicate? */
  1.1096 +        children = original->children;
  1.1097 +
  1.1098 +        if (children) {
  1.1099 +            PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
  1.1100 +                PKIX_LISTGETLENGTHFAILED);
  1.1101 +        }
  1.1102 +
  1.1103 +        for (childIndex = 0; childIndex < numChildren; childIndex++) {
  1.1104 +                PKIX_CHECK(PKIX_List_GetItem
  1.1105 +                        (children,
  1.1106 +                        childIndex,
  1.1107 +                        (PKIX_PL_Object **)&child,
  1.1108 +                        plContext),
  1.1109 +                        PKIX_LISTGETITEMFAILED);
  1.1110 +
  1.1111 +                PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
  1.1112 +                        (child, copy, NULL, plContext),
  1.1113 +                        PKIX_POLICYNODEDUPLICATEHELPERFAILED);
  1.1114 +
  1.1115 +                PKIX_DECREF(child);
  1.1116 +        }
  1.1117 +
  1.1118 +        if (pNewNode) {
  1.1119 +                *pNewNode = copy;
  1.1120 +                copy = NULL; /* no DecRef if we give our handle away */
  1.1121 +        }
  1.1122 +
  1.1123 +cleanup:
  1.1124 +        PKIX_DECREF(copy);
  1.1125 +        PKIX_DECREF(child);
  1.1126 +
  1.1127 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1128 +}
  1.1129 +
  1.1130 +/*
  1.1131 + * FUNCTION: pkix_PolicyNode_Duplicate
  1.1132 + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
  1.1133 + */
  1.1134 +static PKIX_Error *
  1.1135 +pkix_PolicyNode_Duplicate(
  1.1136 +        PKIX_PL_Object *object,
  1.1137 +        PKIX_PL_Object **pNewObject,
  1.1138 +        void *plContext)
  1.1139 +{
  1.1140 +        PKIX_PolicyNode *original = NULL;
  1.1141 +        PKIX_PolicyNode *copy = NULL;
  1.1142 +
  1.1143 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate");
  1.1144 +
  1.1145 +        PKIX_NULLCHECK_TWO(object, pNewObject);
  1.1146 +
  1.1147 +        PKIX_CHECK(pkix_CheckType
  1.1148 +                (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
  1.1149 +                PKIX_OBJECTNOTPOLICYNODE);
  1.1150 +
  1.1151 +        original = (PKIX_PolicyNode *)object;
  1.1152 +
  1.1153 +        PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
  1.1154 +                (original, NULL, &copy, plContext),
  1.1155 +                PKIX_POLICYNODEDUPLICATEHELPERFAILED);
  1.1156 +
  1.1157 +        *pNewObject = (PKIX_PL_Object *)copy;
  1.1158 +
  1.1159 +cleanup:
  1.1160 +
  1.1161 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1162 +}
  1.1163 +
  1.1164 +/*
  1.1165 + * FUNCTION: pkix_PolicyNode_RegisterSelf
  1.1166 + * DESCRIPTION:
  1.1167 + *
  1.1168 + *  Registers PKIX_CERTPOLICYNODE_TYPE and its related
  1.1169 + *  functions with systemClasses[]
  1.1170 + *
  1.1171 + * THREAD SAFETY:
  1.1172 + *  Not Thread Safe - for performance and complexity reasons
  1.1173 + *
  1.1174 + *  Since this function is only called by PKIX_PL_Initialize,
  1.1175 + *  which should only be called once, it is acceptable that
  1.1176 + *  this function is not thread-safe.
  1.1177 + */
  1.1178 +PKIX_Error *
  1.1179 +pkix_PolicyNode_RegisterSelf(void *plContext)
  1.1180 +{
  1.1181 +
  1.1182 +        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
  1.1183 +        pkix_ClassTable_Entry entry;
  1.1184 +
  1.1185 +        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_RegisterSelf");
  1.1186 +
  1.1187 +        entry.description = "PolicyNode";
  1.1188 +        entry.objCounter = 0;
  1.1189 +        entry.typeObjectSize = sizeof(PKIX_PolicyNode);
  1.1190 +        entry.destructor = pkix_PolicyNode_Destroy;
  1.1191 +        entry.equalsFunction = pkix_PolicyNode_Equals;
  1.1192 +        entry.hashcodeFunction = pkix_PolicyNode_Hashcode;
  1.1193 +        entry.toStringFunction = pkix_PolicyNode_ToString;
  1.1194 +        entry.comparator = NULL;
  1.1195 +        entry.duplicateFunction = pkix_PolicyNode_Duplicate;
  1.1196 +
  1.1197 +        systemClasses[PKIX_CERTPOLICYNODE_TYPE] = entry;
  1.1198 +
  1.1199 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1200 +}
  1.1201 +
  1.1202 +
  1.1203 +/* --Public-PolicyNode-Functions----------------------------------- */
  1.1204 +
  1.1205 +/*
  1.1206 + * FUNCTION: PKIX_PolicyNode_GetChildren
  1.1207 + * (see description of this function in pkix_results.h)
  1.1208 + */
  1.1209 +PKIX_Error *
  1.1210 +PKIX_PolicyNode_GetChildren(
  1.1211 +        PKIX_PolicyNode *node,
  1.1212 +        PKIX_List **pChildren,  /* list of PKIX_PolicyNode */
  1.1213 +        void *plContext)
  1.1214 +{
  1.1215 +        PKIX_List *children = NULL;
  1.1216 +
  1.1217 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetChildren");
  1.1218 +
  1.1219 +        PKIX_NULLCHECK_TWO(node, pChildren);
  1.1220 +
  1.1221 +        PKIX_INCREF(node->children);
  1.1222 +        children = node->children;
  1.1223 +
  1.1224 +        if (!children) {
  1.1225 +                PKIX_CHECK(PKIX_List_Create(&children, plContext),
  1.1226 +                        PKIX_LISTCREATEFAILED);
  1.1227 +        }
  1.1228 +
  1.1229 +        PKIX_CHECK(PKIX_List_SetImmutable(children, plContext),
  1.1230 +                PKIX_LISTSETIMMUTABLEFAILED);
  1.1231 +
  1.1232 +        *pChildren = children;
  1.1233 +
  1.1234 +cleanup:
  1.1235 +        if (PKIX_ERROR_RECEIVED) {
  1.1236 +                PKIX_DECREF(children);
  1.1237 +        }
  1.1238 +
  1.1239 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1240 +}
  1.1241 +
  1.1242 +/*
  1.1243 + * FUNCTION: PKIX_PolicyNode_GetParent
  1.1244 + * (see description of this function in pkix_results.h)
  1.1245 + */
  1.1246 +PKIX_Error *
  1.1247 +PKIX_PolicyNode_GetParent(
  1.1248 +        PKIX_PolicyNode *node,
  1.1249 +        PKIX_PolicyNode **pParent,
  1.1250 +        void *plContext)
  1.1251 +{
  1.1252 +
  1.1253 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetParent");
  1.1254 +
  1.1255 +        PKIX_NULLCHECK_TWO(node, pParent);
  1.1256 +
  1.1257 +        PKIX_INCREF(node->parent);
  1.1258 +        *pParent = node->parent;
  1.1259 +
  1.1260 +cleanup:
  1.1261 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1262 +}
  1.1263 +
  1.1264 +/*
  1.1265 + * FUNCTION: PKIX_PolicyNode_GetValidPolicy
  1.1266 + * (see description of this function in pkix_results.h)
  1.1267 + */
  1.1268 +PKIX_Error *
  1.1269 +PKIX_PolicyNode_GetValidPolicy(
  1.1270 +        PKIX_PolicyNode *node,
  1.1271 +        PKIX_PL_OID **pValidPolicy,
  1.1272 +        void *plContext)
  1.1273 +{
  1.1274 +
  1.1275 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetValidPolicy");
  1.1276 +
  1.1277 +        PKIX_NULLCHECK_TWO(node, pValidPolicy);
  1.1278 +
  1.1279 +        PKIX_INCREF(node->validPolicy);
  1.1280 +        *pValidPolicy = node->validPolicy;
  1.1281 +
  1.1282 +cleanup:
  1.1283 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1284 +}
  1.1285 +
  1.1286 +/*
  1.1287 + * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers
  1.1288 + * (see description of this function in pkix_results.h)
  1.1289 + */
  1.1290 +PKIX_Error *
  1.1291 +PKIX_PolicyNode_GetPolicyQualifiers(
  1.1292 +        PKIX_PolicyNode *node,
  1.1293 +        PKIX_List **pQualifiers,  /* list of PKIX_PL_CertPolicyQualifier */
  1.1294 +        void *plContext)
  1.1295 +{
  1.1296 +        PKIX_List *qualifiers = NULL;
  1.1297 +
  1.1298 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetPolicyQualifiers");
  1.1299 +
  1.1300 +        PKIX_NULLCHECK_TWO(node, pQualifiers);
  1.1301 +
  1.1302 +        PKIX_INCREF(node->qualifierSet);
  1.1303 +        qualifiers = node->qualifierSet;
  1.1304 +
  1.1305 +        if (!qualifiers) {
  1.1306 +                PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
  1.1307 +                        PKIX_LISTCREATEFAILED);
  1.1308 +        }
  1.1309 +
  1.1310 +        PKIX_CHECK(PKIX_List_SetImmutable(qualifiers, plContext),
  1.1311 +                PKIX_LISTSETIMMUTABLEFAILED);
  1.1312 +
  1.1313 +        *pQualifiers = qualifiers;
  1.1314 +
  1.1315 +cleanup:
  1.1316 +
  1.1317 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1318 +}
  1.1319 +
  1.1320 +/*
  1.1321 + * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies
  1.1322 + * (see description of this function in pkix_results.h)
  1.1323 + */
  1.1324 +PKIX_Error *
  1.1325 +PKIX_PolicyNode_GetExpectedPolicies(
  1.1326 +        PKIX_PolicyNode *node,
  1.1327 +        PKIX_List **pExpPolicies,  /* list of PKIX_PL_OID */
  1.1328 +        void *plContext)
  1.1329 +{
  1.1330 +
  1.1331 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetExpectedPolicies");
  1.1332 +
  1.1333 +        PKIX_NULLCHECK_TWO(node, pExpPolicies);
  1.1334 +
  1.1335 +        PKIX_INCREF(node->expectedPolicySet);
  1.1336 +        *pExpPolicies = node->expectedPolicySet;
  1.1337 +
  1.1338 +cleanup:
  1.1339 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1340 +}
  1.1341 +
  1.1342 +/*
  1.1343 + * FUNCTION: PKIX_PolicyNode_IsCritical
  1.1344 + * (see description of this function in pkix_results.h)
  1.1345 + */
  1.1346 +PKIX_Error *
  1.1347 +PKIX_PolicyNode_IsCritical(
  1.1348 +        PKIX_PolicyNode *node,
  1.1349 +        PKIX_Boolean *pCritical,
  1.1350 +        void *plContext)
  1.1351 +{
  1.1352 +
  1.1353 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_IsCritical");
  1.1354 +
  1.1355 +        PKIX_NULLCHECK_TWO(node, pCritical);
  1.1356 +
  1.1357 +        *pCritical = node->criticality;
  1.1358 +
  1.1359 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1360 +}
  1.1361 +
  1.1362 +/*
  1.1363 + * FUNCTION: PKIX_PolicyNode_GetDepth
  1.1364 + * (see description of this function in pkix_results.h)
  1.1365 + */
  1.1366 +PKIX_Error *
  1.1367 +PKIX_PolicyNode_GetDepth(
  1.1368 +        PKIX_PolicyNode *node,
  1.1369 +        PKIX_UInt32 *pDepth,
  1.1370 +        void *plContext)
  1.1371 +{
  1.1372 +
  1.1373 +        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetDepth");
  1.1374 +
  1.1375 +        PKIX_NULLCHECK_TWO(node, pDepth);
  1.1376 +
  1.1377 +        *pDepth = node->depth;
  1.1378 +
  1.1379 +        PKIX_RETURN(CERTPOLICYNODE);
  1.1380 +}

mercurial