18 const START_SOAP_ENVELOPE =
'<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"><soap-env:Header/><soap-env:Body>';
19 const END_SOAP_ENVELOPE =
'</soap-env:Body></soap-env:Envelope>';
36 'capture_peer_cert' =>
true,
37 'allow_self_signed' =>
true 42 if ($srcMetadata->
hasValue(
'saml.SOAPClient.certificate')) {
43 $cert = $srcMetadata->
getValue(
'saml.SOAPClient.certificate');
44 if ($cert !==
false) {
46 $srcMetadata->
getString(
'saml.SOAPClient.certificate')
48 if ($srcMetadata->
hasValue(
'saml.SOAPClient.privatekey_pass')) {
49 $ctxOpts[
'ssl'][
'passphrase'] = $srcMetadata->
getString(
'saml.SOAPClient.privatekey_pass');
56 if ($privateKey !== null && $publicKey !== null && isset($publicKey[
'PEM'])) {
57 $keyCertData = $privateKey[
'PEM'] . $publicKey[
'PEM'];
59 if (!file_exists(
$file)) {
62 $ctxOpts[
'ssl'][
'local_cert'] =
$file;
63 if (isset($privateKey[
'password'])) {
64 $ctxOpts[
'ssl'][
'passphrase'] = $privateKey[
'password'];
70 if ($dstMetadata !== null) {
71 $peerPublicKeys = $dstMetadata->getPublicKeys(
'signing',
true);
73 foreach ($peerPublicKeys as
$key) {
74 if ($key[
'type'] !==
'X509Certificate') {
77 $certData .=
"-----BEGIN CERTIFICATE-----\n" .
78 chunk_split($key[
'X509Certificate'], 64) .
79 "-----END CERTIFICATE-----\n";
82 if (!file_exists($peerCertFile)) {
86 $ctxOpts[
'ssl'][
'verify_peer'] =
true;
87 $ctxOpts[
'ssl'][
'verify_depth'] = 1;
88 $ctxOpts[
'ssl'][
'cafile'] = $peerCertFile;
91 if ($srcMetadata->
hasValue(
'saml.SOAPClient.stream_context.ssl.peer_name')) {
92 $ctxOpts[
'ssl'][
'peer_name'] = $srcMetadata->
getString(
'saml.SOAPClient.stream_context.ssl.peer_name');
95 $context = stream_context_create($ctxOpts);
96 if ($context === null) {
97 throw new \Exception(
'Unable to create SSL stream context');
103 'stream_context' => $context,
106 if ($srcMetadata->
hasValue(
'saml.SOAPClient.proxyhost')) {
107 $options[
'proxy_host'] = $srcMetadata->
getValue(
'saml.SOAPClient.proxyhost');
110 if ($srcMetadata->
hasValue(
'saml.SOAPClient.proxyport')) {
111 $options[
'proxy_port'] = $srcMetadata->
getValue(
'saml.SOAPClient.proxyport');
118 $request = self::START_SOAP_ENVELOPE . $request->ownerDocument->saveXML($request) . self::END_SOAP_ENVELOPE;
120 Utils::getContainer()->debugMessage($request,
'out');
122 $action =
'http://www.oasis-open.org/committees/security';
128 if ($soapresponsexml === null || $soapresponsexml ===
"") {
129 throw new \Exception(
'Empty SOAP response, check peer certificate.');
132 Utils::getContainer()->debugMessage($soapresponsexml,
'in');
136 $dom = DOMDocumentFactory::fromString($soapresponsexml);
138 throw new \Exception(
'Not a SOAP response.', 0, $e);
141 $soapfault = $this->getSOAPFault($dom);
142 if (isset($soapfault)) {
143 throw new \Exception($soapfault);
146 $samlresponse = Utils::xpQuery($dom->firstChild,
'/soap-env:Envelope/soap-env:Body/*[1]');
147 $samlresponse = Message::fromXML($samlresponse[0]);
150 self::addSSLValidator($samlresponse, $context);
152 Utils::getContainer()->getLogger()->debug(
"Valid ArtifactResponse received from IdP");
154 return $samlresponse;
165 $options = stream_context_get_options($context);
166 if (!isset(
$options[
'ssl'][
'peer_certificate'])) {
173 $key = openssl_pkey_get_public(
$options[
'ssl'][
'peer_certificate']);
174 if (
$key ===
false) {
175 Utils::getContainer()->getLogger()->warning(
'Unable to get public key from peer certificate.');
180 $keyInfo = openssl_pkey_get_details(
$key);
181 if ($keyInfo ===
false) {
182 Utils::getContainer()->getLogger()->warning(
'Unable to get key details from public key.');
187 if (!isset($keyInfo[
'key'])) {
188 Utils::getContainer()->getLogger()->warning(
'Missing key in public key details.');
205 assert(is_string(
$data));
207 $keyInfo = openssl_pkey_get_details($key->key);
208 if ($keyInfo ===
false) {
209 throw new \Exception(
'Unable to get key details from XMLSecurityKey.');
212 if (!isset($keyInfo[
'key'])) {
213 throw new \Exception(
'Missing key in public key details.');
216 if ($keyInfo[
'key'] !==
$data) {
217 Utils::getContainer()->getLogger()->debug(
'Key on SSL connection did not match key we validated against.');
222 Utils::getContainer()->getLogger()->debug(
'Message validated based on SSL certificate.');
232 $soapFault = Utils::xpQuery($soapMessage->firstChild,
'/soap-env:Envelope/soap-env:Body/soap-env:Fault');
234 if (empty($soapFault)) {
239 $soapFaultElement = $soapFault[0];
241 $soapFaultString =
"Unknown fault string found";
243 $faultStringElement = Utils::xpQuery($soapFaultElement,
'./soap-env:faultstring') ;
244 if (!empty($faultStringElement)) {
245 return $faultStringElement[0]->textContent;
248 return $soapFaultString;
static resolveCert($path)
hasValue($name)
Check whether a key in the configuration exists or not.
getIssuer()
Retrieve the issuer if this message.
toSignedXML()
Convert this message to a signed XML document.
getValue($name, $default=null)
Retrieve a configuration option set in config.php.
static writeFile($filename, $data, $mode=0600)
static loadPublicKey(SimpleSAML_Configuration $metadata, $required=false, $prefix='')
Base class for all SAML 2 messages.
static addSSLValidator(Message $msg, $context)
Add a signature validator based on a SSL context.
catch(Exception $e) if(!($request instanceof \SAML2\ArtifactResolve)) $issuer
Create styles array
The data for the language used.
getString($name, $default=self::REQUIRED_OPTION)
This function retrieves a string configuration option.
static validateSSL($data, XMLSecurityKey $key)
Validate a SOAP message against the certificate on the SSL connection.
getDestination()
Retrieve the destination of this message.
send(Message $msg, SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata=null)
This function sends the SOAP message to the service location and returns SOAP response.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
static loadPrivateKey(SimpleSAML_Configuration $metadata, $required=false, $prefix='')
getSOAPFault($soapMessage)
if(!isset($_REQUEST['ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
addValidator($function, $data)
Add a method for validating this message.