/** * 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; }