From ac51d3bcf02ece33cce2ac8ff007d56cff4e1d37 Mon Sep 17 00:00:00 2001 From: Dorin Marcoci Date: Sat, 18 Oct 2025 13:16:06 +0300 Subject: [PATCH] Check if destination is not specified in SAML message Common checkDestination method in Validator class --- src/Saml2/LogoutRequest.php | 25 ++-------------- src/Saml2/LogoutResponse.php | 26 ++-------------- src/Saml2/Response.php | 28 ++---------------- src/Saml2/Validator.php | 57 ++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 72 deletions(-) create mode 100644 src/Saml2/Validator.php diff --git a/src/Saml2/LogoutRequest.php b/src/Saml2/LogoutRequest.php index 1e539105..8bb8ad29 100644 --- a/src/Saml2/LogoutRequest.php +++ b/src/Saml2/LogoutRequest.php @@ -390,29 +390,8 @@ public function isValid($retrieveParametersFromServer = false) } // Check destination - if ($dom->documentElement->hasAttribute('Destination')) { - $destination = $dom->documentElement->getAttribute('Destination'); - if (empty($destination)) { - if (!$security['relaxDestinationValidation']) { - throw new ValidationError( - "The LogoutRequest has an empty Destination value", - ValidationError::EMPTY_DESTINATION - ); - } - } else { - $urlComparisonLength = $security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURL); - if (strncmp($destination, $currentURL, $urlComparisonLength) !== 0) { - $currentURLNoRouted = Utils::getSelfURLNoQuery(); - $urlComparisonLength = $security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURLNoRouted); - if (strncmp($destination, $currentURLNoRouted, $urlComparisonLength) !== 0) { - throw new ValidationError( - "The LogoutRequest was received at $currentURL instead of $destination", - ValidationError::WRONG_DESTINATION - ); - } - } - } - } + Validator::$security = $security; + Validator::checkDestination($dom, $currentURL, 'LogoutRequest'); $nameId = static::getNameId($dom, $this->_settings->getSPkey()); diff --git a/src/Saml2/LogoutResponse.php b/src/Saml2/LogoutResponse.php index 64e373c1..876065b6 100644 --- a/src/Saml2/LogoutResponse.php +++ b/src/Saml2/LogoutResponse.php @@ -182,29 +182,9 @@ public function isValid($requestId = null, $retrieveParametersFromServer = false $currentURL = Utils::getSelfRoutedURLNoQuery(); - if ($this->document->documentElement->hasAttribute('Destination')) { - $destination = $this->document->documentElement->getAttribute('Destination'); - if (empty($destination)) { - if (!$security['relaxDestinationValidation']) { - throw new ValidationError( - "The LogoutResponse has an empty Destination value", - ValidationError::EMPTY_DESTINATION - ); - } - } else { - $urlComparisonLength = $security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURL); - if (strncmp($destination, $currentURL, $urlComparisonLength) !== 0) { - $currentURLNoRouted = Utils::getSelfURLNoQuery(); - $urlComparisonLength = $security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURLNoRouted); - if (strncmp($destination, $currentURLNoRouted, $urlComparisonLength) !== 0) { - throw new ValidationError( - "The LogoutResponse was received at $currentURL instead of $destination", - ValidationError::WRONG_DESTINATION - ); - } - } - } - } + // Check destination + Validator::$security = $security; + Validator::checkDestination($this->document, $currentURL, 'LogoutResponse'); if ($security['wantMessagesSigned'] && !isset($_GET['Signature'])) { throw new ValidationError( diff --git a/src/Saml2/Response.php b/src/Saml2/Response.php index a3c1859a..ea972e74 100644 --- a/src/Saml2/Response.php +++ b/src/Saml2/Response.php @@ -271,32 +271,8 @@ public function isValid($requestId = null) } // Check destination - if ($this->document->documentElement->hasAttribute('Destination')) { - $destination = $this->document->documentElement->getAttribute('Destination'); - if (isset($destination)) { - $destination = trim($destination); - } - if (empty($destination)) { - if (!$security['relaxDestinationValidation']) { - throw new ValidationError( - "The response has an empty Destination value", - ValidationError::EMPTY_DESTINATION - ); - } - } else { - $urlComparisonLength = $security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURL); - if (strncmp($destination, $currentURL, $urlComparisonLength) !== 0) { - $currentURLNoRouted = Utils::getSelfURLNoQuery(); - $urlComparisonLength = $security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURLNoRouted); - if (strncmp($destination, $currentURLNoRouted, $urlComparisonLength) !== 0) { - throw new ValidationError( - "The response was received at $currentURL instead of $destination", - ValidationError::WRONG_DESTINATION - ); - } - } - } - } + Validator::$security = $security; + Validator::checkDestination($this->document, $currentURL, 'Response'); // Check audience $validAudiences = $this->getAudiences(); diff --git a/src/Saml2/Validator.php b/src/Saml2/Validator.php new file mode 100644 index 00000000..b8de6110 --- /dev/null +++ b/src/Saml2/Validator.php @@ -0,0 +1,57 @@ +documentElement->getAttribute('Destination'); + $destination = trim($destination); + if (empty($destination)) { + if (!self::$security['relaxDestinationValidation']) { + throw new ValidationError( + "The $method has an empty Destination value", + ValidationError::EMPTY_DESTINATION + ); + } + } else { + $urlComparisonLength = self::$security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURL); + if (strncmp($destination, $currentURL, $urlComparisonLength) !== 0) { + $currentURLNoRouted = Utils::getSelfURLNoQuery(); + $urlComparisonLength = self::$security['destinationStrictlyMatches'] ? strlen($destination) : strlen($currentURLNoRouted); + if (strncmp($destination, $currentURLNoRouted, $urlComparisonLength) !== 0) { + throw new ValidationError( + "The $method was received at $currentURL instead of $destination", + ValidationError::WRONG_DESTINATION + ); + } + } + } + } + +}