private function _getComparableXmlString(\DOMNode $node) { if ($node instanceof \DOMDocument) { return $node->C14N(); } $dom = new \DOMDocument(); $dom->appendChild($dom->importNode($node, true)); return $dom->C14N(); }
/** * Test unmarshalling / marshalling of XML with Extensions element */ public function testExtensionOrdering() { $document = new DOMDocument(); $document->loadXML(<<<AUTHNREQUEST <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_306f8ec5b618f361c70b6ffb1480eade" Version="2.0" IssueInstant="2004-12-05T09:21:59Z" Destination="https://idp.example.org/SAML2/SSO/Artifact" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" AssertionConsumerServiceURL="https://sp.example.com/SAML2/SSO/Artifact"> <saml:Issuer>https://sp.example.com/SAML2</saml:Issuer> <samlp:Extensions> <myns:AttributeList xmlns:myns="urn:mynamespace"> <myns:Attribute name="UserName" value=""/> </myns:AttributeList> </samlp:Extensions> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/> </samlp:AuthnRequest> AUTHNREQUEST ); $authnRequest = new SAML2_AuthnRequest($document->documentElement); $this->assertXmlStringEqualsXmlString($document->C14N(), $authnRequest->toUnsignedXML()->C14N()); }
public function testMarshalling() { $fixtureRequestDom = new DOMDocument(); $fixtureRequestDom->loadXML(<<<XML <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_bec424fa5103428909a30ff1e31168327f79474984" Version="2.0" IssueInstant="2007-12-10T11:39:34Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://moodle.bridge.feide.no/simplesaml/saml2/sp/AssertionConsumerService.php"> <saml:Issuer>urn:mace:feide.no:services:no.feide.moodle</saml:Issuer> <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" SPNameQualifier="moodle.bridge.feide.no" AllowCreate="true" /> <samlp:RequestedAuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> </samlp:RequestedAuthnContext> </samlp:AuthnRequest> XML , LIBXML_NOBLANKS); $request = new SAML2_AuthnRequest($fixtureRequestDom->firstChild); $context = $request->getRequestedAuthnContext(); $this->assertEquals('_bec424fa5103428909a30ff1e31168327f79474984', $request->getId()); $this->assertEquals('urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', $context['AuthnContextClassRef'][0]); $requestXml = $requestDocument = $request->toUnsignedXML()->ownerDocument->C14N(); $fixtureXml = $fixtureRequestDom->C14N(); $this->assertXmlStringEqualsXmlString($requestXml, $fixtureXml, 'Request after Unmarshalling and re-marshalling remains the same'); }
protected static function getXMLString($string) { $doc = new DOMDocument(1.0); $doc->preserveWhiteSpace = false; $doc->formatOutput = false; $doc->loadHTML($string); return $doc->C14N(); }
/** * Test building the DOM message to be sent to the token service. */ public function testBuildRequest() { $xmlNs = 'http://schema.gspt.net/token/1.0'; $token = 'abc-123'; $expected = new DOMDocument(); $expected->loadXML(sprintf('<TokenValidateRequest xmlns="%s"><Token>%s</Token></TokenValidateRequest>', $xmlNs, $token)); $cfg = $this->buildCoreConfigRegistry(array('apiXmlNs' => $xmlNs)); $helper = $this->getHelperMock('eb2ccsr/data', array('getConfigModel')); $this->replaceByMock('helper', 'eb2ccsr', $helper); $helper->expects($this->once())->method('getConfigModel')->will($this->returnValue($cfg)); $request = Mage::getModel('eb2ccsr/token_request', array('token' => 'abc-123')); $this->assertSame($expected->C14N(), EcomDev_Utils_Reflection::invokeRestrictedMethod($request, '_buildRequest')->C14N()); }
private function assertXMLEquals($expectXMLFile, $actualXML) { $expectDOM = new DOMDocument(1.0); $expectDOM->formatOutput = false; $expectDOM->preserveWhiteSpace = false; $expectDOM->load($expectXMLFile); $expectXML = $expectDOM->C14N(true, false); $rssDOM = new DOMDocument(1.0); $rssDOM->formatOutput = false; $rssDOM->preserveWhiteSpace = false; $rssDOM->loadXML($actualXML); $rssXML = $rssDOM->C14N(true, false); $this->assertEquals($expectXML, $rssXML); }
/** * Call the API. * * @param DOMDocument $doc The document to send in the request body * @param string $xsdName The basename of the xsd file to validate $doc (The dirname is in config.xml) * @param string $uri The uri to send the request to * @param int $timeout The amount of time in seconds after which the connection is terminated * @param string $adapter The classname of a Zend_Http_Client_Adapter * @param Zend_Http_Client $client * @param string $apiKey Alternate API Key to use * @return string The response from the server */ public function request(DOMDocument $doc, $xsdName, $uri, $timeout = self::DEFAULT_TIMEOUT, $adapter = self::DEFAULT_ADAPTER, Zend_Http_Client $client = null, $apiKey = null) { if (!$apiKey) { $apiKey = Mage::helper('eb2ccore')->getConfigModel()->apiKey; } $xmlStr = $doc->C14N(); $logData = array_merge(['rom_request_body' => $xmlStr], $this->_logAppContext); $logMessage = 'Validating request.'; $this->_logger->debug($logMessage, $this->_context->getMetaData(__CLASS__, $logData)); $this->schemaValidate($doc, $xsdName); $client = $this->_setupClient($client, $apiKey, $uri, $xmlStr, $adapter, $timeout); $logData = array_merge(['rom_request_url' => $uri], $this->_logAppContext); $logMessage = 'Sending request.'; $this->_logger->info($logMessage, $this->_context->getMetaData(__CLASS__, $logData)); try { $response = $client->request(self::DEFAULT_METHOD); return $this->_processResponse($response, $uri); } catch (Zend_Http_Client_Exception $e) { return $this->_processException($e, $uri); } }
public function __toString() { return $this->xml->C14N(); }
/** * Checks XML response does not include provided XML. * Comparison is done by canonicalizing both xml`s. * Parameter can be passed either as XmlBuilder, DOMDocument, DOMNode, XML string, or array (if no attributes). * * @param $xml */ public function dontSeeSoapResponseIncludes($xml) { $xml = $this->canonicalize($xml); \PHPUnit_Framework_Assert::assertNotContains($xml, $this->xmlResponse->C14N(), "found in XML Response"); }
public static function canonicalize($XMLdoc) { $dom = new DOMDocument(); $dom->loadXML($XMLdoc); return $dom->C14N(true, false); }
<?php // This example is from https://github.com/facebook/hhvm/issues/3440 $xml = '<?xml version="1.0"?>' . "\n" . '<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xm' . 'lns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://pro' . 'ject.mysite.com/saml/acs" ID="FIMRSP_5990c800-0147-1411-b087-93da9d684e69" IssueInstant="2014-07-21T15:36:06Z" Ver' . 'sion="2.0"><saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://accessuat.mysite.com/fim/sps' . '/saml20/saml20</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:' . 'Status><saml:Assertion ID="Assertion-uuid5990c7c6-0147-19bd-9537-93da9d684e69" IssueInstant="2014-07-21T15:36:06Z" Versi' . 'on="2.0"><saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://accessuat.mysite.com/fim/sps/s' . 'aml20/saml20</saml:Issuer><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.' . '1:nameid-format:unspecified">testjive</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bear' . 'er"><saml:SubjectConfirmationData NotOnOrAfter="2014-07-21T15:46:06Z" Recipient="https://project.mysite.com/saml/a' . 'cs"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2014-07-21T15:26:06Z" NotOnOrAfter="2014-07-2' . '1T15:46:06Z"><saml:AudienceRestriction><saml:Audience>http://project.mysite.com</saml:Audience></saml:AudienceRest' . 'riction></saml:Conditions><saml:AuthnStatement AuthnInstant="2014-07-21T15:36:06Z" SessionIndex="uuid599090e7-0147-15b6-' . '9dfd-93da9d684e69" SessionNotOnOrAfter="2014-07-21T16:36:06Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:na' . 'mes:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:Attribute' . 'Statement><saml:Attribute Name="LastName" NameFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"><saml:Attri' . 'buteValue xsi:type="xs:string">user</saml:AttributeValue></saml:Attribute><saml:Attribute Name="FirstName" NameFormat="u' . 'rn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"><saml:AttributeValue xsi:type="xs:string">Test</saml:AttributeValu' . 'e></saml:Attribute><saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"><saml' . ':AttributeValue xsi:type="xs:string">idam_support@bp.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name="use' . 'r-id" NameFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"><saml:AttributeValue xsi:type="xs:string">testj' . 'ive</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>'; $doc = new DOMDocument(); $res = $doc->loadXML($xml); $caNode = $doc->C14N(true, false, null, ['xs', 'xsi', 'saml']); echo md5($caNode);
public function testLoop() { $fixtureResponseDom = new DOMDocument(); $fixtureResponseDom->loadXML(<<<XML <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="s2a0da3504aff978b0f8c80f6a62c713c4a2f64c5b" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984" Version="2.0" IssueInstant="2007-12-10T11:39:48Z" Destination="http://moodle.bridge.feide.no/simplesaml/saml2/sp/AssertionConsumerService.php"> <saml:Issuer>max.feide.no</saml:Issuer> <samlp:Extensions> <myns:AttributeList xmlns:myns="urn:mynamespace"> <myns:Attribute name="UserName" value=""/> </myns:AttributeList> </samlp:Extensions> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" Version="2.0" ID="s2b7afe8e21a0910d027dfbc94ec4b862e1fbbd9ab" IssueInstant="2007-12-10T11:39:48Z"> <saml:Issuer>max.feide.no</saml:Issuer> <saml:Subject> <saml:NameID NameQualifier="max.feide.no" SPNameQualifier="urn:mace:feide.no:services:no.feide.moodle" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">UB/WJAaKAPrSHbqlbcKWu7JktcKY</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2007-12-10T19:39:48Z" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984" Recipient="http://moodle.bridge.feide.no/simplesaml/saml2/sp/AssertionConsumerService.php"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2007-12-10T11:29:48Z" NotOnOrAfter="2007-12-10T19:39:48Z"> <saml:AudienceRestriction> <saml:Audience>urn:mace:feide.no:services:no.feide.moodle</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2007-12-10T11:39:48Z" SessionIndex="s259fad9cad0cf7d2b3b68f42b17d0cfa6668e0201"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="givenName"> <saml:AttributeValue xsi:type="xs:string">RkVJREUgVGVzdCBVc2VyIChnaXZlbk5hbWUpIMO4w6bDpcOYw4bDhQ==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="eduPersonPrincipalName"> <saml:AttributeValue xsi:type="xs:string">dGVzdEBmZWlkZS5ubw==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="o"> <saml:AttributeValue xsi:type="xs:string">VU5JTkVUVA==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="ou"> <saml:AttributeValue xsi:type="xs:string">VU5JTkVUVA==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="eduPersonOrgDN"> <saml:AttributeValue xsi:type="xs:string">ZGM9dW5pbmV0dCxkYz1ubw==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="eduPersonPrimaryAffiliation"> <saml:AttributeValue xsi:type="xs:string">c3R1ZGVudA==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="mail"> <saml:AttributeValue xsi:type="xs:string">bW9yaWEtc3VwcG9ydEB1bmluZXR0Lm5v</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="preferredLanguage"> <saml:AttributeValue xsi:type="xs:string">bm8=</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="eduPersonOrgUnitDN"> <saml:AttributeValue xsi:type="xs:string">b3U9dW5pbmV0dCxvdT1vcmdhbml6YXRpb24sZGM9dW5pbmV0dCxkYz1ubw==</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="sn"> <saml:AttributeValue xsi:type="xs:string">RkVJREUgVGVzdCBVc2VyIChzbikgw7jDpsOlw5jDhsOF</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="cn"> <saml:AttributeValue xsi:type="xs:string">RkVJREUgVGVzdCBVc2VyIChjbikgw7jDpsOlw5jDhsOF</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="eduPersonAffiliation"> <saml:AttributeValue xsi:type="xs:string">ZW1wbG95ZWU=_c3RhZmY=_c3R1ZGVudA==</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response> XML ); $request = new SAML2_Response($fixtureResponseDom->firstChild); $requestXml = $requestDocument = $request->toUnsignedXML()->ownerDocument->C14N(); $fixtureXml = $fixtureResponseDom->C14N(); $this->assertXmlStringEqualsXmlString($fixtureXml, $requestXml, 'Response after Unmarshalling and re-marshalling remains the same'); }
function minify() { $target = $this->target; $minifiedJS = $target['library.js']->content; $minifiedJS = preg_replace('~^\\s+~m', '', $minifiedJS); $minifiedJS = preg_replace('~^//.*$\\n~m', '', $minifiedJS); $minifiedJS = preg_replace('~\\n/\\*[\\w\\W]*?\\*/~', '', $minifiedJS); $minifiedCSS = $target['release.css']->content; $minifiedCSS = preg_replace('~/\\*[\\w\\W]*?\\*/~', '', $minifiedCSS); $minifiedCSS = preg_replace('~^\\s+~m', '', $minifiedCSS); $minifiedCSS = preg_replace('~[\\r\\n]~', '', $minifiedCSS); $minifiedXSL = null; if ($target['release.xsl']->exists) { $minifiedXSL = $target['release.xsl']->content; $doc = new \DOMDocument(); $doc->formatOutput = false; $doc->preserveWhiteSpace = false; $doc->loadXML((string) $minifiedXSL); $minifiedXSL = $doc->C14N(); } $minifiedPHP = $target['release.php']->content; if ($minifiedJS) { $target['minified.js']->content = $minifiedJS; } if ($minifiedCSS) { $target['minified.css']->content = $minifiedCSS; } if ($minifiedXSL) { $target['minified.xsl']->content = so_dom::make($minifiedXSL); } if ($minifiedPHP) { $target['minified.php']->content = $minifiedPHP; } return $this; }
<?php $doc = new DOMDocument(); var_dump($doc->C14N());
protected function _verifySignatureXMLElement($publicKey, $xml, $element) { if (!isset($element['ds:Signature'])) { throw new Corto_Module_Bindings_Exception("Element is not signed! " . $xml); } $document = new DOMDocument(); $document->loadXML($xml); $xp = new DomXPath($document); $xp->registerNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#'); foreach ($element['ds:Signature']['ds:SignedInfo']['ds:Reference'] as $reference) { $referencedUri = $reference['_URI']; if (strpos($referencedUri, '#') !== 0) { throw new Corto_Module_Bindings_Exception("Unsupported use of URI Reference, I only know XPointers: " . $xml); } $referencedId = substr($referencedUri, 1); $xpathResults = $xp->query("//*[@ID = '{$referencedId}']"); if ($xpathResults->length === 0) { throw new Corto_Module_Bindings_Exception("URI Reference, not found? " . $xml); } if ($xpathResults->length > 1) { throw new Corto_Module_Bindings_Exception("Multiple nodes found for URI Reference? " . $xml); } $referencedElement = $xpathResults->item(0); $referencedDocument = new DomDocument(); $importedNode = $referencedDocument->importNode($referencedElement->cloneNode(true), true); $referencedDocument->appendChild($importedNode); $referencedDocumentXml = $referencedDocument->saveXML(); // First process any transforms if (isset($reference['ds:Transforms']['ds:Transform'])) { foreach ($reference['ds:Transforms']['ds:Transform'] as $transform) { switch ($transform['_Algorithm']) { case 'http://www.w3.org/2000/09/xmldsig#enveloped-signature': $transformDocument = new DOMDocument(); $transformDocument->loadXML($referencedDocumentXml); $transformXpath = new DomXPath($transformDocument); $transformXpath->registerNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#'); $signature = $transformXpath->query(".//ds:Signature", $transformDocument)->item(0); $signature->parentNode->removeChild($signature); $referencedDocumentXml = $transformDocument->saveXML(); break; case 'http://www.w3.org/2001/10/xml-exc-c14n#': $nsPrefixes = array(); if (isset($transform['ec:InclusiveNamespaces']['_PrefixList'])) { $nsPrefixes = explode(' ', $transform['ec:InclusiveNamespaces']['_PrefixList']); } $transformDocument = new DOMDocument(); $transformDocument->loadXML($referencedDocumentXml); $referencedDocumentXml = $transformDocument->C14N(true, false, null, $nsPrefixes); break; default: throw new Corto_Module_Bindings_Exception("Unsupported transform " . $transform['_Algorithm'] . ' on XML: ' . $xml); } } } // Verify the digest over the (transformed) element if ($reference['ds:DigestMethod']['_Algorithm'] !== 'http://www.w3.org/2000/09/xmldsig#sha1') { throw new Corto_Module_Bindings_Exception("Unsupported DigestMethod " . $reference['ds:DigestMethod']['_Algorithm'] . ' on XML: ' . $xml); } $ourDigest = sha1($referencedDocumentXml, TRUE); $theirDigest = base64_decode($reference['ds:DigestValue']['__v']); if ($ourDigest !== $theirDigest) { throw new Corto_Module_Bindings_Exception("Digests do not match! on XML: " . $xml); } } // Verify the signature over the SignedInfo (not over the entire document, only over the digest) $c14Algorithm = $element['ds:Signature']['ds:SignedInfo']['ds:CanonicalizationMethod']['_Algorithm']; if ($c14Algorithm !== 'http://www.w3.org/2001/10/xml-exc-c14n#') { throw new Corto_Module_Bindings_Exception("Unsupported CanonicalizationMethod '{$c14Algorithm}' on XML: {$xml}"); } if (!isset($element['ds:Signature']['ds:SignatureValue']['__v'])) { throw new Corto_Module_Bindings_Exception("No sigurature value found on element? " . var_export($element, true)); } $signatureAlgorithm = $element['ds:Signature']['ds:SignedInfo']['ds:SignatureMethod']['_Algorithm']; if ($signatureAlgorithm !== "http://www.w3.org/2000/09/xmldsig#rsa-sha1") { throw new Corto_Module_Bindings_Exception("Unsupported SignatureMethod '{$signatureAlgorithm}' on XML: {$xml}"); } // Find the signed element (like an assertion) in the global document (like a response) $id = $element['_ID']; $signedElement = $xp->query("//*[@ID = '{$id}']")->item(0); $signedInfoNode = $xp->query(".//ds:SignedInfo", $signedElement)->item(0); $signedInfoXml = $signedInfoNode->C14N(true, false); $signatureValue = $element['ds:Signature']['ds:SignatureValue']['__v']; $signatureValue = base64_decode($signatureValue); return openssl_verify($signedInfoXml, $signatureValue, $publicKey) == 1; }