.. This is class for parsing of SAML 1.x and SAML 2.0 metadata. Metadata is loaded by calling the static methods parseFile, parseString or parseElement. These functions returns an instance of SimpleSAML_Metadata_SAMLParser. To get metadata from this object, use the methods getMetadata1xSP or getMetadata20SP. To parse a file which can contain a collection of EntityDescriptor or EntitiesDescriptor elements, use the parseDescriptorsFile, parseDescriptorsString or parseDescriptorsElement methods. These functions will return an array of SAMLParser elements where each element represents an EntityDescriptor-element.
Example #1
0
 /**
  * This function processes a SAML metadata file.
  *
  * @param $src  Filename of the metadata file.
  */
 public function loadSource($source)
 {
     $entities = array();
     try {
         $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsFile($source['src']);
     } catch (Exception $e) {
         SimpleSAML_Logger::warning('metarefresh: Failed to retrieve metadata. ' . $e->getMessage());
     }
     foreach ($entities as $entity) {
         if (array_key_exists('validateFingerprint', $source) && $source['validateFingerprint'] !== NULL) {
             if (!$entity->validateFingerprint($source['validateFingerprint'])) {
                 SimpleSAML_Logger::info('Skipping "' . $entity->getEntityId() . '" - could not verify signature.' . "\n");
                 continue;
             }
         }
         $template = NULL;
         if (array_key_exists('template', $source)) {
             $template = $source['template'];
         }
         $this->addMetadata($source['src'], $entity->getMetadata1xSP(), 'shib13-sp-remote', $template);
         $this->addMetadata($source['src'], $entity->getMetadata1xIdP(), 'shib13-idp-remote', $template);
         $this->addMetadata($source['src'], $entity->getMetadata20SP(), 'saml20-sp-remote', $template);
         $this->addMetadata($source['src'], $entity->getMetadata20IdP(), 'saml20-idp-remote', $template);
         $attributeAuthorities = $entity->getAttributeAuthorities();
         if (!empty($attributeAuthorities)) {
             $this->addMetadata($source['src'], $attributeAuthorities[0], 'attributeauthority-remote', $template);
         }
     }
 }
Example #2
0
 function __construct($url, $feedId, $enableCacheOnly = false)
 {
     $this->cachedir = Config::get('cachedir');
     if (!is_dir($this->cachedir)) {
         throw new Exception('Cache dir not present');
     }
     if (!is_writable($this->cachedir)) {
         throw new Exception('Cache dir not writable');
     }
     $cachefile = $this->cachedir . $feedId;
     // echo 'Cache dir: ' . $cachefile;
     // exit;
     try {
         if (!$enableCacheOnly) {
             DiscoUtils::debug('Downloading metadata from ' . tc_colored($url, 'green') . " and storing cache at " . tc_colored($cachefile, 'green'));
             $data = @file_get_contents($url);
             if ($data === false) {
                 throw new Exception('Error retrieving metadata from ' . $url);
             }
             file_put_contents($cachefile, $data);
         } else {
             DiscoUtils::debug('Looking up cached metadata from ' . tc_colored($cachefile, 'green'));
         }
     } catch (Exception $e) {
         error_log('Error updating metadata from source ' . $feedId . ' : ' . $e->getMessage());
     }
     if (!file_exists($cachefile)) {
         throw new Exception('Not able to continue processing this feed, because cannot read cached file');
     }
     DiscoUtils::debug('Metadata ready, starting to parse XML and validate document');
     $this->list = array();
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsFile($cachefile);
     foreach ($entities as $entityId => $entity) {
         $md = $entity->getMetadata1xIdP();
         if ($md !== NULL) {
             $this->list[$entityId] = $md;
         }
         $md = $entity->getMetadata20IdP();
         if ($md !== NULL) {
             $this->list[$entityId] = $md;
         }
         $this->processSPEntity($entity->getMetadata20SP());
     }
     if (count($this->list) === 0) {
         throw new Exception('No entities found at URL ' . $src);
     }
 }
