summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
Diffstat (limited to 'includes')
-rw-r--r--includes/bootstrap.inc32
-rw-r--r--includes/common.inc32
-rw-r--r--includes/form.inc8
-rw-r--r--includes/session.inc84
4 files changed, 119 insertions, 37 deletions
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 28c217b90..ab53ca08b 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -509,7 +509,7 @@ function drupal_settings_initialize() {
global $base_url, $base_path, $base_root;
// Export the following settings.php variables to the global namespace
- global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url;
+ global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $is_https, $base_secure_url, $base_insecure_url;
$conf = array();
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
@@ -519,6 +519,7 @@ function drupal_settings_initialize() {
if (isset($base_url)) {
// Parse fixed base URL from settings.php.
$parts = parse_url($base_url);
+ $http_protocol = $parts['scheme'];
if (!isset($parts['path'])) {
$parts['path'] = '';
}
@@ -528,9 +529,10 @@ function drupal_settings_initialize() {
}
else {
// Create base URL
- $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
+ $http_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
+ $base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST'];
- $base_url = $base_root .= '://' . $_SERVER['HTTP_HOST'];
+ $base_url = $base_root;
// $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not
// be modified by a visitor.
@@ -543,6 +545,9 @@ function drupal_settings_initialize() {
$base_path = '/';
}
}
+ $is_https = $http_protocol == 'https';
+ $base_secure_url = str_replace('http://', 'https://', $base_url);
+ $base_insecure_url = str_replace('https://', 'http://', $base_url);
if ($cookie_domain) {
// If the user specifies the cookie domain, also use it for session name.
@@ -557,15 +562,6 @@ function drupal_settings_initialize() {
$cookie_domain = check_plain($_SERVER['HTTP_HOST']);
}
}
- // To prevent session cookies from being hijacked, a user can configure the
- // SSL version of their website to only transfer session cookies via SSL by
- // using PHP's session.cookie_secure setting. The browser will then use two
- // separate session cookies for the HTTPS and HTTP versions of the site. So we
- // must use different session identifiers for HTTPS and HTTP to prevent a
- // cookie collision.
- if (ini_get('session.cookie_secure')) {
- $session_name .= 'SSL';
- }
// Strip leading periods, www., and port numbers from cookie domain.
$cookie_domain = ltrim($cookie_domain, '.');
if (strpos($cookie_domain, 'www.') === 0) {
@@ -578,7 +574,17 @@ function drupal_settings_initialize() {
if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
ini_set('session.cookie_domain', $cookie_domain);
}
- session_name('SESS' . md5($session_name));
+ // To prevent session cookies from being hijacked, a user can configure the
+ // SSL version of their website to only transfer session cookies via SSL by
+ // using PHP's session.cookie_secure setting. The browser will then use two
+ // separate session cookies for the HTTPS and HTTP versions of the site. So we
+ // must use different session identifiers for HTTPS and HTTP to prevent a
+ // cookie collision.
+ if ($is_https) {
+ ini_set('session.cookie_secure', TRUE);
+ }
+ $prefix = ini_get('session.cookie_secure') ? 'SSESS' : 'SESS';
+ session_name($prefix . md5($session_name));
}
/**
diff --git a/includes/common.inc b/includes/common.inc
index 848bd667c..28897bdf8 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -423,6 +423,14 @@ function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response
extract(parse_url(urldecode($_REQUEST['destination'])));
}
+ $args = array(
+ 'path' => &$path,
+ 'query' => &$query,
+ 'fragment' => &$fragment,
+ 'http_response_code' => &$http_response_code,
+ );
+ drupal_alter('drupal_goto', $args);
+
$url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE));
// Allow modules to react to the end of the page request before redirecting.
@@ -2147,6 +2155,11 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) {
* - 'language'
* An optional language object. Used to build the URL to link to and
* look up the proper alias for the link.
+ * - 'https'
+ * Whether this URL should point to a secure location. If not specified,
+ * the current scheme is used, so the user stays on http or https
+ * respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS
+ * can only be enforced when the variable 'https' is set to TRUE.
* - 'base_url'
* Only used internally, to modify the base URL when a language dependent
* URL requires so.
@@ -2166,6 +2179,7 @@ function url($path = NULL, array $options = array()) {
'query' => '',
'absolute' => FALSE,
'alias' => FALSE,
+ 'https' => FALSE,
'prefix' => ''
);
if (!isset($options['external'])) {
@@ -2203,7 +2217,7 @@ function url($path = NULL, array $options = array()) {
return $path . $options['fragment'];
}
- global $base_url;
+ global $base_url, $base_secure_url, $base_insecure_url;
$script = &drupal_static(__FUNCTION__);
if (!isset($script)) {
@@ -2213,9 +2227,21 @@ function url($path = NULL, array $options = array()) {
$script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : '';
}
+ // The base_url might be rewritten from the language rewrite in domain mode.
if (!isset($options['base_url'])) {
- // The base_url might be rewritten from the language rewrite in domain mode.
- $options['base_url'] = $base_url;
+ if (isset($options['https']) && variable_get('https', FALSE)) {
+ if ($options['https'] === TRUE) {
+ $options['base_url'] = $base_secure_url;
+ $options['absolute'] = TRUE;
+ }
+ elseif ($options['https'] === FALSE) {
+ $options['base_url'] = $base_insecure_url;
+ $options['absolute'] = TRUE;
+ }
+ }
+ else {
+ $options['base_url'] = $base_url;
+ }
}
// Preserve the original path before aliasing.
diff --git a/includes/form.inc b/includes/form.inc
index 6bde787aa..55eb5e5fe 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -979,6 +979,14 @@ function form_builder($form_id, $element, &$form_state) {
// Special handling if we're on the top level form element.
if (isset($element['#type']) && $element['#type'] == 'form') {
+ if (!empty($element['#https']) && variable_get('https', FALSE) &&
+ !menu_path_is_external($element['#action'])) {
+ global $base_root;
+
+ // Not an external URL so ensure that it is secure.
+ $element['#action'] = str_replace('http://', 'https://', $base_root) . $element['#action'];
+ }
+
// Store a complete copy of the form in form_state prior to building the form.
$form_state['complete form'] = $element;
// Set a flag if we have a correct form submission. This is always TRUE for
diff --git a/includes/session.inc b/includes/session.inc
index 272ddc88d..677963ae1 100644
--- a/includes/session.inc
+++ b/includes/session.inc
@@ -66,7 +66,7 @@ function _drupal_session_close() {
* was found or the user is anonymous.
*/
function _drupal_session_read($sid) {
- global $user;
+ global $user, $is_https;
// Write and Close handlers are called after destructing objects
// since PHP 5.0.5.
@@ -76,14 +76,29 @@ function _drupal_session_read($sid) {
// Handle the case of first time visitors and clients that don't store
// cookies (eg. web crawlers).
- if (!isset($_COOKIE[session_name()])) {
+ $insecure_session_name = substr(session_name(), 1);
+ if (!isset($_COOKIE[session_name()]) && !isset($_COOKIE[$insecure_session_name])) {
$user = drupal_anonymous_user();
return '';
}
// Otherwise, if the session is still active, we have a record of the
- // client's session in the database.
- $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();
+ // client's session in the database. If it's HTTPS then we are either have
+ // a HTTPS session or we are about to log in so we check the sessions table
+ // for an anonymous session wth 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();
+ 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(
+ ':sid' => $_COOKIE[$insecure_session_name]))
+ ->fetchObject();
+ }
+ }
+ }
+ 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();
+ }
// We found the client's session record and they are an authenticated user.
if ($user && $user->uid > 0) {
@@ -122,22 +137,27 @@ function _drupal_session_read($sid) {
* This function will always return TRUE.
*/
function _drupal_session_write($sid, $value) {
- global $user;
+ global $user, $is_https;
if (!drupal_save_session()) {
// We don't have anything to do if we are not allowed to save the session.
return;
}
+ $fields = array(
+ 'uid' => $user->uid,
+ 'cache' => isset($user->cache) ? $user->cache : 0,
+ 'hostname' => ip_address(),
+ 'session' => $value,
+ 'timestamp' => REQUEST_TIME,
+ );
+ $insecure_session_name = substr(session_name(), 1);
+ if ($is_https && isset($_COOKIE[$insecure_session_name])) {
+ $fields['sid'] = $_COOKIE[$insecure_session_name];
+ }
db_merge('sessions')
- ->key(array('sid' => $sid))
- ->fields(array(
- 'uid' => $user->uid,
- 'cache' => isset($user->cache) ? $user->cache : 0,
- 'hostname' => ip_address(),
- 'session' => $value,
- 'timestamp' => REQUEST_TIME,
- ))
+ ->key(array($is_https ? 'ssid' : 'sid' => $sid))
+ ->fields($fields)
->execute();
// Last access time is updated no more frequently than once every 180 seconds.
@@ -246,7 +266,14 @@ function drupal_session_started($set = NULL) {
* Called when an anonymous user becomes authenticated or vice-versa.
*/
function drupal_session_regenerate() {
- global $user;
+ global $user, $is_https;
+ if ($is_https && variable_get('https', FALSE)) {
+ $insecure_session_name = substr(session_name(), 1);
+ $params = session_get_cookie_params();
+ $session_id = md5(uniqid(mt_rand(), TRUE));
+ setcookie($insecure_session_name, $session_id, REQUEST_TIME + $params['lifetime'], $params['path'], $params['domain'], FALSE, $params['httponly']);
+ $_COOKIE[$insecure_session_name] = $session_id;
+ }
if (drupal_session_started()) {
$old_session_id = session_id();
@@ -264,7 +291,7 @@ function drupal_session_regenerate() {
if (isset($old_session_id)) {
db_update('sessions')
->fields(array(
- 'sid' => session_id()
+ $is_https ? 'ssid' : 'sid' => session_id()
))
->condition('sid', $old_session_id)
->execute();
@@ -304,11 +331,11 @@ function drupal_session_count($timestamp = 0, $anonymous = TRUE) {
* Session ID.
*/
function _drupal_session_destroy($sid) {
- global $user;
+ global $user, $is_https;
// Delete session data.
db_delete('sessions')
- ->condition('sid', $sid)
+ ->condition($is_https ? 'ssid' : 'sid', $sid)
->execute();
// Reset $_SESSION and $user to prevent a new session from being started
@@ -316,11 +343,26 @@ function _drupal_session_destroy($sid) {
$_SESSION = array();
$user = drupal_anonymous_user();
- // Unset the session cookie.
- if (isset($_COOKIE[session_name()])) {
+ // Unset the session cookies.
+ _drupal_session_delete_cookie(session_name());
+ if ($is_https) {
+ _drupal_session_delete_cookie(substr(session_name(), 1), TRUE);
+ }
+}
+
+/**
+ * Deletes the session cookie.
+ *
+ * @param $name
+ * Name of session cookie to delete.
+ * @param $force_insecure
+ * Fornce cookie to be insecure.
+ */
+function _drupal_session_delete_cookie($name, $force_insecure = FALSE) {
+ if (isset($_COOKIE[$name])) {
$params = session_get_cookie_params();
- setcookie(session_name(), '', REQUEST_TIME - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
- unset($_COOKIE[session_name()]);
+ setcookie($name, '', REQUEST_TIME - 3600, $params['path'], $params['domain'], !$force_insecure && $params['secure'], $params['httponly']);
+ unset($_COOKIE[$name]);
}
}