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 ©, 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, ©, 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 }