Example #3
0
function convert_metadata($xmldata)
{
    $config = SimpleSAML_Configuration::getInstance();
    if ($xmldata) {
        $xmldata = htmlspecialchars_decode($xmldata);
        SimpleSAML_Utilities::validateXMLDocument($xmldata, 'saml-meta');
        $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($xmldata);
        foreach ($entities as &$entity) {
            $entity = array('shib13-sp-remote' => $entity->getMetadata1xSP(), 'shib13-idp-remote' => $entity->getMetadata1xIdP(), 'saml20-sp-remote' => $entity->getMetadata20SP(), 'saml20-idp-remote' => $entity->getMetadata20IdP());
        }
        $output = array($entity['saml20-sp-remote']['entityid'] => $entity['saml20-sp-remote']);
    } else {
        $xmldata = '';
        $output = array();
    }
    return $output;
}
Example #4
0
 public function reviewEndpoints()
 {
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($this->metadataXML);
     $entity = array_pop($entities);
     $spmetadata = $entity->getMetadata20SP();
     #		$spmetadata = $this->metadataXML->getMetadata20SP();
     $allHTTPS = TRUE;
     $acspost = FALSE;
     if (isset($spmetadata)) {
         #			echo '<pre>';
         #			print_r($spmetadata);
     }
     if (isset($spmetadata['AssertionConsumerService'])) {
         foreach ($spmetadata['AssertionConsumerService'] as $e) {
             if ($e['Binding'] === 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST') {
                 $acspost = TRUE;
             }
             if (substr($e['Location'], 0, 5) !== 'https') {
                 #echo 'comparing [' . substr($e['Location'], 0, 5) . ']';
                 $allHTTPS = FALSE;
             }
         }
     }
     if (isset($spmetadata['SingleLogoutService'])) {
         foreach ($spmetadata['SingleLogoutService'] as $e) {
             // if ($e['Binding'] === 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect')
             // 	$acspost = TRUE;
             if (substr($e['Location'], 0, 5) !== 'https') {
                 $allHTTPS = FALSE;
             }
         }
     }
     if ($allHTTPS) {
         $this->setResult(sspmod_fedlab_Tester::STATUS_OK, 'metadata', 'https', 'All endpoints in SP metadata SHOULD be HTTPS (not http) (saml2int)');
     } else {
         $this->setResult(sspmod_fedlab_Tester::STATUS_FATAL, 'metadata', 'https', 'All endpoints in SP metadata SHOULD be HTTPS (not http) (saml2int)');
     }
     if ($acspost) {
         $this->setResult(sspmod_fedlab_Tester::STATUS_OK, 'metadata', 'acspost', 'SP Metadata MUST contain at least an ACS endpoint with the HTTP-POST binding (saml2int)');
     } else {
         $this->setResult(sspmod_fedlab_Tester::STATUS_FATAL, 'metadata', 'acspost', 'SP Metadata MUST contain at least an ACS endpoint with the HTTP-POST binding (saml2int)');
     }
 }
 /**
  * This function initializes the XML metadata source. The configuration must contain one of
  * the following options:
  * - 'file': Path to a file with the metadata. This path is relative to the simpleSAMLphp
  *           base directory.
  * - 'url': URL we should download the metadata from. This is only meant for testing.
  *
  * @param $config  The configuration for this instance of the XML metadata source.
  */
 protected function __construct($config)
 {
     /* Get the configuration. */
     $globalConfig = SimpleSAML_Configuration::getInstance();
     if (array_key_exists('file', $config)) {
         $src = $globalConfig->resolvePath($config['file']);
     } elseif (array_key_exists('url', $config)) {
         $src = $config['url'];
     } else {
         throw new Exception('Missing either \'file\' or \'url\' in XML metadata source configuration.');
     }
     $SP1x = array();
     $IdP1x = array();
     $SP20 = array();
     $IdP20 = array();
     $AAD = array();
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsFile($src);
     foreach ($entities as $entityId => $entity) {
         $md = $entity->getMetadata1xSP();
         if ($md !== NULL) {
             $SP1x[$entityId] = $md;
         }
         $md = $entity->getMetadata1xIdP();
         if ($md !== NULL) {
             $IdP1x[$entityId] = $md;
         }
         $md = $entity->getMetadata20SP();
         if ($md !== NULL) {
             $SP20[$entityId] = $md;
         }
         $md = $entity->getMetadata20IdP();
         if ($md !== NULL) {
             $IdP20[$entityId] = $md;
         }
         $md = $entity->getAttributeAuthorities();
         if (count($md) > 0) {
             $AAD[$entityId] = $md[0];
         }
     }
     $this->metadata = array('shib13-sp-remote' => $SP1x, 'shib13-idp-remote' => $IdP1x, 'saml20-sp-remote' => $SP20, 'saml20-idp-remote' => $IdP20, 'attributeauthority-remote' => $AAD);
 }
