/** * Extract the response element from the SOAP response. * * @param string $soapResponse The SOAP response. * @return string The <saml1p:Response> element, as a string. */ private static function extractResponse($soapResponse) { assert('is_string($soapResponse)'); try { $doc = SAML2_DOMDocumentFactory::fromString($soapResponse); } catch (\Exception $e) { throw new SimpleSAML_Error_Exception('Error parsing SAML 1 artifact response.'); } $soapEnvelope = $doc->firstChild; if (!SimpleSAML\Utils\XML::isDOMElementOfType($soapEnvelope, 'Envelope', 'http://schemas.xmlsoap.org/soap/envelope/')) { throw new SimpleSAML_Error_Exception('Expected artifact response to contain a <soap:Envelope> element.'); } $soapBody = SimpleSAML\Utils\XML::getDOMChildren($soapEnvelope, 'Body', 'http://schemas.xmlsoap.org/soap/envelope/'); if (count($soapBody) === 0) { throw new SimpleSAML_Error_Exception('Couldn\'t find <soap:Body> in <soap:Envelope>.'); } $soapBody = $soapBody[0]; $responseElement = SimpleSAML\Utils\XML::getDOMChildren($soapBody, 'Response', 'urn:oasis:names:tc:SAML:1.0:protocol'); if (count($responseElement) === 0) { throw new SimpleSAML_Error_Exception('Couldn\'t find <saml1p:Response> in <soap:Body>.'); } $responseElement = $responseElement[0]; /* * Save the <saml1p:Response> element. Note that we need to import it * into a new document, in order to preserve namespace declarations. */ $newDoc = SAML2_DOMDocumentFactory::create(); $newDoc->appendChild($newDoc->importNode($responseElement, TRUE)); $responseXML = $newDoc->saveXML(); return $responseXML; }
/** * Retrieve the EntityDescriptor as text. * * This function serializes this EntityDescriptor, and returns it as text. * * @param bool $formatted Whether the returned EntityDescriptor should be formatted first. * * @return string The serialized EntityDescriptor. */ public function getEntityDescriptorText($formatted = true) { assert('is_bool($formatted)'); $xml = $this->getEntityDescriptor(); if ($formatted) { SimpleSAML\Utils\XML::formatDOMElement($xml); } return $xml->ownerDocument->saveXML(); }
/** * Send an authenticationResponse using HTTP-POST. * * @param string $response The response which should be sent. * @param SimpleSAML_Configuration $idpmd The metadata of the IdP which is sending the response. * @param SimpleSAML_Configuration $spmd The metadata of the SP which is receiving the response. * @param string|null $relayState The relaystate for the SP. * @param string $shire The shire which should receive the response. */ public function sendResponse($response, SimpleSAML_Configuration $idpmd, SimpleSAML_Configuration $spmd, $relayState, $shire) { \SimpleSAML\Utils\XML::checkSAMLMessage($response, 'saml11'); $privatekey = SimpleSAML\Utils\Crypto::loadPrivateKey($idpmd, true); $publickey = SimpleSAML\Utils\Crypto::loadPublicKey($idpmd, true); $responsedom = new DOMDocument(); $responsedom->loadXML(str_replace("\r", "", $response)); $responseroot = $responsedom->getElementsByTagName('Response')->item(0); $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0); /* Determine what we should sign - either the Response element or the Assertion. The default is to sign the * Assertion, but that can be overridden by the 'signresponse' option in the SP metadata or * 'saml20.signresponse' in the global configuration. * * TODO: neither 'signresponse' nor 'shib13.signresponse' are valid options any longer. Remove! */ if ($spmd->hasValue('signresponse')) { $signResponse = $spmd->getBoolean('signresponse'); } else { $signResponse = $this->configuration->getBoolean('shib13.signresponse', true); } // check if we have an assertion to sign. Force to sign the response if not if ($firstassertionroot === null) { $signResponse = true; } $signer = new SimpleSAML_XML_Signer(array('privatekey_array' => $privatekey, 'publickey_array' => $publickey, 'id' => $signResponse ? 'ResponseID' : 'AssertionID')); if ($idpmd->hasValue('certificatechain')) { $signer->addCertificate($idpmd->getString('certificatechain')); } if ($signResponse) { // sign the response - this must be done after encrypting the assertion // we insert the signature before the saml2p:Status element $statusElements = SimpleSAML\Utils\XML::getDOMChildren($responseroot, 'Status', '@saml1p'); assert('count($statusElements) === 1'); $signer->sign($responseroot, $responseroot, $statusElements[0]); } else { /* Sign the assertion */ $signer->sign($firstassertionroot, $firstassertionroot); } $response = $responsedom->saveXML(); \SimpleSAML\Utils\XML::debugSAMLMessage($response, 'out'); \SimpleSAML\Utils\HTTP::submitPOSTData($shire, array('TARGET' => $relayState, 'SAMLResponse' => base64_encode($response))); }
/** * This function locates the EntityDescriptor node in a DOMDocument. This node should * be the first (and only) node in the document. * * This function will throw an exception if it is unable to locate the node. * * @param DOMDocument $doc The DOMDocument where we should find the EntityDescriptor node. * * @return SAML2_XML_md_EntityDescriptor The DOMEntity which represents the EntityDescriptor. * @throws Exception If the document is empty or the first element is not an EntityDescriptor element. */ private static function findEntityDescriptor($doc) { assert('$doc instanceof DOMDocument'); // find the EntityDescriptor DOMElement. This should be the first (and only) child of the DOMDocument $ed = $doc->documentElement; if ($ed === null) { throw new Exception('Failed to load SAML metadata from empty XML document.'); } if (SimpleSAML\Utils\XML::isDOMElementOfType($ed, 'EntityDescriptor', '@md') === false) { throw new Exception('Expected first element in the metadata document to be an EntityDescriptor element.'); } return new SAML2_XML_md_EntityDescriptor($ed); }
/** * @deprecated This method will be removed in SSP 2.0. Please use SimpleSAML\Utils\XML::formatXMLString() instead. */ public static function formatXMLString($xml, $indentBase = '') { return SimpleSAML\Utils\XML::formatXMLString($xml, $indentBase); }
#!/usr/bin/env php <?php require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/lib/_autoload.php'; if ($argc < 2) { fwrite(STDERR, "Missing aggregator id.\n"); exit(1); } $id = $argv[1]; error_reporting(E_ALL ^ E_NOTICE); try { $aggregator = sspmod_aggregator2_Aggregator::getAggregator($id); $xml = $aggregator->getMetadata(); $xml = SimpleSAML\Utils\XML::formatXMLString($xml); echo $xml; } catch (Exception $e) { fwrite(STDERR, $e->getMessage() . "\n"); }