Skip to content

Commit 40daae0

Browse files
committed
Move utilities to the place where they belong
1 parent 6f81ec6 commit 40daae0

4 files changed

Lines changed: 119 additions & 139 deletions

File tree

src/Utils/XML.php

Lines changed: 0 additions & 133 deletions
This file was deleted.

src/XML/CanonicalizableElementTrait.php

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
namespace SimpleSAML\XMLSecurity\XML;
66

77
use DOMElement;
8-
use SimpleSAML\XMLSecurity\Utils\XML;
8+
use SimpleSAML\XMLSecurity\Constants as C;
9+
use SimpleSAML\XMLSecurity\Exception\CanonicalizationFailedException;
10+
use SimpleSAML\XMLSecurity\XML\ds\Transforms;
11+
use SimpleSAML\XPath\Constants as XPATH_C;
912

1013
/**
1114
* A trait implementing the CanonicalizableElementInterface.
@@ -25,6 +28,64 @@ trait CanonicalizableElementTrait
2528
abstract protected function getOriginalXML(): DOMElement;
2629

2730

31+
/**
32+
* Canonicalize any given node.
33+
*
34+
* @param \DOMElement $element The DOM element that needs canonicalization.
35+
* @param string $c14nMethod The identifier of the canonicalization algorithm to use.
36+
* See \SimpleSAML\XMLSecurity\Constants.
37+
* @param string[]|null $xpaths An array of xpaths to filter the nodes by. Defaults to null (no filters).
38+
* @param string[]|null $prefixes An array of namespace prefixes to filter the nodes by.
39+
* Defaults to null (no filters).
40+
*
41+
* @return string The canonical representation of the given DOM node, according to the algorithm requested.
42+
*/
43+
public function canonicalizeData(
44+
DOMElement $element,
45+
string $c14nMethod,
46+
?array $xpaths = null,
47+
?array $prefixes = null,
48+
): string {
49+
$withComments = match ($c14nMethod) {
50+
C::C14N_EXCLUSIVE_WITH_COMMENTS, C::C14N_INCLUSIVE_WITH_COMMENTS => true,
51+
default => false,
52+
};
53+
$exclusive = match ($c14nMethod) {
54+
C::C14N_EXCLUSIVE_WITH_COMMENTS, C::C14N_EXCLUSIVE_WITHOUT_COMMENTS => true,
55+
default => false,
56+
};
57+
58+
if (
59+
is_null($xpaths)
60+
&& ($element->ownerDocument !== null)
61+
&& ($element->ownerDocument->documentElement !== null)
62+
&& $element->isSameNode($element->ownerDocument->documentElement)
63+
) {
64+
// check for any PI or comments as they would have been excluded
65+
$current = $element;
66+
for ($refNode = $current->previousSibling; $refNode !== null; $current = $refNode) {
67+
if (
68+
(($refNode->nodeType === XML_COMMENT_NODE) && $withComments)
69+
|| $refNode->nodeType === XML_PI_NODE
70+
) {
71+
break;
72+
}
73+
}
74+
75+
if ($refNode === null) {
76+
$element = $element->ownerDocument;
77+
}
78+
}
79+
80+
$ret = $element->C14N($exclusive, $withComments, $xpaths, $prefixes);
81+
if ($ret === false) {
82+
// GHSA-h25p-2wxc-6584
83+
throw new CanonicalizationFailedException();
84+
}
85+
return $ret;
86+
}
87+
88+
2889
/**
2990
* Get the canonical (string) representation of this object.
3091
*
@@ -39,7 +100,61 @@ abstract protected function getOriginalXML(): DOMElement;
39100
#[\NoDiscard]
40101
public function canonicalize(string $method, ?array $xpaths = null, ?array $prefixes = null): string
41102
{
42-
return XML::canonicalizeData($this->getOriginalXML(), $method, $xpaths, $prefixes);
103+
return $this->canonicalizeData($this->getOriginalXML(), $method, $xpaths, $prefixes);
104+
}
105+
106+
107+
/**
108+
* Process all transforms specified by a given Reference element.
109+
*
110+
* @param \SimpleSAML\XMLSecurity\XML\ds\Transforms $transforms The transforms to apply.
111+
* @param \DOMElement $data The data referenced.
112+
*
113+
* @return string The canonicalized data after applying all transforms specified by $ref.
114+
*
115+
* @see http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel
116+
*/
117+
public function processTransforms(
118+
Transforms $transforms,
119+
DOMElement $data,
120+
): string {
121+
$canonicalMethod = C::C14N_EXCLUSIVE_WITHOUT_COMMENTS;
122+
$arXPath = null;
123+
$prefixList = null;
124+
foreach ($transforms->getTransform() as $transform) {
125+
$canonicalMethod = $transform->getAlgorithm()->getValue();
126+
switch ($canonicalMethod) {
127+
case C::C14N_EXCLUSIVE_WITHOUT_COMMENTS:
128+
case C::C14N_EXCLUSIVE_WITH_COMMENTS:
129+
$inclusiveNamespaces = $transform->getInclusiveNamespaces();
130+
if ($inclusiveNamespaces !== null) {
131+
$prefixes = $inclusiveNamespaces->getPrefixes();
132+
if ($prefixes !== null) {
133+
$prefixList = array_map('strval', $prefixes->toArray());
134+
}
135+
}
136+
break;
137+
case XPATH_C::XPATH10_URI:
138+
$xpath = $transform->getXPath();
139+
if ($xpath !== null) {
140+
$arXPath = [];
141+
$xpathValue = $xpath->getContent()->getValue();
142+
$arXPath['query'] = '(.//. | .//@* | .//namespace::*)[' . $xpathValue . ']';
143+
144+
// $arXpath['namespaces'] = $xpath->getNamespaces();
145+
// TODO: review if $nsnode->localName is equivalent to the keys in getNamespaces()
146+
// $nslist = $xp->query('./namespace::*', $node);
147+
// foreach ($nslist as $nsnode) {
148+
// if ($nsnode->localName != "xml") {
149+
// $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
150+
// }
151+
// }
152+
}
153+
break;
154+
}
155+
}
156+
157+
return $this->canonicalizeData($data, $canonicalMethod, $arXPath, $prefixList);
43158
}
44159

