PageRenderTime 62ms CodeModel.GetById 13ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 1ms

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

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