1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 * Policy Node Object Type Definition
44 #include "pkix_policynode.h"
46 /* --Private-PolicyNode-Functions---------------------------------- */
49 * FUNCTION: pkix_PolicyNode_GetChildrenMutable
52 * Retrieves the List of PolicyNodes representing the child nodes of the
53 * Policy Node pointed to by "node" and stores it at "pChildren". If "node"
54 * has no List of child nodes, this function stores NULL at "pChildren".
56 * Note that the List returned by this function may be mutable. This function
57 * differs from the public function PKIX_PolicyNode_GetChildren in that
58 * respect. (It also differs in that the public function creates an empty
59 * List, if necessary, rather than storing NULL.)
61 * During certificate processing, children Lists are created and modified.
62 * Once the list is accessed using the public call, the List is set immutable.
66 * Address of PolicyNode whose child nodes are to be stored.
69 * Address where object pointer will be stored. Must be non-NULL.
71 * Platform-specific context pointer.
73 * Conditionally Thread Safe
74 * (see Thread Safety Definitions in Programmer's Guide)
76 * Returns NULL if the function succeeds.
77 * Returns a PolicyNode Error if the function fails in a non-fatal way.
78 * Returns a Fatal Error if the function fails in an unrecoverable way.
81 pkix_PolicyNode_GetChildrenMutable(
82 PKIX_PolicyNode
*node
,
83 PKIX_List
**pChildren
, /* list of PKIX_PolicyNode */
87 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_GetChildrenMutable");
89 PKIX_NULLCHECK_TWO(node
, pChildren
);
91 PKIX_INCREF(node
->children
);
93 *pChildren
= node
->children
;
95 PKIX_RETURN(CERTPOLICYNODE
);
99 * FUNCTION: pkix_PolicyNode_Create
102 * Creates a new PolicyNode using the OID pointed to by "validPolicy", the List
103 * of CertPolicyQualifiers pointed to by "qualifierSet", the criticality
104 * indicated by the Boolean value of "criticality", and the List of OIDs
105 * pointed to by "expectedPolicySet", and stores the result at "pObject". The
106 * criticality should be derived from whether the certificate policy extension
107 * was marked as critical in the certificate that led to creation of this
108 * PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made
109 * immutable. The PolicyNode pointers to parent and to children are initialized
110 * to NULL, and the depth is set to zero; those values should be set by using
111 * the pkix_PolicyNode_AddToParent function.
115 * Address of OID of the valid policy for the path. Must be non-NULL
117 * Address of List of CertPolicyQualifiers associated with the validpolicy.
120 * Boolean indicator of whether the criticality should be set in this
122 * "expectedPolicySet"
123 * Address of List of OIDs that would satisfy this policy in the next
124 * certificate. Must be non-NULL
126 * Address where the PolicyNode pointer will be stored. Must be non-NULL.
128 * Platform-specific context pointer.
130 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
132 * Returns NULL if the function succeeds.
133 * Returns a PolicyNode Error if the function fails in a non-fatal way.
134 * Returns a Fatal Error if the function fails in an unrecoverable way.
137 pkix_PolicyNode_Create(
138 PKIX_PL_OID
*validPolicy
,
139 PKIX_List
*qualifierSet
,
140 PKIX_Boolean criticality
,
141 PKIX_List
*expectedPolicySet
,
142 PKIX_PolicyNode
**pObject
,
145 PKIX_PolicyNode
*node
= NULL
;
147 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_Create");
149 PKIX_NULLCHECK_THREE(validPolicy
, expectedPolicySet
, pObject
);
151 PKIX_CHECK(PKIX_PL_Object_Alloc
152 (PKIX_CERTPOLICYNODE_TYPE
,
153 sizeof (PKIX_PolicyNode
),
154 (PKIX_PL_Object
**)&node
,
156 PKIX_COULDNOTCREATEPOLICYNODEOBJECT
);
158 PKIX_INCREF(validPolicy
);
159 node
->validPolicy
= validPolicy
;
161 PKIX_INCREF(qualifierSet
);
162 node
->qualifierSet
= qualifierSet
;
164 PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet
, plContext
),
165 PKIX_LISTSETIMMUTABLEFAILED
);
168 node
->criticality
= criticality
;
170 PKIX_INCREF(expectedPolicySet
);
171 node
->expectedPolicySet
= expectedPolicySet
;
172 PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet
, plContext
),
173 PKIX_LISTSETIMMUTABLEFAILED
);
176 node
->children
= NULL
;
182 if (PKIX_ERROR_RECEIVED
) {
186 PKIX_RETURN(CERTPOLICYNODE
);
190 * FUNCTION: pkix_PolicyNode_AddToParent
193 * Adds the PolicyNode pointed to by "child" to the List of children of
194 * the PolicyNode pointed to by "parentNode". If "parentNode" had a
195 * NULL pointer for the List of children, a new List is created containing
196 * "child". Otherwise "child" is appended to the existing List. The
197 * parent field in "child" is set to "parent", and the depth field is
198 * set to one more than the corresponding value in "parent".
200 * Depth, in this context, means distance from the root node, which
205 * Address of PolicyNode whose List of child PolicyNodes is to be
206 * created or appended to. Must be non-NULL.
208 * Address of PolicyNode to be added to parentNode's List. Must be
211 * Platform-specific context pointer.
213 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
215 * Returns NULL if the function succeeds.
216 * Returns a PolicyNode Error if the function fails in a non-fatal way.
217 * Returns a Fatal Error if the function fails in an unrecoverable way.
220 pkix_PolicyNode_AddToParent(
221 PKIX_PolicyNode
*parentNode
,
222 PKIX_PolicyNode
*child
,
225 PKIX_List
*listOfChildren
= NULL
;
227 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_AddToParent");
229 PKIX_NULLCHECK_TWO(parentNode
, child
);
231 listOfChildren
= parentNode
->children
;
232 if (listOfChildren
== NULL
) {
233 PKIX_CHECK(PKIX_List_Create(&listOfChildren
, plContext
),
234 PKIX_LISTCREATEFAILED
);
235 parentNode
->children
= listOfChildren
;
239 * Note: this link is not reference-counted. The link from parent
240 * to child is counted (actually, the parent "owns" a List which
241 * "owns" children), but the children do not "own" the parent.
242 * Otherwise, there would be loops.
244 child
->parent
= parentNode
;
246 child
->depth
= 1 + (parentNode
->depth
);
248 PKIX_CHECK(PKIX_List_AppendItem
249 (listOfChildren
, (PKIX_PL_Object
*)child
, plContext
),
250 PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST
);
252 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
253 ((PKIX_PL_Object
*)parentNode
, plContext
),
254 PKIX_OBJECTINVALIDATECACHEFAILED
);
256 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
257 ((PKIX_PL_Object
*)child
, plContext
),
258 PKIX_OBJECTINVALIDATECACHEFAILED
);
262 PKIX_RETURN(CERTPOLICYNODE
);
266 * FUNCTION: pkix_PolicyNode_Prune
269 * Prunes a tree below the PolicyNode whose address is pointed to by "node",
270 * using the UInt32 value of "height" as the distance from the leaf level,
271 * and storing at "pDelete" the Boolean value of whether this PolicyNode is,
272 * after pruning, childless and should be pruned.
274 * Any PolicyNode at height 0 is allowed to survive. If the height is greater
275 * than zero, pkix_PolicyNode_Prune is called recursively for each child of
276 * the current PolicyNode. After this process, a node with no children
277 * stores PKIX_TRUE in "pDelete" to indicate that it should be deleted.
281 * Address of the PolicyNode to be pruned. Must be non-NULL.
283 * UInt32 value for the distance from the leaf level
285 * Address to store the Boolean return value of PKIX_TRUE if this node
286 * should be pruned, or PKIX_FALSE if there remains at least one
287 * branch of the required height. Must be non-NULL.
289 * Platform-specific context pointer.
291 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
293 * Returns NULL if the function succeeds.
294 * Returns a PolicyNode Error if the function fails in a non-fatal way.
295 * Returns a Fatal Error if the function fails in an unrecoverable way.
298 pkix_PolicyNode_Prune(
299 PKIX_PolicyNode
*node
,
301 PKIX_Boolean
*pDelete
,
304 PKIX_Boolean childless
= PKIX_FALSE
;
305 PKIX_Boolean shouldBePruned
= PKIX_FALSE
;
306 PKIX_UInt32 listSize
= 0;
307 PKIX_UInt32 listIndex
= 0;
308 PKIX_PolicyNode
*candidate
= NULL
;
310 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_Prune");
312 PKIX_NULLCHECK_TWO(node
, pDelete
);
314 /* Don't prune at the leaf */
319 /* Above the bottom level, childless nodes get pruned */
320 if (!(node
->children
)) {
321 childless
= PKIX_TRUE
;
326 * This node has children. If they are leaf nodes,
327 * we know they will live. Otherwise, check them out.
330 PKIX_CHECK(PKIX_List_GetLength
331 (node
->children
, &listSize
, plContext
),
332 PKIX_LISTGETLENGTHFAILED
);
334 * By working backwards from the end of the list,
335 * we avoid having to worry about possible
336 * decreases in the size of the list, as we
337 * delete items. The only nuisance is that since the
338 * index is UInt32, we can't check for it to reach -1;
339 * we have to use the 1-based index, rather than the
340 * 0-based index that PKIX_List functions require.
342 for (listIndex
= listSize
; listIndex
> 0; listIndex
--) {
343 PKIX_CHECK(PKIX_List_GetItem
346 (PKIX_PL_Object
**)&candidate
,
348 PKIX_LISTGETITEMFAILED
);
350 PKIX_CHECK(pkix_PolicyNode_Prune
355 PKIX_POLICYNODEPRUNEFAILED
);
357 if (shouldBePruned
== PKIX_TRUE
) {
358 PKIX_CHECK(PKIX_List_DeleteItem
362 PKIX_LISTDELETEITEMFAILED
);
365 PKIX_DECREF(candidate
);
369 /* Prune if this node has *become* childless */
370 PKIX_CHECK(PKIX_List_GetLength
371 (node
->children
, &listSize
, plContext
),
372 PKIX_LISTGETLENGTHFAILED
);
374 childless
= PKIX_TRUE
;
378 * Even if we did not change this node, or any of its children,
379 * maybe a [great-]*grandchild was pruned.
381 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
382 ((PKIX_PL_Object
*)node
, plContext
),
383 PKIX_OBJECTINVALIDATECACHEFAILED
);
386 *pDelete
= childless
;
388 PKIX_DECREF(candidate
);
390 PKIX_RETURN(CERTPOLICYNODE
);
394 * FUNCTION: pkix_SinglePolicyNode_ToString
397 * Creates a String representation of the attributes of the PolicyNode
398 * pointed to by "node", other than its parents or children, and
399 * stores the result at "pString".
403 * Address of PolicyNode to be described by the string. Must be non-NULL.
405 * Address where object pointer will be stored. Must be non-NULL.
407 * Platform-specific context pointer.
409 * Conditionally Thread Safe
410 * (see Thread Safety Definitions in Programmer's Guide)
412 * Returns NULL if function succeeds
413 * Returns a PolicyNode Error if the function fails in a non-fatal way.
414 * Returns a Fatal Error if the function fails in a fatal way
417 pkix_SinglePolicyNode_ToString(
418 PKIX_PolicyNode
*node
,
419 PKIX_PL_String
**pString
,
422 PKIX_PL_String
*fmtString
= NULL
;
423 PKIX_PL_String
*validString
= NULL
;
424 PKIX_PL_String
*qualifierString
= NULL
;
425 PKIX_PL_String
*criticalityString
= NULL
;
426 PKIX_PL_String
*expectedString
= NULL
;
427 PKIX_PL_String
*outString
= NULL
;
429 PKIX_ENTER(CERTPOLICYNODE
, "pkix_SinglePolicyNode_ToString");
430 PKIX_NULLCHECK_TWO(node
, pString
);
431 PKIX_NULLCHECK_TWO(node
->validPolicy
, node
->expectedPolicySet
);
433 PKIX_CHECK(PKIX_PL_String_Create
439 PKIX_CANTCREATESTRING
);
441 PKIX_CHECK(PKIX_PL_Object_ToString
442 ((PKIX_PL_Object
*)(node
->validPolicy
),
445 PKIX_OIDTOSTRINGFAILED
);
447 PKIX_CHECK(PKIX_PL_Object_ToString
448 ((PKIX_PL_Object
*)(node
->expectedPolicySet
),
451 PKIX_LISTTOSTRINGFAILED
);
453 if (node
->qualifierSet
) {
454 PKIX_CHECK(PKIX_PL_Object_ToString
455 ((PKIX_PL_Object
*)(node
->qualifierSet
),
458 PKIX_LISTTOSTRINGFAILED
);
460 PKIX_CHECK(PKIX_PL_String_Create
466 PKIX_CANTCREATESTRING
);
469 PKIX_CHECK(PKIX_PL_String_Create
471 (node
->criticality
)?"Critical":"Not Critical",
475 PKIX_CANTCREATESTRING
);
477 PKIX_CHECK(PKIX_PL_Sprintf
488 *pString
= outString
;
492 PKIX_DECREF(fmtString
);
493 PKIX_DECREF(validString
);
494 PKIX_DECREF(qualifierString
);
495 PKIX_DECREF(criticalityString
);
496 PKIX_DECREF(expectedString
);
497 PKIX_RETURN(CERTPOLICYNODE
);
501 * FUNCTION: pkix_PolicyNode_ToString_Helper
504 * Produces a String representation of a PolicyNode tree below the PolicyNode
505 * pointed to by "rootNode", with each line of output prefixed by the String
506 * pointed to by "indent", and stores the result at "pTreeString". It is
507 * called recursively, with ever-increasing indentation, for successively
508 * lower nodes on the tree.
512 * Address of PolicyNode subtree. Must be non-NULL.
514 * Address of String to be prefixed to each line of output. May be NULL
515 * if no indentation is desired
517 * Address where the resulting String will be stored; must be non-NULL
519 * Platform-specific context pointer.
521 * Conditionally Thread Safe
522 * (see Thread Safety Definitions in Programmer's Guide)
524 * Returns NULL if the function succeeds.
525 * Returns a PolicyNode Error if the function fails in a non-fatal way.
526 * Returns a Fatal Error if the function fails in an unrecoverable way.
529 pkix_PolicyNode_ToString_Helper(
530 PKIX_PolicyNode
*rootNode
,
531 PKIX_PL_String
*indent
,
532 PKIX_PL_String
**pTreeString
,
535 PKIX_PL_String
*nextIndentFormat
= NULL
;
536 PKIX_PL_String
*thisNodeFormat
= NULL
;
537 PKIX_PL_String
*childrenFormat
= NULL
;
538 PKIX_PL_String
*nextIndentString
= NULL
;
539 PKIX_PL_String
*resultString
= NULL
;
540 PKIX_PL_String
*thisItemString
= NULL
;
541 PKIX_PL_String
*childString
= NULL
;
542 PKIX_PolicyNode
*childNode
= NULL
;
543 PKIX_UInt32 numberOfChildren
= 0;
544 PKIX_UInt32 childIndex
= 0;
546 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_ToString_Helper");
548 PKIX_NULLCHECK_TWO(rootNode
, pTreeString
);
550 /* Create a string for this node */
551 PKIX_CHECK(pkix_SinglePolicyNode_ToString
552 (rootNode
, &thisItemString
, plContext
),
553 PKIX_ERRORINSINGLEPOLICYNODETOSTRING
);
556 PKIX_CHECK(PKIX_PL_String_Create
562 PKIX_ERRORCREATINGFORMATSTRING
);
564 PKIX_CHECK(PKIX_PL_Sprintf
570 PKIX_ERRORINSPRINTF
);
572 PKIX_CHECK(PKIX_PL_String_Create
578 PKIX_ERRORCREATINGFORMATSTRING
);
580 PKIX_CHECK(PKIX_PL_Sprintf
585 PKIX_ERRORINSPRINTF
);
588 PKIX_DECREF(thisItemString
);
589 thisItemString
= resultString
;
591 /* if no children, we are done */
592 if (rootNode
->children
) {
593 PKIX_CHECK(PKIX_List_GetLength
594 (rootNode
->children
, &numberOfChildren
, plContext
),
595 PKIX_LISTGETLENGTHFAILED
);
598 if (numberOfChildren
!= 0) {
600 * We create a string for each child in turn,
601 * concatenating them to thisItemString.
604 /* Prepare an indent string for each child */
606 PKIX_CHECK(PKIX_PL_String_Create
612 PKIX_ERRORCREATINGFORMATSTRING
);
614 PKIX_CHECK(PKIX_PL_Sprintf
619 PKIX_ERRORINSPRINTF
);
621 PKIX_CHECK(PKIX_PL_String_Create
627 PKIX_ERRORCREATINGINDENTSTRING
);
630 /* Prepare the format for concatenation. */
631 PKIX_CHECK(PKIX_PL_String_Create
637 PKIX_ERRORCREATINGFORMATSTRING
);
640 childIndex
< numberOfChildren
;
642 PKIX_CHECK(PKIX_List_GetItem
645 (PKIX_PL_Object
**)&childNode
,
647 PKIX_LISTGETITEMFAILED
);
649 PKIX_CHECK(pkix_PolicyNode_ToString_Helper
654 PKIX_ERRORCREATINGCHILDSTRING
);
657 PKIX_CHECK(PKIX_PL_Sprintf
663 PKIX_ERRORINSPRINTF
);
665 PKIX_DECREF(childNode
);
666 PKIX_DECREF(childString
);
667 PKIX_DECREF(thisItemString
);
669 thisItemString
= resultString
;
673 *pTreeString
= thisItemString
;
676 if (PKIX_ERROR_RECEIVED
) {
677 PKIX_DECREF(thisItemString
);
680 PKIX_DECREF(nextIndentFormat
);
681 PKIX_DECREF(thisNodeFormat
);
682 PKIX_DECREF(childrenFormat
);
683 PKIX_DECREF(nextIndentString
);
684 PKIX_DECREF(childString
);
685 PKIX_DECREF(childNode
);
687 PKIX_RETURN(CERTPOLICYNODE
);
691 * FUNCTION: pkix_PolicyNode_ToString
692 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
695 pkix_PolicyNode_ToString(
696 PKIX_PL_Object
*object
,
697 PKIX_PL_String
**pTreeString
,
700 PKIX_PolicyNode
*rootNode
= NULL
;
701 PKIX_PL_String
*resultString
= NULL
;
703 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_ToString");
705 PKIX_NULLCHECK_TWO(object
, pTreeString
);
707 PKIX_CHECK(pkix_CheckType(object
, PKIX_CERTPOLICYNODE_TYPE
, plContext
),
708 PKIX_OBJECTNOTPOLICYNODE
);
710 rootNode
= (PKIX_PolicyNode
*)object
;
712 PKIX_CHECK(pkix_PolicyNode_ToString_Helper
713 (rootNode
, NULL
, &resultString
, plContext
),
714 PKIX_ERRORCREATINGSUBTREESTRING
);
716 *pTreeString
= resultString
;
720 PKIX_RETURN(CERTPOLICYNODE
);
724 * FUNCTION: pkix_PolicyNode_Destroy
725 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
728 pkix_PolicyNode_Destroy(
729 PKIX_PL_Object
*object
,
732 PKIX_PolicyNode
*node
= NULL
;
734 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_Destroy");
736 PKIX_NULLCHECK_ONE(object
);
738 PKIX_CHECK(pkix_CheckType(object
, PKIX_CERTPOLICYNODE_TYPE
, plContext
),
739 PKIX_OBJECTNOTPOLICYNODE
);
741 node
= (PKIX_PolicyNode
*)object
;
743 node
->criticality
= PKIX_FALSE
;
744 PKIX_DECREF(node
->validPolicy
);
745 PKIX_DECREF(node
->qualifierSet
);
746 PKIX_DECREF(node
->expectedPolicySet
);
747 PKIX_DECREF(node
->children
);
750 * Note: the link to parent is not reference-counted. See comment
751 * in pkix_PolicyNode_AddToParent for more details.
758 PKIX_RETURN(CERTPOLICYNODE
);
762 * FUNCTION: pkix_SinglePolicyNode_Hashcode
765 * Computes the hashcode of the attributes of the PolicyNode pointed to by
766 * "node", other than its parents and children, and stores the result at
771 * Address of PolicyNode to be hashcoded; must be non-NULL
773 * Address where UInt32 result will be stored; must be non-NULL
775 * Platform-specific context pointer.
777 * Conditionally Thread Safe
778 * (see Thread Safety Definitions in Programmer's Guide)
780 * Returns NULL if function succeeds
781 * Returns a PolicyNode Error if the function fails in a non-fatal way.
782 * Returns a Fatal Error if the function fails in a fatal way
785 pkix_SinglePolicyNode_Hashcode(
786 PKIX_PolicyNode
*node
,
787 PKIX_UInt32
*pHashcode
,
790 PKIX_UInt32 componentHash
= 0;
791 PKIX_UInt32 nodeHash
= 0;
793 PKIX_ENTER(CERTPOLICYNODE
, "pkix_SinglePolicyNode_Hashcode");
794 PKIX_NULLCHECK_TWO(node
, pHashcode
);
795 PKIX_NULLCHECK_TWO(node
->validPolicy
, node
->expectedPolicySet
);
801 PKIX_FAILUREHASHINGLISTQUALIFIERSET
);
803 if (PKIX_TRUE
== (node
->criticality
)) {
804 nodeHash
= 31*nodeHash
+ 0xff;
806 nodeHash
= 31*nodeHash
+ 0x00;
809 PKIX_CHECK(PKIX_PL_Object_Hashcode
810 ((PKIX_PL_Object
*)node
->validPolicy
,
813 PKIX_FAILUREHASHINGOIDVALIDPOLICY
);
815 nodeHash
= 31*nodeHash
+ componentHash
;
817 PKIX_CHECK(PKIX_PL_Object_Hashcode
818 ((PKIX_PL_Object
*)node
->expectedPolicySet
,
821 PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET
);
823 nodeHash
= 31*nodeHash
+ componentHash
;
825 *pHashcode
= nodeHash
;
829 PKIX_RETURN(CERTPOLICYNODE
);
833 * FUNCTION: pkix_PolicyNode_Hashcode
834 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
837 pkix_PolicyNode_Hashcode(
838 PKIX_PL_Object
*object
,
839 PKIX_UInt32
*pHashcode
,
842 PKIX_PolicyNode
*node
= NULL
;
843 PKIX_UInt32 childrenHash
= 0;
844 PKIX_UInt32 nodeHash
= 0;
846 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_Hashcode");
847 PKIX_NULLCHECK_TWO(object
, pHashcode
);
849 PKIX_CHECK(pkix_CheckType
850 (object
, PKIX_CERTPOLICYNODE_TYPE
, plContext
),
851 PKIX_OBJECTNOTPOLICYNODE
);
853 node
= (PKIX_PolicyNode
*)object
;
855 PKIX_CHECK(pkix_SinglePolicyNode_Hashcode
856 (node
, &nodeHash
, plContext
),
857 PKIX_SINGLEPOLICYNODEHASHCODEFAILED
);
859 nodeHash
= 31*nodeHash
+ (PKIX_UInt32
)(node
->parent
);
865 PKIX_OBJECTHASHCODEFAILED
);
867 nodeHash
= 31*nodeHash
+ childrenHash
;
869 *pHashcode
= nodeHash
;
873 PKIX_RETURN(CERTPOLICYNODE
);
877 * FUNCTION: pkix_SinglePolicyNode_Equals
880 * Compares for equality the components of the PolicyNode pointed to by
881 * "firstPN", other than its parents and children, with those of the
882 * PolicyNode pointed to by "secondPN" and stores the result at "pResult"
883 * (PKIX_TRUE if equal; PKIX_FALSE if not).
887 * Address of first of the PolicyNodes to be compared; must be non-NULL
889 * Address of second of the PolicyNodes to be compared; must be non-NULL
891 * Address where Boolean will be stored; must be non-NULL
893 * Platform-specific context pointer.
895 * Conditionally Thread Safe
896 * (see Thread Safety Definitions in Programmer's Guide)
898 * Returns NULL if function succeeds
899 * Returns a PolicyNode Error if the function fails in a non-fatal way.
900 * Returns a Fatal Error if the function fails in a fatal way
903 pkix_SinglePolicyNode_Equals(
904 PKIX_PolicyNode
*firstPN
,
905 PKIX_PolicyNode
*secondPN
,
906 PKIX_Boolean
*pResult
,
909 PKIX_Boolean compResult
= PKIX_FALSE
;
911 PKIX_ENTER(CERTPOLICYNODE
, "pkix_SinglePolicyNode_Equals");
912 PKIX_NULLCHECK_THREE(firstPN
, secondPN
, pResult
);
914 /* If both references are identical, they must be equal */
915 if (firstPN
== secondPN
) {
916 compResult
= PKIX_TRUE
;
921 * It seems we have to do the comparisons. Do
922 * the easiest ones first.
924 if ((firstPN
->criticality
) != (secondPN
->criticality
)) {
927 if ((firstPN
->depth
) != (secondPN
->depth
)) {
932 (firstPN
->qualifierSet
,
933 secondPN
->qualifierSet
,
936 PKIX_OBJECTEQUALSFAILED
);
938 if (compResult
== PKIX_FALSE
) {
942 /* These fields must be non-NULL */
943 PKIX_NULLCHECK_TWO(firstPN
->validPolicy
, secondPN
->validPolicy
);
946 (firstPN
->validPolicy
,
947 secondPN
->validPolicy
,
950 PKIX_OBJECTEQUALSFAILED
);
952 if (compResult
== PKIX_FALSE
) {
956 /* These fields must be non-NULL */
958 (firstPN
->expectedPolicySet
, secondPN
->expectedPolicySet
);
961 (firstPN
->expectedPolicySet
,
962 secondPN
->expectedPolicySet
,
965 PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS
);
969 *pResult
= compResult
;
971 PKIX_RETURN(CERTPOLICYNODE
);
975 * FUNCTION: pkix_PolicyNode_Equals
976 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
979 pkix_PolicyNode_Equals(
980 PKIX_PL_Object
*firstObject
,
981 PKIX_PL_Object
*secondObject
,
982 PKIX_Boolean
*pResult
,
985 PKIX_PolicyNode
*firstPN
= NULL
;
986 PKIX_PolicyNode
*secondPN
= NULL
;
987 PKIX_UInt32 secondType
;
988 PKIX_Boolean compResult
= PKIX_FALSE
;
990 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_Equals");
991 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
993 /* test that firstObject is a PolicyNode */
994 PKIX_CHECK(pkix_CheckType
995 (firstObject
, PKIX_CERTPOLICYNODE_TYPE
, plContext
),
996 PKIX_FIRSTOBJECTNOTPOLICYNODE
);
999 * Since we know firstObject is a PolicyNode,
1000 * if both references are identical, they must be equal
1002 if (firstObject
== secondObject
){
1003 compResult
= PKIX_TRUE
;
1008 * If secondObject isn't a PolicyNode, we
1009 * don't throw an error. We simply return FALSE.
1011 PKIX_CHECK(PKIX_PL_Object_GetType
1012 (secondObject
, &secondType
, plContext
),
1013 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
1015 if (secondType
!= PKIX_CERTPOLICYNODE_TYPE
) {
1020 * Oh, well, we have to do the comparisons. Do
1021 * the easiest ones first.
1023 firstPN
= (PKIX_PolicyNode
*)firstObject
;
1024 secondPN
= (PKIX_PolicyNode
*)secondObject
;
1027 * We don't require the parents to be identical. In the
1028 * course of traversing the tree, we will have checked the
1029 * attributes of the parent nodes, and checking the lists
1030 * of children will determine whether they match.
1038 PKIX_OBJECTEQUALSFAILEDONCHILDREN
);
1040 if (compResult
== PKIX_FALSE
) {
1044 PKIX_CHECK(pkix_SinglePolicyNode_Equals
1045 (firstPN
, secondPN
, &compResult
, plContext
),
1046 PKIX_SINGLEPOLICYNODEEQUALSFAILED
);
1050 *pResult
= compResult
;
1052 PKIX_RETURN(CERTPOLICYNODE
);
1056 * FUNCTION: pkix_PolicyNode_DuplicateHelper
1059 * Duplicates the PolicyNode whose address is pointed to by "original",
1060 * and stores the result at "pNewNode", if a non-NULL pointer is provided
1061 * for "pNewNode". In addition, the created PolicyNode is added as a child
1062 * to "parent", if a non-NULL pointer is provided for "parent". Then this
1063 * function is called recursively to duplicate each of the children of
1064 * "original". At the top level this function is called with a null
1065 * "parent" and a non-NULL "pNewNode". Below the top level "parent" will
1066 * be non-NULL and "pNewNode" will be NULL.
1070 * Address of PolicyNode to be copied; must be non-NULL
1072 * Address of PolicyNode to which the created node is to be added as a
1073 * child; NULL for the top-level call and non-NULL below the top level
1075 * Address to store the node created; should be NULL if "parent" is
1076 * non-NULL and vice versa
1078 * Platform-specific context pointer.
1080 * Conditionally Thread Safe
1081 * (see Thread Safety Definitions in Programmer's Guide)
1083 * Returns NULL if function succeeds
1084 * Returns a PolicyNode Error if the function fails in a non-fatal way.
1085 * Returns a Fatal Error if the function fails in a fatal way
1088 pkix_PolicyNode_DuplicateHelper(
1089 PKIX_PolicyNode
*original
,
1090 PKIX_PolicyNode
*parent
,
1091 PKIX_PolicyNode
**pNewNode
,
1094 PKIX_UInt32 numChildren
= 0;
1095 PKIX_UInt32 childIndex
= 0;
1096 PKIX_List
*children
= NULL
; /* List of PKIX_PolicyNode */
1097 PKIX_PolicyNode
*copy
= NULL
;
1098 PKIX_PolicyNode
*child
= NULL
;
1100 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_DuplicateHelper");
1102 PKIX_NULLCHECK_THREE
1103 (original
, original
->validPolicy
, original
->expectedPolicySet
);
1106 * These components are immutable, so copying the pointers
1107 * is sufficient. The create function increments the reference
1108 * counts as it stores the pointers into the new object.
1110 PKIX_CHECK(pkix_PolicyNode_Create
1111 (original
->validPolicy
,
1112 original
->qualifierSet
,
1113 original
->criticality
,
1114 original
->expectedPolicySet
,
1117 PKIX_POLICYNODECREATEFAILED
);
1120 PKIX_CHECK(pkix_PolicyNode_AddToParent(parent
, copy
, plContext
),
1121 PKIX_POLICYNODEADDTOPARENTFAILED
);
1124 /* Are there any children to duplicate? */
1125 children
= original
->children
;
1128 PKIX_CHECK(PKIX_List_GetLength(children
, &numChildren
, plContext
),
1129 PKIX_LISTGETLENGTHFAILED
);
1132 for (childIndex
= 0; childIndex
< numChildren
; childIndex
++) {
1133 PKIX_CHECK(PKIX_List_GetItem
1136 (PKIX_PL_Object
**)&child
,
1138 PKIX_LISTGETITEMFAILED
);
1140 PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
1141 (child
, copy
, NULL
, plContext
),
1142 PKIX_POLICYNODEDUPLICATEHELPERFAILED
);
1149 copy
= NULL
; /* no DecRef if we give our handle away */
1156 PKIX_RETURN(CERTPOLICYNODE
);
1160 * FUNCTION: pkix_PolicyNode_Duplicate
1161 * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
1164 pkix_PolicyNode_Duplicate(
1165 PKIX_PL_Object
*object
,
1166 PKIX_PL_Object
**pNewObject
,
1169 PKIX_PolicyNode
*original
= NULL
;
1170 PKIX_PolicyNode
*copy
= NULL
;
1172 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_Duplicate");
1174 PKIX_NULLCHECK_TWO(object
, pNewObject
);
1176 PKIX_CHECK(pkix_CheckType
1177 (object
, PKIX_CERTPOLICYNODE_TYPE
, plContext
),
1178 PKIX_OBJECTNOTPOLICYNODE
);
1180 original
= (PKIX_PolicyNode
*)object
;
1182 PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
1183 (original
, NULL
, ©
, plContext
),
1184 PKIX_POLICYNODEDUPLICATEHELPERFAILED
);
1186 *pNewObject
= (PKIX_PL_Object
*)copy
;
1190 PKIX_RETURN(CERTPOLICYNODE
);
1194 * FUNCTION: pkix_PolicyNode_RegisterSelf
1197 * Registers PKIX_CERTPOLICYNODE_TYPE and its related
1198 * functions with systemClasses[]
1201 * Not Thread Safe - for performance and complexity reasons
1203 * Since this function is only called by PKIX_PL_Initialize,
1204 * which should only be called once, it is acceptable that
1205 * this function is not thread-safe.
1208 pkix_PolicyNode_RegisterSelf(void *plContext
)
1211 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
1212 pkix_ClassTable_Entry entry
;
1214 PKIX_ENTER(CERTPOLICYNODE
, "pkix_PolicyNode_RegisterSelf");
1216 entry
.description
= "PolicyNode";
1217 entry
.destructor
= pkix_PolicyNode_Destroy
;
1218 entry
.equalsFunction
= pkix_PolicyNode_Equals
;
1219 entry
.hashcodeFunction
= pkix_PolicyNode_Hashcode
;
1220 entry
.toStringFunction
= pkix_PolicyNode_ToString
;
1221 entry
.comparator
= NULL
;
1222 entry
.duplicateFunction
= pkix_PolicyNode_Duplicate
;
1224 systemClasses
[PKIX_CERTPOLICYNODE_TYPE
] = entry
;
1226 PKIX_RETURN(CERTPOLICYNODE
);
1230 /* --Public-PolicyNode-Functions----------------------------------- */
1233 * FUNCTION: PKIX_PolicyNode_GetChildren
1234 * (see description of this function in pkix_results.h)
1237 PKIX_PolicyNode_GetChildren(
1238 PKIX_PolicyNode
*node
,
1239 PKIX_List
**pChildren
, /* list of PKIX_PolicyNode */
1242 PKIX_List
*children
= NULL
;
1244 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_GetChildren");
1246 PKIX_NULLCHECK_TWO(node
, pChildren
);
1248 PKIX_INCREF(node
->children
);
1249 children
= node
->children
;
1252 PKIX_CHECK(PKIX_List_Create(&children
, plContext
),
1253 PKIX_LISTCREATEFAILED
);
1256 PKIX_CHECK(PKIX_List_SetImmutable(children
, plContext
),
1257 PKIX_LISTSETIMMUTABLEFAILED
);
1259 *pChildren
= children
;
1262 if (PKIX_ERROR_RECEIVED
) {
1263 PKIX_DECREF(children
);
1266 PKIX_RETURN(CERTPOLICYNODE
);
1270 * FUNCTION: PKIX_PolicyNode_GetParent
1271 * (see description of this function in pkix_results.h)
1274 PKIX_PolicyNode_GetParent(
1275 PKIX_PolicyNode
*node
,
1276 PKIX_PolicyNode
**pParent
,
1280 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_GetParent");
1282 PKIX_NULLCHECK_TWO(node
, pParent
);
1284 PKIX_INCREF(node
->parent
);
1285 *pParent
= node
->parent
;
1287 PKIX_RETURN(CERTPOLICYNODE
);
1291 * FUNCTION: PKIX_PolicyNode_GetValidPolicy
1292 * (see description of this function in pkix_results.h)
1295 PKIX_PolicyNode_GetValidPolicy(
1296 PKIX_PolicyNode
*node
,
1297 PKIX_PL_OID
**pValidPolicy
,
1301 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_GetValidPolicy");
1303 PKIX_NULLCHECK_TWO(node
, pValidPolicy
);
1305 PKIX_INCREF(node
->validPolicy
);
1306 *pValidPolicy
= node
->validPolicy
;
1308 PKIX_RETURN(CERTPOLICYNODE
);
1312 * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers
1313 * (see description of this function in pkix_results.h)
1316 PKIX_PolicyNode_GetPolicyQualifiers(
1317 PKIX_PolicyNode
*node
,
1318 PKIX_List
**pQualifiers
, /* list of PKIX_PL_CertPolicyQualifier */
1321 PKIX_List
*qualifiers
= NULL
;
1323 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_GetPolicyQualifiers");
1325 PKIX_NULLCHECK_TWO(node
, pQualifiers
);
1327 PKIX_INCREF(node
->qualifierSet
);
1328 qualifiers
= node
->qualifierSet
;
1331 PKIX_CHECK(PKIX_List_Create(&qualifiers
, plContext
),
1332 PKIX_LISTCREATEFAILED
);
1335 PKIX_CHECK(PKIX_List_SetImmutable(qualifiers
, plContext
),
1336 PKIX_LISTSETIMMUTABLEFAILED
);
1338 *pQualifiers
= qualifiers
;
1342 PKIX_RETURN(CERTPOLICYNODE
);
1346 * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies
1347 * (see description of this function in pkix_results.h)
1350 PKIX_PolicyNode_GetExpectedPolicies(
1351 PKIX_PolicyNode
*node
,
1352 PKIX_List
**pExpPolicies
, /* list of PKIX_PL_OID */
1356 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_GetExpectedPolicies");
1358 PKIX_NULLCHECK_TWO(node
, pExpPolicies
);
1360 PKIX_INCREF(node
->expectedPolicySet
);
1361 *pExpPolicies
= node
->expectedPolicySet
;
1363 PKIX_RETURN(CERTPOLICYNODE
);
1367 * FUNCTION: PKIX_PolicyNode_IsCritical
1368 * (see description of this function in pkix_results.h)
1371 PKIX_PolicyNode_IsCritical(
1372 PKIX_PolicyNode
*node
,
1373 PKIX_Boolean
*pCritical
,
1377 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_IsCritical");
1379 PKIX_NULLCHECK_TWO(node
, pCritical
);
1381 *pCritical
= node
->criticality
;
1383 PKIX_RETURN(CERTPOLICYNODE
);
1387 * FUNCTION: PKIX_PolicyNode_GetDepth
1388 * (see description of this function in pkix_results.h)
1391 PKIX_PolicyNode_GetDepth(
1392 PKIX_PolicyNode
*node
,
1393 PKIX_UInt32
*pDepth
,
1397 PKIX_ENTER(CERTPOLICYNODE
, "PKIX_PolicyNode_GetDepth");
1399 PKIX_NULLCHECK_TWO(node
, pDepth
);
1401 *pDepth
= node
->depth
;
1403 PKIX_RETURN(CERTPOLICYNODE
);