You are here

protected function SessionHttpsTestCase::testHttpsSession in Drupal 7

File

modules/simpletest/tests/session.test, line 502
Provides SimpleTests for core session handling functionality.

Class

SessionHttpsTestCase
Ensure that when running under HTTPS two session cookies are generated.

Code

protected function testHttpsSession() {
  global $is_https;
  if ($is_https) {
    $secure_session_name = session_name();
    $insecure_session_name = substr(session_name(), 1);
  }
  else {
    $secure_session_name = 'S' . session_name();
    $insecure_session_name = session_name();
  }
  $user = $this
    ->drupalCreateUser(array(
    'access administration pages',
  ));

  // Test HTTPS session handling by altering the form action to submit the
  // login form through https.php, which creates a mock HTTPS request.
  $this
    ->drupalGet('user');
  $form = $this
    ->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this
    ->httpsUrl('user');
  $edit = array(
    'name' => $user->name,
    'pass' => $user->pass_raw,
  );
  $this
    ->drupalPost(NULL, $edit, t('Log in'));

  // Test a second concurrent session.
  $this
    ->curlClose();
  $this
    ->drupalGet('user');
  $form = $this
    ->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this
    ->httpsUrl('user');
  $this
    ->drupalPost(NULL, $edit, t('Log in'));

  // Check secure cookie on secure page.
  $this
    ->assertTrue($this->cookies[$secure_session_name]['secure'], 'The secure cookie has the secure attribute');

  // Check insecure cookie is not set.
  $this
    ->assertFalse(isset($this->cookies[$insecure_session_name]));
  $ssid = $this->cookies[$secure_session_name]['value'];
  $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.
  $this
    ->curlClose();
  $this
    ->drupalGet($this
    ->httpsUrl('admin/config'), array(), array(
    'Cookie: ' . $cookie,
  ));
  $this
    ->assertText(t('Configuration'));
  $this
    ->assertResponse(200);

  // Verify that user is not logged in on non-secure URL.
  $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();
  if ($is_https) {

    // The functionality does not make sense when running on HTTPS.
    return;
  }

  // Enable secure pages.
  variable_set('https', TRUE);
  $this
    ->curlClose();

  // Start an anonymous session on the insecure site.
  $session_data = $this
    ->randomName();
  $this
    ->drupalGet('session-test/set/' . $session_data);

  // Check secure cookie on insecure page.
  $this
    ->assertFalse(isset($this->cookies[$secure_session_name]), 'The secure cookie is not sent on insecure pages.');

  // Check insecure cookie on insecure page.
  $this
    ->assertFalse($this->cookies[$insecure_session_name]['secure'], 'The insecure cookie does not have the secure attribute');

  // Store the anonymous cookie so we can validate that its session is killed
  // after login.
  $anonymous_cookie = $insecure_session_name . '=' . $this->cookies[$insecure_session_name]['value'];

  // Check that password request form action is not secure.
  $this
    ->drupalGet('user/password');
  $form = $this
    ->xpath('//form[@id="user-pass"]');
  $this
    ->assertNotEqual(substr($form[0]['action'], 0, 6), 'https:', 'Password request form action is not secure');
  $form[0]['action'] = $this
    ->httpsUrl('user');

  // Check that user login form action is secure.
  $this
    ->drupalGet('user');
  $form = $this
    ->xpath('//form[@id="user-login"]');
  $this
    ->assertEqual(substr($form[0]['action'], 0, 6), 'https:', 'Login form action is secure');
  $form[0]['action'] = $this
    ->httpsUrl('user');
  $edit = array(
    'name' => $user->name,
    'pass' => $user->pass_raw,
  );
  $this
    ->drupalPost(NULL, $edit, t('Log in'));

  // 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.
  $this
    ->assertFalse($this->cookies[$insecure_session_name]['secure'], 'The insecure cookie does not have the secure attribute');
  $sid = $this->cookies[$insecure_session_name]['value'];
  $ssid = $this->cookies[$secure_session_name]['value'];
  $this
    ->assertSessionIds($sid, $ssid, 'Session has both secure and insecure SIDs');
  $cookies = array(
    $insecure_session_name . '=' . $sid,
    $secure_session_name . '=' . $ssid,
  );

  // Test that session data saved before login is still available on the
  // authenticated session.
  $this
    ->drupalGet('session-test/get');
  $this
    ->assertText($session_data, 'Session correctly returned the stored data set by the anonymous session.');
  foreach ($cookies as $cookie_key => $cookie) {
    foreach (array(
      'admin/config',
      $this
        ->httpsUrl('admin/config'),
    ) as $url_key => $url) {
      $this
        ->curlClose();
      $this
        ->drupalGet($url, array(), array(
        'Cookie: ' . $cookie,
      ));
      if ($cookie_key == $url_key) {
        $this
          ->assertText(t('Configuration'));
        $this
          ->assertResponse(200);
      }
      else {
        $this
          ->assertNoText(t('Configuration'));
        $this
          ->assertResponse(403);
      }
    }
  }

  // Test that session data saved before login is not available using the
  // pre-login anonymous cookie.
  $this->cookies = array();
  $this
    ->drupalGet('session-test/get', array(
    'Cookie: ' . $anonymous_cookie,
  ));
  $this
    ->assertNoText($session_data, 'Initial anonymous session is inactive after login.');

  // Clear browser cookie jar.
  $this->cookies = array();

  // Start an anonymous session on the secure site.
  $this
    ->drupalGet($this
    ->httpsUrl('session-test/set/1'));

  // Mock a login to the secure site using the secure session cookie.
  $this
    ->drupalGet('user');
  $form = $this
    ->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this
    ->httpsUrl('user');
  $this
    ->drupalPost(NULL, $edit, t('Log in'));

  // Test that the user is also authenticated on the insecure site.
  $this
    ->drupalGet("user/{$user->uid}/edit");
  $this
    ->assertResponse(200);
}