'Secure Pages', 'description' => 'Test Secure Pages redirects.', 'group' => 'Secure Pages', ); } function setUp() { parent::setUp('securepages', 'comment', 'path'); variable_set('https', TRUE); variable_set('securepages_enable', TRUE); variable_set('comment_form_location_story', COMMENT_FORM_BELOW); variable_set('comment_preview_story', COMMENT_PREVIEW_OPTIONAL); } /** * Runs all the test functions. These are run from a single outer function to avoid * multiple re-installs by simpletest. */ function testSecurePages() { $this->_testSettingsForm(); $this->_testMatch(); $this->_testAnonymous(); $this->_testFormAlter(); $this->_testCachedResponse(); $this->_testPathAlias(); $this->_testOpenRedirect(); $this->_testXHR(); $this->_testRoles(); $this->_testPathNorms(); } /** * Test submitting the settings form */ function _testSettingsForm() { // Undo the setUp() function. variable_del('securepages_enable'); // Enable securepages. $this->web_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages')); $this->loginHTTPS($this->web_user); $edit = array('securepages_enable' => 1); $this->drupalPost($this->_toHTTPS(url('admin/build/securepages', array('absolute' => TRUE))), $edit, t('Save configuration')); $this->assertRaw(t('The configuration options have been saved.')); $this->drupalLogout(); } /** * Tests the securepages_match() function. */ function _testMatch() { variable_set('securepages_ignore', '*/autocomplete/*'); $this->assertTrue(securepages_match('user'), 'path user matches.'); $this->assertTrue(securepages_match('user/login'), 'path user/login matches.'); $this->assertTrue(securepages_match('admin/modules'), 'path admin/modules matches.'); $this->assertFalse(securepages_match('node'), 'path node does not match.'); $this->assertTrue(securepages_match('user/autocomplete/alice') == securepages_is_secure() ? 1 : 0, 'autocomplete path is ignored.'); } /** * Tests for anonymous browsing with securepages. */ function _testAnonymous() { // Visit the home page and /node with plain HTTP. $this->drupalGet(''); $this->assertResponse(200); $this->assertUrl(url('', array('absolute' => TRUE))); $this->drupalGet('node'); $this->assertResponse(200); $this->assertUrl(url('node', array('absolute' => TRUE))); // Visit the login page and confirm that browser is redirected to HTTPS. $this->drupalGet('user'); $this->assertResponse(200); $this->assertUrl($this->_toHTTPS(url('user', array('absolute' => TRUE)))); // Visit the home page and /node with HTTPS and confirm that no redirection happens. $this->drupalGet($this->_toHTTPS(url('', array('absolute' => TRUE)))); $this->assertResponse(200); $this->assertUrl($this->_toHTTPS(url('', array('absolute' => TRUE)))); $this->drupalGet($this->_toHTTPS(url('node', array('absolute' => TRUE)))); $this->assertResponse(200); $this->assertUrl($this->_toHTTPS(url('node', array('absolute' => TRUE)))); // Enable "Switch back to http pages when there are no matches". variable_set('securepages_switch', TRUE); // Visit the home page and /node with HTTPS and confirm that switch-back happens. $this->drupalGet($this->_toHTTPS(url('', array('absolute' => TRUE)))); $this->assertResponse(200); $this->assertUrl(url('', array('absolute' => TRUE))); $this->drupalGet($this->_toHTTPS(url('node', array('absolute' => TRUE)))); $this->assertResponse(200); $this->assertUrl($this->_toHTTP(url('node', array('absolute' => TRUE)))); // Clean up variable_del('securepages_pages'); } /** * Tests the ability to alter form actions. * * Uses the comment form, since it has an #action set. */ function _testFormAlter() { variable_set('securepages_switch', TRUE); // Enable anonymous user comments. db_query("UPDATE {permission} SET perm = '%s' WHERE rid = %d", 'access comments, access content, post comments, post comments without approval', DRUPAL_ANONYMOUS_RID); $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'post comments without approval')); $node = $this->drupalCreateNode(array('type' => 'story', 'promote' => 1)); foreach (array('anonymous', 'authenticated') as $mode) { if ($mode == 'authenticated') { $this->drupalLogin($this->web_user); } // Test plain HTTP posting to HTTPS. variable_set('securepages_pages', "comment/reply/*\nuser*"); $this->drupalGet('node/' . $node->nid); $this->assertFieldByXPath('//form[@id="comment-form" and starts-with(@action, "https:")]', NULL, "The $mode comment form action is https."); $comment_body = $this->randomName(8); $this->drupalPost(NULL, array('comment' => $comment_body), t('Save')); $this->assertRaw($comment_body); // Test HTTPS posting to plain HTTP. variable_set('securepages_pages', "node/*\nuser*"); $this->drupalGet($this->_toHTTPS(url('node/' . $node->nid), array('absolute' => TRUE))); $this->assertUrl($this->_toHTTPS(url('node/' . $node->nid, array('absolute' => TRUE)))); $this->assertFieldByXPath('//form[@id="comment-form" and starts-with(@action, "http:")]', NULL, "The $mode comment form action is http."); $comment_body = $this->randomName(8); $this->drupalPost(NULL, array('comment' => $comment_body), t('Save')); $this->assertRaw($comment_body); } $this->drupalLogout(); // Test the user login block. $this->drupalGet(''); $edit = array( 'name' => $this->web_user->name, 'pass' => $this->web_user->pass_raw, ); $this->drupalPost(NULL, $edit, t('Log in')); $this->drupalGet('user/' . $this->web_user->uid . '/edit'); $this->assertResponse(200); // Clean up $this->drupalLogout(); variable_del('securepages_pages'); variable_del('securepages_switch'); } function _testCachedResponse() { // Enable the page cache and fetch the login page. variable_set('cache', TRUE); $url = url('user/login', array('absolute' => TRUE)); $this->drupalGet($url); // Short-circuit redirects within the simpletest browser. variable_set('simpletest_maximum_redirects', 0); $this->drupalGet($url); $this->assertResponse(302); $this->assertEqual($this->drupalGetHeader('Location'), $this->_toHTTPS(url('user/login', array('absolute' => TRUE)))); // $this->assertEqual($this->drupalGetHeader('X-Securepages-Cache'), 'HIT', 'Page was cached.'); @FIXME // Clean up variable_del('cache'); variable_del('simpletest_maximum_redirects'); } /** * Test redirection on aliased paths. */ function _testPathAlias() { variable_set('securepages_pages', "node/*\nuser*"); // Create test user and login. $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content', 'administer url aliases', 'create url aliases')); $this->drupalLogin($web_user); // Create test node. $node = $this->drupalCreateNode(); // Create alias. $edit = array(); $edit['src'] = 'node/' . $node->nid; $edit['dst'] = $this->randomName(8); $this->drupalPost('admin/build/path/add', $edit, t('Create new alias')); // Short-circuit redirects within the simpletest browser. variable_set('simpletest_maximum_redirects', 0); $this->drupalGet($edit['dst'], array('absolute' => TRUE)); $this->assertResponse(302); $this->assertEqual($this->drupalGetHeader('Location'), $this->_toHTTPS(url($edit['dst'], array('absolute' => TRUE)))); // Clean up variable_del('simpletest_maximum_redirects'); $this->drupalLogout(); variable_del('securepages_pages'); } /** * Verifies that securepages is not an open redirect. */ function _testOpenRedirect() { // Short-circuit redirects within the simpletest browser. variable_set('simpletest_maximum_redirects', 0); variable_set('securepages_switch', TRUE); global $base_url, $base_path; $secure_base_url = str_replace('http', 'https', $base_url); $this->drupalGet($secure_base_url . $base_path . '?q=http://example.com/', array('external' => TRUE)); $this->assertResponse(302); $this->assertTrue(strstr($this->drupalGetHeader('Location'), $base_url), t('Open redirect test passed.')); $this->drupalGet($secure_base_url . $base_path . '?q=' . urlencode('http://example.com/'), array('external' => TRUE)); $this->assertResponse(404); // Clean up variable_del('simpletest_maximum_redirects'); } /** * Test detection of XHR requests. */ function _testXHR() { $admin_user = $this->drupalCreateUser(array('access user profiles', 'administer users', 'access administration pages')); $this->drupalLogin($admin_user); // Without XHR header $this->drupalGet($this->_toHTTP(url('user/autocomplete/a', array('absolute' => TRUE)))); $this->assertResponse(200); $this->assertUrl($this->_toHTTPS(url('user/autocomplete/a', array('absolute' => TRUE)))); // With XHR header $this->drupalGet($this->_toHTTP(url('user/autocomplete/a', array('absolute' => TRUE))), array(), array('X-Requested-With: XMLHttpRequest')); $this->assertResponse(200); $this->assertUrl($this->_toHTTP(url('user/autocomplete/a', array('absolute' => TRUE)))); // Clean up $this->drupalLogout(); } /** * Test role-based switching. */ function _testRoles() { // Enable securepages. $this->web_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access comments', 'post comments')); // Extract the role that was just generated. $role = $this->web_user->roles; unset($role[DRUPAL_AUTHENTICATED_RID]); $role = current(array_keys($role)); $this->loginHTTPS($this->web_user); $edit = array('securepages_enable' => 1, 'securepages_switch' => 1, "securepages_roles[$role]" => 1); $this->drupalPost('admin/build/securepages', $edit, t('Save configuration'), array('https' => TRUE)); $this->assertRaw(t('The configuration options have been saved.')); // Visit the home page and /node with HTTPS and confirm that redirection happens. $this->drupalGet('', array('https' => FALSE)); $this->assertResponse(200); $this->assertUrl($this->_toHTTPS(url('', array('absolute' => TRUE)))); $this->drupalGet($this->_toHTTP(url('node'))); $this->assertResponse(200); $this->assertUrl($this->_toHTTPS(url('', array('absolute' => TRUE)))); // Test that forms actions aren't switched back to http. $node = $this->drupalCreateNode(array('type' => 'story', 'promote' => 1)); $this->drupalGet($this->_toHTTPS(url('node/' . $node->nid, array('absolute' => TRUE)))); $this->assertFieldByXPath('//form[@id="comment-form" and starts-with(@action, "/")]', NULL, "The comment form action is https."); // Clean up variable_del('securepages_switch'); variable_del('securepages_roles'); $this->drupalLogout(); } /** * Test path normalization checks. */ function _testPathNorms() { variable_set('securepages_switch', TRUE); variable_set('securepages_pages', 'user'); // Test mixed-case path. $this->drupalGet('UsEr'); $this->assertUrl($this->_toHTTPS(url('UsEr', array('absolute' => TRUE)))); $this->assertFieldByXPath('//form[@id="user-login" and starts-with(@action, "/")]', NULL, 'The user login form action is https.'); // Test that a trailing slash will not force a protected form's action to // http. $https_path = $this->_toHTTPS(url('user/', array('absolute' => TRUE))); // A http based 'user/' path will become 'user' when doing the redirect, so // best to ensure that the test gets the right conditions the path should be // https based. $this->drupalGet($https_path); $this->assertUrl($https_path); $this->assertFieldByXPath('//form[@id="user-login" and starts-with(@action, "/")]', NULL, 'The user login form action is https.'); // Clean up. variable_del('securepages_switch'); variable_del('securepages_pages'); } /** * Logs in a user using HTTPS. */ function loginHTTPS($user) { $edit = array( 'name' => $user->name, 'pass' => $user->pass_raw, ); $this->drupalPost($this->_toHTTPS(url('user', array('absolute' => TRUE))), $edit, t('Log in')); } /** * Helper function, because url() in D6 lacks 'https' => TRUE */ function _toHTTPS($url) { return str_replace('http://', 'https://', $url); } /** * Helper function, because url() in D6 lacks 'https' => FALSE */ function _toHTTP($url) { return str_replace('https://', 'http://', $url); } }