summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Radtke <patrick@cirrusidentity.com>2016-02-24 13:56:32 -0800
committerPatrick Radtke <patrick@cirrusidentity.com>2016-02-24 14:00:08 -0800
commit8bc1cbc2f1cc716bd422c57d7bd4119b9c34e468 (patch)
treead06d8d7f0244cb8166a8b5c0c05a88173a47bea
parentd1208f569a92992329ae70a9463ff1498b2769d3 (diff)
downloadsimplesamlphp-8bc1cbc2f1cc716bd422c57d7bd4119b9c34e468.zip
simplesamlphp-8bc1cbc2f1cc716bd422c57d7bd4119b9c34e468.tar.gz
simplesamlphp-8bc1cbc2f1cc716bd422c57d7bd4119b9c34e468.tar.bz2
RegistrationInfo can be inherited from EntitiesDescriptor
-rw-r--r--lib/SimpleSAML/Metadata/SAMLParser.php46
-rw-r--r--tests/lib/SimpleSAML/Metadata/SAMLParserTest.php62
2 files changed, 91 insertions, 17 deletions
diff --git a/lib/SimpleSAML/Metadata/SAMLParser.php b/lib/SimpleSAML/Metadata/SAMLParser.php
index 2786fff..7955fba 100644
--- a/lib/SimpleSAML/Metadata/SAMLParser.php
+++ b/lib/SimpleSAML/Metadata/SAMLParser.php
@@ -159,11 +159,13 @@ class SimpleSAML_Metadata_SAMLParser
* @param int|NULL $maxExpireTime The unix timestamp for when this entity should expire, or
* NULL if unknown.
* @param array $validators An array of parent elements that may validate this element.
+ * @param array $parentExtensions An optional array of extensions from the parent element.
*/
private function __construct(
SAML2_XML_md_EntityDescriptor $entityElement,
$maxExpireTime,
- array $validators = array()
+ array $validators = array(),
+ array $parentExtensions = null
) {
assert('is_null($maxExpireTime) || is_int($maxExpireTime)');
@@ -181,7 +183,7 @@ class SimpleSAML_Metadata_SAMLParser
$this->validators[] = $entityElement;
// process Extensions element, if it exists
- $ext = self::processExtensions($entityElement);
+ $ext = self::processExtensions($entityElement, $parentExtensions);
$this->scopes = $ext['scope'];
$this->tags = $ext['tags'];
$this->entityAttributes = $ext['EntityAttributes'];
@@ -379,15 +381,21 @@ class SimpleSAML_Metadata_SAMLParser
* of the entities.
* @param array $validators The parent-elements that may be
* signed.
+ * @param array $parentExtensions An optional array of
+ * extensions from the parent element.
*
* @return SimpleSAML_Metadata_SAMLParser[] Array of SAMLParser instances.
*/
- private static function processDescriptorsElement($element, $maxExpireTime = null, array $validators = array())
- {
+ private static function processDescriptorsElement(
+ $element,
+ $maxExpireTime = null,
+ array $validators = array(),
+ array $parentExtensions = array()
+ ) {
assert('is_null($maxExpireTime) || is_int($maxExpireTime)');
if ($element instanceof SAML2_XML_md_EntityDescriptor) {
- $ret = new SimpleSAML_Metadata_SAMLParser($element, $maxExpireTime, $validators);
+ $ret = new SimpleSAML_Metadata_SAMLParser($element, $maxExpireTime, $validators, $parentExtensions);
$ret = array($ret->getEntityId() => $ret);
/** @var SimpleSAML_Metadata_SAMLParser[] $ret */
return $ret;
@@ -395,13 +403,14 @@ class SimpleSAML_Metadata_SAMLParser
assert('$element instanceof SAML2_XML_md_EntitiesDescriptor');
+ $extensions = self::processExtensions($element, $parentExtensions);
$expTime = self::getExpireTime($element, $maxExpireTime);
$validators[] = $element;
$ret = array();
foreach ($element->children as $child) {
- $ret += self::processDescriptorsElement($child, $expTime, $validators);
+ $ret += self::processDescriptorsElement($child, $expTime, $validators, $extensions);
}
return $ret;
@@ -992,13 +1001,15 @@ class SimpleSAML_Metadata_SAMLParser
/**
- * Parse an Extensions element.
+ * Parse an Extensions element. Extensions may appear in multiple elements and certain extension may get inherited
+ * from a parent element.
*
* @param mixed $element The element which contains the Extensions element.
+ * @param array $parentExtensions An optional array of extensions from the parent element.
*
* @return array An associative array with the extensions parsed.
*/
- private static function processExtensions($element)
+ private static function processExtensions($element, $parentExtensions = array())
{
$ret = array(
'scope' => array(),
@@ -1009,6 +1020,12 @@ class SimpleSAML_Metadata_SAMLParser
'DiscoHints' => array(),
);
+ // Some extensions may get inherited from a parent element
+ if (($element instanceof SAML2_XML_md_EntityDescriptor || $element instanceof SAML2_XML_md_EntitiesDescriptor)
+ && !empty($parentExtensions['RegistrationInfo'])) {
+ $ret['RegistrationInfo'] = $parentExtensions['RegistrationInfo'];
+ }
+
foreach ($element->Extensions as $e) {
if ($e instanceof SAML2_XML_shibmd_Scope) {
@@ -1017,9 +1034,18 @@ class SimpleSAML_Metadata_SAMLParser
}
// Entity Attributes are only allowed at entity level extensions and not at RoleDescriptor level
- if ($element instanceof SAML2_XML_md_EntityDescriptor) {
+ if ($element instanceof SAML2_XML_md_EntityDescriptor ||
+ $element instanceof SAML2_XML_md_EntitiesDescriptor) {
+
+
if ($e instanceof SAML2_XML_mdrpi_RegistrationInfo) {
- $ret['RegistrationInfo']['registrationAuthority'] = $e->registrationAuthority;
+ // Registration Authority cannot be overridden
+ if (isset($ret['RegistrationInfo']['registrationAuthority'])) {
+ SimpleSAML_Logger::debug('Invalid attempt to override registrationAuthority '
+ . $ret['RegistrationInfo']['registrationAuthority'] . " with {$e->registrationAuthority}");
+ } else {
+ $ret['RegistrationInfo']['registrationAuthority'] = $e->registrationAuthority;
+ }
}
if ($e instanceof SAML2_XML_mdattr_EntityAttributes && !empty($e->children)) {
foreach ($e->children as $attr) {
diff --git a/tests/lib/SimpleSAML/Metadata/SAMLParserTest.php b/tests/lib/SimpleSAML/Metadata/SAMLParserTest.php
index ce5fdd5..7239f79 100644
--- a/tests/lib/SimpleSAML/Metadata/SAMLParserTest.php
+++ b/tests/lib/SimpleSAML/Metadata/SAMLParserTest.php
@@ -18,23 +18,71 @@ class SAMLParserTest extends \PHPUnit_Framework_TestCase
$document = \SAML2_DOMDocumentFactory::fromString(
<<<XML
-<EntityDescriptor entityID="theEntityID"
- xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi">
+<EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi">
+ <EntityDescriptor entityID="theEntityID">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="https://incommon.org"/>
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
+ </EntityDescriptor>
+</EntitiesDescriptor>
+XML
+ );
+
+
+ $entities = \SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($document->documentElement);
+ $this->assertArrayHasKey('theEntityID', $entities);
+ // RegistrationInfo is accessible in the SP or IDP metadata accessors
+ $metadata = $entities['theEntityID']->getMetadata20SP();
+ $this->assertEquals($expected, $metadata['RegistrationInfo']);
+
+ }
+
+ /**
+ * Test RegistrationInfo is inherited correctly from parent EntitiesDescriptor.
+ * According to the spec overriding RegistrationInfo is not valid. We ignore attempts to override
+ */
+ public function testRegistrationInfoInheritance()
+ {
+ $expected = array(
+ 'registrationAuthority' => 'https://incommon.org',
+ );
+
+ $document = \SAML2_DOMDocumentFactory::fromString(
+ <<<XML
+<EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi">
<Extensions>
<mdrpi:RegistrationInfo registrationAuthority="https://incommon.org"/>
- </Extensions>
- <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
- </SPSSODescriptor>
-</EntityDescriptor>
+ </Extensions>
+ <EntityDescriptor entityID="theEntityID">
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
+ </EntityDescriptor>
+ <EntitiesDescriptor>
+ <EntityDescriptor entityID="subEntityId">
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
+ </EntityDescriptor>
+ <EntityDescriptor entityID="subEntityIdOverride">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="overrides-are-ignored"/>
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"/>
+ </EntityDescriptor>
+ </EntitiesDescriptor>
+</EntitiesDescriptor>
XML
);
-
$entities = \SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($document->documentElement);
$this->assertArrayHasKey('theEntityID', $entities);
+ $this->assertArrayHasKey('subEntityId', $entities);
// RegistrationInfo is accessible in the SP or IDP metadata accessors
$metadata = $entities['theEntityID']->getMetadata20SP();
$this->assertEquals($expected, $metadata['RegistrationInfo']);
+ $metadata = $entities['subEntityId']->getMetadata20SP();
+ $this->assertEquals($expected, $metadata['RegistrationInfo']);
+
+ $metadata = $entities['subEntityIdOverride']->getMetadata20SP();
+ $this->assertEquals($expected, $metadata['RegistrationInfo']);
}
}