summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
Diffstat (limited to 'includes')
-rw-r--r--includes/bootstrap.inc65
-rw-r--r--includes/session.inc29
-rw-r--r--includes/update.inc2
3 files changed, 55 insertions, 41 deletions
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 6f695814a..e83832d5b 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -2134,15 +2134,7 @@ function _drupal_bootstrap_database() {
// The user agent header is used to pass a database prefix in the request when
// running tests. However, for security reasons, it is imperative that we
// validate we ourselves made the request.
- if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);/", $_SERVER['HTTP_USER_AGENT'], $matches)) {
- if (!drupal_valid_test_ua($_SERVER['HTTP_USER_AGENT'])) {
- header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
- exit;
- }
-
- // The first part of the user agent is the prefix itself.
- $test_prefix = $matches[1];
-
+ if ($test_prefix = drupal_valid_test_ua()) {
// Set the test run id for use in other parts of Drupal.
$test_info = &$GLOBALS['drupal_test_info'];
$test_info['test_run_id'] = $test_prefix;
@@ -2221,22 +2213,40 @@ function drupal_get_bootstrap_phase() {
}
/**
- * Validate the HMAC and timestamp of a user agent header from simpletest.
+ * Checks the current User-Agent string to see if this is an internal request
+ * from SimpleTest. If so, returns the test prefix for this test.
+ *
+ * @return
+ * Either the simpletest prefix (the string "simpletest" followed by any
+ * number of digits) or FALSE if the user agent does not contain a valid
+ * HMAC and timestamp.
*/
-function drupal_valid_test_ua($user_agent) {
+function drupal_valid_test_ua() {
global $drupal_hash_salt;
+ // No reason to reset this.
+ static $test_prefix;
+
+ if (isset($test_prefix)) {
+ return $test_prefix;
+ }
- list($prefix, $time, $salt, $hmac) = explode(';', $user_agent);
- $check_string = $prefix . ';' . $time . ';' . $salt;
- // We use the salt from settings.php to make the HMAC key, since
- // the database is not yet initialized and we can't access any Drupal variables.
- // The file properties add more entropy not easily accessible to others.
- $filepath = DRUPAL_ROOT . '/includes/bootstrap.inc';
- $key = $drupal_hash_salt . filectime($filepath) . fileinode($filepath);
- $time_diff = REQUEST_TIME - $time;
- // Since we are making a local request a 5 second time window is allowed,
- // and the HMAC must match.
- return ($time_diff >= 0) && ($time_diff <= 5) && ($hmac == drupal_hmac_base64($check_string, $key));
+ if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);(.+);(.+);(.+)$/", $_SERVER['HTTP_USER_AGENT'], $matches)) {
+ list(, $prefix, $time, $salt, $hmac) = $matches;
+ $check_string = $prefix . ';' . $time . ';' . $salt;
+ // We use the salt from settings.php to make the HMAC key, since
+ // the database is not yet initialized and we can't access any Drupal variables.
+ // The file properties add more entropy not easily accessible to others.
+ $key = $drupal_hash_salt . filectime(__FILE__) . fileinode(__FILE__);
+ $time_diff = REQUEST_TIME - $time;
+ // Since we are making a local request a 5 second time window is allowed,
+ // and the HMAC must match.
+ if ($time_diff >= 0 && $time_diff <= 5 && $hmac == drupal_hmac_base64($check_string, $key)) {
+ $test_prefix = $prefix;
+ return $test_prefix;
+ }
+ }
+
+ return FALSE;
}
/**
@@ -2250,13 +2260,12 @@ function drupal_generate_test_ua($prefix) {
// We use the salt from settings.php to make the HMAC key, since
// the database is not yet initialized and we can't access any Drupal variables.
// The file properties add more entropy not easily accessible to others.
- $filepath = DRUPAL_ROOT . '/includes/bootstrap.inc';
- $key = $drupal_hash_salt . filectime($filepath) . fileinode($filepath);
+ $key = $drupal_hash_salt . filectime(__FILE__) . fileinode(__FILE__);
}
- // Generate a moderately secure HMAC based on the database credentials.
- $salt = uniqid('', TRUE);
- $check_string = $prefix . ';' . time() . ';' . $salt;
- return $check_string . ';' . drupal_hmac_base64($check_string, $key);
+ // Generate a moderately secure HMAC based on the database credentials.
+ $salt = uniqid('', TRUE);
+ $check_string = $prefix . ';' . time() . ';' . $salt;
+ return $check_string . ';' . drupal_hmac_base64($check_string, $key);
}
/**
diff --git a/includes/session.inc b/includes/session.inc
index 412db118a..c23c23e1c 100644
--- a/includes/session.inc
+++ b/includes/session.inc
@@ -88,7 +88,10 @@ function _drupal_session_read($sid) {
// a HTTPS session or we are about to log in so we check the sessions table
// for an anonymous session with the non-HTTPS-only cookie.
if ($is_https) {
- $user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.ssid = :ssid", array(':ssid' => $sid))->fetchObject();
+ // Ensure that an empty secure session ID cannot be selected.
+ if ($sid) {
+ $user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.ssid = :ssid", array(':ssid' => $sid))->fetchObject();
+ }
if (!$user) {
if (isset($_COOKIE[$insecure_session_name])) {
$user = db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = :sid AND s.uid = 0", array(
@@ -180,21 +183,23 @@ function _drupal_session_write($sid, $value) {
'timestamp' => REQUEST_TIME,
);
- // The "secure pages" setting allows a site to simultaneously use both
- // secure and insecure session cookies. If enabled and both cookies are
- // presented then use both keys. If not enabled but on HTTPS then use the
- // PHP session id as 'ssid'. If on HTTP then use the PHP session id as
- // 'sid'.
+ // 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' => '');
+ // On HTTPS connections, use the session ID as both 'sid' and 'ssid'.
if ($is_https) {
$key['ssid'] = $sid;
- $insecure_session_name = substr(session_name(), 1);
- if (variable_get('https', FALSE) && isset($_COOKIE[$insecure_session_name])) {
- $key['sid'] = $_COOKIE[$insecure_session_name];
+ // The "secure pages" setting allows a site to simultaneously use both
+ // secure and insecure session cookies. If enabled and both cookies are
+ // presented then use both keys.
+ if (variable_get('https', FALSE)) {
+ $insecure_session_name = substr(session_name(), 1);
+ if (isset($_COOKIE[$insecure_session_name])) {
+ $key['sid'] = $_COOKIE[$insecure_session_name];
+ }
}
}
- else {
- $key['sid'] = $sid;
- }
db_merge('sessions')
->key($key)
diff --git a/includes/update.inc b/includes/update.inc
index c352cf8a3..5fdc16981 100644
--- a/includes/update.inc
+++ b/includes/update.inc
@@ -701,7 +701,7 @@ function update_fix_d7_requirements() {
}
// Add ssid column and index.
- db_add_field('sessions', 'ssid', array('description' => "Secure session ID. The value is generated by PHP's Session API.", 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
+ db_add_field('sessions', 'ssid', array('description' => "Secure session ID. The value is generated by Drupal's session handlers.", 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
db_add_index('sessions', 'ssid', array('ssid'));
// Drop existing primary key.
db_drop_primary_key('sessions');