diff --git a/lib/SimpleSAML/SessionHandlerPHP.php b/lib/SimpleSAML/SessionHandlerPHP.php index 085d1d6edf98faeb6fd9472689116ba1d2634c72..7bc7a17a1cc19ed1d67ad2726c5379e9a4a64208 100644 --- a/lib/SimpleSAML/SessionHandlerPHP.php +++ b/lib/SimpleSAML/SessionHandlerPHP.php @@ -1,5 +1,6 @@ <?php + /** * This file is part of SimpleSAMLphp. See the file COPYING in the root of the distribution for licence information. * @@ -8,220 +9,232 @@ * @author Olav Morken, UNINETT AS. <andreas.solberg@uninett.no> * @package SimpleSAMLphp */ -class SimpleSAML_SessionHandlerPHP extends SimpleSAML_SessionHandler { - - /** - * This variable contains the session cookie name. - * - * @var string - */ - protected $cookie_name; - - - /** - * Initialize the PHP session handling. This constructor is protected because it should only be called from - * SimpleSAML_SessionHandler::createSessionHandler(...). - */ - protected function __construct() { - - /* Call the parent constructor in case it should become - * necessary in the future. - */ - parent::__construct(); - - /* Initialize the php session handling. - * - * If session_id() returns a blank string, then we need - * to call session start. Otherwise the session is already - * started, and we should avoid calling session_start(). - */ - if(session_id() === '') { - $config = SimpleSAML_Configuration::getInstance(); - - $params = $this->getCookieParams(); - - session_set_cookie_params($params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']); - - $this->cookie_name = $config->getString('session.phpsession.cookiename', NULL); - if (!empty($this->cookie_name)) { - session_name($this->cookie_name); - } else { - $this->cookie_name = session_name(); - } - - $savepath = $config->getString('session.phpsession.savepath', NULL); - if(!empty($savepath)) { - session_save_path($savepath); - } - } - } - - - /** - * Create and set new session id. - * - * @return string The new session id. - * - * @throws SimpleSAML_Error_Exception If the cookie is marked as secure but we are not using HTTPS, or the headers - * were already sent and therefore we cannot set the cookie. - */ - public function newSessionId() { - $session_cookie_params = session_get_cookie_params(); - - if ($session_cookie_params['secure'] && !\SimpleSAML\Utils\HTTP::isHTTPS()) { - throw new SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.'); - } - - if (headers_sent()) { - throw new SimpleSAML_Error_Exception('Cannot create new session - headers already sent.'); - } - - /* Generate new (secure) session id. */ - $sessionId = bin2hex(openssl_random_pseudo_bytes(16)); - SimpleSAML_Session::createSession($sessionId); - - if (session_id() !== '') { - /* Session already started, close it. */ - session_write_close(); - } - - session_id($sessionId); - session_start(); - - return session_id(); - } - - - /** - * Retrieve the session id of saved in the session cookie. - * - * @return string The session id saved in the cookie. - * - * @throws SimpleSAML_Error_Exception If the cookie is marked as secure but we are not using HTTPS. - */ - public function getCookieSessionId() { - if(session_id() === '') { - if(!self::hasSessionCookie()) { - return self::newSessionId(); - } - - $session_cookie_params = session_get_cookie_params(); - - if ($session_cookie_params['secure'] && !\SimpleSAML\Utils\HTTP::isHTTPS()) { - throw new SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.'); - } - - session_start(); - } - - return session_id(); - } - - - /** - * Retrieve the session cookie name. - * - * @return string The session cookie name. - */ - public function getSessionCookieName() { - - return $this->cookie_name; - } - - - /** - * Save the current session to the PHP session array. - * - * @param SimpleSAML_Session $session The session object we should save. - */ - public function saveSession(SimpleSAML_Session $session) { - - $_SESSION['SimpleSAMLphp_SESSION'] = serialize($session); - } - - - /** - * Load the session from the PHP session array. - * - * @param string|null $sessionId The ID of the session we should load, or NULL to use the default. - * @return SimpleSAML_Session|null The session object, or NULL if it doesn't exist. - * - * @throws SimpleSAML_Error_Exception If it wasn't possible to disable session cookies or load a session with a - * specific identifier. - */ - public function loadSession($sessionId = NULL) { - assert('is_string($sessionId) || is_null($sessionId)'); - - if ($sessionId !== NULL) { - if (session_id() === '') { - /* session not initiated with getCookieSessionId(), start session without setting cookie */ - $ret = ini_set('session.use_cookies', '0'); - if ($ret === FALSE) { - throw new SimpleSAML_Error_Exception('Disabling PHP option session.use_cookies failed.'); - } - - session_id($sessionId); - session_start(); - } elseif ($sessionId !== session_id()) { - throw new SimpleSAML_Error_Exception('Cannot load PHP session with a specific ID.'); - } - } elseif (session_id() === '') { - $sessionId = self::getCookieSessionId(); - } - - if (!isset($_SESSION['SimpleSAMLphp_SESSION'])) { - return NULL; - } - - $session = $_SESSION['SimpleSAMLphp_SESSION']; - assert('is_string($session)'); - - $session = unserialize($session); - assert('$session instanceof SimpleSAML_Session'); - - return $session; - } - - - /** - * Check whether the session cookie is set. - * - * This function will only return false if is is certain that the cookie isn't set. - * - * @return boolean True if it was set, false otherwise. - */ - public function hasSessionCookie() { - - return array_key_exists($this->cookie_name, $_COOKIE); - } - - - /** - * Get the cookie parameters that should be used for session cookies. - * - * This function contains some adjustments from the default to provide backwards-compatibility. - * - * @return array The cookie parameters for our sessions. - * @link http://www.php.net/manual/en/function.session-get-cookie-params.php - * - * @throws SimpleSAML_Error_Exception If both 'session.phpsession.limitedpath' and 'session.cookie.path' options - * are set at the same time in the configuration. - */ - public function getCookieParams() { - - $config = SimpleSAML_Configuration::getInstance(); - - $ret = parent::getCookieParams(); - - if ($config->hasValue('session.phpsession.limitedpath') && $config->hasValue('session.cookie.path')) { - throw new SimpleSAML_Error_Exception('You cannot set both the session.phpsession.limitedpath and session.cookie.path options.'); - } elseif ($config->hasValue('session.phpsession.limitedpath')) { - $ret['path'] = $config->getBoolean('session.phpsession.limitedpath', FALSE) ? '/' . $config->getBaseURL() : '/'; - } - - $ret['httponly'] = $config->getBoolean('session.phpsession.httponly', TRUE); - - return $ret; - } - +class SimpleSAML_SessionHandlerPHP extends SimpleSAML_SessionHandler +{ + + /** + * This variable contains the session cookie name. + * + * @var string + */ + protected $cookie_name; + + + /** + * Initialize the PHP session handling. This constructor is protected because it should only be called from + * SimpleSAML_SessionHandler::createSessionHandler(...). + */ + protected function __construct() + { + // call the parent constructor in case it should become necessary in the future + parent::__construct(); + + /* Initialize the php session handling. + * + * If session_id() returns a blank string, then we need to call session start. Otherwise the session is already + * started, and we should avoid calling session_start(). + */ + if (session_id() === '') { + $config = SimpleSAML_Configuration::getInstance(); + + $params = $this->getCookieParams(); + + session_set_cookie_params( + $params['lifetime'], + $params['path'], + $params['domain'], + $params['secure'], + $params['httponly'] + ); + + $this->cookie_name = $config->getString('session.phpsession.cookiename', null); + if (!empty($this->cookie_name)) { + session_name($this->cookie_name); + } else { + $this->cookie_name = session_name(); + } + + $savepath = $config->getString('session.phpsession.savepath', null); + if (!empty($savepath)) { + session_save_path($savepath); + } + } + } + + + /** + * Create and set new session id. + * + * @return string The new session id. + * + * @throws SimpleSAML_Error_Exception If the cookie is marked as secure but we are not using HTTPS, or the headers + * were already sent and therefore we cannot set the cookie. + */ + public function newSessionId() + { + $session_cookie_params = session_get_cookie_params(); + + if ($session_cookie_params['secure'] && !\SimpleSAML\Utils\HTTP::isHTTPS()) { + throw new SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.'); + } + + if (headers_sent()) { + throw new SimpleSAML_Error_Exception('Cannot create new session - headers already sent.'); + } + + // generate new (secure) session id + $sessionId = bin2hex(openssl_random_pseudo_bytes(16)); + SimpleSAML_Session::createSession($sessionId); + + if (session_id() !== '') { + // session already started, close it + session_write_close(); + } + + session_id($sessionId); + session_start(); + + return session_id(); + } + + + /** + * Retrieve the session id of saved in the session cookie. + * + * @return string The session id saved in the cookie. + * + * @throws SimpleSAML_Error_Exception If the cookie is marked as secure but we are not using HTTPS. + */ + public function getCookieSessionId() + { + if (session_id() === '') { + if (!self::hasSessionCookie()) { + return self::newSessionId(); + } + + $session_cookie_params = session_get_cookie_params(); + + if ($session_cookie_params['secure'] && !\SimpleSAML\Utils\HTTP::isHTTPS()) { + throw new SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.'); + } + + session_start(); + } + + return session_id(); + } + + + /** + * Retrieve the session cookie name. + * + * @return string The session cookie name. + */ + public function getSessionCookieName() + { + return $this->cookie_name; + } + + + /** + * Save the current session to the PHP session array. + * + * @param SimpleSAML_Session $session The session object we should save. + */ + public function saveSession(SimpleSAML_Session $session) + { + $_SESSION['SimpleSAMLphp_SESSION'] = serialize($session); + } + + + /** + * Load the session from the PHP session array. + * + * @param string|null $sessionId The ID of the session we should load, or null to use the default. + * + * @return SimpleSAML_Session|null The session object, or null if it doesn't exist. + * + * @throws SimpleSAML_Error_Exception If it wasn't possible to disable session cookies or we are trying to load a + * PHP session with a specific identifier and it doesn't match with the current session identifier. + */ + public function loadSession($sessionId = null) + { + assert('is_string($sessionId) || is_null($sessionId)'); + + if ($sessionId !== null) { + if (session_id() === '') { + // session not initiated with getCookieSessionId(), start session without setting cookie + $ret = ini_set('session.use_cookies', '0'); + if ($ret === false) { + throw new SimpleSAML_Error_Exception('Disabling PHP option session.use_cookies failed.'); + } + + session_id($sessionId); + session_start(); + } elseif ($sessionId !== session_id()) { + throw new SimpleSAML_Error_Exception('Cannot load PHP session with a specific ID.'); + } + } elseif (session_id() === '') { + self::getCookieSessionId(); + } + + if (!isset($_SESSION['SimpleSAMLphp_SESSION'])) { + return null; + } + + $session = $_SESSION['SimpleSAMLphp_SESSION']; + assert('is_string($session)'); + + $session = unserialize($session); + assert('$session instanceof SimpleSAML_Session'); + + return $session; + } + + + /** + * Check whether the session cookie is set. + * + * This function will only return false if is is certain that the cookie isn't set. + * + * @return boolean True if it was set, false otherwise. + */ + public function hasSessionCookie() + { + return array_key_exists($this->cookie_name, $_COOKIE); + } + + + /** + * Get the cookie parameters that should be used for session cookies. + * + * This function contains some adjustments from the default to provide backwards-compatibility. + * + * @return array The cookie parameters for our sessions. + * @link http://www.php.net/manual/en/function.session-get-cookie-params.php + * + * @throws SimpleSAML_Error_Exception If both 'session.phpsession.limitedpath' and 'session.cookie.path' options + * are set at the same time in the configuration. + */ + public function getCookieParams() + { + $config = SimpleSAML_Configuration::getInstance(); + + $ret = parent::getCookieParams(); + + if ($config->hasValue('session.phpsession.limitedpath') && $config->hasValue('session.cookie.path')) { + throw new SimpleSAML_Error_Exception( + 'You cannot set both the session.phpsession.limitedpath and session.cookie.path options.' + ); + } elseif ($config->hasValue('session.phpsession.limitedpath')) { + $ret['path'] = $config->getBoolean( + 'session.phpsession.limitedpath', + false + ) ? '/'.$config->getBaseURL() : '/'; + } + + $ret['httponly'] = $config->getBoolean('session.phpsession.httponly', true); + + return $ret; + } }