From 81b52aff79cee1268430b590e276bc51d61952dc Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Fri, 18 Jul 2008 06:31:29 +0000
Subject: [PATCH] SAML2: Fix transient NameId for logout.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@787 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SimpleSAML/Session.php                  | 59 +++++++++++++++++++++
 lib/SimpleSAML/XML/SAML20/AuthnResponse.php |  8 +--
 www/saml2/idp/SingleLogoutService.php       |  6 ++-
 3 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index 73a1beb77..0249884ee 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -68,6 +68,14 @@ class SimpleSAML_Session {
 	private $dataStore = null;
 
 
+	/**
+	 * Current NameIDs for sessions.
+	 *
+	 * Stored as a two-level associative array: $sessionNameId[<entityType>][<entityId>]
+	 */
+	private $sessionNameId;
+
+
 	/**
 	 * private constructor restricts instantiaton to getInstance()
 	 */
@@ -291,6 +299,57 @@ class SimpleSAML_Session {
 	}
 
 
+	/**
+	 * Set the NameID of the users session to the specified entity.
+	 *
+	 * @param string $entityType  The type of the entity (saml20-sp-remote, shib13-sp-remote, ...).
+	 * @param string $entityId  The entity id.
+	 * @param array $nameId  The name identifier.
+	 */
+	public function setSessionNameId($entityType, $entityId, $nameId) {
+		assert('is_string($entityType)');
+		assert('is_string($entityId)');
+		assert('is_array($nameId)');
+
+		if(!is_array($this->sessionNameId)) {
+			$this->sessionNameId = array();
+		}
+
+		if(!array_key_exists($entityType, $this->sessionNameId)) {
+			$this->sessionNameId[$entityType] = array();
+		}
+
+		$this->sessionNameId[$entityType][$entityId] = $nameId;
+	}
+
+
+	/**
+	 * Get the NameID of the users session to the specified entity.
+	 *
+	 * @param string $entityType  The type of the entity (saml20-sp-remote, shib13-sp-remote, ...).
+	 * @param string $entityId  The entity id.
+	 * @return array  The name identifier, or NULL if no name identifier is associated with this session.
+	 */
+	public function getSessionNameId($entityType, $entityId) {
+		assert('is_string($entityType)');
+		assert('is_string($entityId)');
+
+		if(!is_array($this->sessionNameId)) {
+			return NULL;
+		}
+
+		if(!array_key_exists($entityType, $this->sessionNameId)) {
+			return NULL;
+		}
+
+		if(!array_key_exists($entityId, $this->sessionNameId[$entityType])) {
+			return NULL;
+		}
+
+		return $this->sessionNameId[$entityType][$entityId];
+	}
+
+
 	/**
 	 * Marks the user as logged in with the specified authority.
 	 *
diff --git a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
index e62416094..5ec634aeb 100644
--- a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
+++ b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
@@ -647,12 +647,14 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 		/**
 		 * Handling NameID
 		 */
-		$nameid = null;
 		if ($nameidformat == self::EMAIL) {
-			$nameid = $this->generateNameID($nameidformat, $attributes[$spmd['simplesaml.nameidattribute']][0], $spnamequalifier);
+			$nameIdValue = $attributes[$spmd['simplesaml.nameidattribute']][0];
 		} else {
-			$nameid = $this->generateNameID($nameidformat, SimpleSAML_Utilities::generateID(), $spnamequalifier);
+			$nameIdValue = SimpleSAML_Utilities::generateID();
 		}
+		$nameIdData = array('Format' => $nameidformat, 'value' => $nameIdValue);
+		$session->setSessionNameId('saml20-sp-remote', $spentityid, $nameIdData);
+		$nameid = $this->generateNameID($nameidformat, $nameIdValue, $spnamequalifier);
 
 		$assertion = "";
 		if ($status === 'Success') {
diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php
index 451d5dd11..b60ce0299 100644
--- a/www/saml2/idp/SingleLogoutService.php
+++ b/www/saml2/idp/SingleLogoutService.php
@@ -248,7 +248,11 @@ if ($spentityid) {
 		$lr = new SimpleSAML_XML_SAML20_LogoutRequest($config, $metadata);
 
 		// ($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) {
-		$req = $lr->generate($idpentityid, $spentityid, $session->getNameID(), $session->getSessionIndex(), 'IdP');
+		$nameId = $session->getSessionNameId('saml20-sp-remote', $spentityid);
+		if($nameId === NULL) {
+			$nameId = $session->getNameID();
+		}
+		$req = $lr->generate($idpentityid, $spentityid, $nameId, $session->getSessionIndex(), 'IdP');
 
 		/* Save the $logoutInfo until we return from the SP. */
 		saveLogoutInfo($lr->getGeneratedID());
-- 
GitLab