diff --git a/lib/SimpleSAML/Metadata/SAMLParser.php b/lib/SimpleSAML/Metadata/SAMLParser.php index d4c793ac44b7063c098e898b84ad20cb0f300ec9..9f00df0ce978be7dcdb2b25c26902cc7343b6cf8 100644 --- a/lib/SimpleSAML/Metadata/SAMLParser.php +++ b/lib/SimpleSAML/Metadata/SAMLParser.php @@ -176,6 +176,11 @@ class SimpleSAML_Metadata_SAMLParser { $this->validator[] = $entitiesValidator; } + /* Process Extensions element, if it exists. */ + $ext = self::processExtensions($entityElement); + $this->scopes = $ext['scopes']; + $this->tags = $ext['tags']; + /* Look over the child nodes for any known element types. */ for($i = 0; $i < $entityElement->childNodes->length; $i++) { $child = $entityElement->childNodes->item($i); @@ -202,11 +207,10 @@ class SimpleSAML_Metadata_SAMLParser { if(SimpleSAML_Utilities::isDOMElementOfType($child, 'Organization', '@md') === TRUE) { $this->processOrganization($child); } - - if(SimpleSAML_Utilities::isDOMElementOfType($child, 'Extensions', '@md') === TRUE) { - $this->processExtensions($child); - } + } + + } @@ -449,14 +453,33 @@ class SimpleSAML_Metadata_SAMLParser { if (!empty($this->organizationURL)) { $ret['url'] = $this->organizationURL; } - - if (!empty($this->tags)) { - $ret['tags'] = $this->tags; - } + return $ret; } + /** + * Add data parsed from extensions to metadata. + * + * @param array &$metadata The metadata that should be updated. + * @param array $roleDescriptor The parsed role desciptor. + */ + private function addExtensions(array &$metadata, array $roleDescriptor) { + assert('array_key_exists("scopes", $roleDescriptor)'); + assert('array_key_exists("tags", $roleDescriptor)'); + + $scopes = array_merge($this->scopes, array_diff($roleDescriptor['scopes'], $this->scopes)); + if (!empty($scopes)) { + $metadata['scopes'] = $scopes; + } + + $tags = array_merge($this->tags, array_diff($roleDescriptor['tags'], $this->tags)); + if (!empty($tags)) { + $metadata['tags'] = $tags; + } + } + + /** * This function returns the metadata for SAML 1.x SPs in the format simpleSAMLphp expects. * This is an associative array with the following fields: @@ -513,6 +536,9 @@ class SimpleSAML_Metadata_SAMLParser { break; } + /* Add extensions. */ + $this->addExtensions($ret, $spd); + return $ret; } @@ -575,6 +601,8 @@ class SimpleSAML_Metadata_SAMLParser { break; } + /* Add extensions. */ + $this->addExtensions($ret, $idp); return $ret; } @@ -650,6 +678,8 @@ class SimpleSAML_Metadata_SAMLParser { } + /* Add extensions. */ + $this->addExtensions($ret, $spd); return $ret; } @@ -690,10 +720,6 @@ class SimpleSAML_Metadata_SAMLParser { if (array_key_exists('expire', $idp)) { $ret['expire'] = $idp['expire']; } - - if (array_key_exists('scopes', $idp)) - $ret['scopes'] = $idp['scopes']; - /* Enable redirect.sign if WantAuthnRequestsSigned is enabled. */ if ($idp['WantAuthnRequestsSigned']) { @@ -730,6 +756,9 @@ class SimpleSAML_Metadata_SAMLParser { break; } + /* Add extensions. */ + $this->addExtensions($ret, $idp); + return $ret; } @@ -790,6 +819,10 @@ class SimpleSAML_Metadata_SAMLParser { } } + $ext = self::processExtensions($element); + $ret['scopes'] = $ext['scopes']; + $ret['tags'] = $ext['tags']; + return $ret; } @@ -872,13 +905,6 @@ class SimpleSAML_Metadata_SAMLParser { assert('is_null($expireTime) || is_int($expireTime)'); $idp = self::parseSSODescriptor($element, $expireTime); - - $extensions = SimpleSAML_Utilities::getDOMChildren($element, 'Extensions', '@md'); - if (!empty($extensions)) - $this->processExtensions($extensions[0]); - - if (!empty($this->scopes)) $idp['scopes'] = $this->scopes; - /* Find all SingleSignOnService elements. */ $idp['SingleSignOnService'] = self::extractEndpoints($element, 'SingleSignOnService', FALSE); @@ -907,12 +933,6 @@ class SimpleSAML_Metadata_SAMLParser { $aad['entityid'] = $this->entityId; $aad['metadata-set'] = 'attributeauthority-remote'; - $extensions = SimpleSAML_Utilities::getDOMChildren($element, 'Extensions', '@md'); - if (!empty($extensions)) - $this->processExtensions($extensions[0]); - - if (!empty($this->scopes)) $aad['scopes'] = $this->scopes; - $aad['AttributeService'] = self::extractEndpoints($element, 'AttributeService', FALSE); $aad['AssertionIDRequestService'] = self::extractEndpoints($element, 'AssertionIDRequestService', FALSE); $aad['NameIDFormat'] = array_map( @@ -925,16 +945,29 @@ class SimpleSAML_Metadata_SAMLParser { /** - * Parse and process a Extensions element. + * Parse an Extensions element. * - * @param DOMElement $element The DOMElement which represents the Extensions element. + * @param DOMElement $element The DOMElement which contains the Extensions element. */ - private function processExtensions(DOMElement $element) { + private static function processExtensions(DOMElement $element) { + $ret = array( + 'scopes' => array(), + 'tags' => array(), + ); + + $extensions = SimpleSAML_Utilities::getDOMChildren($element, 'Extensions', '@md'); + if (empty($extensions)) { + /* No extension element. */ + return $ret; + } + $element = $extensions[0]; + + /* See: https://spaces.internet2.edu/display/SHIB/ShibbolethMetadataProfile */ foreach (SimpleSAML_Utilities::getDOMChildren($element, 'Scope', '@shibmd') as $scope) { $scope = SimpleSAML_Utilities::getDOMText($scope); if (!empty($scope)) { - $this->scopes[] = $scope; + $ret['scopes'][] = $scope; } } @@ -948,11 +981,13 @@ class SimpleSAML_Metadata_SAMLParser { if ($name === 'tags') { foreach ($values as $tagname) { if (!empty($tagname)) { - $this->tags[] = $tagname; + $ret['tags'][] = $tagname; } } } } + + return $ret; }