Skip to content
Snippets Groups Projects
Commit 7513d23f authored by Jaime Perez Crespo's avatar Jaime Perez Crespo
Browse files

Reformat SimpleSAML_Metadata_MetaDataStorageHandlerMDX.

parent dc926d2e
No related branches found
No related tags found
No related merge requests found
<?php <?php
/** /**
* This class implements SAML Metadata Exchange Protocol * This class implements SAML Metadata Exchange Protocol
* *
* @author Andreas Åkre Solberg, UNINETT AS. * @author Andreas Åkre Solberg, UNINETT AS.
* @author Olav Morken, UNINETT AS. * @author Olav Morken, UNINETT AS.
* @author Tamas Frank, NIIFI * @author Tamas Frank, NIIFI
* @package simpleSAMLphp * @package SimpleSAMLphp
*/ */
class SimpleSAML_Metadata_MetaDataStorageHandlerMDX extends SimpleSAML_Metadata_MetaDataStorageSource { class SimpleSAML_Metadata_MetaDataStorageHandlerMDX extends SimpleSAML_Metadata_MetaDataStorageSource
{
/** /**
* The URL of MDX server (url:port) * The URL of MDX server (url:port)
*
* @var string
*/ */
private $server; private $server;
/** /**
* The fingerprint of the certificate used to sign the metadata. You don't need this option if you don't want to validate the signature on the metadata. * The fingerprint of the certificate used to sign the metadata. You don't need this option if you don't want to
* validate the signature on the metadata.
*
* @var string|null
*/ */
private $validateFingerprint; private $validateFingerprint;
/** /**
* The cache directory, or NULL if no cache directory is configured. * The cache directory, or null if no cache directory is configured.
*/ *
private $cacheDir; * @var string|null
*/
private $cacheDir;
/** /**
* The maximum cache length, in seconds. * The maximum cache length, in seconds.
*/ *
private $cacheLength; * @var integer
*/
private $cacheLength;
/** /**
* This function initializes the dynamic XML metadata source. * This function initializes the dynamic XML metadata source.
* *
* Options: * Options:
* - 'server': URL of the MDX server (url:port). Mandatory. * - 'server': URL of the MDX server (url:port). Mandatory.
* - 'validateFingerprint': The fingerprint of the certificate used to sign the metadata. * - 'validateFingerprint': The fingerprint of the certificate used to sign the metadata.
* You don't need this option if you don't want to validate the signature on the metadata. Optional. * You don't need this option if you don't want to validate the signature on the metadata.
* - 'cachedir': Directory where metadata can be cached. Optional. * Optional.
* - 'cachelength': Maximum time metadata cah be cached, in seconds. Default to 24 * - 'cachedir': Directory where metadata can be cached. Optional.
* hours (86400 seconds). * - 'cachelength': Maximum time metadata cah be cached, in seconds. Default to 24
* * hours (86400 seconds).
* @param array $config The configuration for this instance of the XML metadata source. *
* @throws Exception If no server option can be found in the configuration. * @param array $config The configuration for this instance of the XML metadata source.
*/ *
protected function __construct($config) { * @throws Exception If no server option can be found in the configuration.
assert('is_array($config)'); */
protected function __construct($config)
if (!array_key_exists('server', $config)){ {
throw new Exception("The 'server' configuration option is not set."); assert('is_array($config)');
} else {
$this->server = $config['server']; if (!array_key_exists('server', $config)) {
} throw new Exception("The 'server' configuration option is not set.");
} else {
if (array_key_exists('validateFingerprint', $config)) { $this->server = $config['server'];
$this->validateFingerprint = $config['validateFingerprint']; }
} else {
$this->validateFingerprint = NULL; if (array_key_exists('validateFingerprint', $config)) {
} $this->validateFingerprint = $config['validateFingerprint'];
} else {
if (array_key_exists('cachedir', $config)) { $this->validateFingerprint = null;
$globalConfig = SimpleSAML_Configuration::getInstance(); }
$this->cacheDir = $globalConfig->resolvePath($config['cachedir']);
} else { if (array_key_exists('cachedir', $config)) {
$this->cacheDir = NULL; $globalConfig = SimpleSAML_Configuration::getInstance();
} $this->cacheDir = $globalConfig->resolvePath($config['cachedir']);
} else {
if (array_key_exists('cachelength', $config)) { $this->cacheDir = null;
$this->cacheLength = $config['cachelength']; }
} else {
$this->cacheLength = 86400; if (array_key_exists('cachelength', $config)) {
} $this->cacheLength = $config['cachelength'];
} else {
} $this->cacheLength = 86400;
}
}
/**
* This function returns an associative array with metadata for all entities in the given set. The
* key of the array is the entity id. /**
* * This function is not implemented.
* @param string $set The set we want to list metadata for. *
* @return array An associative array with all entities in the given set. * @param string $set The set we want to list metadata for.
*/ *
public function getMetadataSet($set) { * @return array An empty array.
*/
/* We don't have this metadata set. */ public function getMetadataSet($set)
return array(); {
} // we don't have this metadata set
return array();
}
/**
* Find the cache file name for an entity,
* /**
* @param string $set The metadata set this entity belongs to. * Find the cache file name for an entity,
* @param string $entityId The entity id of this entity. *
* @return string The full path to the cache file. * @param string $set The metadata set this entity belongs to.
*/ * @param string $entityId The entity id of this entity.
private function getCacheFilename($set, $entityId) { *
assert('is_string($set)'); * @return string The full path to the cache file.
assert('is_string($entityId)'); */
private function getCacheFilename($set, $entityId)
$cachekey = sha1($entityId); {
return $this->cacheDir . '/' . $set . '-' . $cachekey . '.cached.xml'; assert('is_string($set)');
} assert('is_string($entityId)');
$cachekey = sha1($entityId);
/** return $this->cacheDir.'/'.$set.'-'.$cachekey.'.cached.xml';
* Load a entity from the cache. }
*
* @param string $set The metadata set this entity belongs to.
* @param string $entityId The entity id of this entity. /**
* @return array|NULL The associative array with the metadata for this entity, or NULL * Load a entity from the cache.
* if the entity could not be found. *
* @throws Exception If an error occurs while loading metadata from cache. * @param string $set The metadata set this entity belongs to.
*/ * @param string $entityId The entity id of this entity.
private function getFromCache($set, $entityId) { *
assert('is_string($set)'); * @return array|NULL The associative array with the metadata for this entity, or NULL
assert('is_string($entityId)'); * if the entity could not be found.
* @throws Exception If an error occurs while loading metadata from cache.
if (empty($this->cacheDir)) { */
return NULL; private function getFromCache($set, $entityId)
} {
assert('is_string($set)');
$cachefilename = $this->getCacheFilename($set, $entityId); assert('is_string($entityId)');
if (!file_exists($cachefilename)) return NULL;
if (!is_readable($cachefilename)) throw new Exception('Could not read cache file for entity [' . $cachefilename. ']'); if (empty($this->cacheDir)) {
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Reading cache [' . $entityId . '] => [' . $cachefilename . ']' ); return null;
}
/* Ensure that this metadata isn't older that the cachelength option allows. This
* must be verified based on the file, since this option may be changed after the $cachefilename = $this->getCacheFilename($set, $entityId);
* file is written. if (!file_exists($cachefilename)) {
*/ return null;
$stat = stat($cachefilename); }
if ($stat['mtime'] + $this->cacheLength <= time()) { if (!is_readable($cachefilename)) {
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Cache file older that the cachelength option allows.'); throw new Exception('Could not read cache file for entity ['.$cachefilename.']');
return NULL; }
} SimpleSAML_Logger::debug('MetaData - Handler.MDX: Reading cache ['.$entityId.'] => ['.$cachefilename.']');
$rawData = file_get_contents($cachefilename); /* Ensure that this metadata isn't older that the cachelength option allows. This
if (empty($rawData)) { * must be verified based on the file, since this option may be changed after the
$error = error_get_last(); * file is written.
throw new Exception('Error reading metadata from cache file "' . $cachefilename . '": ' . */
$error['message']); $stat = stat($cachefilename);
} if ($stat['mtime'] + $this->cacheLength <= time()) {
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Cache file older that the cachelength option allows.');
$data = unserialize($rawData); return null;
if ($data === FALSE) { }
throw new Exception('Error deserializing cached data from file "' . $cachefilename .'".');
} $rawData = file_get_contents($cachefilename);
if (empty($rawData)) {
if (!is_array($data)) { $error = error_get_last();
throw new Exception('Cached metadata from "' . $cachefilename . '" wasn\'t an array.'); throw new Exception(
} 'Error reading metadata from cache file "'.$cachefilename.'": '.$error['message']
);
return $data; }
}
$data = unserialize($rawData);
if ($data === false) {
/** throw new Exception('Error unserializing cached data from file "'.$cachefilename.'".');
* Save a entity to the cache. }
*
* @param string $set The metadata set this entity belongs to. if (!is_array($data)) {
* @param string $entityId The entity id of this entity. throw new Exception('Cached metadata from "'.$cachefilename.'" wasn\'t an array.');
* @param array $data The associative array with the metadata for this entity. }
* @throws Exception If metadata cannot be written to cache.
*/ return $data;
private function writeToCache($set, $entityId, $data) { }
assert('is_string($set)');
assert('is_string($entityId)');
assert('is_array($data)'); /**
* Save a entity to the cache.
if (empty($this->cacheDir)) { *
return; * @param string $set The metadata set this entity belongs to.
} * @param string $entityId The entity id of this entity.
* @param array $data The associative array with the metadata for this entity.
$cachefilename = $this->getCacheFilename($set, $entityId); *
if (!is_writable(dirname($cachefilename))) throw new Exception('Could not write cache file for entity [' . $cachefilename. ']'); * @throws Exception If metadata cannot be written to cache.
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Writing cache [' . $entityId . '] => [' . $cachefilename . ']' ); */
file_put_contents($cachefilename, serialize($data)); private function writeToCache($set, $entityId, $data)
} {
assert('is_string($set)');
assert('is_string($entityId)');
/** assert('is_array($data)');
* Retrieve metadata for the correct set from a SAML2Parser.
* if (empty($this->cacheDir)) {
* @param SimpleSAML_Metadata_SAMLParser $entity A SAML2Parser representing an entity. return;
* @param string $set The metadata set we are looking for. }
* @return array|NULL The associative array with the metadata, or NULL if no metadata for
* the given set was found. $cachefilename = $this->getCacheFilename($set, $entityId);
*/ if (!is_writable(dirname($cachefilename))) {
private static function getParsedSet(SimpleSAML_Metadata_SAMLParser $entity, $set) { throw new Exception('Could not write cache file for entity ['.$cachefilename.']');
assert('is_string($set)'); }
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Writing cache ['.$entityId.'] => ['.$cachefilename.']');
switch($set) { file_put_contents($cachefilename, serialize($data));
case 'saml20-idp-remote': }
return $entity->getMetadata20IdP();
case 'saml20-sp-remote':
return $entity->getMetadata20SP(); /**
case 'shib13-idp-remote': * Retrieve metadata for the correct set from a SAML2Parser.
return $entity->getMetadata1xIdP(); *
case 'shib13-sp-remote': * @param SimpleSAML_Metadata_SAMLParser $entity A SAML2Parser representing an entity.
return $entity->getMetadata1xSP(); * @param string $set The metadata set we are looking for.
case 'attributeauthority-remote': *
$ret = $entity->getAttributeAuthorities(); * @return array|NULL The associative array with the metadata, or NULL if no metadata for
return $ret[0]; * the given set was found.
*/
default: private static function getParsedSet(SimpleSAML_Metadata_SAMLParser $entity, $set)
SimpleSAML_Logger::warning('MetaData - Handler.MDX: Unknown metadata set: ' . $set); {
} assert('is_string($set)');
return NULL; switch ($set) {
} case 'saml20-idp-remote':
return $entity->getMetadata20IdP();
case 'saml20-sp-remote':
/** return $entity->getMetadata20SP();
* Overriding this function from the superclass SimpleSAML_Metadata_MetaDataStorageSource. case 'shib13-idp-remote':
* return $entity->getMetadata1xIdP();
* This function retrieves metadata for the given entity id in the given set of metadata. case 'shib13-sp-remote':
* It will return NULL if it is unable to locate the metadata. return $entity->getMetadata1xSP();
* case 'attributeauthority-remote':
* This class implements this function using the getMetadataSet-function. A subclass should $ret = $entity->getAttributeAuthorities();
* override this function if it doesn't implement the getMetadataSet function, or if the return $ret[0];
* implementation of getMetadataSet is slow.
* default:
* @param string $index The entityId or metaindex we are looking up. SimpleSAML_Logger::warning('MetaData - Handler.MDX: Unknown metadata set: '.$set);
* @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. return null;
* @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)'); * Overriding this function from the superclass SimpleSAML_Metadata_MetaDataStorageSource.
*
SimpleSAML_Logger::info('MetaData - Handler.MDX: Loading metadata entity [' . $index . '] from [' . $set . ']' ); * 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.
/* Read from cache if possible. */ *
$data = $this->getFromCache($set, $index); * 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
if ($data !== NULL && array_key_exists('expires', $data) && $data['expires'] < time()) { * implementation of getMetadataSet is slow.
/* Metadata has expired. */ *
$data = NULL; * @param string $index The entityId or metaindex we are looking up.
} * @param string $set The set we are looking for metadata in.
*
if (isset($data)) { * @return array An associative array with metadata for the given entity, or NULL if we are unable to
/* Metadata found in cache and not expired. */ * locate the entity.
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Using cached metadata for: ' . $index . '.'); * @throws Exception If an error occurs while downloading metadata, validating the signature or writing to cache.
return $data; */
} public function getMetaData($index, $set)
{
/* Look at Metadata Query Protocol: https://github.com/iay/md-query/blob/master/draft-young-md-query.txt */ assert('is_string($index)');
$mdx_url = $this->server . '/entities/' . urlencode( $index); assert('is_string($set)');
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Downloading metadata for "'. $index .'" from [' . $mdx_url . ']' ); SimpleSAML_Logger::info('MetaData - Handler.MDX: Loading metadata entity ['.$index.'] from ['.$set.']');
try {
$xmldata = \SimpleSAML\Utils\HTTP::fetch($mdx_url); // read from cache if possible
} catch(Exception $e) { $data = $this->getFromCache($set, $index);
SimpleSAML_Logger::warning('Fetching metadata for ' . $index . ': ' . $e->getMessage());
} if ($data !== null && array_key_exists('expires', $data) && $data['expires'] < time()) {
// metadata has expired
if (empty($xmldata)) { $data = null;
$error = error_get_last(); }
throw new Exception('Error downloading metadata for "'. $index .'" from "' . $mdx_url . '": ' .
$error['message']); if (isset($data)) {
} // metadata found in cache and not expired
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Using cached metadata for: '.$index.'.');
$entity = SimpleSAML_Metadata_SAMLParser::parseString($xmldata); return $data;
SimpleSAML_Logger::debug('MetaData - Handler.MDX: Completed parsing of [' . $mdx_url . ']' ); }
if( $this->validateFingerprint !== NULL) { // look at Metadata Query Protocol: https://github.com/iay/md-query/blob/master/draft-young-md-query.txt
if(!$entity->validateFingerprint($this->validateFingerprint)) { $mdx_url = $this->server.'/entities/'.urlencode($index);
throw new Exception ('Error, could not verify signature for entity: ' . $index . '".');
} SimpleSAML_Logger::debug('MetaData - Handler.MDX: Downloading metadata for "'.$index.'" from ['.$mdx_url.']');
} try {
$xmldata = \SimpleSAML\Utils\HTTP::fetch($mdx_url);
$data = self::getParsedSet($entity, $set); } catch (Exception $e) {
if ($data === NULL) { SimpleSAML_Logger::warning('Fetching metadata for '.$index.': '.$e->getMessage());
throw new Exception('No metadata for set "' . $set . '" available from "' . $index . '".'); }
}
if (empty($xmldata)) {
$this->writeToCache($set, $index, $data); $error = error_get_last();
throw new Exception(
return $data; '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;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment