summaryrefslogtreecommitdiff
path: root/src/enveloped.c
blob: 8047d318f38f26c4dd6d053d2d6dcb721e80a491 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
 * XML Security Library (http://www.aleksey.com/xmlsec).
 *
 * Enveloped transform.
 *
 * This is free software; see Copyright file in the source
 * distribution for preciese wording.
 *
 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
 */
#include "globals.h"

#include <stdlib.h>
#include <string.h>

#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/keys.h>
#include <xmlsec/transforms.h>
#include <xmlsec/errors.h>

/**************************************************************************
 *
 *  Enveloped transform
 *
 *************************************************************************/
static int      xmlSecTransformEnvelopedExecute         (xmlSecTransformPtr transform,
                                                         int last,
                                                         xmlSecTransformCtxPtr transformCtx);


static xmlSecTransformKlass xmlSecTransformEnvelopedKlass = {
    /* klass/object sizes */
    sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
    sizeof(xmlSecTransform),                    /* xmlSecSize objSize */

    xmlSecNameEnveloped,                        /* const xmlChar* name; */
    xmlSecHrefEnveloped,                        /* const xmlChar* href; */
    xmlSecTransformUsageDSigTransform,          /* xmlSecTransformUsage usage; */

    NULL,                                       /* xmlSecTransformInitializeMethod initialize; */
    NULL,                                       /* xmlSecTransformFinalizeMethod finalize; */
    NULL,                                       /* xmlSecTransformNodeReadMethod readNode; */
    NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
    NULL,                                       /* xmlSecTransformSetKeyReqMethod setKeyReq; */
    NULL,                                       /* xmlSecTransformSetKeyMethod setKey; */
    NULL,                                       /* xmlSecTransformValidateMethod validate; */
    xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
    NULL,                                       /* xmlSecTransformPushBinMethod pushBin; */
    NULL,                                       /* xmlSecTransformPopBinMethod popBin; */
    xmlSecTransformDefaultPushXml,              /* xmlSecTransformPushXmlMethod pushXml; */
    xmlSecTransformDefaultPopXml,               /* xmlSecTransformPopXmlMethod popXml; */
    xmlSecTransformEnvelopedExecute,            /* xmlSecTransformExecuteMethod execute; */

    NULL,                                       /* void* reserved0; */
    NULL,                                       /* void* reserved1; */
};

/**
 * xmlSecTransformEnvelopedGetKlass:
 *
 * The enveloped transform klass (http://www.w3.org/TR/xmldsig-core/#sec-EnvelopedSignature):
 *
 * An enveloped signature transform T removes the whole Signature element
 * containing T from the digest calculation of the Reference element
 * containing T. The entire string of characters used by an XML processor
 * to match the Signature with the XML production element is removed.
 * The output of the transform is equivalent to the output that would
 * result from replacing T with an XPath transform containing the following
 * XPath parameter element:
 *
 * <XPath xmlns:dsig="&dsig;">
 *   count(ancestor-or-self::dsig:Signature |
 *   here()/ancestor::dsig:Signature[1]) >
 *   count(ancestor-or-self::dsig:Signature)</XPath>
 *
 * The input and output requirements of this transform are identical to
 * those of the XPath transform, but may only be applied to a node-set from
 * its parent XML document. Note that it is not necessary to use an XPath
 * expression evaluator to create this transform. However, this transform
 * MUST produce output in exactly the same manner as the XPath transform
 * parameterized by the XPath expression above.
 *
 * Returns: enveloped transform id.
 */
xmlSecTransformId
xmlSecTransformEnvelopedGetKlass(void) {
    return(&xmlSecTransformEnvelopedKlass);
}

static int
xmlSecTransformEnvelopedExecute(xmlSecTransformPtr transform, int last,
                                 xmlSecTransformCtxPtr transformCtx) {
    xmlNodePtr node;
    xmlSecNodeSetPtr children;

    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecTransformEnvelopedId), -1);
    xmlSecAssert2(transform->hereNode != NULL, -1);
    xmlSecAssert2(transform->outNodes == NULL, -1);
    xmlSecAssert2(last != 0, -1);
    xmlSecAssert2(transformCtx != NULL, -1);

    if((transform->inNodes != NULL) && (transform->inNodes->doc != transform->hereNode->doc)) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    NULL,
                    XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }

    /* find signature node and get all its children in the nodes set */
    node = xmlSecFindParent(transform->hereNode, xmlSecNodeSignature, xmlSecDSigNs);
    if(node == NULL) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    xmlSecErrorsSafeString(xmlSecNodeSignature),
                    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }

    children = xmlSecNodeSetGetChildren(node->doc, node, 1, 1);
    if(children == NULL) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecNodeSetGetChildren",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "node=%s",
                    xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
        return(-1);
    }

    /* intersect <dsig:Signature/> node children with input nodes (if exist) */
    transform->outNodes = xmlSecNodeSetAdd(transform->inNodes, children, xmlSecNodeSetIntersection);
    if(transform->outNodes == NULL) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
                    "xmlSecNodeSetAdd",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        xmlSecNodeSetDestroy(children);
        return(-1);
    }

    return(0);
}