' . '' . ''; foreach ($artifacts as $a) { $msg .= '' . htmlspecialchars($a) . ''; } $msg .= '' . '' . ''; return $msg; } /** * Extract the response element from the SOAP response. * * @param string $soapResponse The SOAP response. * @return string The element, as a string. */ private static function extractResponse($soapResponse) { assert('is_string($soapResponse)'); $doc = new DOMDocument(); if (!$doc->loadXML($soapResponse)) { throw new SimpleSAML_Error_Exception('Error parsing SAML 1 artifact response.'); } $soapEnvelope = $doc->firstChild; if (!SimpleSAML_Utilities::isDOMElementOfType($soapEnvelope, 'Envelope', 'http://schemas.xmlsoap.org/soap/envelope/')) { throw new SimpleSAML_Error_Exception('Expected artifact response to contain a element.'); } $soapBody = SimpleSAML_Utilities::getDOMChildren($soapEnvelope, 'Body', 'http://schemas.xmlsoap.org/soap/envelope/'); if (count($soapBody) === 0) { throw new SimpleSAML_Error_Exception('Couldn\'t find in .'); } $soapBody = $soapBody[0]; $responseElement = SimpleSAML_Utilities::getDOMChildren($soapBody, 'Response', 'urn:oasis:names:tc:SAML:1.0:protocol'); if (count($responseElement) === 0) { throw new SimpleSAML_Error_Exception('Couldn\'t find in .'); } $responseElement = $responseElement[0]; /* * Save the element. Note that we need to import it * into a new document, in order to preserve namespace declarations. */ $newDoc = new DOMDocument(); $newDoc->appendChild($newDoc->importNode($responseElement, TRUE)); $responseXML = $newDoc->saveXML(); return $responseXML; } /** * This function receives a SAML 1.1 artifact. * * @param SimpleSAML_Configuration $spMetadata The metadata of the SP. * @param SimpleSAML_Configuration $idpMetadata The metadata of the IdP. * @return string The element, as an XML string. */ public static function receive(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata) { $artifacts = self::getArtifacts(); $request = self::buildRequest($artifacts); SimpleSAML_Utilities::debugMessage($msgStr, 'out'); $url = $idpMetadata->getDefaultEndpoint('ArtifactResolutionService', array('urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding')); $url = $url['Location']; $peerPublicKeys = $idpMetadata->getPublicKeys('signing', TRUE); $certData = ''; foreach ($peerPublicKeys as $key) { if ($key['type'] !== 'X509Certificate') { continue; } $certData .= "-----BEGIN CERTIFICATE-----\n" . chunk_split($key['X509Certificate'], 64) . "-----END CERTIFICATE-----\n"; } $file = SimpleSAML_Utilities::getTempDir() . '/' . sha1($certData) . '.crt'; if (!file_exists($file)) { SimpleSAML_Utilities::writeFile($file, $certData); } $spKeyCertFile = SimpleSAML_Utilities::resolveCert($spMetadata->getString('privatekey')); $opts = array( 'ssl' => array( 'verify_peer' => TRUE, 'cafile' => $file, 'local_cert' => $spKeyCertFile, 'capture_peer_cert' => TRUE, 'capture_peer_chain' => TRUE, ), 'http' => array( 'method' => 'POST', 'content' => $request, 'header' => 'SOAPAction: http://www.oasis-open.org/committees/security' . "\r\n" . 'Content-Type: text/xml', ), ); /* Fetch the artifact. */ $response = SimpleSAML_Utilities::fetch($url, $opts); if ($response === FALSE) { throw new SimpleSAML_Error_Exception('Failed to retrieve assertion from IdP.'); } SimpleSAML_Utilities::debugMessage($response, 'in'); /* Find the response in the SOAP message. */ $response = self::extractResponse($response); return $response; } }