/src/xmlsec/src/enveloped.c
Line | Count | Source |
1 | | /* |
2 | | * XML Security Library (http://www.aleksey.com/xmlsec). |
3 | | * |
4 | | * Enveloped transform implementation. |
5 | | * This is free software; see Copyright file in the source |
6 | | * distribution for preciese wording. |
7 | | * |
8 | | * Copyright (C) 2002-2024 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. |
9 | | */ |
10 | | /** |
11 | | * SECTION:transforms |
12 | | * @Short_description: |
13 | | * @Stability: Stable |
14 | | * |
15 | | */ |
16 | | #include "globals.h" |
17 | | |
18 | | #include <stdlib.h> |
19 | | #include <string.h> |
20 | | |
21 | | #include <libxml/tree.h> |
22 | | #include <libxml/xpath.h> |
23 | | #include <libxml/xpathInternals.h> |
24 | | |
25 | | #include <xmlsec/xmlsec.h> |
26 | | #include <xmlsec/xmltree.h> |
27 | | #include <xmlsec/keys.h> |
28 | | #include <xmlsec/transforms.h> |
29 | | #include <xmlsec/errors.h> |
30 | | |
31 | | /************************************************************************** |
32 | | * |
33 | | * Enveloped transform |
34 | | * |
35 | | *************************************************************************/ |
36 | | static int xmlSecTransformEnvelopedExecute (xmlSecTransformPtr transform, |
37 | | int last, |
38 | | xmlSecTransformCtxPtr transformCtx); |
39 | | |
40 | | |
41 | | static xmlSecTransformKlass xmlSecTransformEnvelopedKlass = { |
42 | | /* klass/object sizes */ |
43 | | sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
44 | | sizeof(xmlSecTransform), /* xmlSecSize objSize */ |
45 | | |
46 | | xmlSecNameEnveloped, /* const xmlChar* name; */ |
47 | | xmlSecHrefEnveloped, /* const xmlChar* href; */ |
48 | | xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */ |
49 | | |
50 | | NULL, /* xmlSecTransformInitializeMethod initialize; */ |
51 | | NULL, /* xmlSecTransformFinalizeMethod finalize; */ |
52 | | NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
53 | | NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
54 | | NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
55 | | NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
56 | | NULL, /* xmlSecTransformValidateMethod validate; */ |
57 | | xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
58 | | NULL, /* xmlSecTransformPushBinMethod pushBin; */ |
59 | | NULL, /* xmlSecTransformPopBinMethod popBin; */ |
60 | | xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */ |
61 | | xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */ |
62 | | xmlSecTransformEnvelopedExecute, /* xmlSecTransformExecuteMethod execute; */ |
63 | | |
64 | | NULL, /* void* reserved0; */ |
65 | | NULL, /* void* reserved1; */ |
66 | | }; |
67 | | |
68 | | /** |
69 | | * xmlSecTransformEnvelopedGetKlass: |
70 | | * |
71 | | * The enveloped transform klass (http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature): |
72 | | * |
73 | | * An enveloped signature transform T removes the whole Signature element |
74 | | * containing T from the digest calculation of the Reference element |
75 | | * containing T. The entire string of characters used by an XML processor |
76 | | * to match the Signature with the XML production element is removed. |
77 | | * The output of the transform is equivalent to the output that would |
78 | | * result from replacing T with an XPath transform containing the following |
79 | | * XPath parameter element: |
80 | | * |
81 | | * <XPath xmlns:dsig="..."> |
82 | | * count(ancestor-or-self::dsig:Signature | |
83 | | * here()/ancestor::dsig:Signature[1]) > |
84 | | * count(ancestor-or-self::dsig:Signature) |
85 | | * </XPath> |
86 | | * |
87 | | * The input and output requirements of this transform are identical to |
88 | | * those of the XPath transform, but may only be applied to a node-set from |
89 | | * its parent XML document. Note that it is not necessary to use an XPath |
90 | | * expression evaluator to create this transform. However, this transform |
91 | | * MUST produce output in exactly the same manner as the XPath transform |
92 | | * parameterized by the XPath expression above. |
93 | | * |
94 | | * Returns: enveloped transform id. |
95 | | */ |
96 | | xmlSecTransformId |
97 | 0 | xmlSecTransformEnvelopedGetKlass(void) { |
98 | 0 | return(&xmlSecTransformEnvelopedKlass); |
99 | 0 | } |
100 | | |
101 | | static int |
102 | | xmlSecTransformEnvelopedExecute(xmlSecTransformPtr transform, int last, |
103 | 0 | xmlSecTransformCtxPtr transformCtx) { |
104 | 0 | xmlNodePtr node; |
105 | 0 | xmlSecNodeSetPtr children; |
106 | |
|
107 | 0 | xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformEnvelopedId), -1); |
108 | 0 | xmlSecAssert2(transform->hereNode != NULL, -1); |
109 | 0 | xmlSecAssert2(transform->outNodes == NULL, -1); |
110 | 0 | xmlSecAssert2(last != 0, -1); |
111 | 0 | xmlSecAssert2(transformCtx != NULL, -1); |
112 | |
|
113 | 0 | if((transform->inNodes != NULL) && (transform->inNodes->doc != transform->hereNode->doc)) { |
114 | 0 | xmlSecOtherError(XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED, |
115 | 0 | xmlSecTransformGetName(transform), |
116 | 0 | NULL); |
117 | 0 | return(-1); |
118 | 0 | } |
119 | | |
120 | | /* find signature node and get all its children in the nodes set */ |
121 | 0 | node = xmlSecFindParent(transform->hereNode, xmlSecNodeSignature, xmlSecDSigNs); |
122 | 0 | if(node == NULL) { |
123 | 0 | xmlSecNodeNotFoundError("xmlSecFindParent", transform->hereNode, |
124 | 0 | xmlSecNodeSignature, |
125 | 0 | xmlSecTransformGetName(transform)); |
126 | 0 | return(-1); |
127 | 0 | } |
128 | | |
129 | 0 | children = xmlSecNodeSetGetChildren(node->doc, node, 1, 1); |
130 | 0 | if(children == NULL) { |
131 | 0 | xmlSecInternalError2("xmlSecNodeSetGetChildren", |
132 | 0 | xmlSecTransformGetName(transform), |
133 | 0 | "node=%s", |
134 | 0 | xmlSecErrorsSafeString(xmlSecNodeGetName(node))); |
135 | 0 | return(-1); |
136 | 0 | } |
137 | | |
138 | | /* intersect <dsig:Signature/> node children with input nodes (if exist) */ |
139 | 0 | transform->outNodes = xmlSecNodeSetAdd(transform->inNodes, children, xmlSecNodeSetIntersection); |
140 | 0 | if(transform->outNodes == NULL) { |
141 | 0 | xmlSecInternalError("xmlSecNodeSetAdd", |
142 | 0 | xmlSecTransformGetName(transform)); |
143 | 0 | xmlSecNodeSetDestroy(children); |
144 | 0 | return(-1); |
145 | 0 | } |
146 | | |
147 | 0 | return(0); |
148 | 0 | } |