From 02800d87ab1fca4a041f172bdec4fabc71ce4fe1 Mon Sep 17 00:00:00 2001 From: "jaimepc@gmail.com" Date: Wed, 5 Feb 2014 13:42:18 +0000 Subject: [PATCH] Revert "Fix memory leak in session serialization (issue #594)" This reverts commit 3d3b437a0fe8ab7f7532015041800e2e8951cab3. git-svn-id: http://simplesamlphp.googlecode.com/svn/trunk@3357 44740490-163a-0410-bde0-09ae8108e29a --- lib/SimpleSAML/Memcache.php | 2 +- lib/SimpleSAML/Session.php | 184 ++++++++++++++---------------------- 2 files changed, 71 insertions(+), 115 deletions(-) diff --git a/lib/SimpleSAML/Memcache.php b/lib/SimpleSAML/Memcache.php index 87431682..11cf3b58 100644 --- a/lib/SimpleSAML/Memcache.php +++ b/lib/SimpleSAML/Memcache.php @@ -46,7 +46,7 @@ class SimpleSAML_Memcache { continue; } - /* Unserialize the object. */ + /* Deserialize the object. */ $info = unserialize($serializedInfo); /* diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index bd79616b..404b5481 100644 --- a/lib/SimpleSAML/Session.php +++ b/lib/SimpleSAML/Session.php @@ -12,7 +12,7 @@ * @package simpleSAMLphp * @version $Id$ */ -class SimpleSAML_Session implements Serializable { +class SimpleSAML_Session { /** * This is a timeout value for setData, which indicates that the data should be deleted @@ -95,7 +95,7 @@ class SimpleSAML_Session implements Serializable { /** - * This is an array of objects which will expire automatically after a set time. It is used + * This is an array of objects which will autoexpire after a set time. It is used * where one needs to store some information - for example a logout request, but doesn't * want it to be stored forever. * @@ -159,7 +159,7 @@ class SimpleSAML_Session implements Serializable { /** - * Private constructor that restricts instantiation to getInstance(). + * private constructor restricts instantiaton to getInstance() */ private function __construct($transient = FALSE) { @@ -188,43 +188,6 @@ class SimpleSAML_Session implements Serializable { } } - /** - * Serialize this session into a string that can be stored. - * - * @return string The serialized session. - */ - public function serialize() { - return serialize(get_object_vars(self::$instance)); - } - - - /** - * Restore a previously serialized session into the current instance of the session. If no session exists - * already, a new one will be created. - * - * @param string $data A session previously serialized. - */ - public function unserialize($data) { - /* Check if we already have initialized the singleton. */ - if (!isset(self::$instance)) { - /* Create a new one. */ - self::$instance = new SimpleSAML_Session(); - } - - /* Populate it with the unserialized values. */ - $data = unserialize($data); - if (is_array($data)) { - foreach ($data as $k => $v) { - $this->$k = $v; - } - } - - /* TODO: Remove for version 1.8. */ - if ($this->authData === NULL) { - $this->upgradeAuthData(); - } - } - /** * Upgrade this session object to use the $authData property. @@ -281,10 +244,22 @@ class SimpleSAML_Session implements Serializable { /** - * Retrieves the current session. Will create a new one if there is none. + * This function is called after this class has been deserialized. + */ + public function __wakeup() { + $this->addShutdownFunction(); + + /* TODO: Remove for version 1.8. */ + if ($this->authData === NULL) { + $this->upgradeAuthData(); + } + } + + + /** + * Retrieves the current session. Will create a new session if there isn't a session. * - * @throws Exception If unable to initialize the session. - * @return SimpleSAML_Session The current session. + * @return The current session. */ public static function getInstance() { @@ -360,7 +335,7 @@ class SimpleSAML_Session implements Serializable { /** * Retrieve if session is transient. * - * @return boolean The session transient flag. + * @return boolean The session transient flag. */ public function isTransient() { return $this->transient; @@ -370,8 +345,6 @@ class SimpleSAML_Session implements Serializable { /** * Get a unique ID that will be permanent for this session. * Used for debugging and tracing log files related to a session. - * - * @return string The unique ID. */ public function getTrackID() { return $this->trackid; @@ -379,9 +352,7 @@ class SimpleSAML_Session implements Serializable { /** - * Who authorized this session. Could be for example 'saml2', 'shib13', 'login', 'login-admin' etc. - * - * @return string Who authorized this session. + * Who authorized this session. could be in example saml2, shib13, login,login-admin etc. */ public function getAuthority() { return $this->authority; @@ -393,28 +364,25 @@ class SimpleSAML_Session implements Serializable { * The complete request is not stored, instead the values that will be needed later * are stored in an assoc array. * - * @param string $protocol saml2 or shib13 - * @param string $requestid The request id used as a key to lookup the cache. + * @param $protocol saml2 or shib13 + * @param $requestid The request id used as a key to lookup the cache. * - * @return array Returns an assoc array of cached variables associated with the + * @return Returns an assoc array of cached variables associated with the * authentication request. */ public function getAuthnRequest($protocol, $requestid) { - SimpleSAML_Logger::debug('Library - Session: Get authnrequest from cache ' . $protocol . ' time:' . time() . - ' id: '. $requestid ); + SimpleSAML_Logger::debug('Library - Session: Get authnrequest from cache ' . $protocol . ' time:' . time() . ' id: '. $requestid ); $type = 'AuthnRequest-' . $protocol; $authnRequest = $this->getData($type, $requestid); if($authnRequest === NULL) { /* - * Could not find requested ID. Throw an error. Could be that it is never set, or that it is deleted - * due to age. + * Could not find requested ID. Throw an error. Could be that it is never set, or that it is deleted due to age. */ - throw new Exception('Could not find cached version of authentication request with ID ' . $requestid . - ' (' . $protocol . ')'); + throw new Exception('Could not find cached version of authentication request with ID ' . $requestid . ' (' . $protocol . ')'); } return $authnRequest; @@ -424,14 +392,13 @@ class SimpleSAML_Session implements Serializable { /** * This method sets a cached assoc array to the authentication request cache storage. * - * @param string $protocol 'saml2' or 'shib13' - * @param string $requestid The request id used as a key to lookup the cache. - * @param array $cache The assoc array that will be stored. + * @param $protocol saml2 or shib13 + * @param $requestid The request id used as a key to lookup the cache. + * @param $cache The assoc array that will be stored. */ public function setAuthnRequest($protocol, $requestid, array $cache) { - SimpleSAML_Logger::debug('Library - Session: Set authnrequest ' . $protocol . ' time:' . time() . ' size:' . - count($cache) . ' id: '. $requestid ); + SimpleSAML_Logger::debug('Library - Session: Set authnrequest ' . $protocol . ' time:' . time() . ' size:' . count($cache) . ' id: '. $requestid ); $type = 'AuthnRequest-' . $protocol; $this->setData($type, $requestid, $cache); @@ -441,7 +408,7 @@ class SimpleSAML_Session implements Serializable { /** * Set the IdP we are authenticated against. * - * @param string|NULL $idp Our current IdP, or NULL if we aren't authenticated with an IdP. + * @param string|NULL $idp Our current IdP, or NULL if we aren't authenticated with an IdP. */ public function setIdP($idp) { assert('is_string($idp) || is_null($idp)'); @@ -461,7 +428,7 @@ class SimpleSAML_Session implements Serializable { /** * Retrieve the IdP we are currently authenticated against. * - * @return string|NULL Our current IdP, or NULL if we aren't authenticated with an IdP. + * @return string|NULL Our current IdP, or NULL if we aren't authenticated with an IdP. */ public function getIdP() { if (!isset($this->authData[$this->authority]['saml:sp:IdP'])) { @@ -474,7 +441,7 @@ class SimpleSAML_Session implements Serializable { /** * Set the SessionIndex we received from our IdP. * - * @param string|NULL $sessionindex Our SessionIndex. + * @param string|NULL $sessionindex Our SessionIndex. */ public function setSessionIndex($sessionindex) { assert('is_string($sessionindex) || is_null($sessionindex)'); @@ -493,7 +460,7 @@ class SimpleSAML_Session implements Serializable { /** * Retrieve our SessionIndex. * - * @return string|NULL Our SessionIndex. + * @return string|NULL Our SessionIndex. */ public function getSessionIndex() { if (!isset($this->authData[$this->authority]['saml:sp:SessionIndex'])) { @@ -506,7 +473,7 @@ class SimpleSAML_Session implements Serializable { /** * Set our current NameID. * - * @param array|NULL $nameid The NameID we received from the IdP + * @param array|NULL $nameid The NameID we received from the IdP */ public function setNameID($nameid) { assert('is_array($nameid) || is_null($nameid)'); @@ -538,7 +505,7 @@ class SimpleSAML_Session implements Serializable { /** * Set remember me expire time. * - * @param int $expire Unix timestamp when remember me session cookies expire. + * @param int $expire Unix timestamp when remember me session cookies expire. */ public function setRememberMeExpire($expire = NULL) { assert('is_int($expire) || is_null($expire)'); @@ -576,8 +543,7 @@ class SimpleSAML_Session implements Serializable { if ($this->authToken !== NULL) { $globalConfig = SimpleSAML_Configuration::getInstance(); - $sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', - 'SimpleSAMLAuthToken'), $this->authToken, $params); + $sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken'), $this->authToken, $params); } } @@ -587,8 +553,8 @@ class SimpleSAML_Session implements Serializable { * * If the user already has logged in, the user will be logged out first. * - * @param string $authority The authority the user logged in with. - * @param array|NULL $data The authentication data for this authority. + * @param string $authority The authority the user logged in with. + * @param array|NULL $data The authentication data for this authority. */ public function doLogin($authority, array $data = NULL) { assert('is_string($authority)'); @@ -627,13 +593,10 @@ class SimpleSAML_Session implements Serializable { $this->authToken = SimpleSAML_Utilities::generateID(); $sessionHandler = SimpleSAML_SessionHandler::getSessionHandler(); - if (!$this->transient && (!empty($data['RememberMe']) || $this->rememberMeExpire) && - $globalConfig->getBoolean('session.rememberme.enable', FALSE)) { - - $this->setRememberMeExpire(); + if (!$this->transient && (!empty($data['RememberMe']) || $this->rememberMeExpire) && $globalConfig->getBoolean('session.rememberme.enable', FALSE)) { + $this->setRememberMeExpire(); } else { - $sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', - 'SimpleSAMLAuthToken'), $this->authToken); + $sessionHandler->setCookie($globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken'), $this->authToken); } } @@ -643,7 +606,7 @@ class SimpleSAML_Session implements Serializable { * * This function will call any registered logout handlers before marking the user as logged out. * - * @param string|NULL $authority The authentication source we are logging out of. + * @param string|NULL $authority The authentication source we are logging out of. */ public function doLogout($authority = NULL) { @@ -683,8 +646,8 @@ class SimpleSAML_Session implements Serializable { /** * Set the lifetime for authentication source. * - * @param string $authority The authentication source we are setting expire time for. - * @param int $expire The number of seconds authentication source is valid. + * @param string $authority The authentication source we are setting expire time for. + * @param int $expire The number of seconds authentication source is valid. */ public function setAuthorityExpire($authority, $expire = NULL) { assert('isset($this->authData[$authority])'); @@ -704,7 +667,7 @@ class SimpleSAML_Session implements Serializable { /** * Set the lifetime of our current authentication session. * - * @param int $duration The number of seconds this authentication session is valid. + * @param int $duration The number of seconds this authentication session is valid. */ public function setSessionDuration($duration) { assert('is_int($duration)'); @@ -729,8 +692,7 @@ class SimpleSAML_Session implements Serializable { assert('is_string($authority)'); if (!isset($this->authData[$authority])) { - SimpleSAML_Logger::debug('Session: '. var_export($authority, TRUE) . - ' not valid because we are not authenticated.'); + SimpleSAML_Logger::debug('Session: '. var_export($authority, TRUE) .' not valid because we are not authenticated.'); return FALSE; } @@ -748,7 +710,7 @@ class SimpleSAML_Session implements Serializable { /** * If the user is authenticated, how much time is left of the session. * - * @return int The number of seconds until the session expires. + * @return int The number of seconds until the session expires. */ public function remainingTime() { @@ -764,7 +726,7 @@ class SimpleSAML_Session implements Serializable { /** * Is the user authenticated. This function does not check the session duration. * - * @return bool TRUE if the user is authenticated, FALSE otherwise. + * @return bool TRUE if the user is authenticated, FALSE otherwise. */ public function isAuthenticated() { return isset($this->authData[$this->authority]); @@ -774,7 +736,7 @@ class SimpleSAML_Session implements Serializable { /** * Retrieve the time the user was authenticated. * - * @return int|NULL The timestamp for when the user was authenticated. NULL if the user hasn't authenticated. + * @return int|NULL The timestamp for when the user was authenticated. NULL if the user hasn't authenticated. */ public function getAuthnInstant() { @@ -831,8 +793,8 @@ class SimpleSAML_Session implements Serializable { /** * Set the values of a single attribute. * - * @param string $name The name of the attribute. - * @param array $value The values of the attribute. + * @param string $name The name of the attribute. + * @param array $value The values of the attribute. */ public function setAttribute($name, $value) { assert('isset($this->authData[$this->authority])'); @@ -845,7 +807,7 @@ class SimpleSAML_Session implements Serializable { /** * Calculates the size of the session object after serialization * - * @return int The size of the session measured in bytes. + * @return The size of the session measured in bytes. */ public function getSize() { $s = serialize($this); @@ -856,9 +818,8 @@ class SimpleSAML_Session implements Serializable { /** * This function registers a logout handler. * - * @param string $classname The class which contains the logout handler. - * @param string $functionname The logout handler function. - * @throws Exception If the handler is not a valid function or method. + * @param $classname The class which contains the logout handler. + * @param $functionname The logout handler function. */ public function registerLogoutHandler($classname, $functionname) { assert('isset($this->authData[$this->authority])'); @@ -879,8 +840,7 @@ class SimpleSAML_Session implements Serializable { /** * This function calls all registered logout handlers. * - * @param string $authority The authentication source we are logging out from. - * @throws Exception If the handler is not a valid function or method. + * @param string $authority The authentication source we are logging out from. */ private function callLogoutHandlers($authority) { assert('is_string($authority)'); @@ -997,20 +957,17 @@ class SimpleSAML_Session implements Serializable { * The timeout value can be SimpleSAML_Session::DATA_TIMEOUT_LOGOUT, which indicates * that the data should be deleted on logout (and not before). * - * @param string $type The type of the data. This is checked when retrieving data from the store. - * @param string $id The identifier of the data. - * @param mixed $data The data. - * @param int|NULL $timeout The number of seconds this data should be stored after its last access. - * This parameter is optional. The default value is set in 'session.datastore.timeout', - * and the default is 4 hours. - * @throws Exception If the data couldn't be stored. - * + * @param $type The type of the data. This is checked when retrieving data from the store. + * @param $id The identifier of the data. + * @param $data The data. + * @param $timeout The number of seconds this data should be stored after its last access. + * This parameter is optional. The default value is set in 'session.datastore.timeout', + * and the default is 4 hours. */ public function setData($type, $id, $data, $timeout = NULL) { assert('is_string($type)'); assert('is_string($id)'); - assert('is_int($timeout) || is_null($timeout) || $timeout === self::DATA_TIMEOUT_LOGOUT ||'. - ' $timeout === self::DATA_TIMEOUT_SESSION_END'); + assert('is_int($timeout) || is_null($timeout) || $timeout === self::DATA_TIMEOUT_LOGOUT || $timeout === self::DATA_TIMEOUT_SESSION_END'); /* Clean out old data. */ $this->expireData(); @@ -1070,9 +1027,9 @@ class SimpleSAML_Session implements Serializable { * Note that this will not change when the data stored in the data store will expire. If that is required, * the data should be written back with setData. * - * @param string $type The type of the data. This must match the type used when adding the data. - * @param string|NULL $id The identifier of the data. Can be NULL, in which case NULL will be returned. - * @return mixed The data of the given type with the given id or NULL if the data doesn't exist in the data store. + * @param $type The type of the data. This must match the type used when adding the data. + * @param $id The identifier of the data. Can be NULL, in which case NULL will be returned. + * @return The data of the given type with the given id or NULL if the data doesn't exist in the data store. */ public function getData($type, $id) { assert('is_string($type)'); @@ -1109,8 +1066,8 @@ class SimpleSAML_Session implements Serializable { * * An empty array will be returned if no data of the given type is found. * - * @param string $type The type of the data. - * @return array An associative array with all data of the given type. + * @param $type The type of the data. + * @return An associative array with all data of the given type. */ public function getDataOfType($type) { assert('is_string($type)'); @@ -1180,8 +1137,7 @@ class SimpleSAML_Session implements Serializable { $globalConfig = SimpleSAML_Configuration::getInstance(); if ($session->authToken !== NULL) { - $authTokenCookieName = $globalConfig->getString('session.authtoken.cookiename', - 'SimpleSAMLAuthToken'); + $authTokenCookieName = $globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken'); if (!isset($_COOKIE[$authTokenCookieName])) { SimpleSAML_Logger::warning('Missing AuthToken cookie.'); return NULL; @@ -1413,7 +1369,7 @@ class SimpleSAML_Session implements Serializable { * This function is just for backwards-compatibility. New code should * use the SimpleSAML_IdP::getAssociations()-function. * - * @return array Array of SAML 2 entityIDs. + * @return array Array of SAML 2 entitiyIDs. * @deprecated Will be removed in the future. */ public function get_sp_list() {