Verified Commit 827acb14 authored by Théodore Biadala's avatar Théodore Biadala
Browse files

Issue #2983612 by daniel.bosen, randalv, swatichouhan012, alexpott, aleevas,...

Issue #2983612 by daniel.bosen, randalv, swatichouhan012, alexpott, aleevas, kishor_kolekar, naresh_bavaskar, eli-t, quietone: Different sites served from the same domain share the session cookie name
parent f4268525
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1608,7 +1608,7 @@ services:
  Drupal\Core\Session\AccountProxyInterface: '@current_user'
  session_configuration:
    class: Drupal\Core\Session\SessionConfiguration
    arguments: ['%session.storage.options%']
    arguments: ['%session.storage.options%', '@settings']
  Drupal\Core\Session\SessionConfigurationInterface: '@session_configuration'
  session:
    class: Symfony\Component\HttpFoundation\Session\Session
+13 −1
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\Core\Session;

use Drupal\Core\Site\Settings;
use Symfony\Component\HttpFoundation\Request;

/**
@@ -11,6 +12,8 @@ class SessionConfiguration implements SessionConfigurationInterface {

  /**
   * An associative array of session ini settings.
   *
   * @var array
   */
  protected $options;

@@ -19,12 +22,14 @@ class SessionConfiguration implements SessionConfigurationInterface {
   *
   * @param array $options
   *   An associative array of session ini settings.
   * @param \Drupal\Core\Site\Settings $settings
   *   The settings instance.
   *
   * @see \Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage::__construct()
   * @see http://php.net/manual/session.configuration.php
   * @see https://www.php.net/manual/session.security.ini.php
   */
  public function __construct($options = []) {
  public function __construct($options = [], protected ?Settings $settings = NULL) {
    // Provide sensible defaults for sid_length, sid_bits_per_character and
    // name_suffix.
    // @see core/assets/scaffold/files/default.services.yml
@@ -33,6 +38,10 @@ public function __construct($options = []) {
      'sid_bits_per_character' => 6,
      'name_suffix' => '',
    ];
    if (!isset($this->settings)) {
      @trigger_error('Calling ' . __METHOD__ . '() without the $settings argument is deprecated in drupal:11.1.0 and will be required in drupal:12.0.0. See https://www.drupal.org/node/3462570', E_USER_DEPRECATED);
      $this->settings = \Drupal::service('settings');
    }
  }

  /**
@@ -105,6 +114,9 @@ protected function getUnprefixedName(Request $request) {
      // Replace "core" out of session_name so core scripts redirect properly,
      // specifically install.php.
      $session_name = preg_replace('#/core$#', '', $session_name);
      // Create unique session name for different sites served on the same
      // host name and base path.
      return substr(hash_hmac('sha256', $session_name, $this->settings->getHashSalt()), 0, 32);
    }

    return substr(hash('sha256', $session_name), 0, 32);
+43 −22
Original line number Diff line number Diff line
@@ -4,12 +4,14 @@

namespace Drupal\Tests\Core\Session;

use Drupal\Core\Site\Settings;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;

/**
 * @coversDefaultClass \Drupal\Core\Session\SessionConfiguration
 * @group Session
 * @runTestsInSeparateProcesses
 */
class SessionConfigurationTest extends UnitTestCase {

@@ -18,10 +20,11 @@ class SessionConfigurationTest extends UnitTestCase {
   *
   * @return \Drupal\Core\Session\SessionConfiguration|\PHPUnit\Framework\MockObject\MockObject
   */
  protected function createSessionConfiguration($options = []) {
  protected function createSessionConfiguration($options = [], string $hash_salt = 'some_salt') {
    $settings = new Settings(['hash_salt' => $hash_salt]);
    return $this->getMockBuilder('Drupal\Core\Session\SessionConfiguration')
      ->onlyMethods(['drupalValidTestUa'])
      ->setConstructorArgs([$options])
      ->setConstructorArgs([$options, $settings])
      ->getMock();
  }

@@ -170,8 +173,8 @@ public static function providerTestCookieSecure() {
   *
   * @dataProvider providerTestGeneratedSessionName
   */
  public function testGeneratedSessionName($uri, $expected_name): void {
    $config = $this->createSessionConfiguration();
  public function testGeneratedSessionName(string $uri, string $hash_salt, string $expected_name): void {
    $config = $this->createSessionConfiguration([], $hash_salt);

    $request = Request::create($uri);
    $options = $config->getOptions($request);
@@ -187,27 +190,27 @@ public function testGeneratedSessionName($uri, $expected_name): void {
   */
  public static function providerTestGeneratedSessionName() {
    $data = [
      ['http://example.com/path/index.php', 'SESS', 'example.com'],
      ['http://www.example.com/path/index.php', 'SESS', 'www.example.com'],
      ['http://subdomain.example.com/path/index.php', 'SESS', 'subdomain.example.com'],
      ['http://example.com:8080/path/index.php', 'SESS', 'example.com'],
      ['https://example.com/path/index.php', 'SSESS', 'example.com'],
      ['http://example.com/path/core/install.php', 'SESS', 'example.com'],
      ['http://localhost/path/index.php', 'SESS', 'localhost'],
      ['http://127.0.0.1/path/index.php', 'SESS', '127.0.0.1'],
      ['http://127.0.0.1:8888/path/index.php', 'SESS', '127.0.0.1'],
      ['https://127.0.0.1/path/index.php', 'SSESS', '127.0.0.1'],
      ['https://127.0.0.1:8443/path/index.php', 'SSESS', '127.0.0.1'],
      ['http://1.1.1.1/path/index.php', 'SESS', '1.1.1.1'],
      ['https://1.1.1.1/path/index.php', 'SSESS', '1.1.1.1'],
      ['http://[::1]/path/index.php', 'SESS', '[::1]'],
      ['http://[::1]:8888/path/index.php', 'SESS', '[::1]'],
      ['https://[::1]/path/index.php', 'SSESS', '[::1]'],
      ['https://[::1]:8443/path/index.php', 'SSESS', '[::1]'],
      ['http://example.com/path/index.php', 'example_hash_salt', 'SESS', 'example.com'],
      ['http://www.example.com/path/index.php', 'example_hash_salt', 'SESS', 'www.example.com'],
      ['http://subdomain.example.com/path/index.php', 'example_hash_salt', 'SESS', 'subdomain.example.com'],
      ['http://example.com:8080/path/index.php', 'example_hash_salt', 'SESS', 'example.com'],
      ['https://example.com/path/index.php', 'example_hash_salt', 'SSESS', 'example.com'],
      ['http://example.com/path/core/install.php', 'example_hash_salt', 'SESS', 'example.com'],
      ['http://localhost/path/index.php', 'example_hash_salt', 'SESS', 'localhost'],
      ['http://127.0.0.1/path/index.php', 'example_hash_salt', 'SESS', '127.0.0.1'],
      ['http://127.0.0.1:8888/path/index.php', 'example_hash_salt', 'SESS', '127.0.0.1'],
      ['https://127.0.0.1/path/index.php', 'example_hash_salt', 'SSESS', '127.0.0.1'],
      ['https://127.0.0.1:8443/path/index.php', 'example_hash_salt', 'SSESS', '127.0.0.1'],
      ['http://1.1.1.1/path/index.php', 'example_hash_salt', 'SESS', '1.1.1.1'],
      ['https://1.1.1.1/path/index.php', 'example_hash_salt', 'SSESS', '1.1.1.1'],
      ['http://[::1]/path/index.php', 'example_hash_salt', 'SESS', '[::1]'],
      ['http://[::1]:8888/path/index.php', 'example_hash_salt', 'SESS', '[::1]'],
      ['https://[::1]/path/index.php', 'example_hash_salt', 'SSESS', '[::1]'],
      ['https://[::1]:8443/path/index.php', 'example_hash_salt', 'SSESS', '[::1]'],
    ];

    return array_map(function ($record) {
      return [$record[0], $record[1] . substr(hash('sha256', $record[2]), 0, 32)];
      return [$record[0], $record[1], $record[2] . substr(hash_hmac('sha256', $record[3], $record[1]), 0, 32)];
    }, $data);
  }

@@ -259,6 +262,24 @@ public static function providerTestEnforcedSessionName() {
    }, $data);
  }

  /**
   * Test if session name depends on hash_salt.
   *
   * @covers ::getOptions
   */
  public function testSessionNameDependsOnHashSalt() {
    $uri = "http://example.com/path/index.php";
    $request = Request::create($uri);

    $config_1 = $this->createSessionConfiguration([], 'hash_salt_1');
    $options_1 = $config_1->getOptions($request);

    $config_2 = $this->createSessionConfiguration([], 'hash_salt_2');
    $options_2 = $config_2->getOptions($request);

    $this->assertNotEquals($options_1['name'], $options_2['name']);
  }

  /**
   * Tests constructor's default settings.
   *