Example #6
0
 private function import($metadata, $parserFunction)
 {
     $this->startImport();
     // Parse metadata
     try {
         $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($metadata);
     } catch (Exception $e) {
         SimpleSAML_Logger::error('Importer - Metadata not valid SAML 2.0' . var_export($e, true));
         $this->resetMemoryLimit();
         return 'error_not_valid_saml20';
     }
     SimpleSAML_Logger::debug('Entities Found: ' . count($entities));
     if (count($entities) > 1) {
         // We found multiple entities, So we have to loop through them
         // in order to select the entity ID which we want to import
         foreach ($entities as $entityId => $parser) {
             if ($entityId === $this->_entityId) {
                 SimpleSAML_Logger::debug('Matching EntityIDs found for: ' . $entityId);
                 // Import metadata
                 SimpleSAML_Logger::debug('Processing EntityID: ' . $entityId);
                 $result = $this->importParsedMetadata($parserFunction($parser));
                 $this->resetMemoryLimit();
                 return $result;
             }
         }
         // Apparently the entity was not found in supplied metadata, Log error
         SimpleSAML_Logger::error('importMetadata20SP - EntityId not found');
         $this->resetMemoryLimit();
         return 'error_entityid_not_found';
     } else {
         if (count($entities) == 1) {
             $parser = $entities[key($entities)];
             $result = $this->importParsedMetadata($parserFunction($parser));
             $this->resetMemoryLimit();
             return $result;
         }
     }
     // The parsed metadata contains no entities
     SimpleSAML_Logger::error('importMetadata20SP - EntityId not found');
     return 'error_entityid_not_found';
 }
function transaleXMLToSsPHP($xmldata)
{
    if (!empty($xmldata)) {
        SimpleSAML_Utilities::validateXMLDocument($xmldata, 'saml-meta');
        $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($xmldata);
        /* Get all metadata for the entities. */
        foreach ($entities as &$entity) {
            $entity = array('saml20-sp-remote' => $entity->getMetadata20SP(), 'saml20-idp-remote' => $entity->getMetadata20IdP());
        }
        /* Transpose from $entities[entityid][type] to $output[type][entityid]. */
        $output = SimpleSAML_Utilities::transposeArray($entities);
        /* Merge all metadata of each type to a single string which should be
         * added to the corresponding file.
         */
        foreach ($output as $type => &$entities) {
            $text = '';
            foreach ($entities as $entityId => $entityMetadata) {
                if ($entityMetadata === NULL) {
                    continue;
                }
                /* Remove the entityDescriptor element because it is unused, and only
                 * makes the output harder to read.
                 */
                unset($entityMetadata['entityDescriptor']);
                $text .= '$metadata[' . var_export($entityId, TRUE) . '] = ' . var_export($entityMetadata, TRUE) . ";\n";
            }
            $entities = $text;
        }
    } else {
        $output = array();
    }
    return $output;
}
Example #8
0
 /**
  * Parse XML metadata and return entities
  */
 private function loadXML($data, $source)
 {
     $entities = array();
     $doc = new DOMDocument();
     $res = $doc->loadXML($data);
     if ($res !== TRUE) {
         throw new Exception('Failed to read XML from ' . $source['src']);
     }
     if ($doc->documentElement === NULL) {
         throw new Exception('Opened file is not an XML document: ' . $source['src']);
     }
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($doc->documentElement);
     return $entities;
 }
