From 139b1efb291c0ae9263091125e9f32512be999f1 Mon Sep 17 00:00:00 2001 From: Peter Philipp Date: Fri, 11 Nov 2011 08:48:11 +0100 Subject: [PATCH] Issue #1131986 by das-peter, Damien Tournoud, pisco, akaoni: Session handling fails on multiple switches between http / https --- core/includes/session.inc | 27 +++++++++++++++++++++------ 1 files changed, 21 insertions(+), 6 deletions(-) diff --git a/core/includes/session.inc b/core/includes/session.inc index df70f0e..ef8a0e5 100644 --- a/core/includes/session.inc +++ b/core/includes/session.inc @@ -100,7 +100,14 @@ function _drupal_session_read($sid) { } else { $user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid", array(':sid' => $sid))->fetchObject(); + + // If the user once was stepped up to https don't allow a stepdown + if (!empty($user->ssid)) { + require_once DRUPAL_ROOT . '/core/includes/common.inc'; + drupal_goto($_GET['q'], array('https' => TRUE, 'alias' => TRUE)); + } } + $ssid = (!empty($user->ssid) ? $user->ssid : NULL); // We found the client's session record and they are an authenticated, // active user. @@ -131,6 +138,7 @@ function _drupal_session_read($sid) { $last_read = &drupal_static('drupal_session_last_read'); $last_read = array( 'sid' => $sid, + 'ssid' => $ssid, 'value' => $user->session, ); @@ -168,7 +176,7 @@ function _drupal_session_write($sid, $value) { // Check whether $_SESSION has been changed in this request. $last_read = &drupal_static('drupal_session_last_read'); - $is_changed = !isset($last_read) || $last_read['sid'] != $sid || $last_read['value'] !== $value; + $is_changed = !isset($last_read) || $last_read['sid'] != $sid || (empty($last_read['ssid']) && $is_https) || $last_read['value'] !== $value; // For performance reasons, do not update the sessions table, unless // $_SESSION has changed or more than 180 has passed since the last update. @@ -182,10 +190,9 @@ function _drupal_session_write($sid, $value) { 'timestamp' => REQUEST_TIME, ); - // Use the session ID as 'sid' and an empty string as 'ssid' by default. - // _drupal_session_read() does not allow empty strings so that's a safe - // default. - $key = array('sid' => $sid, 'ssid' => ''); + // Use the session ID as 'sid' without setting a 'ssid' by default to + // prevent a duplication when stepping down from https to http. + $key = array('sid' => $sid); // On HTTPS connections, use the session ID as both 'sid' and 'ssid'. if ($is_https) { $key['ssid'] = $sid; @@ -196,6 +203,14 @@ function _drupal_session_write($sid, $value) { $insecure_session_name = substr(session_name(), 1); if (isset($_COOKIE[$insecure_session_name])) { $key['sid'] = $_COOKIE[$insecure_session_name]; + // If this is the initial setup of the secure session, don't use the + // 'ssid' as key since it doesn't exist yet. But make sure it's set. + if (!isset($_COOKIE[session_name()])) { + // Save the secure session id. + $fields['ssid'] = $sid; + // Don't use 'ssid' as key. + $key['ssid'] = ''; + } } } } @@ -490,4 +505,4 @@ function drupal_save_session($status = NULL) { $save_session = $status; } return $save_session; -} +} \ No newline at end of file -- 1.7.7.msysgit.1