-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
322 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\XML\saml; | ||
|
||
use DateTimeImmutable; | ||
use DOMElement; | ||
use SimpleSAML\Assert\Assert; | ||
use SimpleSAML\SAML11\Constants as C; | ||
use SimpleSAML\SAML11\Exception\ProtocolViolationException; | ||
use SimpleSAML\XML\Exception\InvalidDOMElementException; | ||
|
||
use preg_match; | ||
|
||
/** | ||
* SAML ConditionsType abstract data type. | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
abstract class AbstractConditionsType extends AbstractSamlElement | ||
{ | ||
/** | ||
* Initialize a saml:ConditionsType from scratch | ||
* | ||
* @param array<\SimpleSAML\SAML11\XML\saml\AudienceRestrictionCondition> $audienceRestrictionCondition | ||
* @param array<\SimpleSAML\SAML11\XML\saml\DoNotCacheCondition> $doNotCacheCondition | ||
* @param array<\SimpleSAML\SAML11\XML\saml\AbstractCondition> $condition | ||
* @param \DateTimeImmutable|null $notBefore | ||
* @param \DateTimeImmutable|null $notOnOrAfter | ||
*/ | ||
final public function __construct( | ||
protected array $audienceRestrictionCondition = [], | ||
protected array $doNotCacheCondition = [], | ||
protected array $condition = [], | ||
protected ?DateTimeImmutable $notBefore = null, | ||
protected ?DateTimeImmutable $notOnOrAfter = null, | ||
) { | ||
Assert::allIsInstanceOf($audienceRestrictionCondition, AudienceRestrictionCondition::class); | ||
Assert::allIsInstanceOf($doNotCacheCondition, DoNotCacheCondition::class); | ||
Assert::allIsInstanceOf($condition, AbstractCondition::class); | ||
} | ||
|
||
|
||
/** | ||
* Collect the value of the notBefore-property | ||
* | ||
* @return \DateTimeImmutable|null | ||
*/ | ||
public function getNotBefore(): ?DateTimeImmutable | ||
{ | ||
return $this->notBefore; | ||
} | ||
|
||
|
||
/** | ||
* Collect the value of the notOnOrAfter-property | ||
* | ||
* @return \DateTimeImmutable|null | ||
*/ | ||
public function getNotOnOrAfter(): ?DateTimeImmutable | ||
{ | ||
return $this->notOnOrAfter; | ||
} | ||
|
||
|
||
/** | ||
* Collect the value of the audienceRestrictionCondition-property | ||
* | ||
* @return array<\SimpleSAML\SAML11\XML\saml\AudienceRestrictionCondition> | ||
*/ | ||
public function getAudienceRestrictionCondition(): array | ||
{ | ||
return $this->audienceRestrictionCondition; | ||
} | ||
|
||
|
||
/** | ||
* Collect the value of the doNotCacheCondition-property | ||
* | ||
* @return array<\SimpleSAML\SAML11\XML\saml\DoNotCacheCondition> | ||
*/ | ||
public function getDoNotCacheCondition(): array | ||
{ | ||
return $this->doNotCacheCondition; | ||
} | ||
|
||
|
||
/** | ||
* Collect the value of the condition-property | ||
* | ||
* @return array<\SimpleSAML\SAML11\XML\saml\Condition> | ||
*/ | ||
public function getCondition(): array | ||
{ | ||
return $this->condition; | ||
} | ||
|
||
|
||
/** | ||
* Test if an object, at the state it's in, would produce an empty XML-element | ||
* | ||
* @return bool | ||
*/ | ||
public function isEmptyElement(): bool | ||
{ | ||
return empty($this->getAudienceRestrictionCondition()) | ||
&& empty($this->getDoNotCacheCondition()) | ||
&& empty($this->getCondition()) | ||
&& empty($this->getNotBefore()) | ||
&& empty($this->getNotOnOrAfter()); | ||
} | ||
|
||
|
||
/** | ||
* Convert XML into an ConditionsType | ||
* | ||
* @param \DOMElement $xml The XML element we should load | ||
* @return static | ||
* | ||
* @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::NS, InvalidDOMElementException::class); | ||
|
||
$notBefore = self::getOptionalAttribute($xml, 'NotBefore'); | ||
// Strip sub-seconds - See paragraph 1.2.2 of SAML core specifications | ||
$notBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $notBefore, 1); | ||
|
||
Assert::validDateTimeZulu($notBefore, ProtocolViolationException::class); | ||
$notBefore = new DateTimeImmutable($notBefore); | ||
|
||
$notOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter'); | ||
// Strip sub-seconds - See paragraph 1.2.2 of SAML core specifications | ||
$notOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $notOnOrAfter, 1); | ||
|
||
Assert::validDateTimeZulu($notOnOrAfter, ProtocolViolationException::class); | ||
$notOnOrAfter = new DateTimeImmutable($notOnOrAfter); | ||
|
||
$audienceRestrictionCondition = AudienceRestrictionCondition::getChildrenOfClass($xml); | ||
$doNotCacheCondition = DoNotCacheCondition::getChildrenOfClass($xml); | ||
$condition = AbstractCondition::getChildrenOfClass($xml); | ||
|
||
return new static($audienceRestrictionCondition, $doNotCacheCondition, $condition, $notBefore, $notOnOrAfter); | ||
} | ||
|
||
|
||
/** | ||
* Convert this ConditionsType to XML. | ||
* | ||
* @param \DOMElement $parent The element we are converting to XML. | ||
* @return \DOMElement The XML element after adding the data corresponding to this ConditionsType. | ||
*/ | ||
public function toXML(DOMElement $parent = null): DOMElement | ||
{ | ||
$e = $this->instantiateParentElement($parent); | ||
|
||
if ($this->getNotBefore() !== null) { | ||
$e->setAttribute('NotBefore', $this->getNotBefore()->format(C::DATETIME_FORMAT)); | ||
} | ||
|
||
if ($this->getNotOnOrAfter() !== null) { | ||
$e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->format(C::DATETIME_FORMAT)); | ||
} | ||
|
||
foreach ($this->getAudienceRestrictionCondition() as $audienceRestrictionCondition) { | ||
$audienceRestrictionCondition->toXML($e); | ||
} | ||
|
||
foreach ($this->getDoNotCacheCondition() as $doNotCacheCondition) { | ||
$doNotCacheCondition->toXML($e); | ||
} | ||
|
||
foreach ($this->getCondition() as $condition) { | ||
$condition->toXML($e); | ||
} | ||
|
||
return $e; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\XML\saml; | ||
|
||
/** | ||
* Class representing a saml:Conditions element. | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
final class Conditions extends AbstractConditionsType | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<saml:Conditions xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" NotBefore="2023-01-24T09:42:26Z" NotOnOrAfter="2023-01-24T09:47:26Z"> | ||
<saml:AudienceRestrictionCondition> | ||
<saml:Audience>urn:x-simplesamlphp:audience</saml:Audience> | ||
</saml:AudienceRestrictionCondition> | ||
<saml:DoNotCacheCondition xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" /> | ||
<saml:Condition xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ssp="urn:x-simplesamlphp:namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ssp:CustomConditionType"> | ||
<saml:Audience>urn:some:audience</saml:Audience> | ||
</saml:Condition> | ||
</saml:Conditions> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\Test\SAML11\XML\saml; | ||
|
||
use DateTimeImmutable; | ||
use PHPUnit\Framework\TestCase; | ||
use SimpleSAML\SAML11\Constants as C; | ||
use SimpleSAML\SAML11\XML\saml\Audience; | ||
use SimpleSAML\SAML11\XML\saml\AudienceRestrictionCondition; | ||
use SimpleSAML\SAML11\XML\saml\Condition; | ||
use SimpleSAML\SAML11\XML\saml\Conditions; | ||
use SimpleSAML\SAML11\XML\saml\DoNotCacheCondition; | ||
use SimpleSAML\Test\SAML11\CustomCondition; | ||
use SimpleSAML\XML\DOMDocumentFactory; | ||
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; | ||
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; | ||
|
||
use function dirname; | ||
use function strval; | ||
|
||
/** | ||
* Tests for Conditions elements. | ||
* | ||
* @covers \SimpleSAML\SAML11\XML\saml\Conditions | ||
* @covers \SimpleSAML\SAML11\XML\saml\AbstractConditionsType | ||
* @covers \SimpleSAML\SAML11\XML\saml\AbstractSamlElement | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
final class ConditionsTest extends TestCase | ||
{ | ||
use SchemaValidationTestTrait; | ||
use SerializableElementTestTrait; | ||
|
||
|
||
/** | ||
*/ | ||
public static function setUpBeforeClass(): void | ||
{ | ||
self::$schemaFile = dirname(__FILE__, 5) . '/resources/schemas/simplesamlphp.xsd'; | ||
|
||
self::$testedClass = Conditions::class; | ||
|
||
self::$xmlRepresentation = DOMDocumentFactory::fromFile( | ||
dirname(__FILE__, 5) . '/resources/xml/saml_Conditions.xml', | ||
); | ||
} | ||
|
||
|
||
// marshalling | ||
|
||
|
||
/** | ||
* Test creating an Conditions from scratch | ||
*/ | ||
public function testMarshalling(): void | ||
{ | ||
$audience = new Audience('urn:x-simplesamlphp:audience'); | ||
$audienceRestrictionCondition = new AudienceRestrictionCondition([$audience]); | ||
|
||
$doNotCacheCondition = new DoNotCacheCondition(); | ||
|
||
$condition = new CustomCondition( | ||
[new Audience('urn:some:audience')], | ||
); | ||
|
||
$conditions = new Conditions( | ||
[$audienceRestrictionCondition], | ||
[$doNotCacheCondition], | ||
[$condition], | ||
new DateTimeImmutable('2023-01-24T09:42:26Z'), | ||
new DateTimeImmutable('2023-01-24T09:47:26Z'), | ||
); | ||
|
||
$this->assertEquals( | ||
self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), | ||
strval($conditions), | ||
); | ||
} | ||
|
||
|
||
/** | ||
* Adding an empty Conditions element should yield an empty element. | ||
*/ | ||
public function testMarshallingEmptyElement(): void | ||
{ | ||
$samlns = C::NS_SAML; | ||
$conditions = new Conditions([]); | ||
$this->assertEquals( | ||
"<saml:Conditions xmlns:saml=\"$samlns\"/>", | ||
strval($conditions), | ||
); | ||
$this->assertTrue($conditions->isEmptyElement()); | ||
} | ||
} |