Example #9
0
 private function getMetadata()
 {
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($this->xmlmetadata);
     $entity = array_pop($entities);
     $this->parsed = $entity->getMetadata20SP();
 }
 /**
  * Import IdP SAML 2.0 metadata.
  *
  * Imports IdP SAML 2.0 metadata. The entity id is conpared with that entity id 
  * given in the metadata parsed.
  *
  * @param string $metadata SAML 2.0 metadata
  * @param bool   &$updated Whether the entity was updated
  *
  * @return string Return status_metadata_parsed_ok on success and 
  * error_not_valid_saml20, error_metadata_not_parsed or 
  * error_entityid_no_match on error.
  */
 public function importMetadata20IdP($metadata, &$updated)
 {
     assert('$this->_entity instanceof Sspmod_Janus_Entity');
     assert('$this->_entity->getType() == \'saml20-idp\'');
     assert('is_string($metadata)');
     // Parse metadata
     try {
         $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($metadata);
     } catch (Exception $e) {
         SimpleSAML_Logger::error('importMetadata20IdP - Metadata not valid SAML 2.0' . var_export($e, true));
         return 'error_not_valid_saml20';
     }
     SimpleSAML_Logger::debug('Entities Found: ' . count($entities));
     if (count($entities) > 1) {
         // We found multiple entities, So we have to loop through them
         // in order to select the entity ID which we want to import
         foreach ($entities as $entityId => $parser) {
             if ($entityId === $this->_entity->getEntityid()) {
                 SimpleSAML_Logger::debug('Matching EntityIDs found for: ' . $entityId);
                 // Import metadata
                 SimpleSAML_Logger::debug('Processing EntityID: ' . $entityId);
                 return self::_importMetadata20IdP($parser, $updated);
             }
         }
         // Apparently the entity was not found in supplied metadata, Log error
         SimpleSAML_Logger::error('importMetadata20IdP - EntityId not found');
         return 'error_entityid_not_found';
     } else {
         if (count($entities) == 1) {
             $parser = $entities[key($entities)];
             return self::_importMetadata20IdP($parser, $updated);
         } else {
             // The parsed metadata contains no entities
             SimpleSAML_Logger::error('importMetadata20IdP - EntityId not found');
             return 'error_entityid_not_found';
         }
     }
 }
Example #11
0
 /**
  * Parse XML metadata and return entities
  */
 private function loadXML($data, $source)
 {
     $entities = array();
     try {
         $doc = new DOMDocument();
         $res = $doc->loadXML($data);
         if ($res !== TRUE) {
             throw new Exception('Failed to read XML from ' . $source['src']);
         }
         if ($doc->documentElement === NULL) {
             throw new Exception('Opened file is not an XML document: ' . $source['src']);
         }
         $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($doc->documentElement);
     } catch (Exception $e) {
         SimpleSAML_Logger::warning('metarefresh: Failed to retrieve metadata. ' . $e->getMessage());
     }
     return $entities;
 }
<?php

