| OLD | NEW |
| (Empty) |
| 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 *)NU
LL); | |
| 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 } | |
| OLD | NEW |