diff options
author | Jaime Pérez <jaime.perez@uninett.no> | 2016-07-02 18:48:45 +0200 |
---|---|---|
committer | Jaime Pérez <jaime.perez@uninett.no> | 2016-07-02 18:48:45 +0200 |
commit | 4056af12443d44bd5289c7c6f40cb334a3e99b38 (patch) | |
tree | 3781a1fb192131319003954629e165697e252af6 /lib/SimpleSAML/SessionHandlerPHP.php | |
parent | 5a1edb83b7107473ed7ecb63d68f71a1f893b4af (diff) | |
download | simplesamlphp-4056af12443d44bd5289c7c6f40cb334a3e99b38.zip simplesamlphp-4056af12443d44bd5289c7c6f40cb334a3e99b38.tar.gz simplesamlphp-4056af12443d44bd5289c7c6f40cb334a3e99b38.tar.bz2 |
bugfix: Stop SimpleSAML_SessionHandler::newSessionId() from initializing the session.
Historically, SimpleSAML_SessionHandler::newSessionId() has also created the session, sending the cookies to the browser. This is problematic both because given the name of the method one would not assume such behaviour, and also because even for transient sessions the handler would then try to set cookies. When we are using a transient session, it is likely to be because we cannot set cookies or because there was a temporary error when loading the session. If we try to set the cookies even for transient sessions, we could either get an error because cookies cannot be set, or overwrite the previous session cookies with transient ones, trashing a legitimate session in case a temporary error occurs.
As a side effect, this can also cause behaviours like the one described in issue #413. There's no point in trying to set the cookies when it's not possible, so we shouldn't even try, and save us the errors.
To fix this, we made SimpleSAML_SessionHandler::setCookie() abstract, forcing each extending class to implement it. The former implementation is moved to SimpleSAML_SessionHandlerCookie, and the SimpleSAML_SessionHandlerPHP gets a new method that starts the session, effectively sending the cookie. SimpleSAML_Session would then be responsible to call the setCookie() method of the session handler when creating a regular session, and skip it when creating a transient one. This introduces a bug, since SimpleSAML_Session was trying to set the auth token cookie calling the same setCookie() method in the session handler. We fixed that by using SimpleSAML\Utils\HTTP::setCookie() instead, in 8756835bacc7057734aba7fe349b534e63261253.
This resolves #413.
Diffstat (limited to 'lib/SimpleSAML/SessionHandlerPHP.php')
-rw-r--r-- | lib/SimpleSAML/SessionHandlerPHP.php | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/lib/SimpleSAML/SessionHandlerPHP.php b/lib/SimpleSAML/SessionHandlerPHP.php index 6f952b3..8f6ee83 100644 --- a/lib/SimpleSAML/SessionHandlerPHP.php +++ b/lib/SimpleSAML/SessionHandlerPHP.php @@ -147,38 +147,17 @@ class SimpleSAML_SessionHandlerPHP extends SimpleSAML_SessionHandler /** - * Create and set new session id. + * Create a 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); - $this->sessionStart(); - - return session_id(); + return $sessionId; } @@ -321,4 +300,45 @@ class SimpleSAML_SessionHandlerPHP extends SimpleSAML_SessionHandler return $ret; } + + + /** + * Set a session cookie. + * + * @param string $sessionName The name of the session. + * @param string|null $sessionID The session ID to use. Set to null to delete the cookie. + * @param array|null $cookieParams Additional parameters to use for the session cookie. + * + * @throws \SimpleSAML\Error\CannotSetCookie If we can't set the cookie. + */ + public function setCookie($sessionName, $sessionID, array $cookieParams = null) + { + if ($cookieParams === null) { + $cookieParams = session_get_cookie_params(); + } + + if ($cookieParams['secure'] && !\SimpleSAML\Utils\HTTP::isHTTPS()) { + throw new SimpleSAML\Error\CannotSetCookie('Secure cookies not allowed on http.'); + } + + if (headers_sent()) { + throw new SimpleSAML\Error\CannotSetCookie('Headers already sent.'); + } + + session_set_cookie_params( + $cookieParams['lifetime'], + $cookieParams['path'], + $cookieParams['domain'], + $cookieParams['secure'], + $cookieParams['httponly'] + ); + + if (session_id() !== '') { + // session already started, close it + session_write_close(); + } + + session_id($sessionID); + $this->sessionStart(); + } } |