tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_policynode.c (43671B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_policynode.c
      6 *
      7 * Policy Node Object Type Definition
      8 *
      9 */
     10 
     11 #include "pkix_policynode.h"
     12 
     13 /* --Private-PolicyNode-Functions---------------------------------- */
     14 
     15 /*
     16 * FUNCTION: pkix_PolicyNode_GetChildrenMutable
     17 * DESCRIPTION:
     18 *
     19 *  Retrieves the List of PolicyNodes representing the child nodes of the
     20 *  Policy Node pointed to by "node" and stores it at "pChildren". If "node"
     21 *  has no List of child nodes, this function stores NULL at "pChildren".
     22 *
     23 *  Note that the List returned by this function may be mutable. This function
     24 *  differs from the public function PKIX_PolicyNode_GetChildren in that
     25 *  respect. (It also differs in that the public function creates an empty
     26 *  List, if necessary, rather than storing NULL.)
     27 *
     28 *  During certificate processing, children Lists are created and modified.
     29 *  Once the list is accessed using the public call, the List is set immutable.
     30 *
     31 * PARAMETERS:
     32 *  "node"
     33 *      Address of PolicyNode whose child nodes are to be stored.
     34 *      Must be non-NULL.
     35 *  "pChildren"
     36 *      Address where object pointer will be stored. Must be non-NULL.
     37 *  "plContext"
     38 *      Platform-specific context pointer.
     39 * THREAD SAFETY:
     40 *  Conditionally Thread Safe
     41 *  (see Thread Safety Definitions in Programmer's Guide)
     42 * RETURNS:
     43 *  Returns NULL if the function succeeds.
     44 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
     45 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     46 */
     47 PKIX_Error *
     48 pkix_PolicyNode_GetChildrenMutable(
     49        PKIX_PolicyNode *node,
     50        PKIX_List **pChildren,  /* list of PKIX_PolicyNode */
     51        void *plContext)
     52 {
     53 
     54        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_GetChildrenMutable");
     55 
     56        PKIX_NULLCHECK_TWO(node, pChildren);
     57 
     58        PKIX_INCREF(node->children);
     59 
     60        *pChildren = node->children;
     61 
     62 cleanup:
     63        PKIX_RETURN(CERTPOLICYNODE);
     64 }
     65 
     66 /*
     67 * FUNCTION: pkix_PolicyNode_Create
     68 * DESCRIPTION:
     69 *
     70 *  Creates a new PolicyNode using the OID pointed to by "validPolicy", the List
     71 *  of CertPolicyQualifiers pointed to by "qualifierSet", the criticality
     72 *  indicated by the Boolean value of "criticality", and the List of OIDs
     73 *  pointed to by "expectedPolicySet", and stores the result at "pObject". The
     74 *  criticality should be derived from whether the certificate policy extension
     75 *  was marked as critical in the certificate that led to creation of this
     76 *  PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made
     77 *  immutable. The PolicyNode pointers to parent and to children are initialized
     78 *  to NULL, and the depth is set to zero; those values should be set by using
     79 *  the pkix_PolicyNode_AddToParent function.
     80 *
     81 * PARAMETERS
     82 *  "validPolicy"
     83 *      Address of OID of the valid policy for the path. Must be non-NULL
     84 *  "qualifierSet"
     85 *      Address of List of CertPolicyQualifiers associated with the validpolicy.
     86 *      May be NULL
     87 *  "criticality"
     88 *      Boolean indicator of whether the criticality should be set in this
     89 *      PolicyNode
     90 *  "expectedPolicySet"
     91 *      Address of List of OIDs that would satisfy this policy in the next
     92 *      certificate. Must be non-NULL
     93 *  "pObject"
     94 *      Address where the PolicyNode pointer will be stored. Must be non-NULL.
     95 *  "plContext"
     96 *      Platform-specific context pointer.
     97 * THREAD SAFETY:
     98 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     99 * RETURNS:
    100 *  Returns NULL if the function succeeds.
    101 *  Returns a PolicyNode Error if the function fails  in a non-fatal way.
    102 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    103 */
    104 PKIX_Error *
    105 pkix_PolicyNode_Create(
    106        PKIX_PL_OID *validPolicy,
    107        PKIX_List *qualifierSet,
    108        PKIX_Boolean criticality,
    109        PKIX_List *expectedPolicySet,
    110        PKIX_PolicyNode **pObject,
    111        void *plContext)
    112 {
    113        PKIX_PolicyNode *node = NULL;
    114 
    115        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Create");
    116 
    117        PKIX_NULLCHECK_THREE(validPolicy, expectedPolicySet, pObject);
    118 
    119        PKIX_CHECK(PKIX_PL_Object_Alloc
    120                (PKIX_CERTPOLICYNODE_TYPE,
    121                sizeof (PKIX_PolicyNode),
    122                (PKIX_PL_Object **)&node,
    123                plContext),
    124                PKIX_COULDNOTCREATEPOLICYNODEOBJECT);
    125 
    126        PKIX_INCREF(validPolicy);
    127        node->validPolicy = validPolicy;
    128 
    129        PKIX_INCREF(qualifierSet);
    130        node->qualifierSet = qualifierSet;
    131        if (qualifierSet) {
    132                PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet, plContext),
    133                        PKIX_LISTSETIMMUTABLEFAILED);
    134        }
    135 
    136        node->criticality = criticality;
    137 
    138        PKIX_INCREF(expectedPolicySet);
    139        node->expectedPolicySet = expectedPolicySet;
    140        PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet, plContext),
    141                PKIX_LISTSETIMMUTABLEFAILED);
    142 
    143        node->parent = NULL;
    144        node->children = NULL;
    145        node->depth = 0;
    146 
    147        *pObject = node;
    148        node = NULL;
    149 
    150 cleanup:
    151 
    152        PKIX_DECREF(node);
    153 
    154        PKIX_RETURN(CERTPOLICYNODE);
    155 }
    156 
    157 /*
    158 * FUNCTION: pkix_PolicyNode_AddToParent
    159 * DESCRIPTION:
    160 *
    161 *  Adds the PolicyNode pointed to by "child" to the List of children of
    162 *  the PolicyNode pointed to by "parentNode". If "parentNode" had a
    163 *  NULL pointer for the List of children, a new List is created containing
    164 *  "child". Otherwise "child" is appended to the existing List. The
    165 *  parent field in "child" is set to "parent", and the depth field is
    166 *  set to one more than the corresponding value in "parent".
    167 *
    168 *  Depth, in this context, means distance from the root node, which
    169 *  is at depth zero.
    170 *
    171 * PARAMETERS:
    172 *  "parentNode"
    173 *      Address of PolicyNode whose List of child PolicyNodes is to be
    174 *      created or appended to. Must be non-NULL.
    175 *  "child"
    176 *      Address of PolicyNode to be added to parentNode's List. Must be
    177 *      non-NULL.
    178 *  "plContext"
    179 *      Platform-specific context pointer.
    180 * THREAD SAFETY:
    181 *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    182 * RETURNS:
    183 *  Returns NULL if the function succeeds.
    184 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    185 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    186 */
    187 PKIX_Error *
    188 pkix_PolicyNode_AddToParent(
    189        PKIX_PolicyNode *parentNode,
    190        PKIX_PolicyNode *child,
    191        void *plContext)
    192 {
    193        PKIX_List *listOfChildren = NULL;
    194 
    195        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_AddToParent");
    196 
    197        PKIX_NULLCHECK_TWO(parentNode, child);
    198 
    199        listOfChildren = parentNode->children;
    200        if (listOfChildren == NULL) {
    201                PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
    202                        PKIX_LISTCREATEFAILED);
    203                parentNode->children = listOfChildren;
    204        }
    205 
    206        /*
    207         * Note: this link is not reference-counted. The link from parent
    208         * to child is counted (actually, the parent "owns" a List which
    209         * "owns" children), but the children do not "own" the parent.
    210         * Otherwise, there would be loops.
    211         */
    212        child->parent = parentNode;
    213 
    214        child->depth = 1 + (parentNode->depth);
    215 
    216        PKIX_CHECK(PKIX_List_AppendItem
    217                (listOfChildren, (PKIX_PL_Object *)child, plContext),
    218                PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST);
    219 
    220        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
    221                ((PKIX_PL_Object *)parentNode, plContext),
    222                PKIX_OBJECTINVALIDATECACHEFAILED);
    223 
    224        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
    225                ((PKIX_PL_Object *)child, plContext),
    226                PKIX_OBJECTINVALIDATECACHEFAILED);
    227 
    228 cleanup:
    229 
    230        PKIX_RETURN(CERTPOLICYNODE);
    231 }
    232 
    233 /*
    234 * FUNCTION: pkix_PolicyNode_Prune
    235 * DESCRIPTION:
    236 *
    237 *  Prunes a tree below the PolicyNode whose address is pointed to by "node",
    238 *  using the UInt32 value of "height" as the distance from the leaf level,
    239 *  and storing at "pDelete" the Boolean value of whether this PolicyNode is,
    240 *  after pruning, childless and should be pruned.
    241 *
    242 *  Any PolicyNode at height 0 is allowed to survive. If the height is greater
    243 *  than zero, pkix_PolicyNode_Prune is called recursively for each child of
    244 *  the current PolicyNode. After this process, a node with no children
    245 *  stores PKIX_TRUE in "pDelete" to indicate that it should be deleted.
    246 *
    247 * PARAMETERS:
    248 *  "node"
    249 *      Address of the PolicyNode to be pruned. Must be non-NULL.
    250 *  "height"
    251 *      UInt32 value for the distance from the leaf level
    252 *  "pDelete"
    253 *      Address to store the Boolean return value of PKIX_TRUE if this node
    254 *      should be pruned, or PKIX_FALSE if there remains at least one
    255 *      branch of the required height. Must be non-NULL.
    256 *  "plContext"
    257 *      Platform-specific context pointer.
    258 * THREAD SAFETY:
    259 *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    260 * RETURNS:
    261 *  Returns NULL if the function succeeds.
    262 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    263 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    264 */
    265 PKIX_Error *
    266 pkix_PolicyNode_Prune(
    267        PKIX_PolicyNode *node,
    268        PKIX_UInt32 height,
    269        PKIX_Boolean *pDelete,
    270        void *plContext)
    271 {
    272        PKIX_Boolean childless = PKIX_FALSE;
    273        PKIX_Boolean shouldBePruned = PKIX_FALSE;
    274        PKIX_UInt32 listSize = 0;
    275        PKIX_UInt32 listIndex = 0;
    276        PKIX_PolicyNode *candidate = NULL;
    277 
    278        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Prune");
    279 
    280        PKIX_NULLCHECK_TWO(node, pDelete);
    281 
    282        /* Don't prune at the leaf */
    283        if (height == 0) {
    284                goto cleanup;
    285        }
    286 
    287        /* Above the bottom level, childless nodes get pruned */
    288        if (!(node->children)) {
    289                childless = PKIX_TRUE;
    290                goto cleanup;
    291        }
    292 
    293        /*
    294         * This node has children. If they are leaf nodes,
    295         * we know they will live. Otherwise, check them out.
    296         */
    297        if (height > 1) {
    298                PKIX_CHECK(PKIX_List_GetLength
    299                        (node->children, &listSize, plContext),
    300                        PKIX_LISTGETLENGTHFAILED);
    301                /*
    302                 * By working backwards from the end of the list,
    303                 * we avoid having to worry about possible
    304                 * decreases in the size of the list, as we
    305                 * delete items. The only nuisance is that since the
    306                 * index is UInt32, we can't check for it to reach -1;
    307                 * we have to use the 1-based index, rather than the
    308                 * 0-based index that PKIX_List functions require.
    309                 */
    310                for (listIndex = listSize; listIndex > 0; listIndex--) {
    311                        PKIX_CHECK(PKIX_List_GetItem
    312                                (node->children,
    313                                (listIndex - 1),
    314                                (PKIX_PL_Object **)&candidate,
    315                                plContext),
    316                                PKIX_LISTGETITEMFAILED);
    317 
    318                        PKIX_CHECK(pkix_PolicyNode_Prune
    319                                (candidate,
    320                                height - 1,
    321                                &shouldBePruned,
    322                                plContext),
    323                                PKIX_POLICYNODEPRUNEFAILED);
    324 
    325                        if (shouldBePruned == PKIX_TRUE) {
    326                                PKIX_CHECK(PKIX_List_DeleteItem
    327                                        (node->children,
    328                                        (listIndex - 1),
    329                                        plContext),
    330                                        PKIX_LISTDELETEITEMFAILED);
    331                        }
    332 
    333                        PKIX_DECREF(candidate);
    334                }
    335        }
    336 
    337        /* Prune if this node has *become* childless */
    338        PKIX_CHECK(PKIX_List_GetLength
    339                (node->children, &listSize, plContext),
    340                PKIX_LISTGETLENGTHFAILED);
    341        if (listSize == 0) {
    342                childless = PKIX_TRUE;
    343        }
    344 
    345        /*
    346         * Even if we did not change this node, or any of its children,
    347         * maybe a [great-]*grandchild was pruned.
    348         */
    349        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
    350                ((PKIX_PL_Object *)node, plContext),
    351                PKIX_OBJECTINVALIDATECACHEFAILED);
    352 
    353 cleanup:
    354        *pDelete = childless;
    355 
    356        PKIX_DECREF(candidate);
    357 
    358        PKIX_RETURN(CERTPOLICYNODE);
    359 }
    360 
    361 /*
    362 * FUNCTION: pkix_SinglePolicyNode_ToString
    363 * DESCRIPTION:
    364 *
    365 *  Creates a String representation of the attributes of the PolicyNode
    366 *  pointed to by "node", other than its parents or children, and
    367 *  stores the result at "pString".
    368 *
    369 * PARAMETERS:
    370 *  "node"
    371 *      Address of PolicyNode to be described by the string. Must be non-NULL.
    372 *  "pString"
    373 *      Address where object pointer will be stored. Must be non-NULL.
    374 *  "plContext"
    375 *      Platform-specific context pointer.
    376 * THREAD SAFETY:
    377 *  Conditionally Thread Safe
    378 *  (see Thread Safety Definitions in Programmer's Guide)
    379 * RETURNS:
    380 *  Returns NULL if function succeeds
    381 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    382 *  Returns a Fatal Error if the function fails in a fatal way
    383 */
    384 PKIX_Error *
    385 pkix_SinglePolicyNode_ToString(
    386        PKIX_PolicyNode *node,
    387        PKIX_PL_String **pString,
    388        void *plContext)
    389 {
    390        PKIX_PL_String *fmtString = NULL;
    391        PKIX_PL_String *validString = NULL;
    392        PKIX_PL_String *qualifierString = NULL;
    393        PKIX_PL_String *criticalityString = NULL;
    394        PKIX_PL_String *expectedString = NULL;
    395        PKIX_PL_String *outString = NULL;
    396 
    397        PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_ToString");
    398        PKIX_NULLCHECK_TWO(node, pString);
    399        PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
    400 
    401        PKIX_CHECK(PKIX_PL_String_Create
    402                (PKIX_ESCASCII,
    403                "{%s,%s,%s,%s,%d}",
    404                0,
    405                &fmtString,
    406                plContext),
    407                PKIX_CANTCREATESTRING);
    408 
    409        PKIX_CHECK(PKIX_PL_Object_ToString
    410                ((PKIX_PL_Object *)(node->validPolicy),
    411                &validString,
    412                plContext),
    413                PKIX_OIDTOSTRINGFAILED);
    414 
    415        PKIX_CHECK(PKIX_PL_Object_ToString
    416                ((PKIX_PL_Object *)(node->expectedPolicySet),
    417                &expectedString,
    418                plContext),
    419                PKIX_LISTTOSTRINGFAILED);
    420 
    421        if (node->qualifierSet) {
    422                PKIX_CHECK(PKIX_PL_Object_ToString
    423                        ((PKIX_PL_Object *)(node->qualifierSet),
    424                        &qualifierString,
    425                        plContext),
    426                        PKIX_LISTTOSTRINGFAILED);
    427        } else {
    428                PKIX_CHECK(PKIX_PL_String_Create
    429                        (PKIX_ESCASCII,
    430                        "{}",
    431                        0,
    432                        &qualifierString,
    433                        plContext),
    434                        PKIX_CANTCREATESTRING);
    435        }
    436 
    437        PKIX_CHECK(PKIX_PL_String_Create
    438                (PKIX_ESCASCII,
    439                (node->criticality)?"Critical":"Not Critical",
    440                0,
    441                &criticalityString,
    442                plContext),
    443                PKIX_CANTCREATESTRING);
    444 
    445        PKIX_CHECK(PKIX_PL_Sprintf
    446                (&outString,
    447                plContext,
    448                fmtString,
    449                validString,
    450                qualifierString,
    451                criticalityString,
    452                expectedString,
    453                node->depth),
    454                PKIX_SPRINTFFAILED);
    455 
    456        *pString = outString;
    457 
    458 cleanup:
    459 
    460        PKIX_DECREF(fmtString);
    461        PKIX_DECREF(validString);
    462        PKIX_DECREF(qualifierString);
    463        PKIX_DECREF(criticalityString);
    464        PKIX_DECREF(expectedString);
    465        PKIX_RETURN(CERTPOLICYNODE);
    466 }
    467 
    468 /*
    469 * FUNCTION: pkix_PolicyNode_ToString_Helper
    470 * DESCRIPTION:
    471 *
    472 *  Produces a String representation of a PolicyNode tree below the PolicyNode
    473 *  pointed to by "rootNode", with each line of output prefixed by the String
    474 *  pointed to by "indent", and stores the result at "pTreeString". It is
    475 *  called recursively, with ever-increasing indentation, for successively
    476 *  lower nodes on the tree.
    477 *
    478 * PARAMETERS:
    479 *  "rootNode"
    480 *      Address of PolicyNode subtree. Must be non-NULL.
    481 *  "indent"
    482 *      Address of String to be prefixed to each line of output. May be NULL
    483 *      if no indentation is desired
    484 *  "pTreeString"
    485 *      Address where the resulting String will be stored; must be non-NULL
    486 *  "plContext"
    487 *      Platform-specific context pointer.
    488 * THREAD SAFETY:
    489 *  Conditionally Thread Safe
    490 *  (see Thread Safety Definitions in Programmer's Guide)
    491 * RETURNS:
    492 *  Returns NULL if the function succeeds.
    493 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    494 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    495 */
    496 static PKIX_Error *
    497 pkix_PolicyNode_ToString_Helper(
    498        PKIX_PolicyNode *rootNode,
    499        PKIX_PL_String *indent,
    500        PKIX_PL_String **pTreeString,
    501        void *plContext)
    502 {
    503        PKIX_PL_String *nextIndentFormat = NULL;
    504        PKIX_PL_String *thisNodeFormat = NULL;
    505        PKIX_PL_String *childrenFormat = NULL;
    506        PKIX_PL_String *nextIndentString = NULL;
    507        PKIX_PL_String *resultString = NULL;
    508        PKIX_PL_String *thisItemString = NULL;
    509        PKIX_PL_String *childString = NULL;
    510        PKIX_PolicyNode *childNode = NULL;
    511        PKIX_UInt32 numberOfChildren = 0;
    512        PKIX_UInt32 childIndex = 0;
    513 
    514        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString_Helper");
    515 
    516        PKIX_NULLCHECK_TWO(rootNode, pTreeString);
    517 
    518        /* Create a string for this node */
    519        PKIX_CHECK(pkix_SinglePolicyNode_ToString
    520                (rootNode, &thisItemString, plContext),
    521                PKIX_ERRORINSINGLEPOLICYNODETOSTRING);
    522 
    523        if (indent) {
    524                PKIX_CHECK(PKIX_PL_String_Create
    525                        (PKIX_ESCASCII,
    526                        "%s%s",
    527                        0,
    528                        &thisNodeFormat,
    529                        plContext),
    530                        PKIX_ERRORCREATINGFORMATSTRING);
    531 
    532                PKIX_CHECK(PKIX_PL_Sprintf
    533                        (&resultString,
    534                        plContext,
    535                        thisNodeFormat,
    536                        indent,
    537                        thisItemString),
    538                        PKIX_ERRORINSPRINTF);
    539        } else {
    540                PKIX_CHECK(PKIX_PL_String_Create
    541                        (PKIX_ESCASCII,
    542                        "%s",
    543                        0,
    544                        &thisNodeFormat,
    545                        plContext),
    546                        PKIX_ERRORCREATINGFORMATSTRING);
    547 
    548                PKIX_CHECK(PKIX_PL_Sprintf
    549                        (&resultString,
    550                        plContext,
    551                        thisNodeFormat,
    552                        thisItemString),
    553                        PKIX_ERRORINSPRINTF);
    554        }
    555 
    556        PKIX_DECREF(thisItemString);
    557        thisItemString = resultString;
    558 
    559        /* if no children, we are done */
    560        if (rootNode->children) {
    561                PKIX_CHECK(PKIX_List_GetLength
    562                        (rootNode->children, &numberOfChildren, plContext),
    563                        PKIX_LISTGETLENGTHFAILED);
    564        }
    565 
    566        if (numberOfChildren != 0) {
    567                /*
    568                 * We create a string for each child in turn,
    569                 * concatenating them to thisItemString.
    570                 */
    571 
    572                /* Prepare an indent string for each child */
    573                if (indent) {
    574                        PKIX_CHECK(PKIX_PL_String_Create
    575                                (PKIX_ESCASCII,
    576                                "%s. ",
    577                                0,
    578                                &nextIndentFormat,
    579                                plContext),
    580                                PKIX_ERRORCREATINGFORMATSTRING);
    581 
    582                        PKIX_CHECK(PKIX_PL_Sprintf
    583                                (&nextIndentString,
    584                                plContext,
    585                                nextIndentFormat,
    586                                indent),
    587                                PKIX_ERRORINSPRINTF);
    588                } else {
    589                        PKIX_CHECK(PKIX_PL_String_Create
    590                                (PKIX_ESCASCII,
    591                                ". ",
    592                                0,
    593                                &nextIndentString,
    594                                plContext),
    595                                PKIX_ERRORCREATINGINDENTSTRING);
    596                }
    597 
    598                /* Prepare the format for concatenation. */
    599                PKIX_CHECK(PKIX_PL_String_Create
    600                        (PKIX_ESCASCII,
    601                        "%s\n%s",
    602                        0,
    603                        &childrenFormat,
    604                        plContext),
    605                        PKIX_ERRORCREATINGFORMATSTRING);
    606 
    607                for (childIndex = 0;
    608                        childIndex < numberOfChildren;
    609                        childIndex++) {
    610                        PKIX_CHECK(PKIX_List_GetItem
    611                                (rootNode->children,
    612                                childIndex,
    613                                (PKIX_PL_Object **)&childNode,
    614                                plContext),
    615                                PKIX_LISTGETITEMFAILED);
    616 
    617                        PKIX_CHECK(pkix_PolicyNode_ToString_Helper
    618                                (childNode,
    619                                nextIndentString,
    620                                &childString,
    621                                plContext),
    622                                PKIX_ERRORCREATINGCHILDSTRING);
    623 
    624 
    625                        PKIX_CHECK(PKIX_PL_Sprintf
    626                                (&resultString,
    627                                plContext,
    628                                childrenFormat,
    629                                thisItemString,
    630                                childString),
    631                        PKIX_ERRORINSPRINTF);
    632 
    633                        PKIX_DECREF(childNode);
    634                        PKIX_DECREF(childString);
    635                        PKIX_DECREF(thisItemString);
    636 
    637                        thisItemString = resultString;
    638                }
    639        }
    640 
    641        *pTreeString = thisItemString;
    642 
    643 cleanup:
    644        if (PKIX_ERROR_RECEIVED) {
    645                PKIX_DECREF(thisItemString);
    646        }
    647 
    648        PKIX_DECREF(nextIndentFormat);
    649        PKIX_DECREF(thisNodeFormat);
    650        PKIX_DECREF(childrenFormat);
    651        PKIX_DECREF(nextIndentString);
    652        PKIX_DECREF(childString);
    653        PKIX_DECREF(childNode);
    654 
    655        PKIX_RETURN(CERTPOLICYNODE);
    656 }
    657 
    658 /*
    659 * FUNCTION: pkix_PolicyNode_ToString
    660 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
    661 */
    662 static PKIX_Error *
    663 pkix_PolicyNode_ToString(
    664        PKIX_PL_Object *object,
    665        PKIX_PL_String **pTreeString,
    666        void *plContext)
    667 {
    668        PKIX_PolicyNode *rootNode = NULL;
    669        PKIX_PL_String *resultString = NULL;
    670 
    671        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString");
    672 
    673        PKIX_NULLCHECK_TWO(object, pTreeString);
    674 
    675        PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
    676                PKIX_OBJECTNOTPOLICYNODE);
    677 
    678        rootNode = (PKIX_PolicyNode *)object;
    679 
    680        PKIX_CHECK(pkix_PolicyNode_ToString_Helper
    681                (rootNode, NULL, &resultString, plContext),
    682                PKIX_ERRORCREATINGSUBTREESTRING);
    683 
    684        *pTreeString = resultString;
    685 
    686 cleanup:
    687 
    688        PKIX_RETURN(CERTPOLICYNODE);
    689 }
    690 
    691 /*
    692 * FUNCTION: pkix_PolicyNode_Destroy
    693 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    694 */
    695 static PKIX_Error *
    696 pkix_PolicyNode_Destroy(
    697        PKIX_PL_Object *object,
    698        void *plContext)
    699 {
    700        PKIX_PolicyNode *node = NULL;
    701 
    702        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Destroy");
    703 
    704        PKIX_NULLCHECK_ONE(object);
    705 
    706        PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
    707                PKIX_OBJECTNOTPOLICYNODE);
    708 
    709        node = (PKIX_PolicyNode*)object;
    710 
    711        node->criticality = PKIX_FALSE;
    712        PKIX_DECREF(node->validPolicy);
    713        PKIX_DECREF(node->qualifierSet);
    714        PKIX_DECREF(node->expectedPolicySet);
    715        PKIX_DECREF(node->children);
    716 
    717        /*
    718         * Note: the link to parent is not reference-counted. See comment
    719         * in pkix_PolicyNode_AddToParent for more details.
    720         */
    721        node->parent = NULL;
    722        node->depth = 0;
    723 
    724 cleanup:
    725 
    726        PKIX_RETURN(CERTPOLICYNODE);
    727 }
    728 
    729 /*
    730 * FUNCTION: pkix_SinglePolicyNode_Hashcode
    731 * DESCRIPTION:
    732 *
    733 *  Computes the hashcode of the attributes of the PolicyNode pointed to by
    734 *  "node", other than its parents and children, and stores the result at
    735 *  "pHashcode".
    736 *
    737 * PARAMETERS:
    738 *  "node"
    739 *      Address of PolicyNode to be hashcoded; must be non-NULL
    740 *  "pHashcode"
    741 *      Address where UInt32 result will be stored; must be non-NULL
    742 *  "plContext"
    743 *      Platform-specific context pointer.
    744 * THREAD SAFETY:
    745 *  Conditionally Thread Safe
    746 *  (see Thread Safety Definitions in Programmer's Guide)
    747 * RETURNS:
    748 *  Returns NULL if function succeeds
    749 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    750 *  Returns a Fatal Error if the function fails in a fatal way
    751 */
    752 static PKIX_Error *
    753 pkix_SinglePolicyNode_Hashcode(
    754        PKIX_PolicyNode *node,
    755        PKIX_UInt32 *pHashcode,
    756        void *plContext)
    757 {
    758        PKIX_UInt32 componentHash = 0;
    759        PKIX_UInt32 nodeHash = 0;
    760 
    761        PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Hashcode");
    762        PKIX_NULLCHECK_TWO(node, pHashcode);
    763        PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
    764 
    765        PKIX_HASHCODE
    766                (node->qualifierSet,
    767                &nodeHash,
    768                plContext,
    769                PKIX_FAILUREHASHINGLISTQUALIFIERSET);
    770 
    771        if (PKIX_TRUE == (node->criticality)) {
    772                nodeHash = 31*nodeHash + 0xff;
    773        } else {
    774                nodeHash = 31*nodeHash + 0x00;
    775        }
    776 
    777        PKIX_CHECK(PKIX_PL_Object_Hashcode
    778                ((PKIX_PL_Object *)node->validPolicy,
    779                &componentHash,
    780                plContext),
    781                PKIX_FAILUREHASHINGOIDVALIDPOLICY);
    782 
    783        nodeHash = 31*nodeHash + componentHash;
    784 
    785        PKIX_CHECK(PKIX_PL_Object_Hashcode
    786                ((PKIX_PL_Object *)node->expectedPolicySet,
    787                &componentHash,
    788                plContext),
    789                PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET);
    790 
    791        nodeHash = 31*nodeHash + componentHash;
    792 
    793        *pHashcode = nodeHash;
    794 
    795 cleanup:
    796 
    797        PKIX_RETURN(CERTPOLICYNODE);
    798 }
    799 
    800 /*
    801 * FUNCTION: pkix_PolicyNode_Hashcode
    802 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    803 */
    804 static PKIX_Error *
    805 pkix_PolicyNode_Hashcode(
    806        PKIX_PL_Object *object,
    807        PKIX_UInt32 *pHashcode,
    808        void *plContext)
    809 {
    810        PKIX_PolicyNode *node = NULL;
    811        PKIX_UInt32 childrenHash = 0;
    812        PKIX_UInt32 nodeHash = 0;
    813 
    814        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode");
    815        PKIX_NULLCHECK_TWO(object, pHashcode);
    816 
    817        PKIX_CHECK(pkix_CheckType
    818                (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
    819                PKIX_OBJECTNOTPOLICYNODE);
    820 
    821        node = (PKIX_PolicyNode *)object;
    822 
    823        PKIX_CHECK(pkix_SinglePolicyNode_Hashcode
    824                (node, &nodeHash, plContext),
    825                PKIX_SINGLEPOLICYNODEHASHCODEFAILED);
    826 
    827        nodeHash = 31*nodeHash + (PKIX_UInt32)((char *)node->parent - (char *)NULL);
    828 
    829        PKIX_HASHCODE
    830                (node->children,
    831                &childrenHash,
    832                plContext,
    833                PKIX_OBJECTHASHCODEFAILED);
    834 
    835        nodeHash = 31*nodeHash + childrenHash;
    836 
    837        *pHashcode = nodeHash;
    838 
    839 cleanup:
    840 
    841        PKIX_RETURN(CERTPOLICYNODE);
    842 }
    843 
    844 /*
    845 * FUNCTION: pkix_SinglePolicyNode_Equals
    846 * DESCRIPTION:
    847 *
    848 *  Compares for equality the components of the PolicyNode pointed to by
    849 *  "firstPN", other than its parents and children, with those of the
    850 *  PolicyNode pointed to by "secondPN" and stores the result at "pResult"
    851 *  (PKIX_TRUE if equal; PKIX_FALSE if not).
    852 *
    853 * PARAMETERS:
    854 *  "firstPN"
    855 *      Address of first of the PolicyNodes to be compared; must be non-NULL
    856 *  "secondPN"
    857 *      Address of second of the PolicyNodes to be compared; must be non-NULL
    858 *  "pResult"
    859 *      Address where Boolean will be stored; must be non-NULL
    860 *  "plContext"
    861 *      Platform-specific context pointer.
    862 * THREAD SAFETY:
    863 *  Conditionally Thread Safe
    864 *  (see Thread Safety Definitions in Programmer's Guide)
    865 * RETURNS:
    866 *  Returns NULL if function succeeds
    867 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
    868 *  Returns a Fatal Error if the function fails in a fatal way
    869 */
    870 static PKIX_Error *
    871 pkix_SinglePolicyNode_Equals(
    872        PKIX_PolicyNode *firstPN,
    873        PKIX_PolicyNode *secondPN,
    874        PKIX_Boolean *pResult,
    875        void *plContext)
    876 {
    877        PKIX_Boolean compResult = PKIX_FALSE;
    878 
    879        PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Equals");
    880        PKIX_NULLCHECK_THREE(firstPN, secondPN, pResult);
    881 
    882        /* If both references are identical, they must be equal */
    883        if (firstPN == secondPN) {
    884                compResult = PKIX_TRUE;
    885                goto cleanup;
    886        }
    887 
    888        /*
    889         * It seems we have to do the comparisons. Do
    890         * the easiest ones first.
    891         */
    892        if ((firstPN->criticality) != (secondPN->criticality)) {
    893                goto cleanup;
    894        }
    895        if ((firstPN->depth) != (secondPN->depth)) {
    896                goto cleanup;
    897        }
    898 
    899        PKIX_EQUALS
    900                (firstPN->qualifierSet,
    901                secondPN->qualifierSet,
    902                &compResult,
    903                plContext,
    904                PKIX_OBJECTEQUALSFAILED);
    905 
    906        if (compResult == PKIX_FALSE) {
    907                goto cleanup;
    908        }
    909 
    910        /* These fields must be non-NULL */
    911        PKIX_NULLCHECK_TWO(firstPN->validPolicy, secondPN->validPolicy);
    912 
    913        PKIX_EQUALS
    914                (firstPN->validPolicy,
    915                secondPN->validPolicy,
    916                &compResult,
    917                plContext,
    918                PKIX_OBJECTEQUALSFAILED);
    919 
    920        if (compResult == PKIX_FALSE) {
    921                goto cleanup;
    922        }
    923 
    924        /* These fields must be non-NULL */
    925        PKIX_NULLCHECK_TWO
    926                (firstPN->expectedPolicySet, secondPN->expectedPolicySet);
    927 
    928        PKIX_EQUALS
    929                (firstPN->expectedPolicySet,
    930                secondPN->expectedPolicySet,
    931                &compResult,
    932                plContext,
    933                PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS);
    934 
    935 cleanup:
    936 
    937        *pResult = compResult;
    938 
    939        PKIX_RETURN(CERTPOLICYNODE);
    940 }
    941 
    942 /*
    943 * FUNCTION: pkix_PolicyNode_Equals
    944 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
    945 */
    946 static PKIX_Error *
    947 pkix_PolicyNode_Equals(
    948        PKIX_PL_Object *firstObject,
    949        PKIX_PL_Object *secondObject,
    950        PKIX_Boolean *pResult,
    951        void *plContext)
    952 {
    953        PKIX_PolicyNode *firstPN = NULL;
    954        PKIX_PolicyNode *secondPN = NULL;
    955        PKIX_UInt32 secondType;
    956        PKIX_Boolean compResult = PKIX_FALSE;
    957 
    958        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Equals");
    959        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
    960 
    961        /* test that firstObject is a PolicyNode */
    962        PKIX_CHECK(pkix_CheckType
    963                (firstObject, PKIX_CERTPOLICYNODE_TYPE, plContext),
    964                PKIX_FIRSTOBJECTNOTPOLICYNODE);
    965 
    966        /*
    967         * Since we know firstObject is a PolicyNode,
    968         * if both references are identical, they must be equal
    969         */
    970        if (firstObject == secondObject){
    971                compResult = PKIX_TRUE;
    972                goto cleanup;
    973        }
    974 
    975        /*
    976         * If secondObject isn't a PolicyNode, we
    977         * don't throw an error. We simply return FALSE.
    978         */
    979        PKIX_CHECK(PKIX_PL_Object_GetType
    980                    (secondObject, &secondType, plContext),
    981                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    982 
    983        if (secondType != PKIX_CERTPOLICYNODE_TYPE) {
    984                goto cleanup;
    985        }
    986 
    987        /*
    988         * Oh, well, we have to do the comparisons. Do
    989         * the easiest ones first.
    990         */
    991        firstPN = (PKIX_PolicyNode *)firstObject;
    992        secondPN = (PKIX_PolicyNode *)secondObject;
    993 
    994        /*
    995         * We don't require the parents to be identical. In the
    996         * course of traversing the tree, we will have checked the
    997         * attributes of the parent nodes, and checking the lists
    998         * of children will determine whether they match.
    999         */
   1000 
   1001        PKIX_EQUALS
   1002                (firstPN->children,
   1003                secondPN->children,
   1004                &compResult,
   1005                plContext,
   1006                PKIX_OBJECTEQUALSFAILEDONCHILDREN);
   1007 
   1008        if (compResult == PKIX_FALSE) {
   1009                goto cleanup;
   1010        }
   1011 
   1012        PKIX_CHECK(pkix_SinglePolicyNode_Equals
   1013                (firstPN, secondPN, &compResult, plContext),
   1014                PKIX_SINGLEPOLICYNODEEQUALSFAILED);
   1015 
   1016 cleanup:
   1017 
   1018        *pResult = compResult;
   1019 
   1020        PKIX_RETURN(CERTPOLICYNODE);
   1021 }
   1022 
   1023 /*
   1024 * FUNCTION: pkix_PolicyNode_DuplicateHelper
   1025 * DESCRIPTION:
   1026 *
   1027 *  Duplicates the PolicyNode whose address is pointed to by "original",
   1028 *  and stores the result at "pNewNode", if a non-NULL pointer is provided
   1029 *  for "pNewNode". In addition, the created PolicyNode is added as a child
   1030 *  to "parent", if a non-NULL pointer is provided for "parent". Then this
   1031 *  function is called recursively to duplicate each of the children of
   1032 *  "original". At the top level this function is called with a null
   1033 *  "parent" and a non-NULL "pNewNode". Below the top level "parent" will
   1034 *  be non-NULL and "pNewNode" will be NULL.
   1035 *
   1036 * PARAMETERS:
   1037 *  "original"
   1038 *      Address of PolicyNode to be copied; must be non-NULL
   1039 *  "parent"
   1040 *      Address of PolicyNode to which the created node is to be added as a
   1041 *      child; NULL for the top-level call and non-NULL below the top level
   1042 *  "pNewNode"
   1043 *      Address to store the node created; should be NULL if "parent" is
   1044 *      non-NULL and vice versa
   1045 *  "plContext"
   1046 *      Platform-specific context pointer.
   1047 * THREAD SAFETY:
   1048 *  Conditionally Thread Safe
   1049 *  (see Thread Safety Definitions in Programmer's Guide)
   1050 * RETURNS:
   1051 *  Returns NULL if function succeeds
   1052 *  Returns a PolicyNode Error if the function fails in a non-fatal way.
   1053 *  Returns a Fatal Error if the function fails in a fatal way
   1054 */
   1055 static PKIX_Error *
   1056 pkix_PolicyNode_DuplicateHelper(
   1057        PKIX_PolicyNode *original,
   1058        PKIX_PolicyNode *parent,
   1059        PKIX_PolicyNode **pNewNode,
   1060        void *plContext)
   1061 {
   1062        PKIX_UInt32 numChildren = 0;
   1063        PKIX_UInt32 childIndex = 0;
   1064        PKIX_List *children = NULL; /* List of PKIX_PolicyNode */
   1065        PKIX_PolicyNode *copy = NULL;
   1066        PKIX_PolicyNode *child = NULL;
   1067 
   1068        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper");
   1069 
   1070        PKIX_NULLCHECK_THREE
   1071                (original, original->validPolicy, original->expectedPolicySet);
   1072 
   1073        /*
   1074         * These components are immutable, so copying the pointers
   1075         * is sufficient. The create function increments the reference
   1076         * counts as it stores the pointers into the new object.
   1077         */
   1078        PKIX_CHECK(pkix_PolicyNode_Create
   1079                (original->validPolicy,
   1080                original->qualifierSet,
   1081                original->criticality,
   1082                original->expectedPolicySet,
   1083                &copy,
   1084                plContext),
   1085                PKIX_POLICYNODECREATEFAILED);
   1086 
   1087        if (parent) {
   1088                PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext),
   1089                        PKIX_POLICYNODEADDTOPARENTFAILED);
   1090        }
   1091 
   1092        /* Are there any children to duplicate? */
   1093        children = original->children;
   1094 
   1095        if (children) {
   1096            PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
   1097                PKIX_LISTGETLENGTHFAILED);
   1098        }
   1099 
   1100        for (childIndex = 0; childIndex < numChildren; childIndex++) {
   1101                PKIX_CHECK(PKIX_List_GetItem
   1102                        (children,
   1103                        childIndex,
   1104                        (PKIX_PL_Object **)&child,
   1105                        plContext),
   1106                        PKIX_LISTGETITEMFAILED);
   1107 
   1108                PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
   1109                        (child, copy, NULL, plContext),
   1110                        PKIX_POLICYNODEDUPLICATEHELPERFAILED);
   1111 
   1112                PKIX_DECREF(child);
   1113        }
   1114 
   1115        if (pNewNode) {
   1116                *pNewNode = copy;
   1117                copy = NULL; /* no DecRef if we give our handle away */
   1118        }
   1119 
   1120 cleanup:
   1121        PKIX_DECREF(copy);
   1122        PKIX_DECREF(child);
   1123 
   1124        PKIX_RETURN(CERTPOLICYNODE);
   1125 }
   1126 
   1127 /*
   1128 * FUNCTION: pkix_PolicyNode_Duplicate
   1129 * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
   1130 */
   1131 static PKIX_Error *
   1132 pkix_PolicyNode_Duplicate(
   1133        PKIX_PL_Object *object,
   1134        PKIX_PL_Object **pNewObject,
   1135        void *plContext)
   1136 {
   1137        PKIX_PolicyNode *original = NULL;
   1138        PKIX_PolicyNode *copy = NULL;
   1139 
   1140        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate");
   1141 
   1142        PKIX_NULLCHECK_TWO(object, pNewObject);
   1143 
   1144        PKIX_CHECK(pkix_CheckType
   1145                (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
   1146                PKIX_OBJECTNOTPOLICYNODE);
   1147 
   1148        original = (PKIX_PolicyNode *)object;
   1149 
   1150        PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
   1151                (original, NULL, &copy, plContext),
   1152                PKIX_POLICYNODEDUPLICATEHELPERFAILED);
   1153 
   1154        *pNewObject = (PKIX_PL_Object *)copy;
   1155 
   1156 cleanup:
   1157 
   1158        PKIX_RETURN(CERTPOLICYNODE);
   1159 }
   1160 
   1161 /*
   1162 * FUNCTION: pkix_PolicyNode_RegisterSelf
   1163 * DESCRIPTION:
   1164 *
   1165 *  Registers PKIX_CERTPOLICYNODE_TYPE and its related
   1166 *  functions with systemClasses[]
   1167 *
   1168 * THREAD SAFETY:
   1169 *  Not Thread Safe - for performance and complexity reasons
   1170 *
   1171 *  Since this function is only called by PKIX_PL_Initialize,
   1172 *  which should only be called once, it is acceptable that
   1173 *  this function is not thread-safe.
   1174 */
   1175 PKIX_Error *
   1176 pkix_PolicyNode_RegisterSelf(void *plContext)
   1177 {
   1178 
   1179        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   1180        pkix_ClassTable_Entry entry;
   1181 
   1182        PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_RegisterSelf");
   1183 
   1184        entry.description = "PolicyNode";
   1185        entry.objCounter = 0;
   1186        entry.typeObjectSize = sizeof(PKIX_PolicyNode);
   1187        entry.destructor = pkix_PolicyNode_Destroy;
   1188        entry.equalsFunction = pkix_PolicyNode_Equals;
   1189        entry.hashcodeFunction = pkix_PolicyNode_Hashcode;
   1190        entry.toStringFunction = pkix_PolicyNode_ToString;
   1191        entry.comparator = NULL;
   1192        entry.duplicateFunction = pkix_PolicyNode_Duplicate;
   1193 
   1194        systemClasses[PKIX_CERTPOLICYNODE_TYPE] = entry;
   1195 
   1196        PKIX_RETURN(CERTPOLICYNODE);
   1197 }
   1198 
   1199 
   1200 /* --Public-PolicyNode-Functions----------------------------------- */
   1201 
   1202 /*
   1203 * FUNCTION: PKIX_PolicyNode_GetChildren
   1204 * (see description of this function in pkix_results.h)
   1205 */
   1206 PKIX_Error *
   1207 PKIX_PolicyNode_GetChildren(
   1208        PKIX_PolicyNode *node,
   1209        PKIX_List **pChildren,  /* list of PKIX_PolicyNode */
   1210        void *plContext)
   1211 {
   1212        PKIX_List *children = NULL;
   1213 
   1214        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetChildren");
   1215 
   1216        PKIX_NULLCHECK_TWO(node, pChildren);
   1217 
   1218        PKIX_INCREF(node->children);
   1219        children = node->children;
   1220 
   1221        if (!children) {
   1222                PKIX_CHECK(PKIX_List_Create(&children, plContext),
   1223                        PKIX_LISTCREATEFAILED);
   1224        }
   1225 
   1226        PKIX_CHECK(PKIX_List_SetImmutable(children, plContext),
   1227                PKIX_LISTSETIMMUTABLEFAILED);
   1228 
   1229        *pChildren = children;
   1230 
   1231 cleanup:
   1232        if (PKIX_ERROR_RECEIVED) {
   1233                PKIX_DECREF(children);
   1234        }
   1235 
   1236        PKIX_RETURN(CERTPOLICYNODE);
   1237 }
   1238 
   1239 /*
   1240 * FUNCTION: PKIX_PolicyNode_GetParent
   1241 * (see description of this function in pkix_results.h)
   1242 */
   1243 PKIX_Error *
   1244 PKIX_PolicyNode_GetParent(
   1245        PKIX_PolicyNode *node,
   1246        PKIX_PolicyNode **pParent,
   1247        void *plContext)
   1248 {
   1249 
   1250        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetParent");
   1251 
   1252        PKIX_NULLCHECK_TWO(node, pParent);
   1253 
   1254        PKIX_INCREF(node->parent);
   1255        *pParent = node->parent;
   1256 
   1257 cleanup:
   1258        PKIX_RETURN(CERTPOLICYNODE);
   1259 }
   1260 
   1261 /*
   1262 * FUNCTION: PKIX_PolicyNode_GetValidPolicy
   1263 * (see description of this function in pkix_results.h)
   1264 */
   1265 PKIX_Error *
   1266 PKIX_PolicyNode_GetValidPolicy(
   1267        PKIX_PolicyNode *node,
   1268        PKIX_PL_OID **pValidPolicy,
   1269        void *plContext)
   1270 {
   1271 
   1272        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetValidPolicy");
   1273 
   1274        PKIX_NULLCHECK_TWO(node, pValidPolicy);
   1275 
   1276        PKIX_INCREF(node->validPolicy);
   1277        *pValidPolicy = node->validPolicy;
   1278 
   1279 cleanup:
   1280        PKIX_RETURN(CERTPOLICYNODE);
   1281 }
   1282 
   1283 /*
   1284 * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers
   1285 * (see description of this function in pkix_results.h)
   1286 */
   1287 PKIX_Error *
   1288 PKIX_PolicyNode_GetPolicyQualifiers(
   1289        PKIX_PolicyNode *node,
   1290        PKIX_List **pQualifiers,  /* list of PKIX_PL_CertPolicyQualifier */
   1291        void *plContext)
   1292 {
   1293        PKIX_List *qualifiers = NULL;
   1294 
   1295        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetPolicyQualifiers");
   1296 
   1297        PKIX_NULLCHECK_TWO(node, pQualifiers);
   1298 
   1299        PKIX_INCREF(node->qualifierSet);
   1300        qualifiers = node->qualifierSet;
   1301 
   1302        if (!qualifiers) {
   1303                PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
   1304                        PKIX_LISTCREATEFAILED);
   1305        }
   1306 
   1307        PKIX_CHECK(PKIX_List_SetImmutable(qualifiers, plContext),
   1308                PKIX_LISTSETIMMUTABLEFAILED);
   1309 
   1310        *pQualifiers = qualifiers;
   1311 
   1312 cleanup:
   1313 
   1314        PKIX_RETURN(CERTPOLICYNODE);
   1315 }
   1316 
   1317 /*
   1318 * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies
   1319 * (see description of this function in pkix_results.h)
   1320 */
   1321 PKIX_Error *
   1322 PKIX_PolicyNode_GetExpectedPolicies(
   1323        PKIX_PolicyNode *node,
   1324        PKIX_List **pExpPolicies,  /* list of PKIX_PL_OID */
   1325        void *plContext)
   1326 {
   1327 
   1328        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetExpectedPolicies");
   1329 
   1330        PKIX_NULLCHECK_TWO(node, pExpPolicies);
   1331 
   1332        PKIX_INCREF(node->expectedPolicySet);
   1333        *pExpPolicies = node->expectedPolicySet;
   1334 
   1335 cleanup:
   1336        PKIX_RETURN(CERTPOLICYNODE);
   1337 }
   1338 
   1339 /*
   1340 * FUNCTION: PKIX_PolicyNode_IsCritical
   1341 * (see description of this function in pkix_results.h)
   1342 */
   1343 PKIX_Error *
   1344 PKIX_PolicyNode_IsCritical(
   1345        PKIX_PolicyNode *node,
   1346        PKIX_Boolean *pCritical,
   1347        void *plContext)
   1348 {
   1349 
   1350        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_IsCritical");
   1351 
   1352        PKIX_NULLCHECK_TWO(node, pCritical);
   1353 
   1354        *pCritical = node->criticality;
   1355 
   1356        PKIX_RETURN(CERTPOLICYNODE);
   1357 }
   1358 
   1359 /*
   1360 * FUNCTION: PKIX_PolicyNode_GetDepth
   1361 * (see description of this function in pkix_results.h)
   1362 */
   1363 PKIX_Error *
   1364 PKIX_PolicyNode_GetDepth(
   1365        PKIX_PolicyNode *node,
   1366        PKIX_UInt32 *pDepth,
   1367        void *plContext)
   1368 {
   1369 
   1370        PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetDepth");
   1371 
   1372        PKIX_NULLCHECK_TWO(node, pDepth);
   1373 
   1374        *pDepth = node->depth;
   1375 
   1376        PKIX_RETURN(CERTPOLICYNODE);
   1377 }