diff --git a/core/includes/common.inc b/core/includes/common.inc index 4087a42..3b61f25 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -4532,7 +4532,21 @@ function drupal_get_private_key() { * @see drupal_get_hash_salt() */ function drupal_get_token($value = '') { - return drupal_hmac_base64($value, session_id() . drupal_get_private_key() . drupal_get_hash_salt()); + // For mixed HTTP(S) sessions, use a constant identifier so that tokens can + // be shared between protocols. + $identifier = NULL; + if ($GLOBALS['is_https'] && settings()->get('mixed_mode_sessions', FALSE)) { + $insecure_session_name = substr(session_name(), 1); + if (isset($_COOKIE[$insecure_session_name])) { + $identifier = $_COOKIE[$insecure_session_name]; + } + } + // Otherwise, use the session ID. + if (!isset($identifier)) { + $identifier = session_id(); + } + + return drupal_hmac_base64($value, $identifier . drupal_get_private_key() . drupal_get_hash_salt()); } /** diff --git a/core/includes/form.inc b/core/includes/form.inc index ca9e614..3a5e857 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1184,6 +1184,11 @@ function drupal_validate_form($form_id, &$form, &$form_state) { } } + // Ensure the correct protocol when #https is set. + if (!empty($form['#https']) && !$GLOBALS['is_https'] && settings()->get('mixed_mode_sessions', FALSE)) { + form_set_error('', t('This form must be submitted over a secure connection.')); + } + _form_validate($form, $form_state, $form_id); $validated_forms[$form_id] = TRUE; diff --git a/core/modules/system/lib/Drupal/system/Tests/Session/SessionHttpsTest.php b/core/modules/system/lib/Drupal/system/Tests/Session/SessionHttpsTest.php index 787b7d0..16a9061 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Session/SessionHttpsTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Session/SessionHttpsTest.php @@ -144,13 +144,23 @@ protected function testHttpsSession() { $this->drupalGet('user'); $form = $this->xpath('//form[@id="user-login-form"]'); $this->assertEqual(substr($form[0]['action'], 0, 6), 'https:', 'Login form action is secure'); - $form[0]['action'] = $this->httpsUrl('user'); + // Change the form to submit to an insecure URL and make sure the + // submission fails. + $form[0]['action'] = $this->httpUrl('user'); $edit = array( 'name' => $user->name, 'pass' => $user->pass_raw, ); $this->drupalPost(NULL, $edit, t('Log in')); + $this->assertText(t('This form must be submitted over a secure connection.'), 'Form submission failed over HTTP.'); + + // Now try with a secure URL and make sure the submission succeeds. + $form[0]['action'] = $this->httpsUrl('user'); + $this->drupalPost(NULL, $edit, t('Log in')); + $this->assertNoText(t('This form must be submitted over a secure connection.'), 'Form submission succeeded over HTTPS.'); + $this->assertLink(t('Log out'), 0, t('User %name successfully logged in.', array('%name' => $user->name))); + // Check secure cookie on secure page. $this->assertTrue($this->cookies[$secure_session_name]['secure'], 'The secure cookie has the secure attribute'); // Check insecure cookie on secure page. @@ -206,6 +216,19 @@ protected function testHttpsSession() { // Test that the user is also authenticated on the insecure site. $this->drupalGet("user/{$user->uid}/edit"); $this->assertResponse(200); + + // Test that tokens can be shared in mixed mode. + $this->drupalGet('session-test/drupal-token'); + $matches = array(); + preg_match('/\s*drupal_get_token:(.*)\n/', $this->drupalGetContent(), $matches); + $this->assertTrue(!empty($matches[1]) , 'Found token on the HTTP URL.'); + $token_plain = $matches[1]; + $this->drupalGet($this->httpsUrl('session-test/drupal-token')); + $matches = array(); + preg_match('/\s*drupal_get_token:(.*)\n/', $this->drupalGetContent(), $matches); + $this->assertTrue(!empty($matches[1]) , 'Found token on the HTTPS URL.'); + $token_secure = $matches[1]; + $this->assertEqual($token_plain, $token_secure, 'Tokens are shared in mixed HTTPS sessions.'); } /** diff --git a/core/modules/system/tests/modules/session_test/session_test.module b/core/modules/system/tests/modules/session_test/session_test.module index b3e82fd..0d1e4c7 100644 --- a/core/modules/system/tests/modules/session_test/session_test.module +++ b/core/modules/system/tests/modules/session_test/session_test.module @@ -22,6 +22,12 @@ function session_test_menu() { 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); + $items['session-test/drupal-token'] = array( + 'title' => 'Display a token', + 'page callback' => '_session_test_drupal_token', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); $items['session-test/set/%'] = array( 'title' => 'Set session value', 'page callback' => '_session_test_set', @@ -115,6 +121,13 @@ function _session_test_id_from_cookie() { } /** + * Menu callback: display the result of drupal_get_token(). + */ +function _session_test_drupal_token() { + return 'drupal_get_token:' . drupal_get_token(); +} + +/** * Menu callback, sets a message to me displayed on the following page. */ function _session_test_set_message() {