fromXML() public static method

Convert an XML element into a message.
public static fromXML ( DOMElement $xml ) : Message
$xml DOMElement The root XML element
return Message The message
示例#1
0
 /**
  * @group Message
  */
 public function testCorrectSignatureMethodCanBeExtractedFromResponse()
 {
     $response = new \DOMDocument();
     $response->load(__DIR__ . '/Response/response.xml');
     $privateKey = CertificatesMock::getPrivateKey();
     $unsignedMessage = Message::fromXML($response->documentElement);
     $unsignedMessage->setSignatureKey($privateKey);
     $unsignedMessage->setCertificates(array(CertificatesMock::PUBLIC_KEY_PEM));
     $signedMessage = Message::fromXML($unsignedMessage->toSignedXML());
     $this->assertEquals($privateKey->getAlgorith(), $signedMessage->getSignatureMethod());
 }
示例#2
0
 /**
  * Receive a SAML 2 message sent using the HTTP-Redirect binding.
  *
  * Throws an exception if it is unable receive the message.
  *
  * @return \SAML2\Message The received message.
  * @throws \Exception
  *
  * NPath is currently too high but solving that just moves code around.
  * @SuppressWarnings(PHPMD.NPathComplexity)
  */
 public function receive()
 {
     $data = self::parseQuery();
     if (array_key_exists('SAMLRequest', $data)) {
         $message = $data['SAMLRequest'];
     } elseif (array_key_exists('SAMLResponse', $data)) {
         $message = $data['SAMLResponse'];
     } else {
         throw new \Exception('Missing SAMLRequest or SAMLResponse parameter.');
     }
     if (isset($data['SAMLEncoding']) && $data['SAMLEncoding'] !== self::DEFLATE) {
         throw new \Exception('Unknown SAMLEncoding: ' . var_export($data['SAMLEncoding'], true));
     }
     $message = base64_decode($message);
     if ($message === false) {
         throw new \Exception('Error while base64 decoding SAML message.');
     }
     $message = gzinflate($message);
     if ($message === false) {
         throw new \Exception('Error while inflating SAML message.');
     }
     Utils::getContainer()->debugMessage($message, 'in');
     $document = DOMDocumentFactory::fromString($message);
     $xml = $document->firstChild;
     $message = Message::fromXML($xml);
     if (array_key_exists('RelayState', $data)) {
         $message->setRelayState($data['RelayState']);
     }
     if (!array_key_exists('Signature', $data)) {
         return $message;
     }
     if (!array_key_exists('SigAlg', $data)) {
         throw new \Exception('Missing signature algorithm.');
     }
     $signData = array('Signature' => $data['Signature'], 'SigAlg' => $data['SigAlg'], 'Query' => $data['SignedQuery']);
     $message->addValidator(array(get_class($this), 'validateSignature'), $signData);
     return $message;
 }
