From 8d70e31b495bbc62ef05b0f4f7876dd1dade2e67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20=C3=85kre=20Solberg?= <andreas.solberg@uninett.no>
Date: Mon, 28 Jan 2008 14:29:09 +0000
Subject: [PATCH] More efficient session usage. Now caching only assoc array
 for values from logout request. Also implemented a clean() function to call
 after successfully logged out.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@205 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SimpleSAML/Session.php                  | 92 ++++++++++++---------
 lib/SimpleSAML/XML/SAML20/AuthnResponse.php |  1 -
 www/saml2/idp/SingleLogoutService.php       | 84 +++++++++++++------
 www/saml2/sp/SingleLogoutService.php        |  7 +-
 4 files changed, 117 insertions(+), 67 deletions(-)

diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index 3a01204d3..2e7b3e9da 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -1,4 +1,12 @@
 <?php
+
+require_once('SimpleSAML/Configuration.php');
+require_once('SimpleSAML/Utilities.php');
+require_once('SimpleSAML/Session.php');
+require_once('SimpleSAML/SessionHandler.php');
+require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php');
+require_once('SimpleSAML/XML/AuthnResponse.php');
+
 /**
  * The Session class holds information about a user session, and everything attached to it.
  *
@@ -8,22 +16,9 @@
  * Single-Log-Out.
  *
  * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ * @package simpleSAMLphp
  * @version $Id$
  */
