annotate sites/all/modules/captcha/captcha.test @ 9:830c812b520f

added smtp module
author root <root@paio.local>
date Mon, 28 Oct 2013 15:34:27 +0000
parents b74b41bb73f0
children
rev   line source
danielebarchiesi@2 1 <?php
danielebarchiesi@2 2
danielebarchiesi@2 3 /**
danielebarchiesi@2 4 * @file
danielebarchiesi@2 5 * Tests for CAPTCHA module.
danielebarchiesi@2 6 */
danielebarchiesi@2 7
danielebarchiesi@2 8 // TODO: write test for CAPTCHAs on admin pages
danielebarchiesi@2 9 // TODO: test for default challenge type
danielebarchiesi@2 10 // TODO: test about placement (comment form, node forms, log in form, etc)
danielebarchiesi@2 11 // TODO: test if captcha_cron does it work right
danielebarchiesi@2 12 // TODO: test custom CAPTCHA validation stuff
danielebarchiesi@2 13 // TODO: test if entry on status report (Already X blocked form submissions) works
danielebarchiesi@2 14 // TODO: test space ignoring validation of image CAPTCHA
danielebarchiesi@2 15
danielebarchiesi@2 16 // TODO: refactor the 'comment_body[' . LANGUAGE_NONE . '][0][value]' stuff
danielebarchiesi@2 17
danielebarchiesi@2 18 // Some constants for better reuse.
danielebarchiesi@2 19 define('CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE',
danielebarchiesi@2 20 'The answer you entered for the CAPTCHA was not correct.');
danielebarchiesi@2 21
danielebarchiesi@2 22 define('CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE',
danielebarchiesi@2 23 'CAPTCHA session reuse attack detected.');
danielebarchiesi@2 24
danielebarchiesi@2 25 define('CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE',
danielebarchiesi@2 26 'CAPTCHA validation error: unknown CAPTCHA session ID. Contact the site administrator if this problem persists.');
danielebarchiesi@2 27
danielebarchiesi@2 28
danielebarchiesi@2 29
danielebarchiesi@2 30 /**
danielebarchiesi@2 31 * Base class for CAPTCHA tests.
danielebarchiesi@2 32 *
danielebarchiesi@2 33 * Provides common setup stuff and various helper functions
danielebarchiesi@2 34 */
danielebarchiesi@2 35 abstract class CaptchaBaseWebTestCase extends DrupalWebTestCase {
danielebarchiesi@2 36
danielebarchiesi@2 37 /**
danielebarchiesi@2 38 * User with various administrative permissions.
danielebarchiesi@2 39 * @var Drupal user
danielebarchiesi@2 40 */
danielebarchiesi@2 41 protected $admin_user;
danielebarchiesi@2 42
danielebarchiesi@2 43 /**
danielebarchiesi@2 44 * Normal visitor with limited permissions
danielebarchiesi@2 45 * @var Drupal user;
danielebarchiesi@2 46 */
danielebarchiesi@2 47 protected $normal_user;
danielebarchiesi@2 48
danielebarchiesi@2 49 /**
danielebarchiesi@2 50 * Form ID of comment form on standard (page) node
danielebarchiesi@2 51 * @var string
danielebarchiesi@2 52 */
danielebarchiesi@2 53 const COMMENT_FORM_ID = 'comment_node_page_form';
danielebarchiesi@2 54
danielebarchiesi@2 55 /**
danielebarchiesi@2 56 * Drupal path of the (general) CAPTCHA admin page
danielebarchiesi@2 57 */
danielebarchiesi@2 58 const CAPTCHA_ADMIN_PATH = 'admin/config/people/captcha';
danielebarchiesi@2 59
danielebarchiesi@2 60
danielebarchiesi@2 61 function setUp() {
danielebarchiesi@2 62 // Load two modules: the captcha module itself and the comment module for testing anonymous comments.
danielebarchiesi@2 63 parent::setUp('captcha', 'comment');
danielebarchiesi@2 64 module_load_include('inc', 'captcha');
danielebarchiesi@2 65
danielebarchiesi@2 66 // Create a normal user.
danielebarchiesi@2 67 $permissions = array(
danielebarchiesi@2 68 'access comments', 'post comments', 'skip comment approval',
danielebarchiesi@2 69 'access content', 'create page content', 'edit own page content',
danielebarchiesi@2 70 );
danielebarchiesi@2 71 $this->normal_user = $this->drupalCreateUser($permissions);
danielebarchiesi@2 72
danielebarchiesi@2 73 // Create an admin user.
danielebarchiesi@2 74 $permissions[] = 'administer CAPTCHA settings';
danielebarchiesi@2 75 $permissions[] = 'skip CAPTCHA';
danielebarchiesi@2 76 $permissions[] = 'administer permissions';
danielebarchiesi@2 77 $permissions[] = 'administer content types';
danielebarchiesi@2 78 $this->admin_user = $this->drupalCreateUser($permissions);
danielebarchiesi@2 79
danielebarchiesi@2 80 // Put comments on page nodes on a separate page (default in D7: below post).
danielebarchiesi@2 81 variable_set('comment_form_location_page', COMMENT_FORM_SEPARATE_PAGE);
danielebarchiesi@2 82
danielebarchiesi@2 83 }
danielebarchiesi@2 84
danielebarchiesi@2 85 /**
danielebarchiesi@2 86 * Assert that the response is accepted:
danielebarchiesi@2 87 * no "unknown CSID" message, no "CSID reuse attack detection" message,
danielebarchiesi@2 88 * no "wrong answer" message.
danielebarchiesi@2 89 */
danielebarchiesi@2 90 protected function assertCaptchaResponseAccepted() {
danielebarchiesi@2 91 // There should be no error message about unknown CAPTCHA session ID.
danielebarchiesi@2 92 $this->assertNoText(t(CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE),
danielebarchiesi@2 93 'CAPTCHA response should be accepted (known CSID).',
danielebarchiesi@2 94 'CAPTCHA');
danielebarchiesi@2 95 // There should be no error message about CSID reuse attack.
danielebarchiesi@2 96 $this->assertNoText(t(CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE),
danielebarchiesi@2 97 'CAPTCHA response should be accepted (no CAPTCHA session reuse attack detection).',
danielebarchiesi@2 98 'CAPTCHA');
danielebarchiesi@2 99 // There should be no error message about wrong response.
danielebarchiesi@2 100 $this->assertNoText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
danielebarchiesi@2 101 'CAPTCHA response should be accepted (correct response).',
danielebarchiesi@2 102 'CAPTCHA');
danielebarchiesi@2 103 }
danielebarchiesi@2 104
danielebarchiesi@2 105 /**
danielebarchiesi@2 106 * Assert that there is a CAPTCHA on the form or not.
danielebarchiesi@2 107 * @param bool $presence whether there should be a CAPTCHA or not.
danielebarchiesi@2 108 */
danielebarchiesi@2 109 protected function assertCaptchaPresence($presence) {
danielebarchiesi@2 110 if ($presence) {
danielebarchiesi@2 111 $this->assertText(_captcha_get_description(),
danielebarchiesi@2 112 'There should be a CAPTCHA on the form.', 'CAPTCHA');
danielebarchiesi@2 113 }
danielebarchiesi@2 114 else {
danielebarchiesi@2 115 $this->assertNoText(_captcha_get_description(),
danielebarchiesi@2 116 'There should be no CAPTCHA on the form.', 'CAPTCHA');
danielebarchiesi@2 117 }
danielebarchiesi@2 118 }
danielebarchiesi@2 119
danielebarchiesi@2 120 /**
danielebarchiesi@2 121 * Helper function to create a node with comments enabled.
danielebarchiesi@2 122 *
danielebarchiesi@2 123 * @return
danielebarchiesi@2 124 * Created node object.
danielebarchiesi@2 125 */
danielebarchiesi@2 126 protected function createNodeWithCommentsEnabled($type='page') {
danielebarchiesi@2 127 $node_settings = array(
danielebarchiesi@2 128 'type' => $type,
danielebarchiesi@2 129 'comment' => COMMENT_NODE_OPEN,
danielebarchiesi@2 130 );
danielebarchiesi@2 131 $node = $this->drupalCreateNode($node_settings);
danielebarchiesi@2 132 return $node;
danielebarchiesi@2 133 }
danielebarchiesi@2 134
danielebarchiesi@2 135 /**
danielebarchiesi@2 136 * Helper function to generate a form values array for comment forms
danielebarchiesi@2 137 */
danielebarchiesi@2 138 protected function getCommentFormValues() {
danielebarchiesi@2 139 $edit = array(
danielebarchiesi@2 140 'subject' => 'comment_subject ' . $this->randomName(32),
danielebarchiesi@2 141 'comment_body[' . LANGUAGE_NONE . '][0][value]' => 'comment_body ' . $this->randomName(256),
danielebarchiesi@2 142 );
danielebarchiesi@2 143 return $edit;
danielebarchiesi@2 144 }
danielebarchiesi@2 145
danielebarchiesi@2 146 /**
danielebarchiesi@2 147 * Helper function to generate a form values array for node forms
danielebarchiesi@2 148 */
danielebarchiesi@2 149 protected function getNodeFormValues() {
danielebarchiesi@2 150 $edit = array(
danielebarchiesi@2 151 'title' => 'node_title ' . $this->randomName(32),
danielebarchiesi@2 152 'body[' . LANGUAGE_NONE . '][0][value]' => 'node_body ' . $this->randomName(256),
danielebarchiesi@2 153 );
danielebarchiesi@2 154 return $edit;
danielebarchiesi@2 155 }
danielebarchiesi@2 156
danielebarchiesi@2 157
danielebarchiesi@2 158 /**
danielebarchiesi@2 159 * Get the CAPTCHA session id from the current form in the browser.
danielebarchiesi@2 160 */
danielebarchiesi@2 161 protected function getCaptchaSidFromForm() {
danielebarchiesi@2 162 $elements = $this->xpath('//input[@name="captcha_sid"]');
danielebarchiesi@2 163 $captcha_sid = (int) $elements[0]['value'];
danielebarchiesi@2 164 return $captcha_sid;
danielebarchiesi@2 165 }
danielebarchiesi@2 166 /**
danielebarchiesi@2 167 * Get the CAPTCHA token from the current form in the browser.
danielebarchiesi@2 168 */
danielebarchiesi@2 169 protected function getCaptchaTokenFromForm() {
danielebarchiesi@2 170 $elements = $this->xpath('//input[@name="captcha_token"]');
danielebarchiesi@2 171 $captcha_token = (int) $elements[0]['value'];
danielebarchiesi@2 172 return $captcha_token;
danielebarchiesi@2 173 }
danielebarchiesi@2 174
danielebarchiesi@2 175 /**
danielebarchiesi@2 176 * Get the solution of the math CAPTCHA from the current form in the browser.
danielebarchiesi@2 177 */
danielebarchiesi@2 178 protected function getMathCaptchaSolutionFromForm() {
danielebarchiesi@2 179 // Get the math challenge.
danielebarchiesi@2 180 $elements = $this->xpath('//div[@class="form-item form-type-textfield form-item-captcha-response"]/span[@class="field-prefix"]');
danielebarchiesi@2 181 $challenge = (string) $elements[0];
danielebarchiesi@2 182 // Extract terms and operator from challenge.
danielebarchiesi@2 183 $matches = array();
danielebarchiesi@2 184 $ret = preg_match('/\\s*(\\d+)\\s*(-|\\+)\\s*(\\d+)\\s*=\\s*/', $challenge, $matches);
danielebarchiesi@2 185 // Solve the challenge
danielebarchiesi@2 186 $a = (int) $matches[1];
danielebarchiesi@2 187 $b = (int) $matches[3];
danielebarchiesi@2 188 $solution = $matches[2] == '-' ? $a - $b : $a + $b;
danielebarchiesi@2 189 return $solution;
danielebarchiesi@2 190 }
danielebarchiesi@2 191
danielebarchiesi@2 192 /**
danielebarchiesi@2 193 * Helper function to allow comment posting for anonymous users.
danielebarchiesi@2 194 */
danielebarchiesi@2 195 protected function allowCommentPostingForAnonymousVisitors() {
danielebarchiesi@2 196 // Log in as admin.
danielebarchiesi@2 197 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 198 // Post user permissions form
danielebarchiesi@2 199 $edit = array(
danielebarchiesi@2 200 '1[access comments]' => true,
danielebarchiesi@2 201 '1[post comments]' => true,
danielebarchiesi@2 202 '1[skip comment approval]' => true,
danielebarchiesi@2 203 );
danielebarchiesi@2 204 $this->drupalPost('admin/people/permissions', $edit, 'Save permissions');
danielebarchiesi@2 205 $this->assertText('The changes have been saved.');
danielebarchiesi@2 206 // Log admin out
danielebarchiesi@2 207 $this->drupalLogout();
danielebarchiesi@2 208 }
danielebarchiesi@2 209
danielebarchiesi@2 210 }
danielebarchiesi@2 211
danielebarchiesi@2 212
danielebarchiesi@2 213
danielebarchiesi@2 214 class CaptchaTestCase extends CaptchaBaseWebTestCase {
danielebarchiesi@2 215
danielebarchiesi@2 216 public static function getInfo() {
danielebarchiesi@2 217 return array(
danielebarchiesi@2 218 'name' => t('General CAPTCHA functionality'),
danielebarchiesi@2 219 'description' => t('Testing of the basic CAPTCHA functionality.'),
danielebarchiesi@2 220 'group' => t('CAPTCHA'),
danielebarchiesi@2 221 );
danielebarchiesi@2 222 }
danielebarchiesi@2 223
danielebarchiesi@2 224 /**
danielebarchiesi@2 225 * Testing the protection of the user log in form.
danielebarchiesi@2 226 */
danielebarchiesi@2 227 function testCaptchaOnLoginForm() {
danielebarchiesi@2 228 // Create user and test log in without CAPTCHA.
danielebarchiesi@2 229 $user = $this->drupalCreateUser();
danielebarchiesi@2 230 $this->drupalLogin($user);
danielebarchiesi@2 231 // Log out again.
danielebarchiesi@2 232 $this->drupalLogout();
danielebarchiesi@2 233
danielebarchiesi@2 234 // Set a CAPTCHA on login form
danielebarchiesi@2 235 captcha_set_form_id_setting('user_login', 'captcha/Math');
danielebarchiesi@2 236
danielebarchiesi@2 237 // Check if there is a CAPTCHA on the login form (look for the title).
danielebarchiesi@2 238 $this->drupalGet('user');
danielebarchiesi@2 239 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 240
danielebarchiesi@2 241 // Try to log in, which should fail.
danielebarchiesi@2 242 $edit = array(
danielebarchiesi@2 243 'name' => $user->name,
danielebarchiesi@2 244 'pass' => $user->pass_raw,
danielebarchiesi@2 245 'captcha_response' => '?',
danielebarchiesi@2 246 );
danielebarchiesi@2 247 $this->drupalPost('user', $edit, t('Log in'));
danielebarchiesi@2 248 // Check for error message.
danielebarchiesi@2 249 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
danielebarchiesi@2 250 'CAPTCHA should block user login form', 'CAPTCHA');
danielebarchiesi@2 251
danielebarchiesi@2 252 // And make sure that user is not logged in: check for name and password fields on ?q=user
danielebarchiesi@2 253 $this->drupalGet('user');
danielebarchiesi@2 254 $this->assertField('name', t('Username field found.'), 'CAPTCHA');
danielebarchiesi@2 255 $this->assertField('pass', t('Password field found.'), 'CAPTCHA');
danielebarchiesi@2 256
danielebarchiesi@2 257 }
danielebarchiesi@2 258
danielebarchiesi@2 259
danielebarchiesi@2 260 /**
danielebarchiesi@2 261 * Assert function for testing if comment posting works as it should.
danielebarchiesi@2 262 *
danielebarchiesi@2 263 * Creates node with comment writing enabled, tries to post comment
danielebarchiesi@2 264 * with given CAPTCHA response (caller should enable the desired
danielebarchiesi@2 265 * challenge on page node comment forms) and checks if the result is as expected.
danielebarchiesi@2 266 *
danielebarchiesi@2 267 * @param $captcha_response the response on the CAPTCHA
danielebarchiesi@2 268 * @param $should_pass boolean describing if the posting should pass or should be blocked
danielebarchiesi@2 269 * @param $message message to prefix to nested asserts
danielebarchiesi@2 270 */
danielebarchiesi@2 271 protected function assertCommentPosting($captcha_response, $should_pass, $message) {
danielebarchiesi@2 272 // Make sure comments on pages can be saved directely without preview.
danielebarchiesi@2 273 variable_set('comment_preview_page', DRUPAL_OPTIONAL);
danielebarchiesi@2 274
danielebarchiesi@2 275 // Create a node with comments enabled.
danielebarchiesi@2 276 $node = $this->createNodeWithCommentsEnabled();
danielebarchiesi@2 277
danielebarchiesi@2 278 // Post comment on node.
danielebarchiesi@2 279 $edit = $this->getCommentFormValues();
danielebarchiesi@2 280 $comment_subject = $edit['subject'];
danielebarchiesi@2 281 $comment_body = $edit['comment_body[' . LANGUAGE_NONE . '][0][value]'];
danielebarchiesi@2 282 $edit['captcha_response'] = $captcha_response;
danielebarchiesi@2 283 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Save'));
danielebarchiesi@2 284
danielebarchiesi@2 285 if ($should_pass) {
danielebarchiesi@2 286 // There should be no error message.
danielebarchiesi@2 287 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 288 // Get node page and check that comment shows up.
danielebarchiesi@2 289 $this->drupalGet('node/' . $node->nid);
danielebarchiesi@2 290 $this->assertText($comment_subject, $message .' Comment should show up on node page.', 'CAPTCHA');
danielebarchiesi@2 291 $this->assertText($comment_body, $message . ' Comment should show up on node page.', 'CAPTCHA');
danielebarchiesi@2 292 }
danielebarchiesi@2 293 else {
danielebarchiesi@2 294 // Check for error message.
danielebarchiesi@2 295 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE), $message .' Comment submission should be blocked.', 'CAPTCHA');
danielebarchiesi@2 296 // Get node page and check that comment is not present.
danielebarchiesi@2 297 $this->drupalGet('node/' . $node->nid);
danielebarchiesi@2 298 $this->assertNoText($comment_subject, $message .' Comment should not show up on node page.', 'CAPTCHA');
danielebarchiesi@2 299 $this->assertNoText($comment_body, $message . ' Comment should not show up on node page.', 'CAPTCHA');
danielebarchiesi@2 300 }
danielebarchiesi@2 301 }
danielebarchiesi@2 302
danielebarchiesi@2 303 /*
danielebarchiesi@2 304 * Testing the case sensistive/insensitive validation.
danielebarchiesi@2 305 */
danielebarchiesi@2 306 function testCaseInsensitiveValidation() {
danielebarchiesi@2 307 // Set Test CAPTCHA on comment form
danielebarchiesi@2 308 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
danielebarchiesi@2 309
danielebarchiesi@2 310 // Log in as normal user.
danielebarchiesi@2 311 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 312
danielebarchiesi@2 313 // Test case sensitive posting.
danielebarchiesi@2 314 variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE);
danielebarchiesi@2 315 $this->assertCommentPosting('Test 123', TRUE, 'Case sensitive validation of right casing.');
danielebarchiesi@2 316 $this->assertCommentPosting('test 123', FALSE, 'Case sensitive validation of wrong casing.');
danielebarchiesi@2 317 $this->assertCommentPosting('TEST 123', FALSE, 'Case sensitive validation of wrong casing.');
danielebarchiesi@2 318
danielebarchiesi@2 319 // Test case insensitive posting (the default)
danielebarchiesi@2 320 variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE);
danielebarchiesi@2 321 $this->assertCommentPosting('Test 123', TRUE, 'Case insensitive validation of right casing.');
danielebarchiesi@2 322 $this->assertCommentPosting('test 123', TRUE, 'Case insensitive validation of wrong casing.');
danielebarchiesi@2 323 $this->assertCommentPosting('TEST 123', TRUE, 'Case insensitive validation of wrong casing.');
danielebarchiesi@2 324
danielebarchiesi@2 325 }
danielebarchiesi@2 326
danielebarchiesi@2 327 /**
danielebarchiesi@2 328 * Test if the CAPTCHA description is only shown if there are challenge widgets to show.
danielebarchiesi@2 329 * For example, when a comment is previewed with correct CAPTCHA answer,
danielebarchiesi@2 330 * a challenge is generated and added to the form but removed in the pre_render phase.
danielebarchiesi@2 331 * The CAPTCHA description should not show up either.
danielebarchiesi@2 332 *
danielebarchiesi@2 333 * \see testCaptchaSessionReuseOnNodeForms()
danielebarchiesi@2 334 */
danielebarchiesi@2 335 function testCaptchaDescriptionAfterCommentPreview() {
danielebarchiesi@2 336 // Set Test CAPTCHA on comment form.
danielebarchiesi@2 337 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
danielebarchiesi@2 338
danielebarchiesi@2 339 // Log in as normal user.
danielebarchiesi@2 340 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 341
danielebarchiesi@2 342 // Create a node with comments enabled.
danielebarchiesi@2 343 $node = $this->createNodeWithCommentsEnabled();
danielebarchiesi@2 344
danielebarchiesi@2 345 // Preview comment with correct CAPTCHA answer.
danielebarchiesi@2 346 $edit = $this->getCommentFormValues();
danielebarchiesi@2 347 $edit['captcha_response'] = 'Test 123';
danielebarchiesi@2 348 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
danielebarchiesi@2 349
danielebarchiesi@2 350 // Check that there is no CAPTCHA after preview.
danielebarchiesi@2 351 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 352 }
danielebarchiesi@2 353
danielebarchiesi@2 354 /**
danielebarchiesi@2 355 * Test if the CAPTCHA session ID is reused when previewing nodes:
danielebarchiesi@2 356 * node preview after correct response should not show CAPTCHA anymore.
danielebarchiesi@2 357 * The preview functionality of comments and nodes works slightly different under the hood.
danielebarchiesi@2 358 * CAPTCHA module should be able to handle both.
danielebarchiesi@2 359 *
danielebarchiesi@2 360 * \see testCaptchaDescriptionAfterCommentPreview()
danielebarchiesi@2 361 */
danielebarchiesi@2 362 function testCaptchaSessionReuseOnNodeForms() {
danielebarchiesi@2 363 // Set Test CAPTCHA on page form.
danielebarchiesi@2 364 captcha_set_form_id_setting('page_node_form', 'captcha/Test');
danielebarchiesi@2 365
danielebarchiesi@2 366 // Log in as normal user.
danielebarchiesi@2 367 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 368
danielebarchiesi@2 369 // Page settings to post, with correct CAPTCHA answer.
danielebarchiesi@2 370 $edit = $this->getNodeFormValues();
danielebarchiesi@2 371 $edit['captcha_response'] = 'Test 123';
danielebarchiesi@2 372 // Preview the node
danielebarchiesi@2 373 $this->drupalPost('node/add/page', $edit, t('Preview'));
danielebarchiesi@2 374
danielebarchiesi@2 375 // Check that there is no CAPTCHA after preview.
danielebarchiesi@2 376 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 377 }
danielebarchiesi@2 378
danielebarchiesi@2 379
danielebarchiesi@2 380 /**
danielebarchiesi@2 381 * CAPTCHA should also be put on admin pages even if visitor
danielebarchiesi@2 382 * has no access
danielebarchiesi@2 383 */
danielebarchiesi@2 384 function testCaptchaOnLoginBlockOnAdminPagesIssue893810() {
danielebarchiesi@2 385 // Set a CAPTCHA on login block form
danielebarchiesi@2 386 captcha_set_form_id_setting('user_login_block', 'captcha/Math');
danielebarchiesi@2 387
danielebarchiesi@2 388 // Check if there is a CAPTCHA on home page.
danielebarchiesi@2 389 $this->drupalGet('node');
danielebarchiesi@2 390 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 391
danielebarchiesi@2 392 // Check there is a CAPTCHA on "forbidden" admin pages
danielebarchiesi@2 393 $this->drupalGet('admin');
danielebarchiesi@2 394 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 395 }
danielebarchiesi@2 396
danielebarchiesi@2 397 }
danielebarchiesi@2 398
danielebarchiesi@2 399
danielebarchiesi@2 400 class CaptchaAdminTestCase extends CaptchaBaseWebTestCase {
danielebarchiesi@2 401
danielebarchiesi@2 402 public static function getInfo() {
danielebarchiesi@2 403 return array(
danielebarchiesi@2 404 'name' => t('CAPTCHA administration functionality'),
danielebarchiesi@2 405 'description' => t('Testing of the CAPTCHA administration interface and functionality.'),
danielebarchiesi@2 406 'group' => t('CAPTCHA'),
danielebarchiesi@2 407 );
danielebarchiesi@2 408 }
danielebarchiesi@2 409
danielebarchiesi@2 410 /**
danielebarchiesi@2 411 * Test access to the admin pages.
danielebarchiesi@2 412 */
danielebarchiesi@2 413 function testAdminAccess() {
danielebarchiesi@2 414 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 415 $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
danielebarchiesi@2 416 file_put_contents('tmp.simpletest.html', $this->drupalGetContent());
danielebarchiesi@2 417 $this->assertText(t('Access denied'), 'Normal users should not be able to access the CAPTCHA admin pages', 'CAPTCHA');
danielebarchiesi@2 418
danielebarchiesi@2 419 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 420 $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
danielebarchiesi@2 421 $this->assertNoText(t('Access denied'), 'Admin users should be able to access the CAPTCHA admin pages', 'CAPTCHA');
danielebarchiesi@2 422 }
danielebarchiesi@2 423
danielebarchiesi@2 424 /**
danielebarchiesi@2 425 * Test the CAPTCHA point setting getter/setter.
danielebarchiesi@2 426 */
danielebarchiesi@2 427 function testCaptchaPointSettingGetterAndSetter() {
danielebarchiesi@2 428 $comment_form_id = self::COMMENT_FORM_ID;
danielebarchiesi@2 429 // Set to 'none'.
danielebarchiesi@2 430 captcha_set_form_id_setting($comment_form_id, 'none');
danielebarchiesi@2 431 $result = captcha_get_form_id_setting($comment_form_id);
danielebarchiesi@2 432 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
danielebarchiesi@2 433 $this->assertNull($result->module, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
danielebarchiesi@2 434 $this->assertNull($result->captcha_type, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
danielebarchiesi@2 435 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
danielebarchiesi@2 436 $this->assertEqual($result, 'none', 'Setting and symbolic getting CAPTCHA point: "none"', 'CAPTCHA');
danielebarchiesi@2 437 // Set to 'default'
danielebarchiesi@2 438 captcha_set_form_id_setting($comment_form_id, 'default');
danielebarchiesi@2 439 variable_set('captcha_default_challenge', 'foo/bar');
danielebarchiesi@2 440 $result = captcha_get_form_id_setting($comment_form_id);
danielebarchiesi@2 441 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
danielebarchiesi@2 442 $this->assertEqual($result->module, 'foo', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
danielebarchiesi@2 443 $this->assertEqual($result->captcha_type, 'bar', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
danielebarchiesi@2 444 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
danielebarchiesi@2 445 $this->assertEqual($result, 'default', 'Setting and symbolic getting CAPTCHA point: "default"', 'CAPTCHA');
danielebarchiesi@2 446 // Set to 'baz/boo'.
danielebarchiesi@2 447 captcha_set_form_id_setting($comment_form_id, 'baz/boo');
danielebarchiesi@2 448 $result = captcha_get_form_id_setting($comment_form_id);
danielebarchiesi@2 449 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
danielebarchiesi@2 450 $this->assertEqual($result->module, 'baz', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
danielebarchiesi@2 451 $this->assertEqual($result->captcha_type, 'boo', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
danielebarchiesi@2 452 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
danielebarchiesi@2 453 $this->assertEqual($result, 'baz/boo', 'Setting and symbolic getting CAPTCHA point: "baz/boo"', 'CAPTCHA');
danielebarchiesi@2 454 // Set to NULL (which should delete the CAPTCHA point setting entry).
danielebarchiesi@2 455 captcha_set_form_id_setting($comment_form_id, NULL);
danielebarchiesi@2 456 $result = captcha_get_form_id_setting($comment_form_id);
danielebarchiesi@2 457 $this->assertNull($result, 'Setting and getting CAPTCHA point: NULL', 'CAPTCHA');
danielebarchiesi@2 458 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
danielebarchiesi@2 459 $this->assertNull($result, 'Setting and symbolic getting CAPTCHA point: NULL', 'CAPTCHA');
danielebarchiesi@2 460 // Set with object.
danielebarchiesi@2 461 $captcha_type = new stdClass;
danielebarchiesi@2 462 $captcha_type->module = 'baba';
danielebarchiesi@2 463 $captcha_type->captcha_type = 'fofo';
danielebarchiesi@2 464 captcha_set_form_id_setting($comment_form_id, $captcha_type);
danielebarchiesi@2 465 $result = captcha_get_form_id_setting($comment_form_id);
danielebarchiesi@2 466 $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
danielebarchiesi@2 467 $this->assertEqual($result->module, 'baba', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
danielebarchiesi@2 468 $this->assertEqual($result->captcha_type, 'fofo', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
danielebarchiesi@2 469 $result = captcha_get_form_id_setting($comment_form_id, TRUE);
danielebarchiesi@2 470 $this->assertEqual($result, 'baba/fofo', 'Setting and symbolic getting CAPTCHA point: "baba/fofo"', 'CAPTCHA');
danielebarchiesi@2 471
danielebarchiesi@2 472 }
danielebarchiesi@2 473
danielebarchiesi@2 474
danielebarchiesi@2 475 /**
danielebarchiesi@2 476 * Helper function for checking CAPTCHA setting of a form.
danielebarchiesi@2 477 *
danielebarchiesi@2 478 * @param $form_id the form_id of the form to investigate.
danielebarchiesi@2 479 * @param $challenge_type what the challenge type should be:
danielebarchiesi@2 480 * NULL, 'none', 'default' or something like 'captcha/Math'
danielebarchiesi@2 481 */
danielebarchiesi@2 482 protected function assertCaptchaSetting($form_id, $challenge_type) {
danielebarchiesi@2 483 $result = captcha_get_form_id_setting(self::COMMENT_FORM_ID, TRUE);
danielebarchiesi@2 484 $this->assertEqual($result, $challenge_type,
danielebarchiesi@2 485 t('Check CAPTCHA setting for form: expected: @expected, received: @received.',
danielebarchiesi@2 486 array('@expected' => var_export($challenge_type, TRUE), '@received' => var_export($result, TRUE))),
danielebarchiesi@2 487 'CAPTCHA');
danielebarchiesi@2 488 }
danielebarchiesi@2 489
danielebarchiesi@2 490 /**
danielebarchiesi@2 491 * Testing of the CAPTCHA administration links.
danielebarchiesi@2 492 */
danielebarchiesi@2 493 function testCaptchAdminLinks() {
danielebarchiesi@2 494 // Log in as admin
danielebarchiesi@2 495 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 496
danielebarchiesi@2 497 // Enable CAPTCHA administration links.
danielebarchiesi@2 498 $edit = array(
danielebarchiesi@2 499 'captcha_administration_mode' => TRUE,
danielebarchiesi@2 500 );
danielebarchiesi@2 501 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
danielebarchiesi@2 502
danielebarchiesi@2 503 // Create a node with comments enabled.
danielebarchiesi@2 504 $node = $this->createNodeWithCommentsEnabled();
danielebarchiesi@2 505
danielebarchiesi@2 506 // Go to node page
danielebarchiesi@2 507 $this->drupalGet('node/' . $node->nid);
danielebarchiesi@2 508
danielebarchiesi@2 509 // Click the add new comment link
danielebarchiesi@2 510 $this->clickLink(t('Add new comment'));
danielebarchiesi@2 511 $add_comment_url = $this->getUrl();
danielebarchiesi@2 512 // Remove fragment part from comment URL to avoid problems with later asserts
danielebarchiesi@2 513 $add_comment_url = strtok($add_comment_url, "#");
danielebarchiesi@2 514
danielebarchiesi@2 515 ////////////////////////////////////////////////////////////
danielebarchiesi@2 516 // Click the CAPTCHA admin link to enable a challenge.
danielebarchiesi@2 517 $this->clickLink(t('Place a CAPTCHA here for untrusted users.'));
danielebarchiesi@2 518 // Enable Math CAPTCHA.
danielebarchiesi@2 519 $edit = array('captcha_type' => 'captcha/Math');
danielebarchiesi@2 520 $this->drupalPost($this->getUrl(), $edit, t('Save'));
danielebarchiesi@2 521
danielebarchiesi@2 522 // Check if returned to original comment form.
danielebarchiesi@2 523 $this->assertUrl($add_comment_url, array(),
danielebarchiesi@2 524 'After setting CAPTCHA with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
danielebarchiesi@2 525 // Check if CAPTCHA was successfully enabled (on CAPTCHA admin links fieldset).
danielebarchiesi@2 526 $this->assertText(t('CAPTCHA: challenge "@type" enabled', array('@type' => 'Math')),
danielebarchiesi@2 527 'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
danielebarchiesi@2 528 // Check if CAPTCHA was successfully enabled (through API).
danielebarchiesi@2 529 $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'captcha/Math');
danielebarchiesi@2 530
danielebarchiesi@2 531 //////////////////////////////////////////////////////
danielebarchiesi@2 532 // Edit challenge type through CAPTCHA admin links.
danielebarchiesi@2 533 $this->clickLink(t('change'));
danielebarchiesi@2 534 // Enable Math CAPTCHA.
danielebarchiesi@2 535 $edit = array('captcha_type' => 'default');
danielebarchiesi@2 536 $this->drupalPost($this->getUrl(), $edit, t('Save'));
danielebarchiesi@2 537
danielebarchiesi@2 538 // Check if returned to original comment form.
danielebarchiesi@2 539 $this->assertEqual($add_comment_url, $this->getUrl(),
danielebarchiesi@2 540 'After editing challenge type CAPTCHA admin links: should return to original form.', 'CAPTCHA');
danielebarchiesi@2 541 // Check if CAPTCHA was successfully changed (on CAPTCHA admin links fieldset).
danielebarchiesi@2 542 // This is actually the same as the previous setting because the captcha/Math is the
danielebarchiesi@2 543 // default for the default challenge. TODO Make sure the edit is a real change.
danielebarchiesi@2 544 $this->assertText(t('CAPTCHA: challenge "@type" enabled', array('@type' => 'Math')),
danielebarchiesi@2 545 'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
danielebarchiesi@2 546 // Check if CAPTCHA was successfully edited (through API).
danielebarchiesi@2 547 $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'default');
danielebarchiesi@2 548
danielebarchiesi@2 549
danielebarchiesi@2 550
danielebarchiesi@2 551 //////////////////////////////////////////////////////
danielebarchiesi@2 552 // Disable challenge through CAPTCHA admin links.
danielebarchiesi@2 553 $this->clickLink(t('disable'));
danielebarchiesi@2 554 // And confirm.
danielebarchiesi@2 555 $this->drupalPost($this->getUrl(), array(), 'Disable');
danielebarchiesi@2 556
danielebarchiesi@2 557 // Check if returned to original comment form.
danielebarchiesi@2 558 $this->assertEqual($add_comment_url, $this->getUrl(),
danielebarchiesi@2 559 'After disablin challenge with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
danielebarchiesi@2 560 // Check if CAPTCHA was successfully disabled (on CAPTCHA admin links fieldset).
danielebarchiesi@2 561 $this->assertText(t('CAPTCHA: no challenge enabled'),
danielebarchiesi@2 562 'Disable challenge through the CAPTCHA admin links', 'CAPTCHA');
danielebarchiesi@2 563 // Check if CAPTCHA was successfully disabled (through API).
danielebarchiesi@2 564 $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'none');
danielebarchiesi@2 565
danielebarchiesi@2 566 }
danielebarchiesi@2 567
danielebarchiesi@2 568
danielebarchiesi@2 569 function testUntrustedUserPosting() {
danielebarchiesi@2 570 // Set CAPTCHA on comment form.
danielebarchiesi@2 571 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Math');
danielebarchiesi@2 572
danielebarchiesi@2 573 // Create a node with comments enabled.
danielebarchiesi@2 574 $node = $this->createNodeWithCommentsEnabled();
danielebarchiesi@2 575
danielebarchiesi@2 576 // Log in as normal (untrusted) user.
danielebarchiesi@2 577 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 578
danielebarchiesi@2 579 // Go to node page and click the "add comment" link.
danielebarchiesi@2 580 $this->drupalGet('node/' . $node->nid);
danielebarchiesi@2 581 $this->clickLink(t('Add new comment'));
danielebarchiesi@2 582 $add_comment_url = $this->getUrl();
danielebarchiesi@2 583
danielebarchiesi@2 584 // Check if CAPTCHA is visible on form.
danielebarchiesi@2 585 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 586 // Try to post a comment with wrong answer.
danielebarchiesi@2 587 $edit = $this->getCommentFormValues();
danielebarchiesi@2 588 $edit['captcha_response'] = 'xx';
danielebarchiesi@2 589 $this->drupalPost($add_comment_url, $edit, t('Preview'));
danielebarchiesi@2 590 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
danielebarchiesi@2 591 'wrong CAPTCHA should block form submission.', 'CAPTCHA');
danielebarchiesi@2 592
danielebarchiesi@2 593 //TODO: more testing for untrusted posts.
danielebarchiesi@2 594 }
danielebarchiesi@2 595
danielebarchiesi@2 596
danielebarchiesi@2 597
danielebarchiesi@2 598 /**
danielebarchiesi@2 599 * Test XSS vulnerability on CAPTCHA description.
danielebarchiesi@2 600 */
danielebarchiesi@2 601 function testXssOnCaptchaDescription() {
danielebarchiesi@2 602 // Set CAPTCHA on user register form.
danielebarchiesi@2 603 captcha_set_form_id_setting('user_register', 'captcha/Math');
danielebarchiesi@2 604
danielebarchiesi@2 605 // Put Javascript snippet in CAPTCHA description.
danielebarchiesi@2 606 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 607 $xss = '<script type="text/javascript">alert("xss")</script>';
danielebarchiesi@2 608 $edit = array('captcha_description' => $xss);
danielebarchiesi@2 609 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
danielebarchiesi@2 610
danielebarchiesi@2 611 // Visit user register form and check if Javascript snippet is there.
danielebarchiesi@2 612 $this->drupalLogout();
danielebarchiesi@2 613 $this->drupalGet('user/register');
danielebarchiesi@2 614 $this->assertNoRaw($xss, 'Javascript should not be allowed in CAPTCHA description.', 'CAPTCHA');
danielebarchiesi@2 615
danielebarchiesi@2 616 }
danielebarchiesi@2 617
danielebarchiesi@2 618 /**
danielebarchiesi@2 619 * Test the CAPTCHA placement clearing.
danielebarchiesi@2 620 */
danielebarchiesi@2 621 function testCaptchaPlacementCacheClearing() {
danielebarchiesi@2 622 // Set CAPTCHA on user register form.
danielebarchiesi@2 623 captcha_set_form_id_setting('user_register_form', 'captcha/Math');
danielebarchiesi@2 624 // Visit user register form to fill the CAPTCHA placement cache.
danielebarchiesi@2 625 $this->drupalGet('user/register');
danielebarchiesi@2 626 // Check if there is CAPTCHA placement cache.
danielebarchiesi@2 627 $placement_map = variable_get('captcha_placement_map_cache', NULL);
danielebarchiesi@2 628 $this->assertNotNull($placement_map, 'CAPTCHA placement cache should be set.');
danielebarchiesi@2 629 // Clear the cache
danielebarchiesi@2 630 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 631 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, array(), t('Clear the CAPTCHA placement cache'));
danielebarchiesi@2 632 // Check that the placement cache is unset
danielebarchiesi@2 633 $placement_map = variable_get('captcha_placement_map_cache', NULL);
danielebarchiesi@2 634 $this->assertNull($placement_map, 'CAPTCHA placement cache should be unset after cache clear.');
danielebarchiesi@2 635 }
danielebarchiesi@2 636
danielebarchiesi@2 637 /**
danielebarchiesi@2 638 * Helper function to get the CAPTCHA point setting straight from the database.
danielebarchiesi@2 639 * @param string $form_id
danielebarchiesi@2 640 * @return stdClass object
danielebarchiesi@2 641 */
danielebarchiesi@2 642 private function getCaptchaPointSettingFromDatabase($form_id) {
danielebarchiesi@2 643 $result = db_query(
danielebarchiesi@2 644 "SELECT * FROM {captcha_points} WHERE form_id = :form_id",
danielebarchiesi@2 645 array(':form_id' => $form_id)
danielebarchiesi@2 646 )->fetchObject();
danielebarchiesi@2 647 return $result;
danielebarchiesi@2 648 }
danielebarchiesi@2 649
danielebarchiesi@2 650 /**
danielebarchiesi@2 651 * Method for testing the CAPTCHA point administration
danielebarchiesi@2 652 */
danielebarchiesi@2 653 function testCaptchaPointAdministration() {
danielebarchiesi@2 654 // Generate CAPTCHA point data:
danielebarchiesi@2 655 // Drupal form ID should consist of lowercase alphanumerics and underscore)
danielebarchiesi@2 656 $captcha_point_form_id = 'form_' . strtolower($this->randomName(32));
danielebarchiesi@2 657 // the Math CAPTCHA by the CAPTCHA module is always available, so let's use it
danielebarchiesi@2 658 $captcha_point_module = 'captcha';
danielebarchiesi@2 659 $captcha_point_type = 'Math';
danielebarchiesi@2 660
danielebarchiesi@2 661 // Log in as admin
danielebarchiesi@2 662 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 663
danielebarchiesi@2 664 // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point
danielebarchiesi@2 665 $form_values = array(
danielebarchiesi@2 666 'captcha_point_form_id' => $captcha_point_form_id,
danielebarchiesi@2 667 'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
danielebarchiesi@2 668 );
danielebarchiesi@2 669 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point', $form_values, t('Save'));
danielebarchiesi@2 670 $this->assertText(t('Saved CAPTCHA point settings.'),
danielebarchiesi@2 671 'Saving of CAPTCHA point settings');
danielebarchiesi@2 672
danielebarchiesi@2 673 // Check in database
danielebarchiesi@2 674 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
danielebarchiesi@2 675 $this->assertEqual($result->module, $captcha_point_module,
danielebarchiesi@2 676 'Enabled CAPTCHA point should have module set');
danielebarchiesi@2 677 $this->assertEqual($result->captcha_type, $captcha_point_type,
danielebarchiesi@2 678 'Enabled CAPTCHA point should have type set');
danielebarchiesi@2 679
danielebarchiesi@2 680 // Disable CAPTCHA point again
danielebarchiesi@2 681 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/disable', array(), t('Disable'));
danielebarchiesi@2 682 $this->assertRaw(t('Disabled CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)), 'Disabling of CAPTCHA point');
danielebarchiesi@2 683
danielebarchiesi@2 684 // Check in database
danielebarchiesi@2 685 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
danielebarchiesi@2 686 $this->assertNull($result->module,
danielebarchiesi@2 687 'Disabled CAPTCHA point should have NULL as module');
danielebarchiesi@2 688 $this->assertNull($result->captcha_type,
danielebarchiesi@2 689 'Disabled CAPTCHA point should have NULL as type');
danielebarchiesi@2 690
danielebarchiesi@2 691 // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point/$form_id
danielebarchiesi@2 692 $form_values = array(
danielebarchiesi@2 693 'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
danielebarchiesi@2 694 );
danielebarchiesi@2 695 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id, $form_values, t('Save'));
danielebarchiesi@2 696 $this->assertText(t('Saved CAPTCHA point settings.'),
danielebarchiesi@2 697 'Saving of CAPTCHA point settings');
danielebarchiesi@2 698
danielebarchiesi@2 699 // Check in database
danielebarchiesi@2 700 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
danielebarchiesi@2 701 $this->assertEqual($result->module, $captcha_point_module,
danielebarchiesi@2 702 'Enabled CAPTCHA point should have module set');
danielebarchiesi@2 703 $this->assertEqual($result->captcha_type, $captcha_point_type,
danielebarchiesi@2 704 'Enabled CAPTCHA point should have type set');
danielebarchiesi@2 705
danielebarchiesi@2 706 // Delete CAPTCHA point
danielebarchiesi@2 707 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete', array(), t('Delete'));
danielebarchiesi@2 708 $this->assertRaw(t('Deleted CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)),
danielebarchiesi@2 709 'Deleting of CAPTCHA point');
danielebarchiesi@2 710
danielebarchiesi@2 711 // Check in database
danielebarchiesi@2 712 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
danielebarchiesi@2 713 $this->assertFalse($result, 'Deleted CAPTCHA point should be in database');
danielebarchiesi@2 714 }
danielebarchiesi@2 715
danielebarchiesi@2 716 /**
danielebarchiesi@2 717 * Method for testing the CAPTCHA point administration
danielebarchiesi@2 718 */
danielebarchiesi@2 719 function testCaptchaPointAdministrationByNonAdmin() {
danielebarchiesi@2 720 // First add a CAPTCHA point (as admin)
danielebarchiesi@2 721 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 722 $captcha_point_form_id = 'form_' . strtolower($this->randomName(32));
danielebarchiesi@2 723 $captcha_point_module = 'captcha';
danielebarchiesi@2 724 $captcha_point_type = 'Math';
danielebarchiesi@2 725 $form_values = array(
danielebarchiesi@2 726 'captcha_point_form_id' => $captcha_point_form_id,
danielebarchiesi@2 727 'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
danielebarchiesi@2 728 );
danielebarchiesi@2 729 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/', $form_values, t('Save'));
danielebarchiesi@2 730 $this->assertText(t('Saved CAPTCHA point settings.'),
danielebarchiesi@2 731 'Saving of CAPTCHA point settings');
danielebarchiesi@2 732
danielebarchiesi@2 733 // Switch from admin to nonadmin
danielebarchiesi@2 734 $this->drupalGet(url('logout', array('absolute' => TRUE)));
danielebarchiesi@2 735 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 736
danielebarchiesi@2 737
danielebarchiesi@2 738 // Try to set CAPTCHA point through admin/user/captcha/captcha/captcha_point
danielebarchiesi@2 739 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point');
danielebarchiesi@2 740 $this->assertText(t('You are not authorized to access this page.'),
danielebarchiesi@2 741 'Non admin should not be able to set a CAPTCHA point');
danielebarchiesi@2 742
danielebarchiesi@2 743 // Try to set CAPTCHA point through admin/user/captcha/captcha/captcha_point/$form_id
danielebarchiesi@2 744 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/' . 'form_' . strtolower($this->randomName(32)));
danielebarchiesi@2 745 $this->assertText(t('You are not authorized to access this page.'),
danielebarchiesi@2 746 'Non admin should not be able to set a CAPTCHA point');
danielebarchiesi@2 747
danielebarchiesi@2 748 // Try to disable the CAPTCHA point
danielebarchiesi@2 749 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/disable');
danielebarchiesi@2 750 $this->assertText(t('You are not authorized to access this page.'),
danielebarchiesi@2 751 'Non admin should not be able to disable a CAPTCHA point');
danielebarchiesi@2 752
danielebarchiesi@2 753 // Try to delete the CAPTCHA point
danielebarchiesi@2 754 $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete');
danielebarchiesi@2 755 $this->assertText(t('You are not authorized to access this page.'),
danielebarchiesi@2 756 'Non admin should not be able to delete a CAPTCHA point');
danielebarchiesi@2 757
danielebarchiesi@2 758 // Switch from nonadmin to admin again
danielebarchiesi@2 759 $this->drupalGet(url('logout', array('absolute' => TRUE)));
danielebarchiesi@2 760 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 761
danielebarchiesi@2 762 // Check if original CAPTCHA point still exists in database
danielebarchiesi@2 763 $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
danielebarchiesi@2 764 $this->assertEqual($result->module, $captcha_point_module,
danielebarchiesi@2 765 'Enabled CAPTCHA point should still have module set');
danielebarchiesi@2 766 $this->assertEqual($result->captcha_type, $captcha_point_type,
danielebarchiesi@2 767 'Enabled CAPTCHA point should still have type set');
danielebarchiesi@2 768
danielebarchiesi@2 769 // Delete CAPTCHA point
danielebarchiesi@2 770 $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete', array(), t('Delete'));
danielebarchiesi@2 771 $this->assertRaw(t('Deleted CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)),
danielebarchiesi@2 772 'Deleting of CAPTCHA point');
danielebarchiesi@2 773 }
danielebarchiesi@2 774
danielebarchiesi@2 775
danielebarchiesi@2 776
danielebarchiesi@2 777 }
danielebarchiesi@2 778
danielebarchiesi@2 779
danielebarchiesi@2 780
danielebarchiesi@2 781 class CaptchaPersistenceTestCase extends CaptchaBaseWebTestCase {
danielebarchiesi@2 782
danielebarchiesi@2 783 public static function getInfo() {
danielebarchiesi@2 784 return array(
danielebarchiesi@2 785 'name' => t('CAPTCHA persistence functionality'),
danielebarchiesi@2 786 'description' => t('Testing of the CAPTCHA persistence functionality.'),
danielebarchiesi@2 787 'group' => t('CAPTCHA'),
danielebarchiesi@2 788 );
danielebarchiesi@2 789 }
danielebarchiesi@2 790
danielebarchiesi@2 791 /**
danielebarchiesi@2 792 * Set up the persistence and CAPTCHA settings.
danielebarchiesi@2 793 * @param int $persistence the persistence value.
danielebarchiesi@2 794 */
danielebarchiesi@2 795 private function setUpPersistence($persistence) {
danielebarchiesi@2 796 // Log in as admin
danielebarchiesi@2 797 $this->drupalLogin($this->admin_user);
danielebarchiesi@2 798 // Set persistence.
danielebarchiesi@2 799 $edit = array('captcha_persistence' => $persistence);
danielebarchiesi@2 800 $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
danielebarchiesi@2 801 // Log admin out.
danielebarchiesi@2 802 $this->drupalLogout();
danielebarchiesi@2 803
danielebarchiesi@2 804 // Set the Test123 CAPTCHA on user register and comment form.
danielebarchiesi@2 805 // We have to do this with the function captcha_set_form_id_setting()
danielebarchiesi@2 806 // (because the CATCHA admin form does not show the Test123 option).
danielebarchiesi@2 807 // We also have to do this after all usage of the CAPTCHA admin form
danielebarchiesi@2 808 // (because posting the CAPTCHA admin form would set the CAPTCHA to 'none').
danielebarchiesi@2 809 captcha_set_form_id_setting('user_login', 'captcha/Test');
danielebarchiesi@2 810 $this->drupalGet('user');
danielebarchiesi@2 811 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 812 captcha_set_form_id_setting('user_register_form', 'captcha/Test');
danielebarchiesi@2 813 $this->drupalGet('user/register');
danielebarchiesi@2 814 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 815 }
danielebarchiesi@2 816
danielebarchiesi@2 817 protected function assertPreservedCsid($captcha_sid_initial) {
danielebarchiesi@2 818 $captcha_sid = $this->getCaptchaSidFromForm();
danielebarchiesi@2 819 $this->assertEqual($captcha_sid_initial, $captcha_sid,
danielebarchiesi@2 820 "CAPTCHA session ID should be preserved (expected: $captcha_sid_initial, found: $captcha_sid).");
danielebarchiesi@2 821 }
danielebarchiesi@2 822
danielebarchiesi@2 823 protected function assertDifferentCsid($captcha_sid_initial) {
danielebarchiesi@2 824 $captcha_sid = $this->getCaptchaSidFromForm();
danielebarchiesi@2 825 $this->assertNotEqual($captcha_sid_initial, $captcha_sid,
danielebarchiesi@2 826 "CAPTCHA session ID should be different.");
danielebarchiesi@2 827 }
danielebarchiesi@2 828
danielebarchiesi@2 829 function testPersistenceAlways(){
danielebarchiesi@2 830 // Set up of persistence and CAPTCHAs.
danielebarchiesi@2 831 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SHOW_ALWAYS);
danielebarchiesi@2 832
danielebarchiesi@2 833 // Go to login form and check if there is a CAPTCHA on the login form (look for the title).
danielebarchiesi@2 834 $this->drupalGet('user');
danielebarchiesi@2 835 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 836 $captcha_sid_initial = $this->getCaptchaSidFromForm();
danielebarchiesi@2 837
danielebarchiesi@2 838 // Try to with wrong user name and password, but correct CAPTCHA.
danielebarchiesi@2 839 $edit = array(
danielebarchiesi@2 840 'name' => 'foobar',
danielebarchiesi@2 841 'pass' => 'bazlaz',
danielebarchiesi@2 842 'captcha_response' => 'Test 123',
danielebarchiesi@2 843 );
danielebarchiesi@2 844 $this->drupalPost(NULL, $edit, t('Log in'));
danielebarchiesi@2 845 // Check that there was no error message for the CAPTCHA.
danielebarchiesi@2 846 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 847
danielebarchiesi@2 848 // Name and password were wrong, we should get an updated form with a fresh CAPTCHA.
danielebarchiesi@2 849 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 850 $this->assertPreservedCsid($captcha_sid_initial);
danielebarchiesi@2 851
danielebarchiesi@2 852 // Post from again.
danielebarchiesi@2 853 $this->drupalPost(NULL, $edit, t('Log in'));
danielebarchiesi@2 854 // Check that there was no error message for the CAPTCHA.
danielebarchiesi@2 855 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 856 $this->assertPreservedCsid($captcha_sid_initial);
danielebarchiesi@2 857
danielebarchiesi@2 858 }
danielebarchiesi@2 859
danielebarchiesi@2 860 function testPersistencePerFormInstance(){
danielebarchiesi@2 861 // Set up of persistence and CAPTCHAs.
danielebarchiesi@2 862 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
danielebarchiesi@2 863
danielebarchiesi@2 864 // Go to login form and check if there is a CAPTCHA on the login form.
danielebarchiesi@2 865 $this->drupalGet('user');
danielebarchiesi@2 866 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 867 $captcha_sid_initial = $this->getCaptchaSidFromForm();
danielebarchiesi@2 868
danielebarchiesi@2 869 // Try to with wrong user name and password, but correct CAPTCHA.
danielebarchiesi@2 870 $edit = array(
danielebarchiesi@2 871 'name' => 'foobar',
danielebarchiesi@2 872 'pass' => 'bazlaz',
danielebarchiesi@2 873 'captcha_response' => 'Test 123',
danielebarchiesi@2 874 );
danielebarchiesi@2 875 $this->drupalPost(NULL, $edit, t('Log in'));
danielebarchiesi@2 876 // Check that there was no error message for the CAPTCHA.
danielebarchiesi@2 877 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 878 // There shouldn't be a CAPTCHA on the new form.
danielebarchiesi@2 879 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 880 $this->assertPreservedCsid($captcha_sid_initial);
danielebarchiesi@2 881
danielebarchiesi@2 882 // Start a new form instance/session
danielebarchiesi@2 883 $this->drupalGet('node');
danielebarchiesi@2 884 $this->drupalGet('user');
danielebarchiesi@2 885 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 886 $this->assertDifferentCsid($captcha_sid_initial);
danielebarchiesi@2 887
danielebarchiesi@2 888 // Check another form
danielebarchiesi@2 889 $this->drupalGet('user/register');
danielebarchiesi@2 890 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 891 $this->assertDifferentCsid($captcha_sid_initial);
danielebarchiesi@2 892
danielebarchiesi@2 893 }
danielebarchiesi@2 894
danielebarchiesi@2 895 function testPersistencePerFormType(){
danielebarchiesi@2 896 // Set up of persistence and CAPTCHAs.
danielebarchiesi@2 897 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_TYPE);
danielebarchiesi@2 898
danielebarchiesi@2 899 // Go to login form and check if there is a CAPTCHA on the login form.
danielebarchiesi@2 900 $this->drupalGet('user');
danielebarchiesi@2 901 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 902 $captcha_sid_initial = $this->getCaptchaSidFromForm();
danielebarchiesi@2 903
danielebarchiesi@2 904 // Try to with wrong user name and password, but correct CAPTCHA.
danielebarchiesi@2 905 $edit = array(
danielebarchiesi@2 906 'name' => 'foobar',
danielebarchiesi@2 907 'pass' => 'bazlaz',
danielebarchiesi@2 908 'captcha_response' => 'Test 123',
danielebarchiesi@2 909 );
danielebarchiesi@2 910 $this->drupalPost(NULL, $edit, t('Log in'));
danielebarchiesi@2 911 // Check that there was no error message for the CAPTCHA.
danielebarchiesi@2 912 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 913 // There shouldn't be a CAPTCHA on the new form.
danielebarchiesi@2 914 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 915 $this->assertPreservedCsid($captcha_sid_initial);
danielebarchiesi@2 916
danielebarchiesi@2 917 // Start a new form instance/session
danielebarchiesi@2 918 $this->drupalGet('node');
danielebarchiesi@2 919 $this->drupalGet('user');
danielebarchiesi@2 920 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 921 $this->assertDifferentCsid($captcha_sid_initial);
danielebarchiesi@2 922
danielebarchiesi@2 923 // Check another form
danielebarchiesi@2 924 $this->drupalGet('user/register');
danielebarchiesi@2 925 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 926 $this->assertDifferentCsid($captcha_sid_initial);
danielebarchiesi@2 927 }
danielebarchiesi@2 928
danielebarchiesi@2 929 function testPersistenceOnlyOnce(){
danielebarchiesi@2 930 // Set up of persistence and CAPTCHAs.
danielebarchiesi@2 931 $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL);
danielebarchiesi@2 932
danielebarchiesi@2 933 // Go to login form and check if there is a CAPTCHA on the login form.
danielebarchiesi@2 934 $this->drupalGet('user');
danielebarchiesi@2 935 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 936 $captcha_sid_initial = $this->getCaptchaSidFromForm();
danielebarchiesi@2 937
danielebarchiesi@2 938 // Try to with wrong user name and password, but correct CAPTCHA.
danielebarchiesi@2 939 $edit = array(
danielebarchiesi@2 940 'name' => 'foobar',
danielebarchiesi@2 941 'pass' => 'bazlaz',
danielebarchiesi@2 942 'captcha_response' => 'Test 123',
danielebarchiesi@2 943 );
danielebarchiesi@2 944 $this->drupalPost(NULL, $edit, t('Log in'));
danielebarchiesi@2 945 // Check that there was no error message for the CAPTCHA.
danielebarchiesi@2 946 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 947 // There shouldn't be a CAPTCHA on the new form.
danielebarchiesi@2 948 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 949 $this->assertPreservedCsid($captcha_sid_initial);
danielebarchiesi@2 950
danielebarchiesi@2 951 // Start a new form instance/session
danielebarchiesi@2 952 $this->drupalGet('node');
danielebarchiesi@2 953 $this->drupalGet('user');
danielebarchiesi@2 954 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 955 $this->assertDifferentCsid($captcha_sid_initial);
danielebarchiesi@2 956
danielebarchiesi@2 957 // Check another form
danielebarchiesi@2 958 $this->drupalGet('user/register');
danielebarchiesi@2 959 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 960 $this->assertDifferentCsid($captcha_sid_initial);
danielebarchiesi@2 961 }
danielebarchiesi@2 962
danielebarchiesi@2 963 }
danielebarchiesi@2 964
danielebarchiesi@2 965
danielebarchiesi@2 966 class CaptchaSessionReuseAttackTestCase extends CaptchaBaseWebTestCase {
danielebarchiesi@2 967
danielebarchiesi@2 968 public static function getInfo() {
danielebarchiesi@2 969 return array(
danielebarchiesi@2 970 'name' => t('CAPTCHA session reuse attack tests'),
danielebarchiesi@2 971 'description' => t('Testing of the protection against CAPTCHA session reuse attacks.'),
danielebarchiesi@2 972 'group' => t('CAPTCHA'),
danielebarchiesi@2 973 );
danielebarchiesi@2 974 }
danielebarchiesi@2 975
danielebarchiesi@2 976 /**
danielebarchiesi@2 977 * Assert that the CAPTCHA session ID reuse attack was detected.
danielebarchiesi@2 978 */
danielebarchiesi@2 979 protected function assertCaptchaSessionIdReuseAttackDetection() {
danielebarchiesi@2 980 $this->assertText(t(CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE),
danielebarchiesi@2 981 'CAPTCHA session ID reuse attack should be detected.',
danielebarchiesi@2 982 'CAPTCHA');
danielebarchiesi@2 983 // There should be an error message about wrong response.
danielebarchiesi@2 984 $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
danielebarchiesi@2 985 'CAPTCHA response should flagged as wrong.',
danielebarchiesi@2 986 'CAPTCHA');
danielebarchiesi@2 987 }
danielebarchiesi@2 988
danielebarchiesi@2 989 function testCaptchaSessionReuseAttackDetectionOnCommentPreview() {
danielebarchiesi@2 990 // Create commentable node
danielebarchiesi@2 991 $node = $this->createNodeWithCommentsEnabled();
danielebarchiesi@2 992 // Set Test CAPTCHA on comment form.
danielebarchiesi@2 993 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Math');
danielebarchiesi@2 994 variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
danielebarchiesi@2 995
danielebarchiesi@2 996 // Log in as normal user.
danielebarchiesi@2 997 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 998
danielebarchiesi@2 999 // Go to comment form of commentable node.
danielebarchiesi@2 1000 $this->drupalGet('comment/reply/' . $node->nid);
danielebarchiesi@2 1001 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 1002
danielebarchiesi@2 1003 // Get CAPTCHA session ID and solution of the challenge.
danielebarchiesi@2 1004 $captcha_sid = $this->getCaptchaSidFromForm();
danielebarchiesi@2 1005 $captcha_token = $this->getCaptchaTokenFromForm();
danielebarchiesi@2 1006 $solution = $this->getMathCaptchaSolutionFromForm();
danielebarchiesi@2 1007
danielebarchiesi@2 1008 // Post the form with the solution.
danielebarchiesi@2 1009 $edit = $this->getCommentFormValues();
danielebarchiesi@2 1010 $edit['captcha_response'] = $solution;
danielebarchiesi@2 1011 $this->drupalPost(NULL, $edit, t('Preview'));
danielebarchiesi@2 1012 // Answer should be accepted and further CAPTCHA ommitted.
danielebarchiesi@2 1013 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 1014 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 1015
danielebarchiesi@2 1016 // Post a new comment, reusing the previous CAPTCHA session.
danielebarchiesi@2 1017 $edit = $this->getCommentFormValues();
danielebarchiesi@2 1018 $edit['captcha_sid'] = $captcha_sid;
danielebarchiesi@2 1019 $edit['captcha_token'] = $captcha_token;
danielebarchiesi@2 1020 $edit['captcha_response'] = $solution;
danielebarchiesi@2 1021 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
danielebarchiesi@2 1022 // CAPTCHA session reuse attack should be detected.
danielebarchiesi@2 1023 $this->assertCaptchaSessionIdReuseAttackDetection();
danielebarchiesi@2 1024 // There should be a CAPTCHA.
danielebarchiesi@2 1025 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 1026
danielebarchiesi@2 1027 }
danielebarchiesi@2 1028
danielebarchiesi@2 1029 function testCaptchaSessionReuseAttackDetectionOnNodeForm() {
danielebarchiesi@2 1030 // Set CAPTCHA on page form.
danielebarchiesi@2 1031 captcha_set_form_id_setting('page_node_form', 'captcha/Math');
danielebarchiesi@2 1032 variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
danielebarchiesi@2 1033
danielebarchiesi@2 1034 // Log in as normal user.
danielebarchiesi@2 1035 $this->drupalLogin($this->normal_user);
danielebarchiesi@2 1036
danielebarchiesi@2 1037 // Go to node add form.
danielebarchiesi@2 1038 $this->drupalGet('node/add/page');
danielebarchiesi@2 1039 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 1040
danielebarchiesi@2 1041 // Get CAPTCHA session ID and solution of the challenge.
danielebarchiesi@2 1042 $captcha_sid = $this->getCaptchaSidFromForm();
danielebarchiesi@2 1043 $captcha_token = $this->getCaptchaTokenFromForm();
danielebarchiesi@2 1044 $solution = $this->getMathCaptchaSolutionFromForm();
danielebarchiesi@2 1045
danielebarchiesi@2 1046 // Page settings to post, with correct CAPTCHA answer.
danielebarchiesi@2 1047 $edit = $this->getNodeFormValues();
danielebarchiesi@2 1048 $edit['captcha_response'] = $solution;
danielebarchiesi@2 1049 // Preview the node
danielebarchiesi@2 1050 $this->drupalPost(NULL, $edit, t('Preview'));
danielebarchiesi@2 1051 // Answer should be accepted.
danielebarchiesi@2 1052 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 1053 // Check that there is no CAPTCHA after preview.
danielebarchiesi@2 1054 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 1055
danielebarchiesi@2 1056 // Post a new comment, reusing the previous CAPTCHA session.
danielebarchiesi@2 1057 $edit = $this->getNodeFormValues();
danielebarchiesi@2 1058 $edit['captcha_sid'] = $captcha_sid;
danielebarchiesi@2 1059 $edit['captcha_token'] = $captcha_token;
danielebarchiesi@2 1060 $edit['captcha_response'] = $solution;
danielebarchiesi@2 1061 $this->drupalPost('node/add/page', $edit, t('Preview'));
danielebarchiesi@2 1062 // CAPTCHA session reuse attack should be detected.
danielebarchiesi@2 1063 $this->assertCaptchaSessionIdReuseAttackDetection();
danielebarchiesi@2 1064 // There should be a CAPTCHA.
danielebarchiesi@2 1065 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 1066
danielebarchiesi@2 1067 }
danielebarchiesi@2 1068
danielebarchiesi@2 1069 function testCaptchaSessionReuseAttackDetectionOnLoginForm() {
danielebarchiesi@2 1070 // Set CAPTCHA on login form.
danielebarchiesi@2 1071 captcha_set_form_id_setting('user_login', 'captcha/Math');
danielebarchiesi@2 1072 variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
danielebarchiesi@2 1073
danielebarchiesi@2 1074 // Go to log in form.
danielebarchiesi@2 1075 $this->drupalGet('user');
danielebarchiesi@2 1076 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 1077
danielebarchiesi@2 1078 // Get CAPTCHA session ID and solution of the challenge.
danielebarchiesi@2 1079 $captcha_sid = $this->getCaptchaSidFromForm();
danielebarchiesi@2 1080 $captcha_token = $this->getCaptchaTokenFromForm();
danielebarchiesi@2 1081 $solution = $this->getMathCaptchaSolutionFromForm();
danielebarchiesi@2 1082
danielebarchiesi@2 1083 // Log in through form.
danielebarchiesi@2 1084 $edit = array(
danielebarchiesi@2 1085 'name' => $this->normal_user->name,
danielebarchiesi@2 1086 'pass' => $this->normal_user->pass_raw,
danielebarchiesi@2 1087 'captcha_response' => $solution,
danielebarchiesi@2 1088 );
danielebarchiesi@2 1089 $this->drupalPost(NULL, $edit, t('Log in'));
danielebarchiesi@2 1090 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 1091 $this->assertCaptchaPresence(FALSE);
danielebarchiesi@2 1092 // If a "log out" link appears on the page, it is almost certainly because
danielebarchiesi@2 1093 // the login was successful.
danielebarchiesi@2 1094 $pass = $this->assertLink(t('Log out'), 0, t('User %name successfully logged in.', array('%name' => $this->normal_user->name)), t('User login'));
danielebarchiesi@2 1095
danielebarchiesi@2 1096 // Log out again.
danielebarchiesi@2 1097 $this->drupalLogout();
danielebarchiesi@2 1098
danielebarchiesi@2 1099 // Try to log in again, reusing the previous CAPTCHA session.
danielebarchiesi@2 1100 $edit += array(
danielebarchiesi@2 1101 'captcha_sid' => $captcha_sid,
danielebarchiesi@2 1102 'captcha_token' => $captcha_token,
danielebarchiesi@2 1103 );
danielebarchiesi@2 1104 $this->drupalPost('user', $edit, t('Log in'));
danielebarchiesi@2 1105 // CAPTCHA session reuse attack should be detected.
danielebarchiesi@2 1106 $this->assertCaptchaSessionIdReuseAttackDetection();
danielebarchiesi@2 1107 // There should be a CAPTCHA.
danielebarchiesi@2 1108 $this->assertCaptchaPresence(TRUE);
danielebarchiesi@2 1109 }
danielebarchiesi@2 1110
danielebarchiesi@2 1111
danielebarchiesi@2 1112 public function testMultipleCaptchaProtectedFormsOnOnePage()
danielebarchiesi@2 1113 {
danielebarchiesi@2 1114 // Set Test CAPTCHA on comment form and login block
danielebarchiesi@2 1115 captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
danielebarchiesi@2 1116 captcha_set_form_id_setting('user_login_block', 'captcha/Math');
danielebarchiesi@2 1117 $this->allowCommentPostingForAnonymousVisitors();
danielebarchiesi@2 1118
danielebarchiesi@2 1119 // Create a node with comments enabled.
danielebarchiesi@2 1120 $node = $this->createNodeWithCommentsEnabled();
danielebarchiesi@2 1121
danielebarchiesi@2 1122 // Preview comment with correct CAPTCHA answer.
danielebarchiesi@2 1123 $edit = $this->getCommentFormValues();
danielebarchiesi@2 1124 $comment_subject = $edit['subject'];
danielebarchiesi@2 1125 $edit['captcha_response'] = 'Test 123';
danielebarchiesi@2 1126 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
danielebarchiesi@2 1127 // Post should be accepted: no warnings,
danielebarchiesi@2 1128 // no CAPTCHA reuse detection (which could be used by user log in block).
danielebarchiesi@2 1129 $this->assertCaptchaResponseAccepted();
danielebarchiesi@2 1130 $this->assertText($comment_subject);
danielebarchiesi@2 1131
danielebarchiesi@2 1132 }
danielebarchiesi@2 1133
danielebarchiesi@2 1134 }
danielebarchiesi@2 1135
danielebarchiesi@2 1136
danielebarchiesi@2 1137 // Some tricks to debug:
danielebarchiesi@2 1138 // drupal_debug($data) // from devel module
danielebarchiesi@2 1139 // file_put_contents('tmp.simpletest.html', $this->drupalGetContent());