? .buildpath ? .project ? .settings ? 1002538.patch ? 992540.patch ? bootstrap.patch ? dump.sql ? favicon_error.patch ? sites/all/modules/devel ? sites/default/files ? sites/default/settings.php Index: modules/user/user.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v retrieving revision 1.78 diff -u -p -r1.78 user.pages.inc --- modules/user/user.pages.inc 1 Dec 2010 00:29:41 -0000 1.78 +++ modules/user/user.pages.inc 17 Jan 2011 20:33:04 -0000 @@ -136,6 +136,10 @@ function user_pass_reset($form, &$form_s // Let the user's password be changed without the current password check. $token = drupal_hash_base64(drupal_random_bytes(55)); $_SESSION['pass_reset_' . $user->uid] = $token; + // Clear flood event. + $identifier = $user->uid . '-' . ip_address(); + flood_clear_event('failed_login_attempt_ip'); + flood_clear_event('failed_login_attempt_user', $identifier); drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token))); } else { @@ -320,6 +324,15 @@ function user_profile_form_submit($form, // Remove the password reset tag since a new password was saved. unset($_SESSION['pass_reset_'. $account->uid]); } + + // Clear the flood table. Since we don't know the IP address for this user + // we can't use flood_clear_event because we need to use the LIKE operator. + $identifier = $account->uid .'-%'; + db_delete('flood') + ->condition('event', 'failed_login_attempt_user') + ->condition('identifier', $identifier, 'LIKE') + ->execute(); + // Clear the page cache because pages can contain usernames and/or profile information: cache_clear_all(); Index: modules/user/user.test =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.test,v retrieving revision 1.111 diff -u -p -r1.111 user.test --- modules/user/user.test 18 Dec 2010 00:56:18 -0000 1.111 +++ modules/user/user.test 17 Jan 2011 20:33:05 -0000 @@ -367,6 +367,67 @@ class UserLoginTestCase extends DrupalWe } /** + * Test that flood events are removed after an account has been updated. + */ + function testUpdatetUserFloodControl() { + // Set a high global limit out so that it is not relevant in the test. + variable_set('user_failed_login_ip_limit', 4000); + // Set the per-user login limit. + variable_set('user_failed_login_user_limit', 3); + + $user1 = $this->drupalCreateUser(array('administer users')); + $user2 = $this->drupalCreateUser(array()); + $user2->pass_raw .= 'incorrect'; + + // Try 3 failed logins. + for ($i = 0; $i < 3; $i++) { + $this->assertFailedLogin($user2); + } + + // The next login trial should result in an user-based flood error message. + $this->assertFailedLogin($user2, 'user'); + + // Update the account and assert the user can login again. + $this->drupalLogin($user1); + $user2->pass_raw = 'goodpass'; + $edit = array( + 'pass[pass1]' => $user2->pass_raw, + 'pass[pass2]' => $user2->pass_raw, + ); + $this->drupalPost('user/' . $user2->uid . '/edit', $edit, t('Save')); + $this->drupalLogout(); + $this->drupalLogin($user2); + } + + /** + * Test that flood events are removed after password reset. + */ + function testResetPasswordFloodControl() { + // Set a high global limit out so that it is not relevant in the test. + variable_set('user_failed_login_ip_limit', 4000); + // Set the per-user login limit. + variable_set('user_failed_login_user_limit', 3); + + $user1 = $this->drupalCreateUser(); + $correct = $user1->pass_raw; + $user1->pass_raw .= 'incorrect'; + + // Try 3 failed logins. + for ($i = 0; $i < 3; $i++) { + $this->assertFailedLogin($user1); + } + + // The next login trial should result in an user-based flood error message. + $this->assertFailedLogin($user1, 'user'); + + // Request new password, logout and login. + $this->drupalPost(user_pass_reset_url($user1), array(), t('Log in')); + $this->drupalLogout(); + $user1->pass_raw = $correct; + $this->drupalLogin($user1); + } + + /** * Test that user password is re-hashed upon login after changing $count_log2. */ function testPasswordRehashOnLogin() {