-
-
-require_once('SimpleSAML/Configuration.php');
-require_once('SimpleSAML/Utilities.php');
-require_once('SimpleSAML/Session.php');
-require_once('SimpleSAML/SessionHandler.php');
-require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php');
-require_once('SimpleSAML/XML/SAML20/AuthnRequest.php');
-require_once('SimpleSAML/XML/AuthnResponse.php');
-require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
-
-/**
- * A class representing a session.
- */
 class SimpleSAML_Session {
 
 	const STATE_ONLINE = 1;
@@ -47,16 +42,13 @@ class SimpleSAML_Session {
 	 * This is mostly used at the Shib and SAML 2.0 IdP side, at the SSOService endpoint.
 	 */
 	private $authnrequests = array();
-		
-	private $idp = null;
-	
 	private $logoutrequest = null;
+	private $idp = null;
 	
 	private $authenticated = null;
 	private $protocol = null;
 	private $attributes = null;
 	
-	
 	private $sessionindex = null;
 	private $nameid = null;
 	private $nameidformat = null;
@@ -67,6 +59,7 @@ class SimpleSAML_Session {
 	private $sessionstarted = null;
 	private $sessionduration = null;
 	
+	// Track whether the session object is modified or not.
 	private $dirty = false;
 	
 
@@ -138,11 +131,18 @@ class SimpleSAML_Session {
 	
 	
 	
-	
+	/**
+	 * Get a unique ID that will be permanent for this session.
+	 * Used for debugging and tracing log files related to a session.
+	 */
 	public function getTrackID() {
 		return $this->trackid;
 	}
 	
+	
+	// *** SP list to be used with SAML 2.0 SLO ***
+	// *** *** *** *** *** *** *** *** *** *** ***
+	
 	public function add_sp_session($entityid) {
 		$this->sp_at_idpsessions[$entityid] = self::STATE_ONLINE;
 	}
@@ -173,8 +173,6 @@ class SimpleSAML_Session {
 		return $list;
 	}
 	
-
-	
 	public function set_sp_logout_completed($entityid) {
 		$this->dirty = true;
 		$this->sp_at_idpsessions[$entityid] = self::STATE_LOGGEDOUT;
@@ -186,6 +184,7 @@ class SimpleSAML_Session {
 			error_log('Dump sp sessions: ' . $entityid . ' status: ' . $sp);
 		}
 	}
+	// *** --- ***
 
 
 	
@@ -244,19 +243,9 @@ class SimpleSAML_Session {
 
 	}
 	
-	
-	/*
-	public function setAuthnResponse(SimpleSAML_XML_AuthnResponse $xml) {
-		throw new Exception('setAuthnResponse deprecaed'));
-		$this->authnresponse = $xml;
-	}
-	
-	public function getAuthnResposne() {
-		throw new Exception('getAuthnResponse deprecaed'));
-		return $this->authnresponse;
-	}
-	*/
-	
+
+
+
 	public function setIdP($idp) {
 		$this->dirty = true;
 		$this->idp = $idp;
@@ -265,14 +254,22 @@ class SimpleSAML_Session {
 		return $this->idp;
 	}
 	
-	public function setLogoutRequest(SimpleSAML_XML_SAML20_LogoutRequest $lr) {
+	
+	
+	
+	
+	public function setLogoutRequest($requestcache) {
 		$this->dirty = true;
-		$this->logoutrequest = $lr;
+		$this->logoutrequest = $requestcache;
 	}
 	
 	public function getLogoutRequest() {
 		return $this->logoutrequest;
 	}
+	
+	
+	
+	
 
 	public function setSessionIndex($sessionindex) {
 		$this->dirty = true;
@@ -297,7 +294,8 @@ class SimpleSAML_Session {
 	}
 
 	public function setAuthenticated($auth) {
-		$this->dirty = ($auth || ($this->authenticated != $auth));
+		if ($auth === false) $this->dirty = false;
+		if ($auth != $this->authenticated) $this->dirty = false;
 		$this->authenticated = $auth;
 		if ($auth) {
 			$this->sessionstarted = time();
@@ -361,7 +359,25 @@ class SimpleSAML_Session {
 		$this->dirty = true;
 		$this->attributes[$name] = $value;
 	}
-	 
+	
+	/**
+	 * Clean the session object.
+	 */
+	public function clean() {
+		$this->authnrequests = array();
+		$this->logoutrequest = null;
+		$this->idp = null;
+	
+		$this->authenticated = null;
+		$this->protocol = null;
+		$this->attributes = null;
+	
+		$this->sessionindex = null;
+		$this->nameid = null;
+		$this->nameidformat = null;
+	
+		$this->sp_at_idpsessions = array();	
+	}
 	 
 	/**
 	 * Is this session modified since loaded?
diff --git a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
index 547821489..a40939327 100644
--- a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
+++ b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
@@ -14,7 +14,6 @@ require_once('xmlseclibs.php');
  * @author Andreas Ă…kre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
  * @package simpleSAMLphp
  * @version $Id$
- * @abstract
  */
 class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 
diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php
index ee66ec26c..632cd4915 100644
--- a/www/saml2/idp/SingleLogoutService.php
+++ b/www/saml2/idp/SingleLogoutService.php
@@ -1,5 +1,13 @@
 <?php
 
+/**
+ * This SAML 2.0 endpoint can receive incomming LogoutRequests. It will also send LogoutResponses, and LogoutRequests
+ * and also receive LogoutResponses. It is implemeting SLO at the SAML 2.0 IdP.
+ *
+ * @author Andreas Ĺkre Solberg, UNINETT AS. <andreas.solberg@uninett.no>
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
 
 require_once('../../../www/_include.php');
 
@@ -11,23 +19,25 @@ require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php');
 require_once('SimpleSAML/XML/SAML20/LogoutRequest.php');
 require_once('SimpleSAML/XML/SAML20/LogoutResponse.php');
 require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
-//require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
 require_once('SimpleSAML/XHTML/Template.php');
 
 
 $config = SimpleSAML_Configuration::getInstance();
 $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+$session = SimpleSAML_Session::getInstance();
 
 $idpentityid = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted');
 
-$session = SimpleSAML_Session::getInstance();
-
 $logger = new SimpleSAML_Logger();
-
 $logger->log(LOG_INFO, $session->getTrackID(), 'SAML2.0', 'IdP.SingleLogoutService', 'EVENT', 'Access',
 	'Accessing SAML 2.0 IdP endpoint SingleLogoutService');
-/*
- * If we get an LogoutRequest then we initiate the logout process.
+	
+	
+/**
+ * If we get an incomming LogoutRequest then we initiate the logout process.
+ * in this case an SAML 2.0 SP is sending an request, which also is referred to as
+ * SP initiated Single Logout.
+ *
  */
 if (isset($_GET['SAMLRequest'])) {
 
@@ -54,6 +64,7 @@ if (isset($_GET['SAMLRequest'])) {
 	}
 	/* Check if we have a valid session. */
 	if($session === NULL) {
+	
 		/* Invalid session. To prevent the user from being unable to
 		 * log out from the service provider, we should just return a
 		 * LogoutResponse pretending that the logout was successful to
@@ -89,8 +100,23 @@ if (isset($_GET['SAMLRequest'])) {
 
 	error_log('IdP LogoutService: got Logoutrequest from ' . $logoutrequest->getIssuer() . '  ');
 
+	
+#	$session->setLogoutRequest($logoutrequest);
+
+	/*
+	 * Create an assoc array of the request to store in the session cache.
+	 */
+	$requestcache = array(
+		'Issuer'    	=> $logoutrequest->getIssuer(),
+		'RequestID'		=> $logoutrequest->getRequestID()
+	);
+	if ($relaystate = $logoutrequest->getRelayState() )
+		$requestcache['RelayState'] = $relaystate;
+		
+	$session->setLogoutRequest($requestcache);
+	
 	$session->set_sp_logout_completed($logoutrequest->getIssuer() );
-	$session->setLogoutRequest($logoutrequest);
+	
 
 	/*
 	 * We receive a Logout Response to a Logout Request that we have issued earlier.
@@ -179,29 +205,40 @@ if ($spentityid) {
 error_log('IdP LogoutService:  SPs done ');
 try {
 
-	$logoutrequest = $session->getLogoutRequest();
-	if (!$logoutrequest) {
+	$requestcache = $session->getLogoutRequest();
+	if (!$requestcache) {
 		throw new Exception('Could not get reference to the logout request.');
 	}
-
+	
+	
+	/**
+	 * Clean up session object to save storage.
+	 */
+	if ($config->getValue('debug', false)) 
+		$logger->log(LOG_INFO, $session->getTrackID(), 'SAML2.0', 'IdP.SingleLogoutService', 'EVENT', 'SessionSize', 'Size before cleaning: ' . $session->getSize());
+		
+	$session->clean();
+	
+	if ($config->getValue('debug', false)) 
+		$logger->log(LOG_INFO, $session->getTrackID(), 'SAML2.0', 'IdP.SingleLogoutService', 'EVENT', 'SessionSize', 'Size after cleaning: ' . $session->getSize());
+	
+	
+	/**
+	 * Create a Logot Response.
+	 */
 	$rg = new SimpleSAML_XML_SAML20_LogoutResponse($config, $metadata);
 
-	// generate($issuer, $receiver, $inresponseto, $mode )
-
-	$logoutResponseXML = $rg->generate($idpentityid, $logoutrequest->getIssuer(), $logoutrequest->getRequestID(), 'IdP');
-
-	//	echo '<pre>' . htmlentities($logoutResponseXML) . '</pre>';
-	//	exit();
+	// 							generate($issuer, $receiver, $inresponseto, $mode )
+	$logoutResponseXML = $rg->generate($idpentityid, $requestcache['Issuer'], $requestcache['RequestID'], 'IdP');
 
+	// Create a HTTP-REDIRECT Binding.
 	$httpredirect = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
 
-	$relayState = SimpleSAML_Utilities::selfURL();
-	if (isset($_GET['RelayState'])) {
-		$relayState = $_GET['RelayState'];
-	}
+	// Find the relaystate if cached.
+	$relayState = isset($requestcache['RelayState']) ? $requestcache['RelayState'] : null;
 
-	//$request, $remoteentityid, $relayState = null, $endpoint = 'SingleLogoutService', $direction = 'SAMLRequest', $mode = 'SP'
-	$httpredirect->sendMessage($logoutResponseXML, $idpentityid, $logoutrequest->getIssuer(), $relayState, 'SingleLogoutService', 'SAMLResponse', 'IdP');
+	// Parameters: $request, $remoteentityid, $relayState = null, $endpoint = 'SingleLogoutService', $direction = 'SAMLRequest', $mode = 'SP'
+	$httpredirect->sendMessage($logoutResponseXML, $idpentityid, $requestcache['Issuer'], $relayState, 'SingleLogoutService', 'SAMLResponse', 'IdP');
 
 } catch(Exception $exception) {
 
@@ -212,9 +249,6 @@ try {
 	$et->data['e'] = $exception;
 
 	$et->show();
-
 }
 
-
-
 ?>
\ No newline at end of file
diff --git a/www/saml2/sp/SingleLogoutService.php b/www/saml2/sp/SingleLogoutService.php
index a958c61bc..771469238 100644
--- a/www/saml2/sp/SingleLogoutService.php
+++ b/www/saml2/sp/SingleLogoutService.php
@@ -9,7 +9,8 @@ require_once('SimpleSAML/Logger.php');
 require_once('SimpleSAML/Metadata/MetaDataStorageHandler.php');
 require_once('SimpleSAML/XML/SAML20/LogoutRequest.php');
 require_once('SimpleSAML/XML/SAML20/LogoutResponse.php');
-require_once('SimpleSAML/Bindings/SAML20/HTTPPost.php');
+require_once('SimpleSAML/Bindings/SAML20/HTTPRedirect.php');
+
 require_once('SimpleSAML/XHTML/Template.php');
 
 $config = SimpleSAML_Configuration::getInstance();
@@ -35,11 +36,11 @@ $logger->log(LOG_INFO, $trackId, 'SAML2.0', 'SP.SingleLogoutService', 'EVENT', '
 // Destroy local session if exists.
 if (isset($session) && $session->isAuthenticated() ) {
 	$session->setAuthenticated(false);
+	$session->clean();
 }
 
 
 
-
 if (isset($_GET['SAMLRequest'])) {
 
 	// Create a HTTPRedirect binding
@@ -74,7 +75,6 @@ if (isset($_GET['SAMLRequest'])) {
 	}
 
 
-
 	$logger->log(LOG_NOTICE, $trackId, 'SAML2.0', 'SP.SingleLogoutService', 'LogoutRequest', $requestid,
 		'IdP (' . $requester . ') is sending logout request to me SP (' . $responder . ')');
 
@@ -98,6 +98,7 @@ if (isset($_GET['SAMLRequest'])) {
 
 	// Create a HTTPRedirect binding
 	$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
+	
 	try {
 		// Decode the LogoutResponse using the HTTP Redirect binding.
 		$logoutresponse = $binding->decodeLogoutResponse($_GET);
-- 
GitLab