From 08f99932953245c9c9ad1e712774c15a26f9f8aa Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Fri, 10 Sep 2010 08:29:32 +0000 Subject: [PATCH] SAML_SOAPClient: Allow received message to be validated based on the SSL certificate. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2540 44740490-163a-0410-bde0-09ae8108e29a --- lib/SAML2/SOAPClient.php | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/SAML2/SOAPClient.php b/lib/SAML2/SOAPClient.php index 612b5d40f..292d16699 100644 --- a/lib/SAML2/SOAPClient.php +++ b/lib/SAML2/SOAPClient.php @@ -25,6 +25,7 @@ class SAML2_SOAPClient { $ctxOpts = array( 'ssl' => array( + 'capture_peer_cert' => TRUE, ), ); @@ -116,6 +117,8 @@ class SAML2_SOAPClient { $samlresponse = SAML2_Utils::xpQuery($dom->firstChild, '/soap-env:Envelope/soap-env:Body/*[1]'); $samlresponse = SAML2_Message::fromXML($samlresponse[0]); + /* Add validator to message which uses the SSL context. */ + self::addSSLValidator($samlresponse, $context); SimpleSAML_Logger::debug("Valid ArtifactResponse received from IdP"); @@ -124,6 +127,68 @@ class SAML2_SOAPClient { } + /** + * Add a signature validator based on a SSL context. + * + * @param SAML2_Message $msg The message we should add a validator to. + * @param resource $context The stream context. + */ + private static function addSSLValidator(SAML2_Message $msg, $context) { + $options = stream_context_get_options($context); + if (!isset($options['ssl']['peer_certificate'])) { + return; + } + + //$out = ''; + //openssl_x509_export($options['ssl']['peer_certificate'], $out); + + $key = openssl_pkey_get_public($options['ssl']['peer_certificate']); + if ($key === FALSE) { + SimpleSAML_Logger::warning('Unable to get public key from peer certificate.'); + return; + } + + $keyInfo = openssl_pkey_get_details($key); + if ($keyInfo === FALSE) { + SimpleSAML_Logger::warning('Unable to get key details from public key.'); + return; + } + + if (!isset($keyInfo['key'])) { + SimpleSAML_Logger::warning('Missing key in public key details.'); + return; + } + + $msg->addValidator(array('SAML2_SOAPClient', 'validateSSL'), $keyInfo['key']); + } + + + /** + * Validate a SOAP message against the certificate on the SSL connection. + * + * @param string $data The public key that was used on the connection. + * @param XMLSecurityKey $key The key we should validate the certificate against. + */ + public static function validateSSL($data, XMLSecurityKey $key) { + assert('is_string($data)'); + + $keyInfo = openssl_pkey_get_details($key->key); + if ($keyInfo === FALSE) { + throw new Exception('Unable to get key details from XMLSecurityKey.'); + } + + if (!isset($keyInfo['key'])) { + throw new Exception('Missing key in public key details.'); + } + + if ($keyInfo['key'] !== $data) { + throw new Exception('Key on SSL connection did not match key we validated against.'); + } + + SimpleSAML_Logger::debug('Message validated based on SSL certificate.'); + } + + /* * Extracts the SOAP Fault from SOAP message * @param $soapmessage Soap response needs to be type DOMDocument -- GitLab