From 66cb3d6acaf740a0c527b6724d1b7ed372e936fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaime=20P=C3=A9rez=20Crespo?= <jaime.perez@uninett.no>
Date: Tue, 26 Nov 2013 14:30:26 +0000
Subject: [PATCH] Split binding prioritizing out of getDefaultEndpoint to a new
 getEndpointPrioritizedByBinding function.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3303 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SimpleSAML/Configuration.php     | 48 ++++++++++++++++------------
 modules/saml/lib/Auth/Source/SP.php  |  2 +-
 modules/saml/lib/IdP/SAML2.php       |  6 ++--
 modules/saml/www/sp/saml2-logout.php |  2 +-
 www/saml2/sp/SingleLogoutService.php |  2 +-
 www/saml2/sp/initSLO.php             |  5 ++-
 6 files changed, 37 insertions(+), 28 deletions(-)

diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php
index ff376551f..1cf5b593b 100644
--- a/lib/SimpleSAML/Configuration.php
+++ b/lib/SimpleSAML/Configuration.php
@@ -984,42 +984,48 @@ class SimpleSAML_Configuration {
 
 
 	/**
-	 * Find the default endpoint of the given type.
+	 * Find an endpoint of the given type, using a list of supported bindings as a way to prioritize.
 	 *
 	 * @param string $endpointType  The endpoint type.
-	 * @param array $bindings  Array with acceptable bindings. Can be NULL if any binding is allowed.
+	 * @param array $bindings  Sorted array of acceptable bindings.
 	 * @param mixed $default  The default value to return if no matching endpoint is found. If no default is provided, an exception will be thrown.
 	 * @return  array|NULL  The default endpoint, or NULL if no acceptable endpoints are used.
 	 */
-	public function getDefaultEndpoint($endpointType, array $bindings = NULL, $default = self::REQUIRED_OPTION) {
+	public function getEndpointPrioritizedByBinding($endpointType, array $bindings, $default = self::REQUIRED_OPTION) {
 		assert('is_string($endpointType)');
 
 		$endpoints = $this->getEndpoints($endpointType);
 
-		// SingleLogoutService is not an IndexedEndpointType, so we are free to choose the default.
-		if ($endpointType === "SingleLogoutService") {
-			
-
-			$eps = array();
+		foreach ($bindings as $binding) {
 			foreach ($endpoints as $ep) {
-				if ($bindings !== NULL && !in_array($ep['Binding'], $bindings, TRUE)) {
-					/* Unsupported binding. Skip it. */
-					continue;
+				if ($ep['Binding'] === $binding) {
+					return $ep;
 				}
-				$eps[$ep['Binding']] = $ep;
 			}
+		}
 
-			// We will apply the following order:
-			// 1st: SAML2_Const::BINDING_SOAP
-			// 2nd: SAML2_Const::BINDING_HTTP_REDIRECT
-			if (isset($eps[SAML2_Const::BINDING_SOAP])) {
-				return $eps[SAML2_Const::BINDING_SOAP];
-			}
-			if (isset($eps[SAML2_Const::BINDING_HTTP_REDIRECT])) {
-				return $eps[SAML2_Const::BINDING_HTTP_REDIRECT];
-			}
+		if ($default === self::REQUIRED_OPTION) {
+			$loc = $this->location . '[' . var_export($endpointType, TRUE) . ']:';
+			throw new Exception($loc . 'Could not find a supported ' . $endpointType . ' endpoint.');
 		}
 
+		return $default;
+	}
+
+
+	/**
+	 * Find the default endpoint of the given type.
+	 *
+	 * @param string $endpointType  The endpoint type.
+	 * @param array $bindings  Array with acceptable bindings. Can be NULL if any binding is allowed.
+	 * @param mixed $default  The default value to return if no matching endpoint is found. If no default is provided, an exception will be thrown.
+	 * @return  array|NULL  The default endpoint, or NULL if no acceptable endpoints are used.
+	 */
+	public function getDefaultEndpoint($endpointType, array $bindings = NULL, $default = self::REQUIRED_OPTION) {
+		assert('is_string($endpointType)');
+
+		$endpoints = $this->getEndpoints($endpointType);
+
 		$defaultEndpoint = SimpleSAML_Utilities::getDefaultEndpoint($endpoints, $bindings);
 		if ($defaultEndpoint !== NULL) {
 			return $defaultEndpoint;
diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php
index 1154bdc8e..4246ab104 100644
--- a/modules/saml/lib/Auth/Source/SP.php
+++ b/modules/saml/lib/Auth/Source/SP.php
@@ -407,7 +407,7 @@ class sspmod_saml_Auth_Source_SP extends SimpleSAML_Auth_Source {
 
 		$idpMetadata = $this->getIdPMetadata($idp);
 
-		$endpoint = $idpMetadata->getDefaultEndpoint('SingleLogoutService', array(
+		$endpoint = $idpMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
 			SAML2_Const::BINDING_HTTP_REDIRECT,
 			SAML2_Const::BINDING_HTTP_POST), FALSE);
 		if ($endpoint === FALSE) {
diff --git a/modules/saml/lib/IdP/SAML2.php b/modules/saml/lib/IdP/SAML2.php
index 7fe20d936..3b33c7b34 100644
--- a/modules/saml/lib/IdP/SAML2.php
+++ b/modules/saml/lib/IdP/SAML2.php
@@ -403,7 +403,7 @@ class sspmod_saml_IdP_SAML2 {
 			'idpEntityID' => $idpMetadata->getString('entityid'),
 		));
 
-		$dst = $spMetadata->getDefaultEndpoint('SingleLogoutService', array(
+		$dst = $spMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
 			SAML2_Const::BINDING_HTTP_REDIRECT,
 			SAML2_Const::BINDING_HTTP_POST)
 		);
@@ -453,7 +453,7 @@ class sspmod_saml_IdP_SAML2 {
 			'idpEntityID' => $idpMetadata->getString('entityid'),
 			'partial' => $partial
 		));
-		$dst = $spMetadata->getDefaultEndpoint('SingleLogoutService', array(
+		$dst = $spMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
 			SAML2_Const::BINDING_HTTP_REDIRECT,
 			SAML2_Const::BINDING_HTTP_POST)
 		);
@@ -563,7 +563,7 @@ class sspmod_saml_IdP_SAML2 {
 
 		$bindings = array(SAML2_Const::BINDING_HTTP_REDIRECT,
 						  SAML2_Const::BINDING_HTTP_POST);
-		$dst = $spMetadata->getDefaultEndpoint('SingleLogoutService', $bindings);
+		$dst = $spMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', $bindings);
 
 		if ($dst['Binding'] === SAML2_Const::BINDING_HTTP_POST) {
 			$params = array('association' => $association['id'], 'idp' => $idp->getId());
diff --git a/modules/saml/www/sp/saml2-logout.php b/modules/saml/www/sp/saml2-logout.php
index ca168fdc0..d2b26b06e 100644
--- a/modules/saml/www/sp/saml2-logout.php
+++ b/modules/saml/www/sp/saml2-logout.php
@@ -108,7 +108,7 @@ if ($message instanceof SAML2_LogoutResponse) {
 		SimpleSAML_Logger::warning('Logged out of ' . $numLoggedOut  . ' of ' . count($sessionIndexes) . ' sessions.');
 	}
 
-	$dst = $idpMetadata->getDefaultEndpoint('SingleLogoutService', array(
+	$dst = $idpMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
 		SAML2_Const::BINDING_HTTP_REDIRECT,
 		SAML2_Const::BINDING_HTTP_POST)
 	);
diff --git a/www/saml2/sp/SingleLogoutService.php b/www/saml2/sp/SingleLogoutService.php
index bf1a8dbbf..a2546f74e 100644
--- a/www/saml2/sp/SingleLogoutService.php
+++ b/www/saml2/sp/SingleLogoutService.php
@@ -52,7 +52,7 @@ if ($message instanceof SAML2_LogoutRequest) {
 
 		SimpleSAML_Logger::info('SAML2.0 - SP.SingleLogoutService: SP me (' . $spEntityId . ') is sending logout response to IdP (' . $idpEntityId . ')');
 
-		$dst = $idpMetadata->getDefaultEndpoint('SingleLogoutService', array(
+		$dst = $idpMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
 			SAML2_Const::BINDING_HTTP_REDIRECT,
 			SAML2_Const::BINDING_HTTP_POST)
 		);
diff --git a/www/saml2/sp/initSLO.php b/www/saml2/sp/initSLO.php
index d9aa0069c..688680ed9 100644
--- a/www/saml2/sp/initSLO.php
+++ b/www/saml2/sp/initSLO.php
@@ -28,7 +28,10 @@ try {
 		SimpleSAML_Utilities::redirect($returnTo);
 	}
 	$idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-remote');
-	$SLOendpoint = $idpMetadata->getDefaultEndpoint('SingleLogoutService', array(SAML2_Const::BINDING_HTTP_REDIRECT, SAML2_Const::BINDING_HTTP_POST), NULL);
+	$SLOendpoint = $idpMetadata->getEndpointPrioritizedByBinding('SingleLogoutService', array(
+			SAML2_Const::BINDING_HTTP_REDIRECT,
+			SAML2_Const::BINDING_HTTP_POST),
+		NULL);
 	if ($SLOendpoint === NULL) {
 		$session->doLogout('saml2');
 		SimpleSAML_Logger::info('SAML2.0 - SP.initSLO: No supported SingleLogoutService endpoint in IdP.');
-- 
GitLab