require_once '../_include.php';
/* Make sure that the user has admin access rights. */
SimpleSAML\Utils\Auth::requireAdmin();
$config = SimpleSAML_Configuration::getInstance();
if (!empty($_FILES['xmlfile']['tmp_name'])) {
    $xmldata = file_get_contents($_FILES['xmlfile']['tmp_name']);
} elseif (array_key_exists('xmldata', $_POST)) {
    $xmldata = $_POST['xmldata'];
}
if (!empty($xmldata)) {
    \SimpleSAML\Utils\XML::checkSAMLMessage($xmldata, 'saml-meta');
    $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($xmldata);
    /* Get all metadata for the entities. */
    foreach ($entities as &$entity) {
        $entity = array('shib13-sp-remote' => $entity->getMetadata1xSP(), 'shib13-idp-remote' => $entity->getMetadata1xIdP(), 'saml20-sp-remote' => $entity->getMetadata20SP(), 'saml20-idp-remote' => $entity->getMetadata20IdP());
    }
    /* Transpose from $entities[entityid][type] to $output[type][entityid]. */
    $output = SimpleSAML\Utils\Arrays::transpose($entities);
    /* Merge all metadata of each type to a single string which should be
     * added to the corresponding file.
     */
    foreach ($output as $type => &$entities) {
        $text = '';
        foreach ($entities as $entityId => $entityMetadata) {
            if ($entityMetadata === NULL) {
                continue;
            }
            /* Remove the entityDescriptor element because it is unused, and only
             * makes the output harder to read.
 /**
  * Parse XML metadata and return entities
  */
 private function loadXML($data, $source)
 {
     $entities = array();
     $doc = new DOMDocument();
     $res = $doc->loadXML($data);
     if ($res !== TRUE) {
         throw new Exception('Failed to read XML from ' . $source['src']);
     }
     if ($doc->documentElement === NULL) {
         throw new Exception('Opened file is not an XML document: ' . $source['src']);
     }
     if (SimpleSAML_Utilities::isDOMElementOfType($doc->documentElement, 'EntitiesDescriptor', '@md') === TRUE) {
         foreach (SAML2_Utils::xpQuery($doc->documentElement, './saml_metadata:EntityDescriptor|./saml_metadata:EntitiesDescriptor') as $node) {
             if ($node->localName === 'EntityDescriptor') {
                 try {
                     $entities = array_merge($entities, SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($node));
                 } catch (Exception $e) {
                     $entityID = $node->getAttribute('entityID');
                     if (empty($entityID)) {
                         $entityID = "unknown";
                     }
                     SimpleSAML_Logger::warning('[metarefresh]: Error while parsing entity (' . $entityID . '): ' . $e->getMessage());
                 }
             } else {
                 $entities = array_merge($entities, $this->loadXML($node->ownerDocument->saveXML($node), $source));
             }
         }
     } else {
         $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($doc->documentElement);
     }
     return $entities;
 }
Example #14
0
 /**
  * This function parses a DOMElement which represents either an EntityDescriptor element or an
  * EntitiesDescriptor element. It will return an associative array of SAMLParser instances in both cases.
  *
  * @param $element  The DOMElement which contains the EntityDescriptor element or the EntitiesDescriptor
  *                  element.
  * @return An associative array of SAMLParser instances. The key of the array will be the entity id.
  */
 public static function parseDescriptorsElement($element)
 {
     if ($element === NULL) {
         throw new Exception('Document was empty.');
     }
     assert('$element instanceof DOMElement');
     $entitiesValidator = NULL;
     if (SimpleSAML_Utilities::isDOMElementOfType($element, 'EntityDescriptor', '@md') === TRUE) {
         $elements = array($element);
         $expireTime = NULL;
     } elseif (SimpleSAML_Utilities::isDOMElementOfType($element, 'EntitiesDescriptor', '@md') === TRUE) {
         /* Check if there is a signature element in the EntitiesDescriptor. */
         if (count(SimpleSAML_Utilities::getDOMChildren($element, 'Signature', '@ds')) > 0) {
             try {
                 $entitiesValidator = new SimpleSAML_XML_Validator($element, 'ID');
             } catch (Exception $e) {
                 SimpleSAML_Logger::warning('SAMLParser: Error creating XML Signature validator for XML document: ' . $e->getMessage());
                 $entitiesValidator = NULL;
             }
         }
         $expireTime = self::getExpireTime($element);
         $elements = SimpleSAML_Utilities::getDOMChildren($element, 'EntityDescriptor', '@md');
     } else {
         throw new Exception('Unexpected root node: [' . $element->namespaceURI . ']:' . $element->localName);
     }
     $ret = array();
     foreach ($elements as $e) {
         $entity = new SimpleSAML_Metadata_SAMLParser($e, $entitiesValidator, $expireTime);
         $ret[$entity->getEntityId()] = $entity;
     }
     return $ret;
 }
    /**
     * Test AttributeConsumingService is parsed
     */
    public function testAttributeConsumingServiceParsing()
    {
        $document = \SAML2\DOMDocumentFactory::fromString(<<<XML
<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">
      <AttributeConsumingService index="0">
        <ServiceName xml:lang="en">Example service</ServiceName>
        <ServiceDescription xml:lang="nl">Dit is een voorbeeld voor de unittest.</ServiceDescription>

        <RequestedAttribute FriendlyName="eduPersonPrincipalName" Name="urn:mace:dir:attribute-def:eduPersonPrincipalName" NameFormat="urn:mace:shibboleth:1.0:attributeNamespace:uri" isRequired="true"/>
        <RequestedAttribute FriendlyName="mail" Name="urn:mace:dir:attribute-def:mail" NameFormat="urn:mace:shibboleth:1.0:attributeNamespace:uri"/>
        <RequestedAttribute FriendlyName="displayName" Name="urn:mace:dir:attribute-def:displayName" NameFormat="urn:mace:shibboleth:1.0:attributeNamespace:uri"/>
      </AttributeConsumingService>
    </SPSSODescriptor>

  </EntityDescriptor>
</EntitiesDescriptor>
XML
);
        $entities = \SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($document->documentElement);
        $this->assertArrayHasKey('theEntityID', $entities);
        $metadata = $entities['theEntityID']->getMetadata20SP();
        $this->assertEquals("Example service", $metadata['name']['en']);
        $this->assertEquals("Dit is een voorbeeld voor de unittest.", $metadata['description']['nl']);
        $expected_a = array("urn:mace:dir:attribute-def:eduPersonPrincipalName", "urn:mace:dir:attribute-def:mail", "urn:mace:dir:attribute-def:displayName");
        $expected_r = array("urn:mace:dir:attribute-def:eduPersonPrincipalName");
        $this->assertEquals($expected_a, $metadata['attributes']);
        $this->assertEquals($expected_r, $metadata['attributes.required']);
    }
 /**
  * Overriding this function from the superclass SimpleSAML_Metadata_MetaDataStorageSource.
  *
  * This function retrieves metadata for the given entity id in the given set of metadata.
  * It will return NULL if it is unable to locate the metadata.
  *
  * This class implements this function using the getMetadataSet-function. A subclass should
  * override this function if it doesn't implement the getMetadataSet function, or if the
  * implementation of getMetadataSet is slow.
  *
  * @param $index  The entityId or metaindex we are looking up.
  * @param $set  The set we are looking for metadata in.
  * @return An associative array with metadata for the given entity, or NULL if we are unable to
  *         locate the entity.
  */
 public function getMetaData($index, $set)
 {
     assert('is_string($index)');
     assert('is_string($set)');
     if (!preg_match('@(https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?)@', $index)) {
         SimpleSAML_Logger::info('MetaData - Handler.DynamicXML: EntityID/index [' . $index . '] does not look like a URL. Skipping.');
         return NULL;
     }
     SimpleSAML_Logger::info('MetaData - Handler.DynamicXML: Loading metadata entity [' . $index . '] from [' . $set . ']');
     /* Read from cache if possible. */
     $data = $this->getFromCache($set, $index);
     if ($data !== NULL && array_key_exists('expires', $data) && $data['expires'] < time()) {
         /* Metadata has expired. */
         $data = NULL;
     }
     if (isset($data)) {
         /* Metadata found in cache and not expired. */
         SimpleSAML_Logger::debug('MetaData - Handler.DynamicXML: Using cached metadata.');
         return $data;
     }
     SimpleSAML_Logger::debug('MetaData - Handler.DynamicXML: Downloading [' . $index . ']');
     $xmldata = file_get_contents($index);
     if (empty($xmldata)) {
         throw new Exception('Error downloading metadata from "' . $index . '": ' . SimpleSAML_Utilities::getLastError());
     }
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($xmldata);
     SimpleSAML_Logger::debug('MetaData - Handler.DynamicXML: Completed parsing of [' . $index . '] Found [' . count($entities) . '] entries.');
     if (count($entities) === 0) {
         throw new Exception('No entities found in "' . $index . '".');
     }
     if (!array_key_exists($index, $entities)) {
         throw new Exception('No entity with correct entity id found in "' . $index . '".');
     }
     $entity = $entities[$index];
     $data = self::getParsedSet($entity, $set);
     if ($data === NULL) {
         throw new Exception('No metadata for set "' . $set . '" available from "' . $index . '".');
     }
     $this->writeToCache($set, $index, $data);
     return $data;
 }
 /**
  * Parse XML metadata and return entities
  */
 private function loadXML($data, $source)
 {
     $entities = array();
     try {
         $doc = \SAML2\DOMDocumentFactory::fromString($data);
     } catch (Exception $e) {
         throw new Exception('Failed to read XML from ' . $source['src']);
     }
     if ($doc->documentElement === NULL) {
         throw new Exception('Opened file is not an XML document: ' . $source['src']);
     }
     $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($doc->documentElement);
     return $entities;
 }
 /**
  * Overriding this function from the superclass SimpleSAML_Metadata_MetaDataStorageSource.
  *
  * This function retrieves metadata for the given entity id in the given set of metadata.
  * It will return NULL if it is unable to locate the metadata.
  *
  * This class implements this function using the getMetadataSet-function. A subclass should
  * override this function if it doesn't implement the getMetadataSet function, or if the
  * implementation of getMetadataSet is slow.
  *
  * @param $index  The entityId or metaindex we are looking up.
  * @param $set  The set we are looking for metadata in.
  * @return An associative array with metadata for the given entity, or NULL if we are unable to
  *         locate the entity.
  */
 public function getMetaData($index, $set)
 {
     assert('is_string($index)');
     assert('is_string($set)');
     SimpleSAML_Logger::info('MetaData - Handler.MDX: Loading metadata entity [' . $index . '] from [' . $set . ']');
     /* Read from cache if possible. */
     $data = $this->getFromCache($set, $index);
     if ($data !== NULL && array_key_exists('expires', $data) && $data['expires'] < time()) {
         /* Metadata has expired. */
         $data = NULL;
     }
     if (isset($data)) {
         /* Metadata found in cache and not expired. */
         SimpleSAML_Logger::debug('MetaData - Handler.MDX: Using cached metadata for: ' . $index . '.');
         return $data;
     }
     /* Look at Metadata Query Protocol: https://github.com/iay/md-query/blob/master/draft-young-md-query.txt */
     $mdx_url = $this->server . '/entities/' . urlencode($index);
     SimpleSAML_Logger::debug('MetaData - Handler.MDX: Downloading metadata for "' . $index . '" from [' . $mdx_url . ']');
     try {
         $xmldata = \SimpleSAML\Utils\HTTP::fetch($mdx_url);
     } catch (Exception $e) {
         SimpleSAML_Logger::warning('Fetching metadata for ' . $index . ': ' . $e->getMessage());
     }
     if (empty($xmldata)) {
         $error = error_get_last();
         throw new Exception('Error downloading metadata for "' . $index . '" from "' . $mdx_url . '": ' . $error['message']);
     }
     $entity = SimpleSAML_Metadata_SAMLParser::parseString($xmldata);
     SimpleSAML_Logger::debug('MetaData - Handler.MDX: Completed parsing of [' . $mdx_url . ']');
     if ($this->validateFingerprint !== NULL) {
         if (!$entity->validateFingerprint($this->validateFingerprint)) {
             throw new Exception('Error, could not verify signature for entity: ' . $index . '".');
         }
     }
     $data = self::getParsedSet($entity, $set);
     if ($data === NULL) {
         throw new Exception('No metadata for set "' . $set . '" available from "' . $index . '".');
     }
     $this->writeToCache($set, $index, $data);
     return $data;
 }
 /**
  *
  * @param SAML2_XML_md_EntityDescriptor|SAML2_XML_md_EntitiesDescriptor $element  The element we should process.
  * @param int|NULL $maxExpireTime  The maximum expiration time of the entitites.
  * @param array $validators  The parent-elements that may be signed.
  * @return array  Array of SAMLParser instances.
  */
 private static function processDescriptorsElement($element, $maxExpireTime = NULL, array $validators = array())
 {
     assert('is_null($maxExpireTime) || is_int($maxExpireTime)');
     if ($element instanceof SAML2_XML_md_EntityDescriptor) {
         $ret = new SimpleSAML_Metadata_SAMLParser($element, $maxExpireTime, $validators);
         return array($ret->getEntityId() => $ret);
     }
     assert('$element instanceof SAML2_XML_md_EntitiesDescriptor');
     $expTime = self::getExpireTime($element, $maxExpireTime);
     $validators[] = $element;
     $ret = array();
     foreach ($element->children as $child) {
         $ret += self::processDescriptorsElement($child, $expTime, $validators);
     }
     return $ret;
 }
Example #20
0
 /**
  * Overriding this function from the superclass SimpleSAML_Metadata_MetaDataStorageSource.
  *
  * This function retrieves metadata for the given entity id in the given set of metadata.
  * It will return NULL if it is unable to locate the metadata.
  *
  * This class implements this function using the getMetadataSet-function. A subclass should
  * override this function if it doesn't implement the getMetadataSet function, or if the
  * implementation of getMetadataSet is slow.
  *
  * @param string $index The entityId or metaindex we are looking up.
  * @param string $set The set we are looking for metadata in.
  *
  * @return array An associative array with metadata for the given entity, or NULL if we are unable to
  *         locate the entity.
  * @throws \Exception If an error occurs while downloading metadata, validating the signature or writing to cache.
  */
 public function getMetaData($index, $set)
 {
     assert('is_string($index)');
     assert('is_string($set)');
     Logger::info(__CLASS__ . ': loading metadata entity [' . $index . '] from [' . $set . ']');
     // read from cache if possible
     $data = $this->getFromCache($set, $index);
     if ($data !== null && array_key_exists('expires', $data) && $data['expires'] < time()) {
         // metadata has expired
         $data = null;
     }
     if (isset($data)) {
         // metadata found in cache and not expired
         Logger::debug(__CLASS__ . ': using cached metadata for: ' . $index . '.');
         return $data;
     }
     // look at Metadata Query Protocol: https://github.com/iay/md-query/blob/master/draft-young-md-query.txt
     $mdq_url = $this->server . '/entities/' . urlencode($index);
     Logger::debug(__CLASS__ . ': downloading metadata for "' . $index . '" from [' . $mdq_url . ']');
     try {
         $xmldata = HTTP::fetch($mdq_url);
     } catch (\Exception $e) {
         Logger::warning('Fetching metadata for ' . $index . ': ' . $e->getMessage());
     }
     if (empty($xmldata)) {
         $error = error_get_last();
         throw new \Exception('Error downloading metadata for "' . $index . '" from "' . $mdq_url . '": ' . $error['message']);
     }
     /** @var string $xmldata */
     $entity = \SimpleSAML_Metadata_SAMLParser::parseString($xmldata);
     Logger::debug(__CLASS__ . ': completed parsing of [' . $mdq_url . ']');
     if ($this->validateFingerprint !== null) {
         if (!$entity->validateFingerprint($this->validateFingerprint)) {
             throw new \Exception(__CLASS__ . ': error, could not verify signature for entity: ' . $index . '".');
         }
     }
     $data = self::getParsedSet($entity, $set);
     if ($data === null) {
         throw new \Exception(__CLASS__ . ': no metadata for set "' . $set . '" available from "' . $index . '".');
     }
     $this->writeToCache($set, $index, $data);
     return $data;
 }