19 'attributeauthority-remote'
33 $this->metadata = array();
36 $this->changed =
false;
43 $this->state = array();
81 if (preg_match(
'@^https?://@i',
$source[
'src'])) {
88 }
catch(Exception $e) {
93 if (!isset($responseHeaders)) {
98 } elseif (preg_match(
'@^HTTP/1\.[01]\s304\s@', $responseHeaders[0])) {
103 } elseif (!preg_match(
'@^HTTP/1\.[01]\s200\s@', $responseHeaders[0])) {
112 $responseHeaders =
null;
116 if (isset(
$source[
'conditionalGET']) &&
$source[
'conditionalGET']) {
123 }
catch(Exception $e) {
130 foreach ($entities as $entity) {
132 if (isset(
$source[
'blacklist'])) {
133 if (!empty(
$source[
'blacklist']) && in_array($entity->getEntityID(),
$source[
'blacklist'],
true)) {
139 if (isset(
$source[
'whitelist'])) {
140 if (!empty(
$source[
'whitelist']) && !in_array($entity->getEntityID(),
$source[
'whitelist'],
true)) {
146 if (array_key_exists(
'certificates',
$source) &&
$source[
'certificates'] !==
null) {
147 if (!$entity->validateSignature(
$source[
'certificates'])) {
148 SimpleSAML\Logger::info(
'Skipping "' . $entity->getEntityId() .
'" - could not verify signature using certificate.' .
"\n");
153 if (array_key_exists(
'validateFingerprint',
$source) &&
$source[
'validateFingerprint'] !==
null) {
154 if (!array_key_exists(
'certificates',
$source) ||
$source[
'certificates'] ==
null) {
155 if (!$entity->validateFingerprint(
$source[
'validateFingerprint'])) {
156 SimpleSAML\Logger::info(
'Skipping "' . $entity->getEntityId() .
'" - could not verify signature using fingerprint.' .
"\n");
165 if (array_key_exists(
'template',
$source)) {
169 if (in_array(
'shib13-sp-remote', $this->types,
true)) {
172 if (in_array(
'shib13-idp-remote', $this->types,
true)) {
175 if (in_array(
'saml20-sp-remote', $this->types,
true)) {
178 if (in_array(
'saml20-idp-remote', $this->types,
true)) {
181 if (in_array(
'attributeauthority-remote', $this->types,
true)) {
182 $attributeAuthorities = $entity->getAttributeAuthorities();
183 if (!empty($attributeAuthorities)) {
198 $name =
$config->getString(
'technicalcontact_name',
null);
199 $mail =
$config->getString(
'technicalcontact_email',
null);
201 $rawheader =
"User-Agent: SimpleSAMLphp metarefresh, run by $name <$mail>\r\n";
203 if (isset(
$source[
'conditionalGET']) &&
$source[
'conditionalGET']) {
204 if (array_key_exists(
$source[
'src'], $this->state)) {
205 $sourceState = $this->state[
$source[
'src']];
207 if (isset($sourceState[
'last-modified'])) {
208 $rawheader .=
'If-Modified-Since: ' . $sourceState[
'last-modified'] .
"\r\n";
211 if (isset($sourceState[
'etag'])) {
212 $rawheader .=
'If-None-Match: ' . $sourceState[
'etag'] .
"\r\n";
217 return array(
'http' => array(
'header' => $rawheader));
223 if (isset($this->oldMetadataSrc)) {
224 foreach ($this->types as
$type) {
225 foreach ($this->oldMetadataSrc->getMetadataSet(
$type) as $entity) {
226 if (array_key_exists(
'metarefresh:src', $entity)) {
227 if ($entity[
'metarefresh:src'] ==
$source[
'src']) {
242 if (isset(
$source[
'conditionalGET']) &&
$source[
'conditionalGET']) {
244 if ($responseHeaders !==
null) {
245 $candidates = array(
'last-modified',
'etag');
247 foreach ($candidates as $candidate) {
248 if (array_key_exists($candidate, $responseHeaders)) {
249 $this->state[
$source[
'src']][$candidate] = $responseHeaders[$candidate];
254 if (!empty($this->state[
$source[
'src']])) {
257 $this->changed =
true;
269 }
catch (Exception $e) {
270 throw new Exception(
'Failed to read XML from ' .
$source[
'src']);
272 if ($doc->documentElement ===
null) {
273 throw new Exception(
'Opened file is not an XML document: ' .
$source[
'src']);
284 if ($this->changed) {
288 "<?php\n/* This file was generated by the metarefresh module at ".$this->
getTime() .
".\n".
289 " Do not update it manually as it will get overwritten. */\n".
290 '$state = ' . var_export($this->state,
true) .
";\n?>\n",
302 foreach ($this->metadata as $category => $elements) {
304 echo
'/* The following data should be added to metadata/' . $category .
'.php. */' .
"\n";
306 foreach ($elements as
$m) {
308 $entityID =
$m[
'metadata'][
'entityid'];
311 echo
'/* The following metadata was generated from ' .
$filename .
' on ' . $this->
getTime() .
'. */' .
"\n";
312 echo
'$metadata[\'' . addslashes($entityID) .
'\'] =
' . var_export($m['metadata
'], true) . ';
' . "\n";
330 private function addMetadata($filename, $metadata, $type, $template = null)
332 if ($metadata === null) {
336 if (isset($template)) {
337 $metadata = array_merge($metadata, $template);
340 $metadata['metarefresh:src
'] = $filename;
341 if (!array_key_exists($type, $this->metadata)) {
342 $this->metadata[$type] = array();
345 // If expire is defined in constructor...
346 if (!empty($this->expire)) {
347 // If expire is already in metadata
348 if (array_key_exists('expire
', $metadata)) {
349 // Override metadata expire with more restrictive global config-
350 if ($this->expire < $metadata['expire
']) {
351 $metadata['expire
'] = $this->expire;
354 // If expire is not already in metadata use global config
356 $metadata['expire
'] = $this->expire;
359 $this->metadata[$type][] = array('filename
' => $filename, 'metadata
' => $metadata);
366 public function writeARPfile($config)
368 assert($config instanceof SimpleSAML_Configuration);
370 $arpfile = $config->getValue('arpfile
');
371 $types = array('saml20-sp-remote
');
374 foreach ($this->metadata as $category => $elements) {
375 if (!in_array($category, $types, true)) {
378 $md = array_merge($md, $elements);
381 // $metadata, $attributemap, $prefix, $suffix
382 $arp = new sspmod_metarefresh_ARP($md,
383 $config->getValue('attributemap
', ''),
384 $config->getValue('prefix
', ''),
385 $config->getValue('suffix
', '')
389 $arpxml = $arp->getXML();
391 SimpleSAML\Logger::info('Writing ARP file:
' . $arpfile . "\n");
392 file_put_contents($arpfile, $arpxml);
399 public function writeMetadataFiles($outputDir)
401 while (strlen($outputDir) > 0 && $outputDir[strlen($outputDir) - 1] === '/
') {
402 $outputDir = substr($outputDir, 0, strlen($outputDir) - 1);
405 if (!file_exists($outputDir)) {
406 SimpleSAML\Logger::info('Creating directory:
' . $outputDir . "\n");
407 $res = @mkdir($outputDir, 0777, true);
408 if ($res === false) {
409 throw new Exception('Error creating directory:
' . $outputDir);
413 foreach ($this->types as $type) {
414 $filename = $outputDir . '/
' . $type . '.php
';
416 if (array_key_exists($type, $this->metadata)) {
417 $elements = $this->metadata[$type];
418 SimpleSAML\Logger::debug('Writing:
' . $filename);
420 $content = '<?
php' . "\n" . '
423 foreach ($elements as $m) {
424 $entityID = $m['metadata
']['entityid
'];
426 $content .= '$metadata[\
'' . addslashes($entityID) .
'\'] =
' . var_export($m['metadata
'], true) . ';
' . "\n";
429 $content .= "\n" . '?>
';
431 SimpleSAML\Utils\System::writeFile($filename, $content, 0644);
432 } elseif (is_file($filename)) {
433 if (unlink($filename)) {
434 SimpleSAML\Logger::debug('Deleting stale metadata file:
' . $filename);
436 SimpleSAML\Logger::warning('Could not
delete stale metadata file:
' . $filename);
448 public function writeMetadataSerialize($outputDir)
450 assert(is_string($outputDir));
452 $metaHandler = new SimpleSAML_Metadata_MetaDataStorageHandlerSerialize(array('directory
' => $outputDir));
454 /* First we add all the metadata entries to the metadata handler. */
455 foreach ($this->metadata as $set => $elements) {
456 foreach ($elements as $m) {
457 $entityId = $m['metadata
']['entityid
'];
459 SimpleSAML\Logger::debug(
460 'metarefresh: Add metadata entry
' .
461 var_export($entityId, true) . ' in
set ' . var_export($set, true) . '.
'
463 $metaHandler->saveMetadata($entityId, $set, $m['metadata
']);
467 /* Then we delete old entries which should no longer exist. */
469 foreach ($metaHandler->getMetadataSets() as $set) {
470 foreach ($metaHandler->getMetadataSet($set) as $entityId => $metadata) {
471 if (!array_key_exists('expire
', $metadata)) {
472 SimpleSAML\Logger::warning(
473 'metarefresh: Metadata entry without expire timestamp:
' . var_export($entityId, true) .
474 ' in
set ' . var_export($set, true) . '.
'
478 if ($metadata['expire
'] > $ct) {
481 SimpleSAML\Logger::debug('metarefresh:
' . $entityId . ' expired
' . date('l jS \of
F Y h:i:s A
', $metadata['expire
']));
482 SimpleSAML\Logger::debug(
483 'metarefresh: Delete expired metadata entry
' .
484 var_export($entityId, true) . ' in
set ' . var_export($set, true) . '. (
' . ($ct - $metadata['expire
']) . ' sec)
'
486 $metaHandler->deleteMetadata($entityId, $set);
492 private function getTime()
494 /* The current date, as a string. */
495 date_default_timezone_set('UTC
');
496 return date('Y-m-d\\TH:i:s\\Z
');
An exception for terminatinating execution or to throw for unit testing.
static fetch($url, $context=array(), $getHeaders=false)
Helper function to retrieve a file or URL with proxy support, also supporting proxy basic authorizati...
static writeFile($filename, $data, $mode=0600)
Atomically write a file.
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.