From f359bf1cd75b3a494880862be18397a78874d3fc Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Tue, 30 Nov 2010 12:50:41 +0000
Subject: [PATCH] saml:sp: Return partial logout when not logging out of all
 requested sessionindexes.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2672 44740490-163a-0410-bde0-09ae8108e29a
---
 modules/saml/lib/SP/LogoutStore.php  |  6 ++++--
 modules/saml/www/sp/saml2-logout.php | 13 ++++++++++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/modules/saml/lib/SP/LogoutStore.php b/modules/saml/lib/SP/LogoutStore.php
index 5576dba7f..ee47c2df3 100644
--- a/modules/saml/lib/SP/LogoutStore.php
+++ b/modules/saml/lib/SP/LogoutStore.php
@@ -194,7 +194,7 @@ class sspmod_saml_SP_LogoutStore {
 	 * @param string $authId  The authsource ID.
 	 * @param array $nameId  The NameID of the user.
 	 * @param array $sessionIndexes  The SessionIndexes we should log out of. Logs out of all if this is empty.
-	 * @returns bool  TRUE if OK, FALSE if not supported.
+	 * @returns int|FALSE  Number of sessions logged out, or FALSE if not supported.
 	 */
 	public static function logoutSessions($authId, array $nameId, array $sessionIndexes) {
 		assert('is_string($authId)');
@@ -235,6 +235,7 @@ class sspmod_saml_SP_LogoutStore {
 
 		$sessionHandler = SimpleSAML_SessionHandler::getSessionHandler();
 
+		$numLoggedOut = 0;
 		foreach ($sessionIndexes as $sessionIndex) {
 			if (!isset($sessions[$sessionIndex])) {
 				SimpleSAML_Logger::info('saml.LogoutStore: Logout requested for unknown SessionIndex.');
@@ -256,9 +257,10 @@ class sspmod_saml_SP_LogoutStore {
 
 			SimpleSAML_Logger::info('saml.LogoutStore: Logging out of session with trackId [' . $session->getTrackId() . '].');
 			$session->doLogout($authId);
+			$numLoggedOut += 1;
 		}
 
-		return TRUE;
+		return $numLoggedOut;
 	}
 
 }
diff --git a/modules/saml/www/sp/saml2-logout.php b/modules/saml/www/sp/saml2-logout.php
index 0df055c18..2d7d69c10 100644
--- a/modules/saml/www/sp/saml2-logout.php
+++ b/modules/saml/www/sp/saml2-logout.php
@@ -85,9 +85,11 @@ if ($message instanceof SAML2_LogoutResponse) {
 	$nameId = $message->getNameId();
 	$sessionIndexes = $message->getSessionIndexes();
 
-	if (!sspmod_saml_SP_LogoutStore::logoutSessions($sourceId, $nameId, $sessionIndexes)) {
+	$numLoggedOut = sspmod_saml_SP_LogoutStore::logoutSessions($sourceId, $nameId, $sessionIndexes);
+	if ($numLoggedOut === FALSE) {
 		/* This type of logout was unsupported. Use the old method. */
 		$source->handleLogout($idpEntityId);
+		$numLoggedOut = count($sessionIndexes);
 	}
 
 	/* Create an send response. */
@@ -95,6 +97,15 @@ if ($message instanceof SAML2_LogoutResponse) {
 	$lr->setRelayState($message->getRelayState());
 	$lr->setInResponseTo($message->getId());
 
+	/* We should return a partial logout if we were unable to log out of all the given session(s). */
+	if ($numLoggedOut < count($sessionIndexes)) {
+		$lr->setStatus(array(
+			'Code' => SAML2_Const::STATUS_SUCCESS,
+			'SubCode' => SAML2_Const::STATUS_PARTIAL_LOGOUT,
+			'Message' => 'Logged out of ' . $numLoggedOut  . ' of ' . count($sessionIndexes) . ' sessions.'
+		));
+	}
+
 	$binding->send($lr);
 } else {
 	throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message));
-- 
GitLab