Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.1000 diff -u -r1.1000 user.module --- modules/user/user.module 8 Jun 2009 05:00:11 -0000 1.1000 +++ modules/user/user.module 9 Jun 2009 06:33:20 -0000 @@ -1654,7 +1654,14 @@ function user_login_final_validate($form, &$form_state) { global $user; if (!$user->uid) { - form_set_error('name', t('Sorry, unrecognized username or password. Have you forgotten your password?', array('@password' => url('user/password')))); + if (flood_is_allowed('failed_login_attempt', 10)) { + flood_register_event('failed_login_attempt'); + form_set_error('name', t('Sorry, unrecognized username or password. Have you forgotten your password?', array('@password' => url('user/password')))); + } + else { + form_set_error('name', t('Sorry, too many failed password attempts, you are temporarily prohibited from logging in. Please try again in one hour')); + } + watchdog('user', 'Login attempt failed for %user.', array('%user' => $form_state['values']['name'])); } } @@ -1672,27 +1679,30 @@ function user_authenticate($form_values = array()) { global $user; - $password = trim($form_values['pass']); - // Name and pass keys are required. - if (!empty($form_values['name']) && !empty($password)) { - $account = db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' => $form_values['name']))->fetchObject(); - if ($account) { - // Allow alternate password hashing schemes. - require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); - if (user_check_password($password, $account)) { - if (user_needs_new_hash($account)) { - $new_hash = user_hash_password($password); - if ($new_hash) { - db_update('users') - ->fields(array('pass' => $new_hash)) - ->condition('uid', $account->uid) - ->execute(); + // Flood control is used to prevent automated attempts at guessing passwords. + if (flood_is_allowed('failed_login_attempt', 10)) { + $password = trim($form_values['pass']); + // Name and pass keys are required. + if (!empty($form_values['name']) && !empty($password)) { + $account = db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' => $form_values['name']))->fetchObject(); + if ($account) { + // Allow alternate password hashing schemes. + require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); + if (user_check_password($password, $account)) { + if (user_needs_new_hash($account)) { + $new_hash = user_hash_password($password); + if ($new_hash) { + db_update('users') + ->fields(array('pass' => $new_hash)) + ->condition('uid', $account->uid) + ->execute(); + } } + $users = user_load_multiple(array($account->uid), array('status' => '1')); + $user = reset($users); + user_authenticate_finalize($form_values); + return $user; } - $users = user_load_multiple(array($account->uid), array('status' => '1')); - $user = reset($users); - user_authenticate_finalize($form_values); - return $user; } } }