Skip to content

Commit 3b7b304

Browse files
committed
Perform optional schema validation (default: true)
1 parent 6a84e5d commit 3b7b304

File tree

6 files changed

+69
-10
lines changed

6 files changed

+69
-10
lines changed

src/Binding.php

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@
2525
*/
2626
abstract class Binding
2727
{
28+
/**
29+
* The schema to be used for schema validation
30+
*
31+
* @var string
32+
*/
33+
protected static string $schemaFile = 'resources/schemas/saml-schema-protocol-2.0.xsd';
34+
35+
/**
36+
* Whether or not to perform schema validation
37+
*
38+
* @var bool
39+
*/
40+
protected bool $schemaValidation = true;
41+
2842
/**
2943
* The RelayState associated with the message.
3044
*
@@ -157,7 +171,20 @@ public function getDestination(): ?string
157171

158172

159173
/**
160-
* Set the RelayState associated with he message.
174+
* Override the destination of a message.
175+
*
176+
* Set to null to use the destination set in the message.
177+
*
178+
* @param string|null $destination The destination the message should be delivered to.
179+
*/
180+
public function setDestination(?string $destination = null): void
181+
{
182+
$this->destination = $destination;
183+
}
184+
185+
186+
/**
187+
* Set the RelayState associated with the message.
161188
*
162189
* @param string|null $relayState The RelayState.
163190
*/
@@ -179,15 +206,24 @@ public function getRelayState(): ?string
179206

180207

181208
/**
182-
* Override the destination of a message.
209+
* Set the schema validation for the message.
183210
*
184-
* Set to null to use the destination set in the message.
211+
* @param bool $schemaValidation
212+
*/
213+
public function setSchemaValidation(bool $schemaValidation): void
214+
{
215+
$this->schemaValidation = $schemaValidation;
216+
}
217+
218+
219+
/**
220+
* Get the schema validation setting.
185221
*
186-
* @param string|null $destination The destination the message should be delivered to.
222+
* @return bool
187223
*/
188-
public function setDestination(?string $destination = null): void
224+
public function getSchemaValidation(): bool
189225
{
190-
$this->destination = $destination;
226+
return $this->schemaValidation;
191227
}
192228

193229

src/Binding/HTTPPost.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ public function receive(ServerRequestInterface $request): AbstractMessage
9191
}
9292

9393
$msgStr = base64_decode($msgStr, true);
94-
$msgStr = DOMDocumentFactory::fromString($msgStr)->saveXML();
9594

96-
$document = DOMDocumentFactory::fromString($msgStr);
95+
$document = DOMDocumentFactory::fromString(
96+
xml: $msgStr,
97+
schemaFile: $this->getSchemaValidation() ? self::$schemaFile : null,
98+
);
9799
Utils::getContainer()->debugMessage($document->documentElement, 'in');
98100

99101
$msg = MessageFactory::fromXML($document->documentElement);

src/Binding/HTTPRedirect.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ public function receive(ServerRequestInterface $request): AbstractMessage
148148
throw new Exception('Error while inflating SAML message.');
149149
}
150150

151-
$document = DOMDocumentFactory::fromString($message);
151+
$document = DOMDocumentFactory::fromString(
152+
xml: $message,
153+
schemaFile: $this->getSchemaValidation() ? self::$schemaFile : null,
154+
);
152155
Utils::getContainer()->debugMessage($document->documentElement, 'in');
153156
$message = MessageFactory::fromXML($document->documentElement);
154157

src/Binding/SOAP.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,12 @@ public function receive(/** @scrutinizer ignore-unused */ServerRequestInterface
101101
$xpCache = XPath::getXPath($document->documentElement);
102102
/** @var \DOMElement[] $results */
103103
$results = XPath::xpQuery($xml, '/SOAP-ENV:Envelope/SOAP-ENV:Body/*[1]', $xpCache);
104+
$document = DOMDocumentFactory::fromString(
105+
xml: $results[0]->ownerDocument->saveXML($results[0]),
106+
schemaFile: $this->getSchemaValidation() ? self::$schemaFile : null,
107+
);
104108

105-
return MessageFactory::fromXML($results[0]);
109+
return MessageFactory::fromXML($document->documentElement);
106110
}
107111

108112

src/SAML2/Entity/ServiceProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ final class ServiceProvider
5757
protected bool $responseWasSigned;
5858

5959
/**
60+
* @param bool $performSchemaValidation Whether messages must be validated against the schema
6061
* @param bool $encryptedAssertions Whether assertions must be encrypted
6162
* @param bool $disableScoping Whether to send the samlp:Scoping element in requests
6263
* @param bool $enableUnsolicited Whether to process unsolicited responses
@@ -68,6 +69,7 @@ final class ServiceProvider
6869
public function __construct(
6970
protected MetadataProviderInterface $metadataProvider,
7071
protected Metadata\ServiceProvider $spMetadata,
72+
protected readonly bool $performSchemaValidation = true,
7173
protected readonly bool $encryptedAssertions = false,
7274
protected readonly bool $disableScoping = false,
7375
protected readonly bool $enableUnsolicited = false,
@@ -139,6 +141,7 @@ public function receiveResponse(ServerRequestInterface $request): Response
139141
$binding->setSPMetadata($this->spMetadata);
140142
}
141143

144+
$binding->setSchemaValidation($this->performSchemaValidation);
142145
$rawResponse = $binding->receive($request);
143146
Assert::isInstanceOf($rawResponse, Response::class, ResourceNotRecognizedException::class); // Wrong type of msg
144147

src/SOAPClient.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,17 @@ public function send(
172172
);
173173
}
174174

175+
$xpCache = XPath::getXPath($document->documentElement);
176+
/** @var \DOMElement[] $results */
177+
$results = XPath::xpQuery($xml, '/SOAP-ENV:Envelope/SOAP-ENV:Body/*[1]', $xpCache);
178+
179+
// This is already too late to perform schema validation.
180+
// TODO: refactor the SOAPClient and artifact binding. The SOAPClient should be a generic tool from xml-soap
181+
$document = DOMDocumentFactory::fromString(
182+
xml: $results[0]->ownerDocument->saveXML(),
183+
schemaFile: $this->getSchemaValidation() ? self::$schemaFile : null,
184+
);
185+
175186
// Extract the message from the response
176187
/** @var \SimpleSAML\XML\SerializableElementInterface[] $messages */
177188
$messages = $env->getBody()->getElements();

0 commit comments

Comments
 (0)