Coverage Report

Created: 2025-10-10 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 &lt;dsig:Signature/&gt; 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
}