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 *
pkix_PolicyNode_GetChildrenMutable(PKIX_PolicyNode * node,PKIX_List ** pChildren,void * plContext)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 *
pkix_PolicyNode_Create(PKIX_PL_OID * validPolicy,PKIX_List * qualifierSet,PKIX_Boolean criticality,PKIX_List * expectedPolicySet,PKIX_PolicyNode ** pObject,void * plContext)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 *
pkix_PolicyNode_AddToParent(PKIX_PolicyNode * parentNode,PKIX_PolicyNode * child,void * plContext)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 *
pkix_PolicyNode_Prune(PKIX_PolicyNode * node,PKIX_UInt32 height,PKIX_Boolean * pDelete,void * plContext)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 *
pkix_SinglePolicyNode_ToString(PKIX_PolicyNode * node,PKIX_PL_String ** pString,void * plContext)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 *
pkix_PolicyNode_ToString_Helper(PKIX_PolicyNode * rootNode,PKIX_PL_String * indent,PKIX_PL_String ** pTreeString,void * plContext)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 *
pkix_PolicyNode_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pTreeString,void * plContext)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 *
pkix_PolicyNode_Destroy(PKIX_PL_Object * object,void * plContext)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 *
pkix_SinglePolicyNode_Hashcode(PKIX_PolicyNode * node,PKIX_UInt32 * pHashcode,void * plContext)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 *
pkix_PolicyNode_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)805 pkix_PolicyNode_Hashcode(
806         PKIX_PL_Object *object,
807         PKIX_UInt32 *pHashcode,
808         void *plContext)
809 {
810         PKIX_PolicyNode *node = NULL;
811         PKIX_UInt32 childrenHash = 0;
812         PKIX_UInt32 nodeHash = 0;
813 
814         PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode");
815         PKIX_NULLCHECK_TWO(object, pHashcode);
816 
817         PKIX_CHECK(pkix_CheckType
818                 (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
819                 PKIX_OBJECTNOTPOLICYNODE);
820 
821         node = (PKIX_PolicyNode *)object;
822 
823         PKIX_CHECK(pkix_SinglePolicyNode_Hashcode
824                 (node, &nodeHash, plContext),
825                 PKIX_SINGLEPOLICYNODEHASHCODEFAILED);
826 
827         nodeHash = 31*nodeHash + (PKIX_UInt32)((char *)node->parent - (char *)NULL);
828 
829         PKIX_HASHCODE
830                 (node->children,
831                 &childrenHash,
832                 plContext,
833                 PKIX_OBJECTHASHCODEFAILED);
834 
835         nodeHash = 31*nodeHash + childrenHash;
836 
837         *pHashcode = nodeHash;
838 
839 cleanup:
840 
841         PKIX_RETURN(CERTPOLICYNODE);
842 }
843 
844 /*
845  * FUNCTION: pkix_SinglePolicyNode_Equals
846  * DESCRIPTION:
847  *
848  *  Compares for equality the components of the PolicyNode pointed to by
849  *  "firstPN", other than its parents and children, with those of the
850  *  PolicyNode pointed to by "secondPN" and stores the result at "pResult"
851  *  (PKIX_TRUE if equal; PKIX_FALSE if not).
852  *
853  * PARAMETERS:
854  *  "firstPN"
855  *      Address of first of the PolicyNodes to be compared; must be non-NULL
856  *  "secondPN"
857  *      Address of second of the PolicyNodes to be compared; must be non-NULL
858  *  "pResult"
859  *      Address where Boolean will be stored; must be non-NULL
860  *  "plContext"
861  *      Platform-specific context pointer.
862  * THREAD SAFETY:
863  *  Conditionally Thread Safe
864  *  (see Thread Safety Definitions in Programmer's Guide)
865  * RETURNS:
866  *  Returns NULL if function succeeds
867  *  Returns a PolicyNode Error if the function fails in a non-fatal way.
868  *  Returns a Fatal Error if the function fails in a fatal way
869  */
870 static PKIX_Error *
pkix_SinglePolicyNode_Equals(PKIX_PolicyNode * firstPN,PKIX_PolicyNode * secondPN,PKIX_Boolean * pResult,void * plContext)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 *
pkix_PolicyNode_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Boolean * pResult,void * plContext)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 *
pkix_PolicyNode_DuplicateHelper(PKIX_PolicyNode * original,PKIX_PolicyNode * parent,PKIX_PolicyNode ** pNewNode,void * plContext)1056 pkix_PolicyNode_DuplicateHelper(
1057         PKIX_PolicyNode *original,
1058         PKIX_PolicyNode *parent,
1059         PKIX_PolicyNode **pNewNode,
1060         void *plContext)
1061 {
1062         PKIX_UInt32 numChildren = 0;
1063         PKIX_UInt32 childIndex = 0;
1064         PKIX_List *children = NULL; /* List of PKIX_PolicyNode */
1065         PKIX_PolicyNode *copy = NULL;
1066         PKIX_PolicyNode *child = NULL;
1067 
1068         PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper");
1069 
1070         PKIX_NULLCHECK_THREE
1071                 (original, original->validPolicy, original->expectedPolicySet);
1072 
1073         /*
1074          * These components are immutable, so copying the pointers
1075          * is sufficient. The create function increments the reference
1076          * counts as it stores the pointers into the new object.
1077          */
1078         PKIX_CHECK(pkix_PolicyNode_Create
1079                 (original->validPolicy,
1080                 original->qualifierSet,
1081                 original->criticality,
1082                 original->expectedPolicySet,
1083                 &copy,
1084                 plContext),
1085                 PKIX_POLICYNODECREATEFAILED);
1086 
1087         if (parent) {
1088                 PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext),
1089                         PKIX_POLICYNODEADDTOPARENTFAILED);
1090         }
1091 
1092         /* Are there any children to duplicate? */
1093         children = original->children;
1094 
1095         if (children) {
1096             PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
1097                 PKIX_LISTGETLENGTHFAILED);
1098         }
1099 
1100         for (childIndex = 0; childIndex < numChildren; childIndex++) {
1101                 PKIX_CHECK(PKIX_List_GetItem
1102                         (children,
1103                         childIndex,
1104                         (PKIX_PL_Object **)&child,
1105                         plContext),
1106                         PKIX_LISTGETITEMFAILED);
1107 
1108                 PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
1109                         (child, copy, NULL, plContext),
1110                         PKIX_POLICYNODEDUPLICATEHELPERFAILED);
1111 
1112                 PKIX_DECREF(child);
1113         }
1114 
1115         if (pNewNode) {
1116                 *pNewNode = copy;
1117                 copy = NULL; /* no DecRef if we give our handle away */
1118         }
1119 
1120 cleanup:
1121         PKIX_DECREF(copy);
1122         PKIX_DECREF(child);
1123 
1124         PKIX_RETURN(CERTPOLICYNODE);
1125 }
1126 
1127 /*
1128  * FUNCTION: pkix_PolicyNode_Duplicate
1129  * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
1130  */
1131 static PKIX_Error *
pkix_PolicyNode_Duplicate(PKIX_PL_Object * object,PKIX_PL_Object ** pNewObject,void * plContext)1132 pkix_PolicyNode_Duplicate(
1133         PKIX_PL_Object *object,
1134         PKIX_PL_Object **pNewObject,
1135         void *plContext)
1136 {
1137         PKIX_PolicyNode *original = NULL;
1138         PKIX_PolicyNode *copy = NULL;
1139 
1140         PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate");
1141 
1142         PKIX_NULLCHECK_TWO(object, pNewObject);
1143 
1144         PKIX_CHECK(pkix_CheckType
1145                 (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
1146                 PKIX_OBJECTNOTPOLICYNODE);
1147 
1148         original = (PKIX_PolicyNode *)object;
1149 
1150         PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
1151                 (original, NULL, &copy, plContext),
1152                 PKIX_POLICYNODEDUPLICATEHELPERFAILED);
1153 
1154         *pNewObject = (PKIX_PL_Object *)copy;
1155 
1156 cleanup:
1157 
1158         PKIX_RETURN(CERTPOLICYNODE);
1159 }
1160 
1161 /*
1162  * FUNCTION: pkix_PolicyNode_RegisterSelf
1163  * DESCRIPTION:
1164  *
1165  *  Registers PKIX_CERTPOLICYNODE_TYPE and its related
1166  *  functions with systemClasses[]
1167  *
1168  * THREAD SAFETY:
1169  *  Not Thread Safe - for performance and complexity reasons
1170  *
1171  *  Since this function is only called by PKIX_PL_Initialize,
1172  *  which should only be called once, it is acceptable that
1173  *  this function is not thread-safe.
1174  */
1175 PKIX_Error *
pkix_PolicyNode_RegisterSelf(void * plContext)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 *
PKIX_PolicyNode_GetChildren(PKIX_PolicyNode * node,PKIX_List ** pChildren,void * plContext)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 *
PKIX_PolicyNode_GetParent(PKIX_PolicyNode * node,PKIX_PolicyNode ** pParent,void * plContext)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 *
PKIX_PolicyNode_GetValidPolicy(PKIX_PolicyNode * node,PKIX_PL_OID ** pValidPolicy,void * plContext)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 *
PKIX_PolicyNode_GetPolicyQualifiers(PKIX_PolicyNode * node,PKIX_List ** pQualifiers,void * plContext)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 *
PKIX_PolicyNode_GetExpectedPolicies(PKIX_PolicyNode * node,PKIX_List ** pExpPolicies,void * plContext)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 *
PKIX_PolicyNode_IsCritical(PKIX_PolicyNode * node,PKIX_Boolean * pCritical,void * plContext)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 *
PKIX_PolicyNode_GetDepth(PKIX_PolicyNode * node,PKIX_UInt32 * pDepth,void * plContext)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 }
1378