45160

src/XML/SignableElementTrait.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use SimpleSAML\XMLSecurity\Exception\RuntimeException;
1616
use SimpleSAML\XMLSecurity\Exception\UnsupportedAlgorithmException;
1717
use SimpleSAML\XMLSecurity\Type\DigestValue as DigestValueType;
18-
use SimpleSAML\XMLSecurity\Utils\XML;
1918
use SimpleSAML\XMLSecurity\XML\ds\CanonicalizationMethod;
2019
use SimpleSAML\XMLSecurity\XML\ds\DigestMethod;
2120
use SimpleSAML\XMLSecurity\XML\ds\DigestValue;
@@ -188,7 +187,7 @@ protected function doSign(DOMElement $xml): DOMElement
188187
),
189188
]);
190189

191-
$canonicalDocument = XML::processTransforms($transforms, $xml);
190+
$canonicalDocument = $this->processTransforms($transforms, $xml);
192191

193192
$signedInfo = new SignedInfo(
194193
new CanonicalizationMethod(

src/XML/SignedElementTrait.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use SimpleSAML\XMLSecurity\Exception\SignatureVerificationFailedException;
2121
use SimpleSAML\XMLSecurity\Key;
2222
use SimpleSAML\XMLSecurity\Key\KeyInterface;
23-
use SimpleSAML\XMLSecurity\Utils\XML;
2423
use SimpleSAML\XMLSecurity\Utils\XPath;
2524
use SimpleSAML\XMLSecurity\XML\ds\Reference;
2625
use SimpleSAML\XMLSecurity\XML\ds\Signature;
@@ -157,7 +156,7 @@ private function validateReference(SignedInfo $signedInfo): SignedElementInterfa
157156
Assert::maxCount($sigNode, 1, 'More than one signature found in object.', TooManyElementsException::class);
158157

159158
$doc->documentElement->removeChild($sigNode[0]);
160-
$data = XML::processTransforms($reference->getTransforms(), $doc->documentElement);
159+
$data = $this->processTransforms($reference->getTransforms(), $doc->documentElement);
161160
$algo = $reference->getDigestMethod()->getAlgorithm()->getValue();
162161
Assert::keyExists(
163162
C::$DIGEST_ALGORITHMS,

0 commit comments

Comments
 (0)