simplesamlphp /
saml2
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace SimpleSAML\SAML2\XML\saml; |
||
| 6 | |||
| 7 | use DOMElement; |
||
| 8 | use SimpleSAML\SAML2\Assert\Assert; |
||
| 9 | use SimpleSAML\SAML2\Constants as C; |
||
|
0 ignored issues
–
show
|
|||
| 10 | use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; |
||
|
0 ignored issues
–
show
The type
SimpleSAML\SAML2\Excepti...VersionTooHighException was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 11 | use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; |
||
|
0 ignored issues
–
show
The type
SimpleSAML\SAML2\Excepti...tVersionTooLowException was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 12 | use SimpleSAML\SAML2\Exception\ProtocolViolationException; |
||
| 13 | use SimpleSAML\SAML2\Type\SAMLDateTimeValue; |
||
|
0 ignored issues
–
show
The type
SimpleSAML\SAML2\Type\SAMLDateTimeValue was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 14 | use SimpleSAML\SAML2\Type\SAMLStringValue; |
||
| 15 | use SimpleSAML\SAML2\Utils\XPath; |
||
| 16 | use SimpleSAML\SAML2\XML\EncryptableElementTrait; |
||
| 17 | use SimpleSAML\SAML2\XML\SignableElementTrait; |
||
| 18 | use SimpleSAML\SAML2\XML\SignedElementTrait; |
||
| 19 | use SimpleSAML\XML\SchemaValidatableElementInterface; |
||
| 20 | use SimpleSAML\XML\SchemaValidatableElementTrait; |
||
| 21 | use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; |
||
| 22 | use SimpleSAML\XMLSchema\Exception\MissingElementException; |
||
| 23 | use SimpleSAML\XMLSchema\Exception\TooManyElementsException; |
||
| 24 | use SimpleSAML\XMLSchema\Type\IDValue; |
||
|
0 ignored issues
–
show
The type
SimpleSAML\XMLSchema\Type\IDValue was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 25 | use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; |
||
| 26 | use SimpleSAML\XMLSecurity\XML\ds\Signature; |
||
| 27 | use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; |
||
| 28 | use SimpleSAML\XMLSecurity\XML\SignableElementInterface; |
||
| 29 | use SimpleSAML\XMLSecurity\XML\SignedElementInterface; |
||
| 30 | |||
| 31 | use function array_filter; |
||
| 32 | use function array_merge; |
||
| 33 | use function array_pop; |
||
| 34 | use function array_values; |
||
| 35 | use function count; |
||
| 36 | use function strval; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * Class representing a SAML 2 assertion. |
||
| 40 | * |
||
| 41 | * @package simplesamlphp/saml2 |
||
| 42 | */ |
||
| 43 | final class Assertion extends AbstractSamlElement implements |
||
|
0 ignored issues
–
show
The type
SimpleSAML\SAML2\XML\saml\AbstractSamlElement was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||
| 44 | EncryptableElementInterface, |
||
| 45 | SchemaValidatableElementInterface, |
||
| 46 | SignableElementInterface, |
||
| 47 | SignedElementInterface |
||
| 48 | { |
||
| 49 | use EncryptableElementTrait { |
||
| 50 | EncryptableElementTrait::getBlacklistedAlgorithms insteadof SignedElementTrait; |
||
| 51 | EncryptableElementTrait::getBlacklistedAlgorithms insteadof SignableElementTrait; |
||
| 52 | } |
||
| 53 | |||
| 54 | |||
| 55 | use SchemaValidatableElementTrait; |
||
| 56 | use SignableElementTrait; |
||
| 57 | use SignedElementTrait; |
||
| 58 | |||
| 59 | |||
| 60 | protected bool $wasSignedAtConstruction = false; |
||
| 61 | |||
| 62 | /** |
||
| 63 | * The original signed XML |
||
| 64 | */ |
||
| 65 | protected DOMElement $xml; |
||
| 66 | |||
| 67 | |||
| 68 | /** |
||
| 69 | * Assertion constructor. |
||
| 70 | * |
||
| 71 | * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer |
||
| 72 | * @param \SimpleSAML\XMLSchema\Type\IDValue $id |
||
| 73 | * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant |
||
| 74 | * @param \SimpleSAML\SAML2\XML\saml\Subject|null $subject |
||
| 75 | * @param \SimpleSAML\SAML2\XML\saml\Conditions|null $conditions |
||
| 76 | * @param \SimpleSAML\SAML2\XML\saml\AbstractStatementType[] $statements |
||
| 77 | */ |
||
| 78 | public function __construct( |
||
| 79 | protected Issuer $issuer, |
||
| 80 | protected SAMLDateTimeValue $issueInstant, |
||
| 81 | protected IDValue $id, |
||
| 82 | protected ?Subject $subject = null, |
||
| 83 | protected ?Conditions $conditions = null, |
||
| 84 | protected array $statements = [], |
||
| 85 | ) { |
||
| 86 | Assert::true( |
||
| 87 | $subject || !empty($statements), |
||
| 88 | "Either a <saml:Subject> or some statement must be present in a <saml:Assertion>", |
||
| 89 | ProtocolViolationException::class, |
||
| 90 | ); |
||
| 91 | Assert::maxCount($statements, C::UNBOUNDED_LIMIT); |
||
| 92 | Assert::allIsInstanceOf($statements, AbstractStatementType::class); |
||
| 93 | |||
| 94 | $authnStatements = array_values(array_filter($statements, function ($statement) { |
||
| 95 | return $statement instanceof AuthnStatement; |
||
| 96 | })); |
||
| 97 | |||
| 98 | if (count($authnStatements) > 0) { |
||
| 99 | Assert::notNull( |
||
| 100 | $subject, |
||
| 101 | "Assertions containing an <AuthnStatement> element MUST contain a <Subject> element.", |
||
| 102 | ProtocolViolationException::class, |
||
| 103 | ); |
||
| 104 | } |
||
| 105 | |||
| 106 | $authzDecisionStatements = array_values(array_filter($statements, function ($statement) { |
||
| 107 | return $statement instanceof AuthzDecisionStatement; |
||
| 108 | })); |
||
| 109 | |||
| 110 | if (count($authzDecisionStatements) > 0) { |
||
| 111 | Assert::notNull( |
||
| 112 | $subject, |
||
| 113 | "Assertions containing an <AuthzDecisionStatement> element MUST contain a <Subject> element.", |
||
| 114 | ProtocolViolationException::class, |
||
| 115 | ); |
||
| 116 | } |
||
| 117 | |||
| 118 | $attributeStatements = array_values(array_filter($statements, function ($statement) { |
||
| 119 | return $statement instanceof AttributeStatement; |
||
| 120 | })); |
||
| 121 | |||
| 122 | if (count($attributeStatements) > 0) { |
||
| 123 | Assert::notNull( |
||
| 124 | $subject, |
||
| 125 | "Assertions containing an <AttributeStatement> element MUST contain a <Subject> element.", |
||
| 126 | ProtocolViolationException::class, |
||
| 127 | ); |
||
| 128 | } |
||
| 129 | } |
||
| 130 | |||
| 131 | |||
| 132 | /** |
||
| 133 | * Collect the value of the subject |
||
| 134 | * |
||
| 135 | * @return \SimpleSAML\SAML2\XML\saml\Subject|null |
||
| 136 | */ |
||
| 137 | public function getSubject(): ?Subject |
||
| 138 | { |
||
| 139 | return $this->subject; |
||
| 140 | } |
||
| 141 | |||
| 142 | |||
| 143 | /** |
||
| 144 | * Collect the value of the conditions-property |
||
| 145 | * |
||
| 146 | * @return \SimpleSAML\SAML2\XML\saml\Conditions|null |
||
| 147 | */ |
||
| 148 | public function getConditions(): ?Conditions |
||
| 149 | { |
||
| 150 | return $this->conditions; |
||
| 151 | } |
||
| 152 | |||
| 153 | |||
| 154 | /** |
||
| 155 | * @return \SimpleSAML\SAML2\XML\saml\AttributeStatement[] |
||
| 156 | */ |
||
| 157 | public function getAttributeStatements(): array |
||
| 158 | { |
||
| 159 | return array_values(array_filter($this->statements, function ($statement) { |
||
| 160 | return $statement instanceof AttributeStatement; |
||
| 161 | })); |
||
| 162 | } |
||
| 163 | |||
| 164 | |||
| 165 | /** |
||
| 166 | * @return \SimpleSAML\SAML2\XML\saml\AuthnStatement[] |
||
| 167 | */ |
||
| 168 | public function getAuthnStatements(): array |
||
| 169 | { |
||
| 170 | return array_values(array_filter($this->statements, function ($statement) { |
||
| 171 | return $statement instanceof AuthnStatement; |
||
| 172 | })); |
||
| 173 | } |
||
| 174 | |||
| 175 | |||
| 176 | /** |
||
| 177 | * @return \SimpleSAML\SAML2\XML\saml\AbstractStatement[] |
||
| 178 | */ |
||
| 179 | public function getStatements(): array |
||
| 180 | { |
||
| 181 | return array_values(array_filter($this->statements, function ($statement) { |
||
| 182 | return $statement instanceof AbstractStatement; |
||
| 183 | })); |
||
| 184 | } |
||
| 185 | |||
| 186 | |||
| 187 | /** |
||
| 188 | * Retrieve the identifier of this assertion. |
||
| 189 | * |
||
| 190 | * @return \SimpleSAML\XMLSchema\Type\IDValue The identifier of this assertion. |
||
| 191 | */ |
||
| 192 | public function getId(): IDValue |
||
| 193 | { |
||
| 194 | return $this->id; |
||
| 195 | } |
||
| 196 | |||
| 197 | |||
| 198 | /** |
||
| 199 | * Retrieve the issue timestamp of this assertion. |
||
| 200 | * |
||
| 201 | * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue The issue timestamp of this assertion, as an UNIX timestamp. |
||
| 202 | */ |
||
| 203 | public function getIssueInstant(): SAMLDateTimeValue |
||
| 204 | { |
||
| 205 | return $this->issueInstant; |
||
| 206 | } |
||
| 207 | |||
| 208 | |||
| 209 | /** |
||
| 210 | * Retrieve the issuer if this assertion. |
||
| 211 | * |
||
| 212 | * @return \SimpleSAML\SAML2\XML\saml\Issuer The issuer of this assertion. |
||
| 213 | */ |
||
| 214 | public function getIssuer(): Issuer |
||
| 215 | { |
||
| 216 | return $this->issuer; |
||
| 217 | } |
||
| 218 | |||
| 219 | |||
| 220 | /** |
||
| 221 | */ |
||
| 222 | public function wasSignedAtConstruction(): bool |
||
| 223 | { |
||
| 224 | return $this->wasSignedAtConstruction; |
||
| 225 | } |
||
| 226 | |||
| 227 | |||
| 228 | /** |
||
| 229 | * Get the XML element. |
||
| 230 | */ |
||
| 231 | public function getXML(): DOMElement |
||
| 232 | { |
||
| 233 | return $this->xml; |
||
| 234 | } |
||
| 235 | |||
| 236 | |||
| 237 | /** |
||
| 238 | * Set the XML element. |
||
| 239 | */ |
||
| 240 | private function setXML(DOMElement $xml): void |
||
| 241 | { |
||
| 242 | $this->xml = $xml; |
||
| 243 | } |
||
| 244 | |||
| 245 | |||
| 246 | /** |
||
| 247 | */ |
||
| 248 | protected function getOriginalXML(): DOMElement |
||
| 249 | { |
||
| 250 | return $this->xml ?? $this->toUnsignedXML(); |
||
| 251 | } |
||
| 252 | |||
| 253 | |||
| 254 | /** |
||
| 255 | * @return \SimpleSAML\XMLSecurity\Backend\EncryptionBackend|null |
||
| 256 | */ |
||
| 257 | public function getEncryptionBackend(): ?EncryptionBackend |
||
| 258 | { |
||
| 259 | // return the encryption backend you want to use, |
||
| 260 | // or null if you are fine with the default |
||
| 261 | return null; |
||
| 262 | } |
||
| 263 | |||
| 264 | |||
| 265 | /** |
||
| 266 | * Convert XML into an Assertion |
||
| 267 | * |
||
| 268 | * @throws \SimpleSAML\Assert\AssertionFailedException if assertions are false |
||
| 269 | * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException |
||
| 270 | * if the qualified name of the supplied element is wrong |
||
| 271 | * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException |
||
| 272 | * if the supplied element is missing one of the mandatory attributes |
||
| 273 | * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException |
||
| 274 | * if one of the mandatory child-elements is missing |
||
| 275 | * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException |
||
| 276 | * if too many child-elements of a type are specified |
||
| 277 | * @throws \Exception |
||
| 278 | */ |
||
| 279 | public static function fromXML(DOMElement $xml): static |
||
| 280 | { |
||
| 281 | Assert::same($xml->localName, 'Assertion', InvalidDOMElementException::class); |
||
| 282 | Assert::same($xml->namespaceURI, Assertion::NS, InvalidDOMElementException::class); |
||
| 283 | |||
| 284 | $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); |
||
| 285 | Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); |
||
| 286 | Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); |
||
| 287 | |||
| 288 | $issuer = Issuer::getChildrenOfClass($xml); |
||
| 289 | Assert::minCount($issuer, 1, 'Missing <saml:Issuer> in assertion.', MissingElementException::class); |
||
| 290 | Assert::maxCount($issuer, 1, 'More than one <saml:Issuer> in assertion.', TooManyElementsException::class); |
||
| 291 | |||
| 292 | $subject = Subject::getChildrenOfClass($xml); |
||
| 293 | Assert::maxCount( |
||
| 294 | $subject, |
||
| 295 | 1, |
||
| 296 | 'More than one <saml:Subject> in <saml:Assertion>', |
||
| 297 | TooManyElementsException::class, |
||
| 298 | ); |
||
| 299 | |||
| 300 | $conditions = Conditions::getChildrenOfClass($xml); |
||
| 301 | Assert::maxCount( |
||
| 302 | $conditions, |
||
| 303 | 1, |
||
| 304 | 'More than one <saml:Conditions> in <saml:Assertion>.', |
||
| 305 | TooManyElementsException::class, |
||
| 306 | ); |
||
| 307 | |||
| 308 | $signature = Signature::getChildrenOfClass($xml); |
||
| 309 | Assert::maxCount($signature, 1, 'Only one <ds:Signature> element is allowed.', TooManyElementsException::class); |
||
| 310 | |||
| 311 | $authnStatement = AuthnStatement::getChildrenOfClass($xml); |
||
| 312 | $attrStatement = AttributeStatement::getChildrenOfClass($xml); |
||
| 313 | $statements = AbstractStatement::getChildrenOfClass($xml); |
||
| 314 | |||
| 315 | $assertion = new static( |
||
| 316 | array_pop($issuer), |
||
| 317 | self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), |
||
| 318 | self::getAttribute($xml, 'ID', IDValue::class), |
||
| 319 | array_pop($subject), |
||
| 320 | array_pop($conditions), |
||
| 321 | array_merge($authnStatement, $attrStatement, $statements), |
||
| 322 | ); |
||
| 323 | |||
| 324 | if (!empty($signature)) { |
||
| 325 | $assertion->setSignature($signature[0]); |
||
| 326 | $assertion->wasSignedAtConstruction = true; |
||
| 327 | $assertion->setXML($xml); |
||
| 328 | } |
||
| 329 | |||
| 330 | return $assertion; |
||
| 331 | } |
||
| 332 | |||
| 333 | |||
| 334 | /** |
||
| 335 | * Convert this assertion to an unsigned XML document. |
||
| 336 | * This method does not sign the resulting XML document. |
||
| 337 | */ |
||
| 338 | protected function toUnsignedXML(?DOMElement $parent = null): DOMElement |
||
| 339 | { |
||
| 340 | $e = $this->instantiateParentElement($parent); |
||
| 341 | |||
| 342 | $e->setAttribute('Version', '2.0'); |
||
| 343 | $e->setAttribute('ID', strval($this->getId())); |
||
| 344 | $e->setAttribute('IssueInstant', strval($this->getIssueInstant())); |
||
| 345 | |||
| 346 | $this->getIssuer()->toXML($e); |
||
| 347 | $this->getSubject()?->toXML($e); |
||
| 348 | $this->getConditions()?->toXML($e); |
||
| 349 | |||
| 350 | foreach ($this->statements as $statement) { |
||
| 351 | $statement->toXML($e); |
||
| 352 | } |
||
| 353 | |||
| 354 | return $e; |
||
| 355 | } |
||
| 356 | |||
| 357 | |||
| 358 | /** |
||
| 359 | * Convert this assertion to a signed XML element, if a signer was set. |
||
| 360 | * |
||
| 361 | * @throws \Exception |
||
| 362 | */ |
||
| 363 | public function toXML(?DOMElement $parent = null): DOMElement |
||
| 364 | { |
||
| 365 | if ($this->isSigned() === true && $this->signer === null) { |
||
| 366 | // We already have a signed document and no signer was set to re-sign it |
||
| 367 | if ($parent === null) { |
||
| 368 | return $this->getXML(); |
||
| 369 | } |
||
| 370 | |||
| 371 | $node = $parent->ownerDocument?->importNode($this->getXML(), true); |
||
| 372 | $parent->appendChild($node); |
||
| 373 | return $parent; |
||
| 374 | } |
||
| 375 | |||
| 376 | $e = $this->toUnsignedXML($parent); |
||
| 377 | |||
| 378 | if ($this->signer !== null) { |
||
| 379 | $signedXML = $this->doSign($e); |
||
| 380 | |||
| 381 | // Test for an Issuer |
||
| 382 | $messageElements = XPath::xpQuery($signedXML, './saml_assertion:Issuer', XPath::getXPath($signedXML)); |
||
| 383 | $issuer = array_pop($messageElements); |
||
| 384 | |||
| 385 | $signedXML->insertBefore($this->signature?->toXML($signedXML), $issuer->nextSibling); |
||
| 386 | return $signedXML; |
||
| 387 | } |
||
| 388 | |||
| 389 | return $e; |
||
| 390 | } |
||
| 391 | } |
||
| 392 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths