From e9a10dc01bc1a76761c7074cea6230afad722c95 Mon Sep 17 00:00:00 2001 From: Tim van Dijen Date: Sun, 21 Jan 2024 17:40:47 +0100 Subject: [PATCH 1/2] Add missing xenc:EncryptionProperty + xenc:EncryptionProperties --- resources/schemas/xenc-schema.xsd | 7 +- resources/schemas/xml.xsd | 286 ++++++++++++++++++ .../xenc/AbstractEncryptionPropertiesType.php | 92 ++++++ .../xenc/AbstractEncryptionPropertyType.php | 136 +++++++++ src/XML/xenc/EncryptionProperties.php | 14 + src/XML/xenc/EncryptionProperty.php | 14 + tests/XML/xenc/EncryptionPropertiesTest.php | 90 ++++++ tests/XML/xenc/EncryptionPropertyTest.php | 73 +++++ .../xml/xenc_EncryptionProperties.xml | 8 + .../resources/xml/xenc_EncryptionProperty.xml | 3 + 10 files changed, 720 insertions(+), 3 deletions(-) create mode 100644 resources/schemas/xml.xsd create mode 100644 src/XML/xenc/AbstractEncryptionPropertiesType.php create mode 100644 src/XML/xenc/AbstractEncryptionPropertyType.php create mode 100644 src/XML/xenc/EncryptionProperties.php create mode 100644 src/XML/xenc/EncryptionProperty.php create mode 100644 tests/XML/xenc/EncryptionPropertiesTest.php create mode 100644 tests/XML/xenc/EncryptionPropertyTest.php create mode 100644 tests/resources/xml/xenc_EncryptionProperties.xml create mode 100644 tests/resources/xml/xenc_EncryptionProperty.xml diff --git a/resources/schemas/xenc-schema.xsd b/resources/schemas/xenc-schema.xsd index 6f2a3ded..02e06858 100644 --- a/resources/schemas/xenc-schema.xsd +++ b/resources/schemas/xenc-schema.xsd @@ -31,6 +31,7 @@ targetNamespace='http://www.w3.org/2001/04/xmlenc#' elementFormDefault='qualified'> + @@ -59,9 +60,9 @@ - - - + + + diff --git a/resources/schemas/xml.xsd b/resources/schemas/xml.xsd new file mode 100644 index 00000000..bd291f3d --- /dev/null +++ b/resources/schemas/xml.xsd @@ -0,0 +1,286 @@ + + + + + + +
+

About the XML namespace

