/**
  * Retrieve and parse the metadata.
  *
  * @return SAML2_XML_md_EntitiesDescriptor|SAML2_XML_md_EntityDescriptor|NULL
  * The downloaded metadata or NULL if we were unable to download or parse it.
  */
 private function downloadMetadata()
 {
     SimpleSAML\Logger::debug($this->logLoc . 'Downloading metadata from ' . var_export($this->url, TRUE));
     $context = array('ssl' => array());
     if ($this->sslCAFile !== NULL) {
         $context['ssl']['cafile'] = SimpleSAML_Utilities::resolveCert($this->sslCAFile);
         SimpleSAML\Logger::debug($this->logLoc . 'Validating https connection against CA certificate(s) found in ' . var_export($context['ssl']['cafile'], TRUE));
         $context['ssl']['verify_peer'] = TRUE;
         $context['ssl']['CN_match'] = parse_url($this->url, PHP_URL_HOST);
     }
     $data = SimpleSAML_Utilities::fetch($this->url, $context);
     if ($data === FALSE || $data === NULL) {
         SimpleSAML\Logger::error($this->logLoc . 'Unable to load metadata from ' . var_export($this->url, TRUE));
         return NULL;
     }
     $doc = new DOMDocument();
     $res = $doc->loadXML($data);
     if (!$res) {
         SimpleSAML\Logger::error($this->logLoc . 'Error parsing XML from ' . var_export($this->url, TRUE));
         return NULL;
     }
     $root = SAML2_Utils::xpQuery($doc->firstChild, '/saml_metadata:EntityDescriptor|/saml_metadata:EntitiesDescriptor');
     if (count($root) === 0) {
         SimpleSAML\Logger::error($this->logLoc . 'No <EntityDescriptor> or <EntitiesDescriptor> in metadata from ' . var_export($this->url, TRUE));
         return NULL;
     }
     if (count($root) > 1) {
         SimpleSAML\Logger::error($this->logLoc . 'More than one <EntityDescriptor> or <EntitiesDescriptor> in metadata from ' . var_export($this->url, TRUE));
         return NULL;
     }
     $root = $root[0];
     try {
         if ($root->localName === 'EntityDescriptor') {
             $md = new SAML2_XML_md_EntityDescriptor($root);
         } else {
             $md = new SAML2_XML_md_EntitiesDescriptor($root);
         }
     } catch (Exception $e) {
         SimpleSAML\Logger::error($this->logLoc . 'Unable to parse metadata from ' . var_export($this->url, TRUE) . ': ' . $e->getMessage());
         return NULL;
     }
     if ($this->certificate !== NULL) {
         $file = SimpleSAML_Utilities::resolveCert($this->certificate);
         $certData = file_get_contents($file);
         if ($certData === FALSE) {
             throw new SimpleSAML_Error_Exception('Error loading certificate from ' . var_export($file, TRUE));
         }
         // Extract the public key from the certificate for validation
         $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
         $key->loadKey($file, TRUE);
         if (!$md->validate($key)) {
             SimpleSAML\Logger::error($this->logLoc . 'Error validating signature on metadata.');
             return NULL;
         }
         SimpleSAML\Logger::debug($this->logLoc . 'Validated signature on metadata from ' . var_export($this->url, TRUE));
     }
     return $md;
 }
Exemplo n.º 2
0
 public function getMetadataDocument()
 {
     // Get metadata entries
     $entities = $this->getSources();
     $maxDuration = $this->getMaxDuration();
     $reconstruct = $this->getReconstruct();
     $entitiesDescriptor = new SAML2_XML_md_EntitiesDescriptor();
     $entitiesDescriptor->Name = $this->id;
     $entitiesDescriptor->validUntil = time() + $maxDuration;
     // add RegistrationInfo extension if enabled
     if ($this->gConfig->hasValue('RegistrationInfo')) {
         $ri = new SAML2_XML_mdrpi_RegistrationInfo();
         foreach ($this->gConfig->getArray('RegistrationInfo') as $riName => $riValues) {
             switch ($riName) {
                 case 'authority':
                     $ri->registrationAuthority = $riValues;
                     break;
                 case 'instant':
                     $ri->registrationInstant = SAML2_Utils::xsDateTimeToTimestamp($riValues);
                     break;
                 case 'policies':
                     $ri->RegistrationPolicy = $riValues;
                     break;
             }
         }
         $entitiesDescriptor->Extensions[] = $ri;
     }
     /* Build EntityDescriptor elements for them. */
     foreach ($entities as $entity => $sets) {
         $entityDescriptor = NULL;
         foreach ($sets as $set => $metadata) {
             if (!array_key_exists('entityDescriptor', $metadata)) {
                 /* One of the sets doesn't contain an EntityDescriptor element. */
                 $entityDescriptor = FALSE;
                 break;
             }
             if ($entityDescriptor == NULL) {
                 /* First EntityDescriptor elements. */
                 $entityDescriptor = $metadata['entityDescriptor'];
                 continue;
             }
             assert('is_string($entityDescriptor)');
             if ($entityDescriptor !== $metadata['entityDescriptor']) {
                 /* Entity contains multiple different EntityDescriptor elements. */
                 $entityDescriptor = FALSE;
                 break;
             }
         }
         if (is_string($entityDescriptor) && !$reconstruct) {
             /* All metadata sets for the entity contain the same entity descriptor. Use that one. */
             $tmp = new DOMDocument();
             $tmp->loadXML(base64_decode($entityDescriptor));
             $entitiesDescriptor->children[] = new SAML2_XML_md_EntityDescriptor($tmp->documentElement);
         } else {
             $tmp = new SimpleSAML_Metadata_SAMLBuilder($entity, $maxDuration, $maxDuration);
             $orgmeta = NULL;
             foreach ($sets as $set => $metadata) {
                 $tmp->addMetadata($set, $metadata);
                 $orgmeta = $metadata;
             }
             $tmp->addOrganizationInfo($orgmeta);
             $entitiesDescriptor->children[] = $tmp->getEntityDescriptor();
         }
     }
     $document = $entitiesDescriptor->toXML();
     // sign the metadata if enabled
     if ($this->shouldSign()) {
         $signer = new SimpleSAML_XML_Signer($this->getSigningInfo());
         $signer->sign($document, $document, $document->firstChild);
     }
     return $document;
 }