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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial