2 * XML Security Library (http://www.aleksey.com/xmlsec).
6 * This is free software; see Copyright file in the source
7 * distribution for preciese wording.
9 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
16 #include <libxml/tree.h>
17 #include <libxml/xpath.h>
18 #include <libxml/xpathInternals.h>
20 #include <xmlsec/xmlsec.h>
21 #include <xmlsec/xmltree.h>
22 #include <xmlsec/keys.h>
23 #include <xmlsec/transforms.h>
24 #include <xmlsec/errors.h>
26 /**************************************************************************
30 *************************************************************************/
31 static int xmlSecTransformEnvelopedExecute (xmlSecTransformPtr transform,
33 xmlSecTransformCtxPtr transformCtx);
36 static xmlSecTransformKlass xmlSecTransformEnvelopedKlass = {
37 /* klass/object sizes */
38 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
39 sizeof(xmlSecTransform), /* xmlSecSize objSize */
41 xmlSecNameEnveloped, /* const xmlChar* name; */
42 xmlSecHrefEnveloped, /* const xmlChar* href; */
43 xmlSecTransformUsageDSigTransform, /* xmlSecTransformUsage usage; */
45 NULL, /* xmlSecTransformInitializeMethod initialize; */
46 NULL, /* xmlSecTransformFinalizeMethod finalize; */
47 NULL, /* xmlSecTransformNodeReadMethod readNode; */
48 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
49 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
50 NULL, /* xmlSecTransformSetKeyMethod setKey; */
51 NULL, /* xmlSecTransformValidateMethod validate; */
52 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
53 NULL, /* xmlSecTransformPushBinMethod pushBin; */
54 NULL, /* xmlSecTransformPopBinMethod popBin; */
55 xmlSecTransformDefaultPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
56 xmlSecTransformDefaultPopXml, /* xmlSecTransformPopXmlMethod popXml; */
57 xmlSecTransformEnvelopedExecute, /* xmlSecTransformExecuteMethod execute; */
59 NULL, /* void* reserved0; */
60 NULL, /* void* reserved1; */
64 * xmlSecTransformEnvelopedGetKlass:
66 * The enveloped transform klass (http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature):
68 * An enveloped signature transform T removes the whole Signature element
69 * containing T from the digest calculation of the Reference element
70 * containing T. The entire string of characters used by an XML processor
71 * to match the Signature with the XML production element is removed.
72 * The output of the transform is equivalent to the output that would
73 * result from replacing T with an XPath transform containing the following
74 * XPath parameter element:
76 * <XPath xmlns:dsig="&dsig;">
77 * count(ancestor-or-self::dsig:Signature |
78 * here()/ancestor::dsig:Signature[1]) >
79 * count(ancestor-or-self::dsig:Signature)</XPath>
81 * The input and output requirements of this transform are identical to
82 * those of the XPath transform, but may only be applied to a node-set from
83 * its parent XML document. Note that it is not necessary to use an XPath
84 * expression evaluator to create this transform. However, this transform
85 * MUST produce output in exactly the same manner as the XPath transform
86 * parameterized by the XPath expression above.
88 * Returns: enveloped transform id.
91 xmlSecTransformEnvelopedGetKlass(void) {
92 return(&xmlSecTransformEnvelopedKlass);
96 xmlSecTransformEnvelopedExecute(xmlSecTransformPtr transform, int last,
97 xmlSecTransformCtxPtr transformCtx) {
99 xmlSecNodeSetPtr children;
101 xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformEnvelopedId), -1);
102 xmlSecAssert2(transform->hereNode != NULL, -1);
103 xmlSecAssert2(transform->outNodes == NULL, -1);
104 xmlSecAssert2(last != 0, -1);
105 xmlSecAssert2(transformCtx != NULL, -1);
107 if((transform->inNodes != NULL) && (transform->inNodes->doc != transform->hereNode->doc)) {
108 xmlSecError(XMLSEC_ERRORS_HERE,
109 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
111 XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,
112 XMLSEC_ERRORS_NO_MESSAGE);
116 /* find signature node and get all its children in the nodes set */
117 node = xmlSecFindParent(transform->hereNode, xmlSecNodeSignature, xmlSecDSigNs);
119 xmlSecError(XMLSEC_ERRORS_HERE,
120 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
121 xmlSecErrorsSafeString(xmlSecNodeSignature),
122 XMLSEC_ERRORS_R_NODE_NOT_FOUND,
123 XMLSEC_ERRORS_NO_MESSAGE);
127 children = xmlSecNodeSetGetChildren(node->doc, node, 1, 1);
128 if(children == NULL) {
129 xmlSecError(XMLSEC_ERRORS_HERE,
130 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
131 "xmlSecNodeSetGetChildren",
132 XMLSEC_ERRORS_R_XMLSEC_FAILED,
134 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
138 /* intersect <dsig:Signature/> node children with input nodes (if exist) */
139 transform->outNodes = xmlSecNodeSetAdd(transform->inNodes, children, xmlSecNodeSetIntersection);
140 if(transform->outNodes == NULL) {
141 xmlSecError(XMLSEC_ERRORS_HERE,
142 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
144 XMLSEC_ERRORS_R_XMLSEC_FAILED,
145 XMLSEC_ERRORS_NO_MESSAGE);
146 xmlSecNodeSetDestroy(children);