Git init
[external/xmlsec1.git] / src / enveloped.c
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  */
11 #include "globals.h"
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <libxml/tree.h>
17 #include <libxml/xpath.h>
18 #include <libxml/xpathInternals.h>
19
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>
25
26 /**************************************************************************
27  *
28  *  Enveloped transform 
29  *
30  *************************************************************************/
31 static int      xmlSecTransformEnvelopedExecute         (xmlSecTransformPtr transform,
32                                                          int last, 
33                                                          xmlSecTransformCtxPtr transformCtx);
34
35
36 static xmlSecTransformKlass xmlSecTransformEnvelopedKlass = {
37     /* klass/object sizes */
38     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
39     sizeof(xmlSecTransform),                    /* xmlSecSize objSize */
40
41     xmlSecNameEnveloped,                        /* const xmlChar* name; */
42     xmlSecHrefEnveloped,                        /* const xmlChar* href; */
43     xmlSecTransformUsageDSigTransform,          /* xmlSecTransformUsage usage; */
44     
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; */
58
59     NULL,                                       /* void* reserved0; */
60     NULL,                                       /* void* reserved1; */
61 };
62
63 /**
64  * xmlSecTransformEnvelopedGetKlass:
65  *
66  * The enveloped transform klass (http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature):
67  *
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:
75  *
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>
80  *    
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.
87  *
88  * Returns: enveloped transform id.
89  */
90 xmlSecTransformId 
91 xmlSecTransformEnvelopedGetKlass(void) {
92     return(&xmlSecTransformEnvelopedKlass);
93 }
94
95 static int
96 xmlSecTransformEnvelopedExecute(xmlSecTransformPtr transform, int last, 
97                                  xmlSecTransformCtxPtr transformCtx) {
98     xmlNodePtr node;
99     xmlSecNodeSetPtr children;
100
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);
106     
107     if((transform->inNodes != NULL) && (transform->inNodes->doc != transform->hereNode->doc)) {
108         xmlSecError(XMLSEC_ERRORS_HERE,
109                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
110                     NULL,
111                     XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,
112                     XMLSEC_ERRORS_NO_MESSAGE);
113         return(-1);
114     }
115     
116     /* find signature node and get all its children in the nodes set */
117     node = xmlSecFindParent(transform->hereNode, xmlSecNodeSignature, xmlSecDSigNs);
118     if(node == NULL) {
119         xmlSecError(XMLSEC_ERRORS_HERE,
120                     xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
121                     xmlSecErrorsSafeString(xmlSecNodeSignature),
122                     XMLSEC_ERRORS_R_NODE_NOT_FOUND,
123                     XMLSEC_ERRORS_NO_MESSAGE);
124         return(-1);
125     }
126     
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,
133                     "node=%s",
134                     xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
135         return(-1);
136     }
137
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)),
143                     "xmlSecNodeSetAdd",             
144                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
145                     XMLSEC_ERRORS_NO_MESSAGE);
146         xmlSecNodeSetDestroy(children);
147         return(-1);
148     }
149     
150     return(0);
151 }
152