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. <a href="@password">Have you forgotten your password?</a>', 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. <a href="@password">Have you forgotten your password?</a>', 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;
       }
     }
   }
