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