diff --git a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php index 30ddf25ae196ec9c8b5407ef83ae112aa5306829..635fd05dad4edcce5130e91ddbda15c933b4deb5 100644 --- a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php +++ b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php @@ -80,7 +80,7 @@ class SimpleSAML_Bindings_Shib13_HTTPPost $signResponse = true; } - $signer = new SimpleSAML_XML_Signer(array( + $signer = new \SimpleSAML\XML\Signer(array( 'privatekey_array' => $privatekey, 'publickey_array' => $publickey, 'id' => ($signResponse ? 'ResponseID' : 'AssertionID'), @@ -117,7 +117,7 @@ class SimpleSAML_Bindings_Shib13_HTTPPost * * @param array $post POST data received. * - * @return SimpleSAML_XML_Shib13_AuthnResponse The response decoded into an object. + * @return \SimpleSAML\XML\Shib13\AuthnResponse The response decoded into an object. * * @throws Exception If there is no SAMLResponse parameter. */ @@ -135,7 +135,7 @@ class SimpleSAML_Bindings_Shib13_HTTPPost \SimpleSAML\Utils\XML::checkSAMLMessage($samlResponseXML, 'saml11'); - $samlResponse = new SimpleSAML_XML_Shib13_AuthnResponse(); + $samlResponse = new \SimpleSAML\XML\Shib13\AuthnResponse(); $samlResponse->setXML($samlResponseXML); if (array_key_exists('TARGET', $post)) { diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php index e9cda0ae60db538cb8915ce804badbd53e505ae5..fd8f04e78b52b3f361a2cf42703357fd822c81eb 100644 --- a/lib/SimpleSAML/Utilities.php +++ b/lib/SimpleSAML/Utilities.php @@ -583,7 +583,7 @@ class SimpleSAML_Utilities */ public static function validateCA($certificate, $caFile) { - SimpleSAML_XML_Validator::validateCertificate($certificate, $caFile); + \SimpleSAML\XML\Validator::validateCertificate($certificate, $caFile); } diff --git a/lib/SimpleSAML/Utils/XML.php b/lib/SimpleSAML/Utils/XML.php index abaa00543cfd2aa433a6472a0fc5b5c4066a205f..8a8acd7daf5bd0051157fa3b7b92c39f1301acde 100644 --- a/lib/SimpleSAML/Utils/XML.php +++ b/lib/SimpleSAML/Utils/XML.php @@ -8,6 +8,7 @@ namespace SimpleSAML\Utils; use SimpleSAML\Logger; +use SimpleSAML\XML\Errors; class XML { @@ -409,7 +410,7 @@ class XML throw new \InvalidArgumentException('Invalid input parameters.'); } - \SimpleSAML_XML_Errors::begin(); + Errors::begin(); if ($xml instanceof \DOMDocument) { $dom = $xml; @@ -431,7 +432,7 @@ class XML $res = $dom->schemaValidate($schemaFile); if ($res) { - \SimpleSAML_XML_Errors::end(); + Errors::end(); return true; } @@ -440,8 +441,8 @@ class XML $errorText = "Failed to parse XML string for schema validation:\n"; } - $errors = \SimpleSAML_XML_Errors::end(); - $errorText .= \SimpleSAML_XML_Errors::formatErrors($errors); + $errors = Errors::end(); + $errorText .= Errors::formatErrors($errors); return $errorText; } diff --git a/lib/SimpleSAML/XML/Errors.php b/lib/SimpleSAML/XML/Errors.php index c56d95b74b8ec8679f1c2a78aac349d6f06ed609..a6d14dd9ff97c2d115cc1bff185b52eaad3d0f2c 100644 --- a/lib/SimpleSAML/XML/Errors.php +++ b/lib/SimpleSAML/XML/Errors.php @@ -9,7 +9,10 @@ * @author Olav Morken, UNINETT AS. * @package SimpleSAMLphp */ -class SimpleSAML_XML_Errors { + +namespace SimpleSAML\XML; + +class Errors { /** * This is an stack of error logs. The topmost element is the one we are @@ -68,7 +71,7 @@ class SimpleSAML_XML_Errors { /** * End error logging. * - * @return An array with the LibXMLErrors which has occurred since begin() was called. + * @return array An array with the LibXMLErrors which has occurred since begin() was called. */ public static function end() { @@ -98,8 +101,8 @@ class SimpleSAML_XML_Errors { * * This function formats the given LibXMLError object as a string. * - * @param $error The LibXMLError which should be formatted. - * @return A string representing the given LibXMLError. + * @param $error \LibXMLError The LibXMLError which should be formatted. + * @return string A string representing the given LibXMLError. */ public static function formatError($error) { assert('$error instanceof LibXMLError'); @@ -114,8 +117,8 @@ class SimpleSAML_XML_Errors { * This fucntion takes an array of LibXMLError objects and creates a string with all the errors. * Each error will be separated by a newline, and the string will end with a newline-character. * - * @param $errors An array of errors. - * @return A string representing the errors. An empty string will be returned if there were no + * @param $errors array An array of errors. + * @return string A string representing the errors. An empty string will be returned if there were no * errors in the array. */ public static function formatErrors($errors) { diff --git a/lib/SimpleSAML/XML/Parser.php b/lib/SimpleSAML/XML/Parser.php index 42b4731b9de159f75d8c4b3817e64a7183556f7d..d36beb4fde9e446dbbfb2c8d2d1dedde8ad9675f 100644 --- a/lib/SimpleSAML/XML/Parser.php +++ b/lib/SimpleSAML/XML/Parser.php @@ -6,19 +6,22 @@ * @author Andreas Ă…kre Solberg, UNINETT AS. <andreas.solberg@uninett.no> * @package SimpleSAMLphp */ -class SimpleSAML_XML_Parser { + +namespace SimpleSAML\XML; + +class Parser { var $simplexml = null; function __construct($xml) {; - $this->simplexml = new SimpleXMLElement($xml); + $this->simplexml = new \SimpleXMLElement($xml); $this->simplexml->registerXPathNamespace('saml2', 'urn:oasis:names:tc:SAML:2.0:assertion'); $this->simplexml->registerXPathNamespace('saml2meta', 'urn:oasis:names:tc:SAML:2.0:metadata'); $this->simplexml->registerXPathNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#'); } - public static function fromSimpleXMLElement(SimpleXMLElement $element) { + public static function fromSimpleXMLElement(\SimpleXMLElement $element) { // Traverse all existing namespaces in element $namespaces = $element->getNamespaces(); @@ -29,7 +32,7 @@ class SimpleSAML_XML_Parser { /* Create a new parser with the xml document where the namespace definitions * are added. */ - $parser = new SimpleSAML_XML_Parser($element->asXML()); + $parser = new Parser($element->asXML()); return $parser; } @@ -37,7 +40,7 @@ class SimpleSAML_XML_Parser { public function getValueDefault($xpath, $defvalue) { try { return $this->getValue($xpath, true); - } catch (Exception $e) { + } catch (\Exception $e) { return $defvalue; } } @@ -46,7 +49,7 @@ class SimpleSAML_XML_Parser { $result = $this->simplexml->xpath($xpath); if (! $result or !is_array($result)) { - if ($required) throw new Exception('Could not get value from XML document using the following XPath expression: ' . $xpath); + if ($required) throw new \Exception('Could not get value from XML document using the following XPath expression: ' . $xpath); else return null; } return (string) $result[0]; @@ -57,7 +60,7 @@ class SimpleSAML_XML_Parser { $seek = $this->getValue($x); if ($seek) return $seek; } - if ($required) throw new Exception('Could not get value from XML document using multiple alternative XPath expressions.'); + if ($required) throw new \Exception('Could not get value from XML document using multiple alternative XPath expressions.'); else return null; } diff --git a/lib/SimpleSAML/XML/Shib13/AuthnRequest.php b/lib/SimpleSAML/XML/Shib13/AuthnRequest.php index aaecb2e9f75b6ed54b625afcd0dfd3375f42d235..47fecc60e171837e1e959ddcce9d0378fc5d88c2 100644 --- a/lib/SimpleSAML/XML/Shib13/AuthnRequest.php +++ b/lib/SimpleSAML/XML/Shib13/AuthnRequest.php @@ -7,7 +7,10 @@ * @author Andreas Ă…kre Solberg, UNINETT AS. <andreas.solberg@uninett.no> * @package SimpleSAMLphp */ -class SimpleSAML_XML_Shib13_AuthnRequest { + +namespace SimpleSAML\XML\Shib13; + +class AuthnRequest { private $issuer = null; private $relayState = null; @@ -28,7 +31,7 @@ class SimpleSAML_XML_Shib13_AuthnRequest { } public function createRedirect($destination, $shire) { - $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); + $metadata = \SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpmetadata = $metadata->getMetaDataConfig($destination, 'shib13-idp-remote'); $desturl = $idpmetadata->getDefaultEndpoint('SingleSignOnService', array('urn:mace:shibboleth:1.0:profiles:AuthnRequest')); diff --git a/lib/SimpleSAML/XML/Shib13/AuthnResponse.php b/lib/SimpleSAML/XML/Shib13/AuthnResponse.php index ce0dbaa4e9161100f7426bfe5ce45e1959f1a623..17ae3b90baafc1f4904a97a68a452ff57c98aa43 100644 --- a/lib/SimpleSAML/XML/Shib13/AuthnResponse.php +++ b/lib/SimpleSAML/XML/Shib13/AuthnResponse.php @@ -6,12 +6,23 @@ * @author Andreas Ă…kre Solberg, UNINETT AS. <andreas.solberg@uninett.no> * @package SimpleSAMLphp */ -class SimpleSAML_XML_Shib13_AuthnResponse { + +namespace SimpleSAML\XML\Shib13; + + +use SAML2\DOMDocumentFactory; +use SAML2\Utils; +use SimpleSAML\Utils\Config; +use SimpleSAML\Utils\Random; +use SimpleSAML\Utils\Time; +use SimpleSAML\XML\Validator; + +class AuthnResponse { /** - * This variable contains an XML validator for this message. + * @var Validator This variable contains an XML validator for this message. */ - private $validator = null; + private $validator = null; /** @@ -29,7 +40,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { /** * The DOMDocument which represents this message. * - * @var DOMDocument + * @var \DOMDocument */ private $dom; @@ -57,9 +68,9 @@ class SimpleSAML_XML_Shib13_AuthnResponse { assert('is_string($xml)'); try { - $this->dom = \SAML2\DOMDocumentFactory::fromString(str_replace ("\r", "", $xml)); + $this->dom = DOMDocumentFactory::fromString(str_replace ("\r", "", $xml)); } catch(\Exception $e) { - throw new Exception('Unable to parse AuthnResponse XML.'); + throw new \Exception('Unable to parse AuthnResponse XML.'); } } @@ -80,13 +91,13 @@ class SimpleSAML_XML_Shib13_AuthnResponse { } // Validate the signature - $this->validator = new SimpleSAML_XML_Validator($this->dom, array('ResponseID', 'AssertionID')); + $this->validator = new Validator($this->dom, array('ResponseID', 'AssertionID')); // Get the issuer of the response $issuer = $this->getIssuer(); // Get the metadata of the issuer - $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); + $metadata = \SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $md = $metadata->getMetaDataConfig($issuer, 'shib13-idp-remote'); $publicKeys = $md->getPublicKeys('signing'); @@ -106,9 +117,9 @@ class SimpleSAML_XML_Shib13_AuthnResponse { $this->validator->validateFingerprint($certFingerprints); } elseif ($md->hasValue('caFile')) { // Validate against CA - $this->validator->validateCA(\SimpleSAML\Utils\Config::getCertPath($md->getString('caFile'))); + $this->validator->validateCA(Config::getCertPath($md->getString('caFile'))); } else { - throw new SimpleSAML_Error_Exception('Missing certificate in Shibboleth 1.3 IdP Remote metadata for identity provider [' . $issuer . '].'); + throw new \SimpleSAML_Error_Exception('Missing certificate in Shibboleth 1.3 IdP Remote metadata for identity provider [' . $issuer . '].'); } return true; @@ -132,7 +143,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { } // Convert the node to a DOM node if it is an element from SimpleXML - if($node instanceof SimpleXMLElement) { + if($node instanceof \SimpleXMLElement) { $node = dom_import_simplexml($node); } @@ -142,13 +153,14 @@ class SimpleSAML_XML_Shib13_AuthnResponse { } - /** - * This function runs an xPath query on this authentication response. - * - * @param $query The query which should be run. - * @param $node The node which this query is relative to. If this node is NULL (the default) - * then the query will be relative to the root of the response. - */ + /** + * This function runs an xPath query on this authentication response. + * + * @param $query string The query which should be run. + * @param $node \DOMNode The node which this query is relative to. If this node is NULL (the default) + * then the query will be relative to the root of the response. + * @return \DOMNodeList + */ private function doXPathQuery($query, $node = NULL) { assert('is_string($query)'); assert('$this->dom instanceof DOMDocument'); @@ -159,7 +171,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { assert('$node instanceof DOMNode'); - $xPath = new DOMXpath($this->dom); + $xPath = new \DOMXpath($this->dom); $xPath->registerNamespace('shibp', self::SHIB_PROTOCOL_NS); $xPath->registerNamespace('shib', self::SHIB_ASSERT_NS); @@ -186,11 +198,11 @@ class SimpleSAML_XML_Shib13_AuthnResponse { public function getAttributes() { - $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); + $metadata = \SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $md = $metadata->getMetadata($this->getIssuer(), 'shib13-idp-remote'); $base64 = isset($md['base64attributes']) ? $md['base64attributes'] : false; - if (! ($this->dom instanceof DOMDocument) ) { + if (! ($this->dom instanceof \DOMDocument) ) { return array(); } @@ -201,7 +213,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { foreach ($assertions AS $assertion) { if(!$this->isNodeValidated($assertion)) { - throw new Exception('Shib13 AuthnResponse contained an unsigned assertion.'); + throw new \Exception('Shib13 AuthnResponse contained an unsigned assertion.'); } $conditions = $this->doXPathQuery('shib:Conditions', $assertion); @@ -220,6 +232,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { } $attribute_nodes = $this->doXPathQuery('shib:AttributeStatement/shib:Attribute/shib:AttributeValue', $assertion); + /** @var \DOMElement $attribute */ foreach($attribute_nodes as $attribute) { $value = $attribute->textContent; @@ -232,7 +245,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { } if(!is_string($name)) { - throw new Exception('Shib13 Attribute node without an AttributeName.'); + throw new \Exception('Shib13 Attribute node without an AttributeName.'); } if(!array_key_exists($name, $attributes)) { @@ -260,9 +273,9 @@ class SimpleSAML_XML_Shib13_AuthnResponse { $nodelist = $this->doXPathQuery($query); if ($attr = $nodelist->item(0)) { - return $attr->value; + return $attr->nodeValue; } else { - throw new Exception('Could not find Issuer field in Authentication response'); + throw new \Exception('Could not find Issuer field in Authentication response'); } } @@ -283,16 +296,16 @@ class SimpleSAML_XML_Shib13_AuthnResponse { } - /** - * Build a authentication response. - * - * @param array $idp Metadata for the IdP the response is sent from. - * @param array $sp Metadata for the SP the response is sent to. - * @param string $shire The endpoint on the SP the response is sent to. - * @param array|NULL $attributes The attributes which should be included in the response. - * @return string The response. - */ - public function generate(SimpleSAML_Configuration $idp, SimpleSAML_Configuration $sp, $shire, $attributes) { + /** + * Build a authentication response. + * + * @param $idp \SimpleSAML_Configuration Metadata for the IdP the response is sent from. + * @param $sp \SimpleSAML_Configuration Metadata for the SP the response is sent to. + * @param string $shire The endpoint on the SP the response is sent to. + * @param array|NULL $attributes The attributes which should be included in the response. + * @return string The response. + */ + public function generate(\SimpleSAML_Configuration $idp, \SimpleSAML_Configuration $sp, $shire, $attributes) { assert('is_string($shire)'); assert('$attributes === NULL || is_array($attributes)'); @@ -304,16 +317,16 @@ class SimpleSAML_XML_Shib13_AuthnResponse { $scopedAttributes = array(); } - $id = SimpleSAML\Utils\Random::generateID(); + $id = Random::generateID(); - $issueInstant = SimpleSAML\Utils\Time::generateTimestamp(); + $issueInstant = Time::generateTimestamp(); // 30 seconds timeskew back in time to allow differing clocks - $notBefore = SimpleSAML\Utils\Time::generateTimestamp(time() - 30); + $notBefore = Time::generateTimestamp(time() - 30); - $assertionExpire = SimpleSAML\Utils\Time::generateTimestamp(time() + 60 * 5);# 5 minutes - $assertionid = SimpleSAML\Utils\Random::generateID(); + $assertionExpire = Time::generateTimestamp(time() + 60 * 5);# 5 minutes + $assertionid = Random::generateID(); $spEntityId = $sp->getString('entityid'); @@ -321,7 +334,7 @@ class SimpleSAML_XML_Shib13_AuthnResponse { $base64 = $sp->getBoolean('base64attributes', FALSE); $namequalifier = $sp->getString('NameQualifier', $spEntityId); - $nameid = SimpleSAML\Utils\Random::generateID(); + $nameid = Random::generateID(); $subjectNode = '<Subject>' . '<NameIdentifier' . @@ -449,14 +462,14 @@ class SimpleSAML_XML_Shib13_AuthnResponse { $currentTime = time(); if (!empty($start)) { - $startTime = \SAML2\Utils::xsDateTimeToTimestamp($start); + $startTime = Utils::xsDateTimeToTimestamp($start); // allow for a 10 minute difference in time if (($startTime < 0) || (($startTime - 600) > $currentTime)) { return false; } } if (!empty($end)) { - $endTime = \SAML2\Utils::xsDateTimeToTimestamp($end); + $endTime = Utils::xsDateTimeToTimestamp($end); if (($endTime < 0) || ($endTime <= $currentTime)) { return false; } diff --git a/lib/SimpleSAML/XML/Signer.php b/lib/SimpleSAML/XML/Signer.php index 04f176c3d56d7532966f36e8470753f023cfbcde..9e5622bab38b0f19b24055c478947e605d8ecfb3 100644 --- a/lib/SimpleSAML/XML/Signer.php +++ b/lib/SimpleSAML/XML/Signer.php @@ -8,27 +8,34 @@ * @author Olav Morken, UNINETT AS. * @package SimpleSAMLphp */ -class SimpleSAML_XML_Signer { + +namespace SimpleSAML\XML; + +use RobRichards\XMLSecLibs\XMLSecurityDSig; +use RobRichards\XMLSecLibs\XMLSecurityKey; +use SimpleSAML\Utils\Config; + +class Signer { /** - * The name of the ID attribute. + * @var string The name of the ID attribute. */ private $idAttrName; - /** - * The private key (as an XMLSecurityKey). - */ + /** + * @var XMLSecurityKey|bool The private key (as an XMLSecurityKey). + */ private $privateKey; /** - * The certificate (as text). + * @var string The certificate (as text). */ private $certificate; /** - * Extra certificates which should be included in the response. + * @var string Extra certificates which should be included in the response. */ private $extraCertificates; @@ -47,7 +54,7 @@ class SimpleSAML_XML_Signer { * - publickey_array The public key, as an array returned from SimpleSAML_Utilities::loadPublicKey. * - id The name of the ID attribute. * - * @param $options Associative array with options for the constructor. Defaults to an empty array. + * @param $options array Associative array with options for the constructor. Defaults to an empty array. */ public function __construct($options = array()) { assert('is_array($options)'); @@ -104,26 +111,28 @@ class SimpleSAML_XML_Signer { } - /** - * Set the private key. - * - * Will throw an exception if unable to load the private key. - * - * @param $file The file which contains the private key. The path is assumed to be relative - * to the cert-directory. - * @param $pass The passphrase on the private key. Pass no value or NULL if the private key is unencrypted. - */ + /** + * Set the private key. + * + * Will throw an exception if unable to load the private key. + * + * @param $file string The file which contains the private key. The path is assumed to be relative + * to the cert-directory. + * @param $pass string|null The passphrase on the private key. Pass no value or NULL if the private + * key is unencrypted. + * @throws \Exception + */ public function loadPrivateKey($file, $pass = NULL) { assert('is_string($file)'); assert('is_string($pass) || is_null($pass)'); - $keyFile = \SimpleSAML\Utils\Config::getCertPath($file); + $keyFile = Config::getCertPath($file); if (!file_exists($keyFile)) { - throw new Exception('Could not find private key file "' . $keyFile . '".'); + throw new \Exception('Could not find private key file "' . $keyFile . '".'); } $keyData = file_get_contents($keyFile); if($keyData === FALSE) { - throw new Exception('Unable to read private key file "' . $keyFile . '".'); + throw new \Exception('Unable to read private key file "' . $keyFile . '".'); } $privatekey = array('PEM' => $keyData); @@ -134,20 +143,21 @@ class SimpleSAML_XML_Signer { } - /** - * Set the public key / certificate we should include in the signature. - * - * This function loads the public key from an array matching what is returned - * by SimpleSAML_Utilities::loadPublicKey(...). - * - * @param array $publickey The public key. - */ + /** + * Set the public key / certificate we should include in the signature. + * + * This function loads the public key from an array matching what is returned + * by SimpleSAML_Utilities::loadPublicKey(...). + * + * @param array $publickey The public key. + * @throws \Exception + */ public function loadPublicKeyArray($publickey) { assert('is_array($publickey)'); if (!array_key_exists('PEM', $publickey)) { // We have a public key with only a fingerprint - throw new Exception('Tried to add a certificate fingerprint in a signature.'); + throw new \Exception('Tried to add a certificate fingerprint in a signature.'); } // For now, we only assume that the public key is an X509 certificate @@ -155,26 +165,27 @@ class SimpleSAML_XML_Signer { } - /** - * Set the certificate we should include in the signature. - * - * If this function isn't called, no certificate will be included. - * Will throw an exception if unable to load the certificate. - * - * @param $file The file which contains the certificate. The path is assumed to be relative to - * the cert-directory. - */ + /** + * Set the certificate we should include in the signature. + * + * If this function isn't called, no certificate will be included. + * Will throw an exception if unable to load the certificate. + * + * @param $file string The file which contains the certificate. The path is assumed to be relative to + * the cert-directory. + * @throws \Exception + */ public function loadCertificate($file) { assert('is_string($file)'); - $certFile = \SimpleSAML\Utils\Config::getCertPath($file); + $certFile = Config::getCertPath($file); if (!file_exists($certFile)) { - throw new Exception('Could not find certificate file "' . $certFile . '".'); + throw new \Exception('Could not find certificate file "' . $certFile . '".'); } $this->certificate = file_get_contents($certFile); if($this->certificate === FALSE) { - throw new Exception('Unable to read certificate file "' . $certFile . '".'); + throw new \Exception('Unable to read certificate file "' . $certFile . '".'); } } @@ -182,7 +193,7 @@ class SimpleSAML_XML_Signer { /** * Set the attribute name for the ID value. * - * @param $idAttrName The name of the attribute which contains the id. + * @param $idAttrName string The name of the attribute which contains the id. */ public function setIDAttribute($idAttrName) { assert('is_string($idAttrName)'); @@ -191,42 +202,44 @@ class SimpleSAML_XML_Signer { } - /** - * Add an extra certificate to the certificate chain in the signature. - * - * Extra certificates will be added to the certificate chain in the order they - * are added. - * - * @param $file The file which contains the certificate, relative to the cert-directory. - */ + /** + * Add an extra certificate to the certificate chain in the signature. + * + * Extra certificates will be added to the certificate chain in the order they + * are added. + * + * @param $file string The file which contains the certificate, relative to the cert-directory. + * @throws \Exception + */ public function addCertificate($file) { assert('is_string($file)'); - $certFile = \SimpleSAML\Utils\Config::getCertPath($file); + $certFile = Config::getCertPath($file); if (!file_exists($certFile)) { - throw new Exception('Could not find extra certificate file "' . $certFile . '".'); + throw new \Exception('Could not find extra certificate file "' . $certFile . '".'); } $certificate = file_get_contents($certFile); if($certificate === FALSE) { - throw new Exception('Unable to read extra certificate file "' . $certFile . '".'); + throw new \Exception('Unable to read extra certificate file "' . $certFile . '".'); } $this->extraCertificates[] = $certificate; } - /** - * Signs the given DOMElement and inserts the signature at the given position. - * - * The private key must be set before calling this function. - * - * @param $node The DOMElement we should generate a signature for. - * @param $insertInto The DOMElement we should insert the signature element into. - * @param $insertBefore The element we should insert the signature element before. Defaults to NULL, - * in which case the signature will be appended to the element spesified in - * $insertInto. - */ + /** + * Signs the given DOMElement and inserts the signature at the given position. + * + * The private key must be set before calling this function. + * + * @param $node \DOMElement The DOMElement we should generate a signature for. + * @param $insertInto \DOMElement The DOMElement we should insert the signature element into. + * @param $insertBefore \DOMElement The element we should insert the signature element before. Defaults to NULL, + * in which case the signature will be appended to the element spesified in + * $insertInto. + * @throws \Exception + */ public function sign($node, $insertInto, $insertBefore = NULL) { assert('$node instanceof DOMElement'); assert('$insertInto instanceof DOMElement'); @@ -234,7 +247,7 @@ class SimpleSAML_XML_Signer { '|| $insertBefore instanceof DOMComment || $insertBefore instanceof DOMText'); if($this->privateKey === FALSE) { - throw new Exception('Private key not set.'); + throw new \Exception('Private key not set.'); } diff --git a/lib/SimpleSAML/XML/Validator.php b/lib/SimpleSAML/XML/Validator.php index be283c0775adf99e214971e93896283ae5e48f65..c04067bbe7c022ad5bdc34a4ae07dadbbc595b5b 100644 --- a/lib/SimpleSAML/XML/Validator.php +++ b/lib/SimpleSAML/XML/Validator.php @@ -6,7 +6,14 @@ * @author Olav Morken, UNINETT AS. * @package SimpleSAMLphp */ -class SimpleSAML_XML_Validator { + +namespace SimpleSAML\XML; + +use RobRichards\XMLSecLibs\XMLSecEnc; +use RobRichards\XMLSecLibs\XMLSecurityDSig; +use SimpleSAML\Logger; + +class Validator { /** * This variable contains the X509 certificate the XML document @@ -20,25 +27,26 @@ class SimpleSAML_XML_Validator { private $validNodes = null; - /** - * This function initializes the validator. - * - * This function accepts an optional parameter $publickey, which is the public key - * or certificate which should be used to validate the signature. This parameter can - * take the following values: - * - NULL/FALSE: No validation will be performed. This is the default. - * - A string: Assumed to be a PEM-encoded certificate / public key. - * - An array: Assumed to be an array returned by SimpleSAML_Utilities::loadPublicKey. - * - * @param DOMNode $xmlNode The XML node which contains the Signature element. - * @param string|array $idAttribute The ID attribute which is used in node references. If - * this attribute is NULL (the default), then we will use whatever is the default - * ID. Can be eigther a string with one value, or an array with multiple ID - * attrbute names. - * @param array $publickey The public key / certificate which should be used to validate the XML node. - */ + /** + * This function initializes the validator. + * + * This function accepts an optional parameter $publickey, which is the public key + * or certificate which should be used to validate the signature. This parameter can + * take the following values: + * - NULL/FALSE: No validation will be performed. This is the default. + * - A string: Assumed to be a PEM-encoded certificate / public key. + * - An array: Assumed to be an array returned by SimpleSAML_Utilities::loadPublicKey. + * + * @param \DOMNode $xmlNode The XML node which contains the Signature element. + * @param string|array $idAttribute The ID attribute which is used in node references. If + * this attribute is NULL (the default), then we will use whatever is the default + * ID. Can be eigther a string with one value, or an array with multiple ID + * attrbute names. + * @param array|bool $publickey The public key / certificate which should be used to validate the XML node. + * @throws \Exception + */ public function __construct($xmlNode, $idAttribute = NULL, $publickey = FALSE) { - assert('$xmlNode instanceof DOMNode'); + assert('$xmlNode instanceof \DOMNode'); if ($publickey === NULL) { $publickey = FALSE; @@ -66,7 +74,7 @@ class SimpleSAML_XML_Validator { // Locate the XMLDSig Signature element to be used $signatureElement = $objXMLSecDSig->locateSignature($xmlNode); if (!$signatureElement) { - throw new Exception('Could not locate XML Signature element.'); + throw new \Exception('Could not locate XML Signature element.'); } // Canonicalize the XMLDSig SignedInfo element in the message @@ -74,14 +82,14 @@ class SimpleSAML_XML_Validator { // Validate referenced xml nodes if (!$objXMLSecDSig->validateReference()) { - throw new Exception('XMLsec: digest validation failed'); + throw new \Exception('XMLsec: digest validation failed'); } // Find the key used to sign the document $objKey = $objXMLSecDSig->locateKey(); if (empty($objKey)) { - throw new Exception('Error loading key to handle XML signature'); + throw new \Exception('Error loading key to handle XML signature'); } // Load the key data @@ -92,7 +100,7 @@ class SimpleSAML_XML_Validator { // No PEM data. Search for key in signature if (!XMLSecEnc::staticLocateKeyInfo($objKey, $signatureElement)) { - throw new Exception('Error finding key data for XML signature validation.'); + throw new \Exception('Error finding key data for XML signature validation.'); } if ($publickey !== FALSE) { @@ -105,7 +113,7 @@ class SimpleSAML_XML_Validator { $certificate = $objKey->getX509Certificate(); if ($certificate === NULL) { // Wasn't signed with an X509 certificate - throw new Exception('Message wasn\'t signed with an X509 certificate,' . + throw new \Exception('Message wasn\'t signed with an X509 certificate,' . ' and no public key was provided in the metadata.'); } @@ -116,7 +124,7 @@ class SimpleSAML_XML_Validator { // Check the signature if ($objXMLSecDSig->verify($objKey) !== 1) { - throw new Exception("Unable to validate Signature"); + throw new \Exception("Unable to validate Signature"); } // Extract the certificate @@ -133,7 +141,7 @@ class SimpleSAML_XML_Validator { * This function will return the certificate as a PEM-encoded string. If the XML * wasn't signed by an X509 certificate, NULL will be returned. * - * @return The certificate as a PEM-encoded string, or NULL if not signed with an X509 certificate. + * @return string The certificate as a PEM-encoded string, or NULL if not signed with an X509 certificate. */ public function getX509Certificate() { return $this->x509Certificate; @@ -143,10 +151,10 @@ class SimpleSAML_XML_Validator { /** * Calculates the fingerprint of an X509 certificate. * - * @param $x509cert The certificate as a base64-encoded string. The string may optionally - * be framed with '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----'. - * @return The fingerprint as a 40-character lowercase hexadecimal number. NULL is returned if the - * argument isn't an X509 certificate. + * @param $x509cert string The certificate as a base64-encoded string. The string may optionally + * be framed with '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----'. + * @return string The fingerprint as a 40-character lowercase hexadecimal number. NULL is returned if the + * argument isn't an X509 certificate. */ private static function calculateX509Fingerprint($x509cert) { assert('is_string($x509cert)'); @@ -180,15 +188,16 @@ class SimpleSAML_XML_Validator { } - /** - * Helper function for validating the fingerprint. - * - * Checks the fingerprint of a certificate against an array of valid fingerprints. - * Will throw an exception if none of the fingerprints matches. - * - * @param string $certificate The X509 certificate we should validate. - * @param array $fingerprints The valid fingerprints. - */ + /** + * Helper function for validating the fingerprint. + * + * Checks the fingerprint of a certificate against an array of valid fingerprints. + * Will throw an exception if none of the fingerprints matches. + * + * @param string $certificate The X509 certificate we should validate. + * @param array $fingerprints The valid fingerprints. + * @throws \Exception + */ private static function validateCertificateFingerprint($certificate, $fingerprints) { assert('is_string($certificate)'); assert('is_array($fingerprints)'); @@ -196,7 +205,7 @@ class SimpleSAML_XML_Validator { $certFingerprint = self::calculateX509Fingerprint($certificate); if ($certFingerprint === NULL) { // Couldn't calculate fingerprint from X509 certificate. Should not happen. - throw new Exception('Unable to calculate fingerprint from X509' . + throw new \Exception('Unable to calculate fingerprint from X509' . ' certificate. Maybe it isn\'t an X509 certificate?'); } @@ -211,26 +220,27 @@ class SimpleSAML_XML_Validator { } // None of the fingerprints matched. Throw an exception describing the error. - throw new Exception('Invalid fingerprint of certificate. Expected one of [' . + throw new \Exception('Invalid fingerprint of certificate. Expected one of [' . implode('], [', $fingerprints) . '], but got [' . $certFingerprint . ']'); } - /** - * Validate the fingerprint of the certificate which was used to sign this document. - * - * This function accepts either a string, or an array of strings as a parameter. If this - * is an array, then any string (certificate) in the array can match. If this is a string, - * then that string must match, - * - * @param $fingerprints The fingerprints which should match. This can be a single string, - * or an array of fingerprints. - */ + /** + * Validate the fingerprint of the certificate which was used to sign this document. + * + * This function accepts either a string, or an array of strings as a parameter. If this + * is an array, then any string (certificate) in the array can match. If this is a string, + * then that string must match, + * + * @param $fingerprints string|array The fingerprints which should match. This can be a single string, + * or an array of fingerprints. + * @throws \Exception + */ public function validateFingerprint($fingerprints) { assert('is_string($fingerprints) || is_array($fingerprints)'); if($this->x509Certificate === NULL) { - throw new Exception('Key used to sign the message was not an X509 certificate.'); + throw new \Exception('Key used to sign the message was not an X509 certificate.'); } if(!is_array($fingerprints)) { @@ -252,12 +262,12 @@ class SimpleSAML_XML_Validator { /** * This function checks if the given XML node was signed. * - * @param $node The XML node which we should verify that was signed. + * @param $node \DOMNode The XML node which we should verify that was signed. * - * @return TRUE if this node (or a parent node) was signed. FALSE if not. + * @return bool TRUE if this node (or a parent node) was signed. FALSE if not. */ public function isNodeValidated($node) { - assert('$node instanceof DOMNode'); + assert('$node instanceof \DOMNode'); while($node !== NULL) { if(in_array($node, $this->validNodes)) { @@ -274,19 +284,20 @@ class SimpleSAML_XML_Validator { } - /** - * Validate the certificate used to sign the XML against a CA file. - * - * This function throws an exception if unable to validate against the given CA file. - * - * @param $caFile File with trusted certificates, in PEM-format. - */ + /** + * Validate the certificate used to sign the XML against a CA file. + * + * This function throws an exception if unable to validate against the given CA file. + * + * @param $caFile string File with trusted certificates, in PEM-format. + * @throws \Exception + */ public function validateCA($caFile) { assert('is_string($caFile)'); if($this->x509Certificate === NULL) { - throw new Exception('Key used to sign the message was not an X509 certificate.'); + throw new \Exception('Key used to sign the message was not an X509 certificate.'); } self::validateCertificate($this->x509Certificate, $caFile); @@ -324,18 +335,19 @@ class SimpleSAML_XML_Validator { } - /** - * Validate the certificate used to sign the XML against a CA file, by using the "openssl verify" command. - * - * This function uses the openssl verify command to verify a certificate, to work around limitations - * on the openssl_x509_checkpurpose function. That function will not work on certificates without a purpose - * set. - * - * @param string $certificate The certificate, in PEM format. - * @param string $caFile File with trusted certificates, in PEM-format. - * @return boolean|string TRUE on success, a string with error messages on failure. - * @deprecated - */ + /** + * Validate the certificate used to sign the XML against a CA file, by using the "openssl verify" command. + * + * This function uses the openssl verify command to verify a certificate, to work around limitations + * on the openssl_x509_checkpurpose function. That function will not work on certificates without a purpose + * set. + * + * @param string $certificate The certificate, in PEM format. + * @param string $caFile File with trusted certificates, in PEM-format. + * @return bool|string TRUE on success, a string with error messages on failure. + * @throws \Exception + * @deprecated + */ private static function validateCAExec($certificate, $caFile) { assert('is_string($certificate)'); assert('is_string($caFile)'); @@ -358,11 +370,11 @@ class SimpleSAML_XML_Validator { ); $process = proc_open($cmdline, $descSpec, $pipes); if (!is_resource($process)) { - throw new Exception('Failed to execute verification command: ' . $cmdline); + throw new \Exception('Failed to execute verification command: ' . $cmdline); } if (fwrite($pipes[0], $certificate) === FALSE) { - throw new Exception('Failed to write certificate for verification.'); + throw new \Exception('Failed to write certificate for verification.'); } fclose($pipes[0]); @@ -384,39 +396,40 @@ class SimpleSAML_XML_Validator { } - /** - * Validate the certificate used to sign the XML against a CA file. - * - * This function throws an exception if unable to validate against the given CA file. - * - * @param string $certificate The certificate, in PEM format. - * @param string $caFile File with trusted certificates, in PEM-format. - * @deprecated - */ + /** + * Validate the certificate used to sign the XML against a CA file. + * + * This function throws an exception if unable to validate against the given CA file. + * + * @param string $certificate The certificate, in PEM format. + * @param string $caFile File with trusted certificates, in PEM-format. + * @throws \Exception + * @deprecated + */ public static function validateCertificate($certificate, $caFile) { assert('is_string($certificate)'); assert('is_string($caFile)'); if (!file_exists($caFile)) { - throw new Exception('Could not load CA file: ' . $caFile); + throw new \Exception('Could not load CA file: ' . $caFile); } - SimpleSAML\Logger::debug('Validating certificate against CA file: ' . var_export($caFile, TRUE)); + Logger::debug('Validating certificate against CA file: ' . var_export($caFile, TRUE)); $resBuiltin = self::validateCABuiltIn($certificate, $caFile); if ($resBuiltin !== TRUE) { - SimpleSAML\Logger::debug('Failed to validate with internal function: ' . var_export($resBuiltin, TRUE)); + Logger::debug('Failed to validate with internal function: ' . var_export($resBuiltin, TRUE)); $resExternal = self::validateCAExec($certificate, $caFile); if ($resExternal !== TRUE) { - SimpleSAML\Logger::debug('Failed to validate with external function: ' . var_export($resExternal, TRUE)); - throw new Exception('Could not verify certificate against CA file "' + Logger::debug('Failed to validate with external function: ' . var_export($resExternal, TRUE)); + throw new \Exception('Could not verify certificate against CA file "' . $caFile . '". Internal result:' . $resBuiltin . ' External result:' . $resExternal); } } - SimpleSAML\Logger::debug('Successfully validated certificate.'); + Logger::debug('Successfully validated certificate.'); } } diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php index c866a2de4fe4d953bf3747f2f0e4beb5df7ecb56..504ce9f18e458e2ea8df6f722a06fdbddec305be 100644 --- a/modules/saml/lib/Auth/Source/SP.php +++ b/modules/saml/lib/Auth/Source/SP.php @@ -147,7 +147,7 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source { $state['saml:idp'] = $idpEntityId; - $ar = new SimpleSAML_XML_Shib13_AuthnRequest(); + $ar = new \SimpleSAML\XML\Shib13\AuthnRequest(); $ar->setIssuer($this->entityId); $id = SimpleSAML_Auth_State::saveState($state, 'saml:sp:sso'); diff --git a/modules/saml/lib/IdP/SAML1.php b/modules/saml/lib/IdP/SAML1.php index d6f5e3bd094b2a10c0f5bbb007db074314cdaf70..135883eeae2af205db141aea45dc148c213b16e1 100644 --- a/modules/saml/lib/IdP/SAML1.php +++ b/modules/saml/lib/IdP/SAML1.php @@ -47,7 +47,7 @@ class sspmod_saml_IdP_SAML1 { SimpleSAML_Stats::log('saml:idp:Response', $statsData); // Generate and send response. - $ar = new SimpleSAML_XML_Shib13_AuthnResponse(); + $ar = new \SimpleSAML\XML\Shib13\AuthnResponse(); $authnResponseXML = $ar->generate($idpMetadata, $spMetadata, $shire, $attributes); $httppost = new SimpleSAML_Bindings_Shib13_HTTPPost($config, $metadata); diff --git a/modules/saml/www/sp/saml1-acs.php b/modules/saml/www/sp/saml1-acs.php index fb5b40d5adda3f67ef03bf46520a55eeece743e9..75e2444b6f14457315e9d59bdd36467446de23f1 100644 --- a/modules/saml/www/sp/saml1-acs.php +++ b/modules/saml/www/sp/saml1-acs.php @@ -63,7 +63,7 @@ if (array_key_exists('SAMLart', $_REQUEST)) { assert('FALSE'); } -$response = new SimpleSAML_XML_Shib13_AuthnResponse(); +$response = new \SimpleSAML\XML\Shib13\AuthnResponse(); $response->setXML($responseXML); $response->setMessageValidated($isValidated); diff --git a/tests/lib/SimpleSAML/XML/ErrorsTest.php b/tests/lib/SimpleSAML/XML/ErrorsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c73580a500bd2f007fa558ea22af35867a915a16 --- /dev/null +++ b/tests/lib/SimpleSAML/XML/ErrorsTest.php @@ -0,0 +1,60 @@ +<?php +/** + * Tests for the SQL store. + * + * For the full copyright and license information, please view the LICENSE file that was distributed with this source + * code. + * + * @author Sergio GĂłmez <sergio@uco.es> + * @package simplesamlphp/simplesamlphp + */ + + +namespace SimpleSAML\Test\XML; + +use SimpleSAML\XML\Errors; + +class ErrorsTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers \SimpleSAML\XML\Errors::begin + * @covers \SimpleSAML\XML\Errors::addErrors + * @covers \SimpleSAML\XML\Errors::end + * @test + */ + public function loggingErrors() + { + Errors::begin(); + $xmlstr = "<Test>Test</test>"; + simplexml_load_string($xmlstr); + $errors = Errors::end(); + $errors = Errors::formatErrors($errors); + + $this->assertEquals( + "level=3,code=76,line=1,col=18,msg=Opening and ending tag mismatch: Test line 1 and test\n", + $errors + ); + } + + /** + * @covers \SimpleSAML\XML\Errors::formatError + * @covers \SimpleSAML\XML\Errors::formatErrors + * @test + */ + public function formatErrors() + { + $error = new \LibXMLError(); + $error->level = 'level'; + $error->code = 'code'; + $error->line = 'line'; + $error->column = 'col'; + $error->message = ' msg '; + + $errors = Errors::formatErrors(array($error, $error)); + + $this->assertEquals( + "level=level,code=code,line=line,col=col,msg=msg\nlevel=level,code=code,line=line,col=col,msg=msg\n", + $errors + ); + } +} diff --git a/tests/lib/SimpleSAML/XML/ParserTest.php b/tests/lib/SimpleSAML/XML/ParserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9470d01f3998216504b2dd69c6a09056f55edcc4 --- /dev/null +++ b/tests/lib/SimpleSAML/XML/ParserTest.php @@ -0,0 +1,147 @@ +<?php +/* + * This file is part of the sgomezsimplesamlphp. + * + * (c) Sergio GĂłmez <sergio@uco.es> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + + +namespace SimpleSAML\Test\XML; + +use SimpleSAML\XML\Parser; + +class ParserTest extends \PHPUnit_Framework_TestCase +{ + const XMLDOC = <<< XML +<?xml version="1.0" encoding="UTF-8"?> +<Root> + <Value>Hello, World!</Value> +</Root> +XML; + + /** @var Parser */ + private $xml; + + protected function setUp() + { + $this->xml = new Parser(static::XMLDOC); + } + + /** + * @covers \SimpleSAML\XML\Parser::getValue + * @covers \SimpleSAML\XML\Parser::__construct + * @test + */ + public function getValue() + { + $result = $this->xml->getValue('/Root/Value', true); + $this->assertEquals( + 'Hello, World!', + $result + ); + } + + /** + * @covers \SimpleSAML\XML\Parser::getValue + * @covers \SimpleSAML\XML\Parser::__construct + * @test + */ + public function getEmptyValue() + { + $result = $this->xml->getValue('/Root/Foo', false); + $this->assertEquals( + null, + $result + ); + } + + + + /** + * @covers \SimpleSAML\XML\Parser::getValue + * @covers \SimpleSAML\XML\Parser::__construct + * @expectedException \Exception + * @test + */ + public function getValueException() + { + $this->xml->getValue('/Root/Foo', true); + } + + /** + * @covers \SimpleSAML\XML\Parser::getValueDefault + * @covers \SimpleSAML\XML\Parser::__construct + * @test + */ + public function getDefaultValue() + { + $result = $this->xml->getValueDefault('/Root/Other', 'Hello'); + $this->assertEquals( + 'Hello', + $result + ); + } + + + /** + * @covers \SimpleSAML\XML\Parser::getValueAlternatives + * @covers \SimpleSAML\XML\Parser::__construct + * @test + */ + public function getValueAlternatives() + { + $result = $this + ->xml + ->getValueAlternatives([ + '/Root/Other', + '/Root/Value' + ], true) + ; + + $this->assertEquals( + 'Hello, World!', + $result + ); + } + + /** + * @covers \SimpleSAML\XML\Parser::getValueAlternatives + * @covers \SimpleSAML\XML\Parser::__construct + * @test + */ + public function getEmptyValueAlternatives() + { + $result = $this + ->xml + ->getValueAlternatives([ + '/Root/Foo', + '/Root/Bar' + ], false) + ; + + $this->assertEquals( + null, + $result + ); + } + + /** + * @covers \SimpleSAML\XML\Parser::getValueAlternatives + * @covers \SimpleSAML\XML\Parser::__construct + * @expectedException \Exception + * @test + */ + public function getValueAlternativesException() + { + $this + ->xml + ->getValueAlternatives([ + '/Root/Foo', + '/Root/Bar' + ], true) + ; + } +} diff --git a/tests/lib/SimpleSAML/XML/Shib13/AuthnResponseTest.php b/tests/lib/SimpleSAML/XML/Shib13/AuthnResponseTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f10423c0aaa6712a134ec86507deb102c2da5f94 --- /dev/null +++ b/tests/lib/SimpleSAML/XML/Shib13/AuthnResponseTest.php @@ -0,0 +1,121 @@ +<?php +/* + * This file is part of the sgomezsimpleshibphp. + * + * (c) Sergio GĂłmez <sergio@uco.es> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + + +namespace SimpleSAML\Test\XML\Shib13; + +use SimpleSAML\XML\Shib13\AuthnResponse; + +class AuthnResponseTest extends \PHPUnit_Framework_TestCase +{ + const XMLDOC = <<< XML +<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" + MajorVersion="1" MinorVersion="1" + ResponseID="" IssueInstant=""> + <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" + AssertionID="" IssueInstant="" + MajorVersion="1" MinorVersion="1" + Issuer="Issuer" + > + <AuthenticationStatement AuthenticationInstant="" AuthenticationMethod=""> + <Subject> + <NameIdentifier Format="urn:mace:shibboleth:1.0:nameIdentifier">NameIdentifier</NameIdentifier> + </Subject> + </AuthenticationStatement> + </Assertion> +</Response> +XML; + + const BADXMLDOC = <<< XML +<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" + MajorVersion="1" MinorVersion="1" + ResponseID="" IssueInstant=""> + <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" + AssertionID="" IssueInstant="" + MajorVersion="1" MinorVersion="1" + > + <AuthenticationStatement AuthenticationInstant="" AuthenticationMethod=""> + <Subject> + <NameIdentifier Format="urn:mace:shibboleth:1.0:nameIdentifier">NameIdentifier</NameIdentifier> + </Subject> + </AuthenticationStatement> + </Assertion> +</Response> +XML; + + /** + * @var AuthnResponse + */ + private $xml; + + protected function setUp() + { + $this->xml = new AuthnResponse(); + $this->xml->setXML(static::XMLDOC); + } + + /** + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML + * @test + */ + public function setXML() + { + $this->xml = new AuthnResponse(); + $this->xml->setXML(static::XMLDOC); + } + + /** + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::doXPathQuery + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::getIssuer + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML + * @test + */ + public function getIssuer() + { + $result = $this->xml->getIssuer(); + + $this->assertEquals( + 'Issuer', + $result + ); + } + + /** + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::getIssuer + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML + * @expectedException \Exception + * @test + */ + public function getIssuerException() + { + $xml = new AuthnResponse(); + $xml->setXML(static::BADXMLDOC); + + $xml->getIssuer(); + } + + /** + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::getNameID + * @covers \SimpleSAML\XML\Shib13\AuthnResponse::setXML + * @test + */ + public function getNameID() + { + $result = $this->xml->getNameID(); + + $this->assertEquals( + array( + 'Value' => 'NameIdentifier', + 'Format' => 'urn:mace:shibboleth:1.0:nameIdentifier', + ), + $result + ); + } +}