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