示例#3
0
 /**
  * This function sends the SOAP message to the service location and returns SOAP response
  *
  * @param  \SAML2\Message            $msg         The request that should be sent.
  * @param  \SimpleSAML_Configuration $srcMetadata The metadata of the issuer of the message.
  * @param  \SimpleSAML_Configuration $dstMetadata The metadata of the destination of the message.
  * @return \SAML2\Message            The response we received.
  * @throws \Exception
  */
 public function send(Message $msg, SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata = null)
 {
     $issuer = $msg->getIssuer();
     $ctxOpts = array('ssl' => array('verify_peer' => true, 'verify_peer_name' => true, 'capture_peer_cert' => true, 'verify_depth' => 5, 'peer_name' => 'as.ite.logon.realme.govt.nz', 'cafile' => 'mysite/certificate-bundle.pem'));
     // Determine if we are going to do a MutualSSL connection between the IdP and SP  - Shoaib
     if ($srcMetadata->hasValue('saml.SOAPClient.certificate')) {
         $cert = $srcMetadata->getValue('saml.SOAPClient.certificate');
         if ($cert !== false) {
             $ctxOpts['ssl']['local_cert'] = SimpleSAML_Utilities::resolveCert($srcMetadata->getString('saml.SOAPClient.certificate'));
             if ($srcMetadata->hasValue('saml.SOAPClient.privatekey_pass')) {
                 $ctxOpts['ssl']['passphrase'] = $srcMetadata->getString('saml.SOAPClient.privatekey_pass');
             }
         }
     } else {
         /* Use the SP certificate and privatekey if it is configured. */
         $privateKey = SimpleSAML_Utilities::loadPrivateKey($srcMetadata);
         $publicKey = SimpleSAML_Utilities::loadPublicKey($srcMetadata);
         if ($privateKey !== null && $publicKey !== null && isset($publicKey['PEM'])) {
             $keyCertData = $privateKey['PEM'] . $publicKey['PEM'];
             $file = SimpleSAML_Utilities::getTempDir() . '/' . sha1($keyCertData) . '.pem';
             if (!file_exists($file)) {
                 SimpleSAML_Utilities::writeFile($file, $keyCertData);
             }
             $ctxOpts['ssl']['local_cert'] = $file;
             if (isset($privateKey['password'])) {
                 $ctxOpts['ssl']['passphrase'] = $privateKey['password'];
             }
         }
     }
     // do peer certificate verification
     if ($dstMetadata !== null) {
         $peerPublicKeys = $dstMetadata->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";
         }
         $peerCertFile = SimpleSAML_Utilities::getTempDir() . '/' . sha1($certData) . '.pem';
         if (!file_exists($peerCertFile)) {
             SimpleSAML_Utilities::writeFile($peerCertFile, $certData);
         }
         // create ssl context
         $ctxOpts['ssl']['verify_peer'] = true;
         $ctxOpts['ssl']['verify_depth'] = 1;
         $ctxOpts['ssl']['cafile'] = $peerCertFile;
     }
     $context = stream_context_create($ctxOpts);
     if ($context === null) {
         throw new \Exception('Unable to create SSL stream context');
     }
     $options = array('uri' => $issuer, 'location' => $msg->getDestination(), 'stream_context' => $context);
     if ($srcMetadata->hasValue('saml.SOAPClient.proxyhost')) {
         $options['proxy_host'] = $srcMetadata->getValue('saml.SOAPClient.proxyhost');
     }
     if ($srcMetadata->hasValue('saml.SOAPClient.proxyport')) {
         $options['proxy_port'] = $srcMetadata->getValue('saml.SOAPClient.proxyport');
     }
     $x = new SoapClient(null, $options);
     // Add soap-envelopes
     $request = $msg->toSignedXML();
     $request = self::START_SOAP_ENVELOPE . $request->ownerDocument->saveXML($request) . self::END_SOAP_ENVELOPE;
     Utils::getContainer()->debugMessage($request, 'out');
     $action = 'http://www.oasis-open.org/committees/security';
     $version = '1.1';
     $destination = $msg->getDestination();
     /* Perform SOAP Request over HTTP */
     $soapresponsexml = $x->__doRequest($request, $destination, $action, $version);
     if ($soapresponsexml === null || $soapresponsexml === "") {
         throw new \Exception('Empty SOAP response, check peer certificate.');
     }
     Utils::getContainer()->debugMessage($soapresponsexml, 'in');
     // Convert to SAML2\Message (\DOMElement)
     try {
         $dom = DOMDocumentFactory::fromString($soapresponsexml);
     } catch (RuntimeException $e) {
         throw new \Exception('Not a SOAP response.', 0, $e);
     }
     $soapfault = $this->getSOAPFault($dom);
     if (isset($soapfault)) {
         throw new \Exception($soapfault);
     }
     //Extract the message from the response
     $samlresponse = Utils::xpQuery($dom->firstChild, '/soap-env:Envelope/soap-env:Body/*[1]');
     $samlresponse = Message::fromXML($samlresponse[0]);
     /* Add validator to message which uses the SSL context. */
     self::addSSLValidator($samlresponse, $context);
     Utils::getContainer()->getLogger()->debug("Valid ArtifactResponse received from IdP");
     return $samlresponse;
 }
示例#4
0
 /**
  * Receive a SAML 2 message sent using the HTTP-Artifact binding.
  *
  * Throws an exception if it is unable receive the message.
  *
  * @return \SAML2\Message The received message.
  * @throws \Exception
  */
 public function receive()
 {
     if (array_key_exists('SAMLart', $_REQUEST)) {
         $artifact = base64_decode($_REQUEST['SAMLart']);
         $endpointIndex = bin2hex(substr($artifact, 2, 2));
         $sourceId = bin2hex(substr($artifact, 4, 20));
     } else {
         throw new \Exception('Missing SAMLArt parameter.');
     }
     $metadataHandler = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
     $idpMetadata = $metadataHandler->getMetaDataConfigForSha1($sourceId, 'saml20-idp-remote');
     if ($idpMetadata === null) {
         throw new \Exception('No metadata found for remote provider with SHA1 ID: ' . var_export($sourceId, true));
     }
     $endpoint = null;
     foreach ($idpMetadata->getEndpoints('ArtifactResolutionService') as $ep) {
         if ($ep['index'] === hexdec($endpointIndex)) {
             $endpoint = $ep;
             break;
         }
     }
     if ($endpoint === null) {
         throw new \Exception('No ArtifactResolutionService with the correct index.');
     }
     Utils::getContainer()->getLogger()->debug("ArtifactResolutionService endpoint being used is := " . $endpoint['Location']);
     //Construct the ArtifactResolve Request
     $ar = new ArtifactResolve();
     /* Set the request attributes */
     $ar->setIssuer($this->spMetadata->getString('entityid'));
     $ar->setArtifact($_REQUEST['SAMLart']);
     $ar->setDestination($endpoint['Location']);
     /* Sign the request */
     sspmod_saml_Message::addSign($this->spMetadata, $idpMetadata, $ar);
     // Shoaib - moved from the SOAPClient.
     $soap = new SOAPClient();
     // Send message through SoapClient
     /** @var \SAML2\ArtifactResponse $artifactResponse */
     $artifactResponse = $soap->send($ar, $this->spMetadata);
     if (!$artifactResponse->isSuccess()) {
         throw new \Exception('Received error from ArtifactResolutionService.');
     }
     $xml = $artifactResponse->getAny();
     if ($xml === null) {
         /* Empty ArtifactResponse - possibly because of Artifact replay? */
         return null;
     }
     $samlResponse = Message::fromXML($xml);
     $samlResponse->addValidator(array(get_class($this), 'validateSignature'), $artifactResponse);
     if (isset($_REQUEST['RelayState'])) {
         $samlResponse->setRelayState($_REQUEST['RelayState']);
     }
     return $samlResponse;
 }