+ +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
+
+
+ + + + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+
+ + + + + + + + + +
+ + + + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
+ + + + + + +
+ + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
+
+
+ + + + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+
+ + + + + + + + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+ +
diff --git a/src/XML/xenc/AbstractEncryptionPropertiesType.php b/src/XML/xenc/AbstractEncryptionPropertiesType.php new file mode 100644 index 00000000..79c31fde --- /dev/null +++ b/src/XML/xenc/AbstractEncryptionPropertiesType.php @@ -0,0 +1,92 @@ +. + * + * @package simplesamlphp/xml-security + */ +abstract class AbstractEncryptionPropertiesType extends AbstractXencElement +{ + /** + * EncryptionProperty constructor. + * + * @param \SimpleSAML\XML\EncryptionProperty[] $encryptionProperty + * @param string|null $Id + */ + final public function __construct( + protected array $encryptionProperty, + protected ?string $Id = null, + ) { + Assert::minCount($encryptionProperty, 1, MissingElementException::class); + Assert::nullOrValidNCName($Id, SchemaViolationException::class); + } + + + /** + * Get the value of the $encryptionProperty property. + * + * @return \SimpleSAML\XML\EncryptionProperty[] + */ + public function getEncryptionProperty(): array + { + return $this->encryptionProperty; + } + + + /** + * Get the value of the $Id property. + * + * @return string|null + */ + public function getId(): ?string + { + return $this->Id; + } + + + /** + * @inheritDoc + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * If the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::getNamespaceURI(), InvalidDOMElementException::class); + + return new static( + EncryptionProperty::getChildrenOfClass($xml), + self::getOptionalAttribute($xml, 'Id', null), + ); + } + + + /** + * @inheritDoc + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + foreach ($this->getEncryptionProperty() as $ep) { + $ep->toXML($e); + } + + if ($this->getId() !== null) { + $e->setAttribute('Id', $this->getId()); + } + + return $e; + } +} diff --git a/src/XML/xenc/AbstractEncryptionPropertyType.php b/src/XML/xenc/AbstractEncryptionPropertyType.php new file mode 100644 index 00000000..e2fd2284 --- /dev/null +++ b/src/XML/xenc/AbstractEncryptionPropertyType.php @@ -0,0 +1,136 @@ +. + * + * @package simplesamlphp/xml-security + */ +abstract class AbstractEncryptionPropertyType extends AbstractXencElement +{ + use ExtendableAttributesTrait; + use ExtendableElementTrait; + + /** The namespace-attribute for the xs:anyAttribute element */ + public const XS_ANY_ATTR_NAMESPACE = [C::NS_XML]; + + /** The namespace-attribute for the xs:any element */ + public const XS_ANY_ELT_NAMESPACE = NS::OTHER; + + + /** + * EncryptionProperty constructor. + * + * @param \SimpleSAML\XML\SerializableElement[] $children + * @param string|null $Target + * @param string|null $Id + * @param \SimpleSAML\XML\Attribute[] $namespacedAttributes + */ + final public function __construct( + array $children, + protected ?string $Target = null, + protected ?string $Id = null, + array $namespacedAttributes = [], + ) { + Assert::minCount($children, 1, MissingElementException::class); + Assert::nullOrValidURI($Target, SchemaViolationException::class); + Assert::nullOrValidNCName($Id, SchemaViolationException::class); + + $this->setElements($children); + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Get the value of the $Target property. + * + * @return string|null + */ + public function getTarget(): ?string + { + return $this->Target; + } + + + /** + * Get the value of the $Id property. + * + * @return string|null + */ + public function getId(): ?string + { + return $this->Id; + } + + + /** + * @inheritDoc + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * If the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::getNamespaceURI(), InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + $children, + self::getOptionalAttribute($xml, 'Target', null), + self::getOptionalAttribute($xml, 'Id', null), + self::getAttributesNSFromXML($xml), + ); + } + + + /** + * @inheritDoc + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + if ($this->getTarget() !== null) { + $e->setAttribute('Target', $this->getTarget()); + } + + if ($this->getId() !== null) { + $e->setAttribute('Id', $this->getId()); + } + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + foreach ($this->getElements() as $child) { + if (!$child->isEmptyElement()) { + $child->toXML($e); + } + } + + return $e; + } +} diff --git a/src/XML/xenc/EncryptionProperties.php b/src/XML/xenc/EncryptionProperties.php new file mode 100644 index 00000000..23c154d9 --- /dev/null +++ b/src/XML/xenc/EncryptionProperties.php @@ -0,0 +1,14 @@ +Some', + ); + $otherDoc = DOMDocumentFactory::fromString( + 'Other', + ); + + /** @var \DOMElement $someElt */ + $someElt = $someDoc->documentElement; + /** @var \DOMElement $otherElt */ + $otherElt = $otherDoc->documentElement; + + $attr1 = new XMLAttribute(C::NS_XML, 'xml', 'lang', 'en'); + $attr2 = new XMLAttribute(C::NS_XML, 'xml', 'lang', 'nl'); + + $encryptionProperty1 = new EncryptionProperty( + [new Chunk($someElt)], + 'urn:x-simplesamlphp:phpunit', + 'inner-first', + [$attr1], + ); + $encryptionProperty2 = new EncryptionProperty( + [new Chunk($otherElt)], + 'urn:x-simplesamlphp:phpunit', + 'inner-second', + [$attr2], + ); + + $encryptionProperties = new EncryptionProperties([$encryptionProperty1, $encryptionProperty2], 'outer'); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($encryptionProperties), + ); + } +} diff --git a/tests/XML/xenc/EncryptionPropertyTest.php b/tests/XML/xenc/EncryptionPropertyTest.php new file mode 100644 index 00000000..c3ed151d --- /dev/null +++ b/tests/XML/xenc/EncryptionPropertyTest.php @@ -0,0 +1,73 @@ +Some', + ); + /** @var \DOMElement $elt */ + $elt = $doc->documentElement; + + $attr = new XMLAttribute(C::NS_XML, 'xml', 'lang', 'en'); + $encryptionProperty = new EncryptionProperty( + [new Chunk($elt)], + 'urn:x-simplesamlphp:phpunit', + 'phpunit', + [$attr], + ); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($encryptionProperty), + ); + } +} diff --git a/tests/resources/xml/xenc_EncryptionProperties.xml b/tests/resources/xml/xenc_EncryptionProperties.xml new file mode 100644 index 00000000..424d83db --- /dev/null +++ b/tests/resources/xml/xenc_EncryptionProperties.xml @@ -0,0 +1,8 @@ + + + Some + + + Other + + diff --git a/tests/resources/xml/xenc_EncryptionProperty.xml b/tests/resources/xml/xenc_EncryptionProperty.xml new file mode 100644 index 00000000..3c216cda --- /dev/null +++ b/tests/resources/xml/xenc_EncryptionProperty.xml @@ -0,0 +1,3 @@ + + Some + From 6d8ac606a7c2e4ddbd549f13c90ff8e0d397f30a Mon Sep 17 00:00:00 2001 From: Tim van Dijen Date: Sun, 21 Jan 2024 17:48:03 +0100 Subject: [PATCH 2/2] Fix order of use-statements --- tests/XML/xenc/EncryptionPropertiesTest.php | 2 +- tests/XML/xenc/EncryptionPropertyTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/XML/xenc/EncryptionPropertiesTest.php b/tests/XML/xenc/EncryptionPropertiesTest.php index 2931f580..cf06752e 100644 --- a/tests/XML/xenc/EncryptionPropertiesTest.php +++ b/tests/XML/xenc/EncryptionPropertiesTest.php @@ -7,8 +7,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Constants as C; +use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; use SimpleSAML\XMLSecurity\XML\xenc\EncryptionProperties; diff --git a/tests/XML/xenc/EncryptionPropertyTest.php b/tests/XML/xenc/EncryptionPropertyTest.php index c3ed151d..3ffcd9bd 100644 --- a/tests/XML/xenc/EncryptionPropertyTest.php +++ b/tests/XML/xenc/EncryptionPropertyTest.php @@ -7,8 +7,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Constants as C; +use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; use SimpleSAML\XMLSecurity\XML\xenc\EncryptionProperty;