summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-11-05 19:05:02 +0000
committerDries Buytaert <dries@buytaert.net>2010-11-05 19:05:02 +0000
commite920fe34ef16d30af0f4fb8e33b565e572ab30c8 (patch)
tree9282e247144413df5d94ddfa4863a02a9514672b /modules
parent5f550ab80ca279706fd1681920e45172ab23748b (diff)
downloadbrdo-e920fe34ef16d30af0f4fb8e33b565e572ab30c8.tar.gz
brdo-e920fe34ef16d30af0f4fb8e33b565e572ab30c8.tar.bz2
- Patch #575280 by mfb, carlos8f, chx, bleen18: impersonation when an https session exists.
Diffstat (limited to 'modules')
-rw-r--r--modules/simpletest/simpletest.test42
-rw-r--r--modules/simpletest/tests/http.php33
-rw-r--r--modules/simpletest/tests/https.php24
-rw-r--r--modules/simpletest/tests/session.test61
-rw-r--r--modules/simpletest/tests/upgrade/upgrade.test5
-rw-r--r--modules/system/system.install18
6 files changed, 159 insertions, 24 deletions
diff --git a/modules/simpletest/simpletest.test b/modules/simpletest/simpletest.test
index a457d1329..dbed36760 100644
--- a/modules/simpletest/simpletest.test
+++ b/modules/simpletest/simpletest.test
@@ -78,6 +78,43 @@ class SimpleTestFunctionalTest extends DrupalWebTestCase {
}
/**
+ * Test validation of the User-Agent header we use to perform test requests.
+ */
+ function testUserAgentValidation() {
+ if (!$this->inCURL()) {
+ global $base_url;
+ $simpletest_path = $base_url . '/' . drupal_get_path('module', 'simpletest');
+ $HTTP_path = $simpletest_path .'/tests/http.php?q=node';
+ $https_path = $simpletest_path .'/tests/https.php?q=node';
+ // Generate a valid simpletest User-Agent to pass validation.
+ $this->assertTrue(preg_match('/simpletest\d+/', $this->databasePrefix, $matches), t('Database prefix contains simpletest prefix.'));
+ $test_ua = drupal_generate_test_ua($matches[0]);
+ $this->additionalCurlOptions = array(CURLOPT_USERAGENT => $test_ua);
+
+ // Test pages only available for testing.
+ $this->drupalGet($HTTP_path);
+ $this->assertResponse(200, t('Requesting http.php with a legitimate simpletest User-Agent returns OK.'));
+ $this->drupalGet($https_path);
+ $this->assertResponse(200, t('Requesting https.php with a legitimate simpletest User-Agent returns OK.'));
+
+ // Now slightly modify the HMAC on the header, which should not validate.
+ $this->additionalCurlOptions = array(CURLOPT_USERAGENT => $test_ua . 'X');
+ $this->drupalGet($HTTP_path);
+ $this->assertResponse(403, t('Requesting http.php with a bad simpletest User-Agent fails.'));
+ $this->drupalGet($https_path);
+ $this->assertResponse(403, t('Requesting https.php with a bad simpletest User-Agent fails.'));
+
+ // Use a real User-Agent and verify that the special files http.php and
+ // https.php can't be accessed.
+ $this->additionalCurlOptions = array(CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12');
+ $this->drupalGet($HTTP_path);
+ $this->assertResponse(403, t('Requesting http.php with a normal User-Agent fails.'));
+ $this->drupalGet($https_path);
+ $this->assertResponse(403, t('Requesting https.php with a normal User-Agent fails.'));
+ }
+ }
+
+ /**
* Make sure that tests selected through the web interface are run and
* that the results are displayed correctly.
*/
@@ -274,10 +311,7 @@ class SimpleTestFunctionalTest extends DrupalWebTestCase {
* Check if the test is being run from inside a CURL request.
*/
function inCURL() {
- // We cannot rely on drupal_static('drupal_test_info') here, because
- // 'in_child_site' would be FALSE for the parent site when we are
- // executing the tests. Default to direct detection of the HTTP headers.
- return isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^simpletest\d+/", $_SERVER['HTTP_USER_AGENT']);
+ return (bool) drupal_valid_test_ua();
}
}
diff --git a/modules/simpletest/tests/http.php b/modules/simpletest/tests/http.php
new file mode 100644
index 000000000..0c5f1eb78
--- /dev/null
+++ b/modules/simpletest/tests/http.php
@@ -0,0 +1,33 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Fake an HTTP request, for use during testing.
+ */
+
+// Set a global variable to indicate a mock HTTP request.
+$is_http_mock = !empty($_SERVER['HTTPS']);
+
+// Change to HTTP.
+$_SERVER['HTTPS'] = NULL;
+ini_set('session.cookie_secure', FALSE);
+foreach ($_SERVER as $key => $value) {
+ $_SERVER[$key] = str_replace('modules/simpletest/tests/http.php', 'index.php', $value);
+ $_SERVER[$key] = str_replace('https://', 'http://', $_SERVER[$key]);
+}
+
+// Change current directory to the Drupal root.
+chdir('../../..');
+define('DRUPAL_ROOT', getcwd());
+require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+
+// Make sure this file can only be used by simpletest.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+if (!drupal_valid_test_ua()) {
+ header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
+ exit;
+}
+
+drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+menu_execute_active_handler();
diff --git a/modules/simpletest/tests/https.php b/modules/simpletest/tests/https.php
index 121e4ee17..ba618c151 100644
--- a/modules/simpletest/tests/https.php
+++ b/modules/simpletest/tests/https.php
@@ -6,23 +6,27 @@
* Fake an https request, for use during testing.
*/
-// Negated copy of the condition in _drupal_bootstrap(). If the user agent is
-// not from simpletest then disallow access.
-if (!(isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], "simpletest") !== FALSE))) {
- exit;
-}
-
// Set a global variable to indicate a mock HTTPS request.
$is_https_mock = empty($_SERVER['HTTPS']);
// Change to https.
$_SERVER['HTTPS'] = 'on';
-
-// Change to index.php.
-chdir('../../..');
foreach ($_SERVER as $key => $value) {
$_SERVER[$key] = str_replace('modules/simpletest/tests/https.php', 'index.php', $value);
$_SERVER[$key] = str_replace('http://', 'https://', $_SERVER[$key]);
}
-require_once 'index.php';
+// Change current directory to the Drupal root.
+chdir('../../..');
+define('DRUPAL_ROOT', getcwd());
+require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+
+// Make sure this file can only be used by simpletest.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+if (!drupal_valid_test_ua()) {
+ header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
+ exit;
+}
+
+drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+menu_execute_active_handler();
diff --git a/modules/simpletest/tests/session.test b/modules/simpletest/tests/session.test
index 88931a8eb..f02cbef40 100644
--- a/modules/simpletest/tests/session.test
+++ b/modules/simpletest/tests/session.test
@@ -316,7 +316,7 @@ class SessionHttpsTestCase extends DrupalWebTestCase {
// Check insecure cookie is not set.
$this->assertFalse(isset($this->cookies[$insecure_session_name]));
$ssid = $this->cookies[$secure_session_name]['value'];
- $this->assertSessionIds('', $ssid, 'Session has NULL for SID and a correct secure SID.');
+ $this->assertSessionIds($ssid, $ssid, 'Session has a non-empty SID and a correct secure SID.');
$cookie = $secure_session_name . '=' . $ssid;
// Verify that user is logged in on secure URL.
@@ -326,12 +326,36 @@ class SessionHttpsTestCase extends DrupalWebTestCase {
$this->assertResponse(200);
// Verify that user is not logged in on non-secure URL.
- if (!$is_https) {
- $this->curlClose();
- $this->drupalGet('admin/config', array(), array('Cookie: ' . $cookie));
- $this->assertNoText(t('Configuration'));
- $this->assertResponse(403);
- }
+ $this->curlClose();
+ $this->drupalGet($this->httpUrl('admin/config'), array(), array('Cookie: ' . $cookie));
+ $this->assertNoText(t('Configuration'));
+ $this->assertResponse(403);
+
+ // Verify that empty SID cannot be used on the non-secure site.
+ $this->curlClose();
+ $cookie = $insecure_session_name . '=';
+ $this->drupalGet($this->httpUrl('admin/config'), array(), array('Cookie: ' . $cookie));
+ $this->assertResponse(403);
+
+ // Test HTTP session handling by altering the form action to submit the
+ // login form through http.php, which creates a mock HTTP request on HTTPS
+ // test environments.
+ $this->curlClose();
+ $this->drupalGet('user');
+ $form = $this->xpath('//form[@id="user-login"]');
+ $form[0]['action'] = $this->httpUrl('user');
+ $edit = array('name' => $user->name, 'pass' => $user->pass_raw);
+ $this->drupalPost(NULL, $edit, t('Log in'));
+ $this->drupalGet($this->httpUrl('admin/config'));
+ $this->assertResponse(200);
+ $sid = $this->cookies[$insecure_session_name]['value'];
+ $this->assertSessionIds($sid, '', 'Session has the correct SID and an empty secure SID.');
+
+ // Verify that empty secure SID cannot be used on the secure site.
+ $this->curlClose();
+ $cookie = $secure_session_name . '=';
+ $this->drupalGet($this->httpsUrl('admin/config'), array(), array('Cookie: ' . $cookie));
+ $this->assertResponse(403);
// Clear browser cookie jar.
$this->cookies = array();
@@ -458,9 +482,32 @@ class SessionHttpsTestCase extends DrupalWebTestCase {
return $this->assertTrue(db_query('SELECT timestamp FROM {sessions} WHERE sid = :sid AND ssid = :ssid', $args)->fetchField(), $assertion_text);
}
+ /**
+ * Builds a URL for submitting a mock HTTPS request to HTTP test environments.
+ *
+ * @param $url
+ * A Drupal path such as 'user'.
+ *
+ * @return
+ * An absolute URL.
+ */
protected function httpsUrl($url) {
global $base_url;
return $base_url . '/modules/simpletest/tests/https.php?q=' . $url;
}
+
+ /**
+ * Builds a URL for submitting a mock HTTP request to HTTPS test environments.
+ *
+ * @param $url
+ * A Drupal path such as 'user'.
+ *
+ * @return
+ * An absolute URL.
+ */
+ protected function httpUrl($url) {
+ global $base_url;
+ return $base_url . '/modules/simpletest/tests/http.php?q=' . $url;
+ }
}
diff --git a/modules/simpletest/tests/upgrade/upgrade.test b/modules/simpletest/tests/upgrade/upgrade.test
index 4220faebb..8ea93deba 100644
--- a/modules/simpletest/tests/upgrade/upgrade.test
+++ b/modules/simpletest/tests/upgrade/upgrade.test
@@ -113,7 +113,12 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
// Force our way into the session of the child site.
drupal_save_session(TRUE);
+ // A session cannot be written without the ssid column which is missing on
+ // Drupal 6 sites.
+ 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' => ''));
_drupal_session_write($sid, '');
+ // Remove the temporarily added ssid column.
+ db_drop_field('sessions', 'ssid');
drupal_save_session(FALSE);
// Restore necessary variables.
diff --git a/modules/system/system.install b/modules/system/system.install
index ca98e390b..f56ef4055 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -1469,14 +1469,13 @@ function system_schema() {
'not null' => TRUE,
),
'sid' => array(
- 'description' => "A session ID. The value is generated by PHP's Session API.",
+ 'description' => "A session ID. The value is generated by Drupal's session handlers.",
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
- 'default' => '',
),
'ssid' => array(
- 'description' => "Secure session ID. The value is generated by PHP's Session API.",
+ 'description' => "Secure session ID. The value is generated by Drupal's session handlers.",
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
@@ -2902,6 +2901,19 @@ function system_update_7064() {
}
/**
+ * Remove the default value for sid.
+ */
+function system_update_7065() {
+ $spec = array(
+ 'description' => "A session ID. The value is generated by Drupal's session handlers.",
+ 'type' => 'varchar',
+ 'length' => 128,
+ 'not null' => TRUE,
+ );
+ db_change_field('sessions', 'sid', 'sid', $spec);
+}
+
+/**
* @} End of "defgroup updates-6.x-to-7.x"
* The next series of updates should start at 8000.
*/