Login LockDown - Version 1.4

Version Description

Download this release

Release Info

Developer mvandemar
Plugin Icon 128x128 Login LockDown
Version 1.4
Comparing to
See all releases

Code changes from version 1.3 to 1.4

Files changed (3) hide show
  1. loginlockdown.php +99 -53
  2. readme.txt +3 -3
  3. version.txt +1 -1
loginlockdown.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Login LockDown
4
  Plugin URI: http://www.bad-neighborhood.com/
5
- Version: v1.3
6
  Author: Michael VanDeMar
7
  Description: Adds some extra security to WordPress by restricting the rate at which failed logins can be re-attempted from a given IP range. Distributed through <a href="http://www.bad-neighborhood.com/" target="_blank">Bad Neighborhood</a>.
8
  */
@@ -10,6 +10,12 @@ Description: Adds some extra security to WordPress by restricting the rate at wh
10
  /*
11
  * Change Log
12
  *
 
 
 
 
 
 
13
  * ver. 1.3 23-Feb-2009
14
  * - adjusted positioning of plugin byline
15
  * - allowed for dynamic location of plugin files
@@ -40,7 +46,7 @@ Description: Adds some extra security to WordPress by restricting the rate at wh
40
  | |
41
  | Login LockDown - added security measures to WordPress intended to |
42
  | inhibit or reduce brute force password discovery. |
43
- | Copyright (C) 2007, Michael VanDeMar, |
44
  | http://www.bad-neighborhood.com |
45
  | All rights reserved. |
46
  | |
@@ -117,15 +123,16 @@ function countFails($username = "") {
117
  }
118
 
119
  function incrementFails($username = "") {
120
- global $wpdb;
 
121
  $table_name = $wpdb->prefix . "login_fails";
122
  $ip = $_SERVER['REMOTE_ADDR'];
123
 
124
  $username = sanitize_user($username);
125
  $user = get_userdatabylogin($username);
126
- if ( $user ) {
127
  $insert = "INSERT INTO " . $table_name . " (user_id, login_attempt_date, login_attempt_IP) " .
128
- "VALUES ('" . $user->ID . "', now(), '" . $ip . "')";
129
  $results = $wpdb->query($insert);
130
  }
131
  }
@@ -138,7 +145,7 @@ function lockDown($username = "") {
138
 
139
  $username = sanitize_user($username);
140
  $user = get_userdatabylogin($username);
141
- if ( $user ) {
142
  $insert = "INSERT INTO " . $table_name . " (user_id, lockdown_date, release_date, lockdown_IP) " .
143
  "VALUES ('" . $user->ID . "', now(), date_add(now(), INTERVAL " .
144
  $loginlockdownOptions['lockout_length'] . " MINUTE), '" . $ip . "')";
@@ -173,7 +180,9 @@ function get_loginlockdownOptions() {
173
  $loginlockdownAdminOptions = array(
174
  'max_login_retries' => 3,
175
  'retries_within' => 5,
176
- 'lockout_length' => 60);
 
 
177
  $loginlockdownOptions = get_option("loginlockdownAdminOptions");
178
  if ( !empty($loginlockdownOptions) ) {
179
  foreach ( $loginlockdownOptions as $key => $option ) {
@@ -199,6 +208,12 @@ function print_loginlockdownAdminPage() {
199
  if (isset($_POST['ll_lockout_length'])) {
200
  $loginlockdownAdminOptions['lockout_length'] = $_POST['ll_lockout_length'];
201
  }
 
 
 
 
 
 
202
  update_option("loginlockdownAdminOptions", $loginlockdownAdminOptions);
203
  ?>
204
  <div class="updated"><p><strong><?php _e("Settings Updated.", "loginlockdown");?></strong></p></div>
@@ -223,11 +238,15 @@ function print_loginlockdownAdminPage() {
223
  <form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
224
  <h2><?php _e('Login LockDown Options', 'loginlockdown') ?></h2>
225
  <h3><?php _e('Max Login Retries', 'loginlockdown') ?></h3>
226
- <input name="ll_max_login_retries" size="8" value="<?php echo $loginlockdownAdminOptions['max_login_retries']; ?>">
227
  <h3><?php _e('Retry Time Period Restriction (minutes)', 'loginlockdown') ?></h3>
228
- <input name="ll_retries_within" size="8" value="<?php echo $loginlockdownAdminOptions['retries_within']; ?>">
229
  <h3><?php _e('Lockout Length (minutes)', 'loginlockdown') ?></h3>
230
- <input name="ll_lockout_length" size="8" value="<?php echo $loginlockdownAdminOptions['lockout_length']; ?>">
 
 
 
 
231
  <div class="submit">
232
  <input type="submit" name="update_loginlockdownSettings" value="<?php _e('Update Settings', 'loginlockdown') ?>" /></div>
233
  </form>
@@ -267,66 +286,93 @@ function ll_credit_link(){
267
  if ( isset($loginlockdown_db_version) ) {
268
  //Actions
269
  add_action('admin_menu', 'loginlockdown_ap');
270
- if(!defined('PLUGINDIR')){
271
- define('PLUGINDIR', 'wp-content/plugins');
272
  }
273
- $activatestr = str_replace(ABSPATH.PLUGINDIR."/", "activate_", __FILE__);
274
  add_action($activatestr, 'loginLockdown_install');
275
- add_action('login_form', 'll_credit_link');
 
 
 
276
  //Filters
277
- //Functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  if ( !function_exists('wp_authenticate') ) :
279
  function wp_authenticate($username, $password) {
280
  global $wpdb, $error;
281
- global $loginlockdownOptions;
282
-
 
 
 
283
  if ( 0 < isLockedDown() ) {
284
  return new WP_Error('incorrect_password', "<strong>ERROR</strong>: We're sorry, but this IP range has been blocked due to too many recent " .
285
  "failed login attempts.<br /><br />Please try again later.");
286
  }
287
-
288
- if ( '' == $username )
289
- return new WP_Error('empty_username', __('<strong>ERROR</strong>: The username field is empty.'));
290
-
291
- if ( '' == $password ) {
292
- return new WP_Error('empty_password', __('<strong>ERROR</strong>: The password field is empty.'));
293
- }
294
-
295
- $user = get_userdatabylogin($username);
296
-
297
- if ( !$user || ($user->user_login != $username) ) {
298
- do_action( 'wp_login_failed', $username );
299
- return new WP_Error('invalid_username', __('<strong>ERROR</strong>: Invalid username.'));
300
- }
301
-
302
- $user = apply_filters('wp_authenticate_user', $user, $password);
303
- if ( is_wp_error($user) ) {
304
  incrementFails($username);
305
  if ( $loginlockdownOptions['max_login_retries'] <= countFails($username) ) {
306
  lockDown($username);
307
  return new WP_Error('incorrect_password', __("<strong>ERROR</strong>: We're sorry, but this IP range has been blocked due to too many recent " .
308
  "failed login attempts.<br /><br />Please try again later."));
309
- }
310
- do_action( 'wp_login_failed', $username );
311
- return $user;
312
- }
313
-
314
- if ( !wp_check_password($password, $user->user_pass, $user->ID) ) {
315
- incrementFails($username);
316
- if ( $loginlockdownOptions['max_login_retries'] <= countFails($username) ) {
317
- lockDown($username);
318
- return new WP_Error('incorrect_password', __("<strong>ERROR</strong>: We're sorry, but this IP range has been blocked due to too many recent " .
319
- "failed login attempts.<br /><br />Please try again later."));
320
- }
321
- do_action( 'wp_login_failed', $username );
322
- return new WP_Error('incorrect_password', __('<strong>ERROR</strong>: Incorrect password.'));
323
- }
324
-
325
- return new WP_User($user->ID);
326
-
327
  }
328
  endif;
329
  }
330
 
331
 
332
- ?>
2
  /*
3
  Plugin Name: Login LockDown
4
  Plugin URI: http://www.bad-neighborhood.com/
5
+ Version: v1.4
6
  Author: Michael VanDeMar
7
  Description: Adds some extra security to WordPress by restricting the rate at which failed logins can be re-attempted from a given IP range. Distributed through <a href="http://www.bad-neighborhood.com/" target="_blank">Bad Neighborhood</a>.
8
  */
10
  /*
11
  * Change Log
12
  *
13
+ * ver. 1.4 29-Aug-2009
14
+ * - removed erroneous error affecting WP 2.8+
15
+ * - fixed activation error caused by customizing the location of the wp-content folder
16
+ * - added in the option to mask which specific login error (invalid username or invalid password) was generated
17
+ * - added in the option to lock out failed login attempts even if the username doesn't exist
18
+ *
19
  * ver. 1.3 23-Feb-2009
20
  * - adjusted positioning of plugin byline
21
  * - allowed for dynamic location of plugin files
46
  | |
47
  | Login LockDown - added security measures to WordPress intended to |
48
  | inhibit or reduce brute force password discovery. |
49
+ | Copyright (C) 2007 - 2009, Michael VanDeMar, |
50
  | http://www.bad-neighborhood.com |
51
  | All rights reserved. |
52
  | |
123
  }
124
 
125
  function incrementFails($username = "") {
126
+ global $wpdb;
127
+ global $loginlockdownOptions;
128
  $table_name = $wpdb->prefix . "login_fails";
129
  $ip = $_SERVER['REMOTE_ADDR'];
130
 
131
  $username = sanitize_user($username);
132
  $user = get_userdatabylogin($username);
133
+ if ( $user || "yes" == $loginlockdownOptions['lockout_invalid_usernames'] ) {
134
  $insert = "INSERT INTO " . $table_name . " (user_id, login_attempt_date, login_attempt_IP) " .
135
+ "VALUES ('" . $user->ID . "', now(), '" . mysql_real_escape_string($ip) . "')";
136
  $results = $wpdb->query($insert);
137
  }
138
  }
145
 
146
  $username = sanitize_user($username);
147
  $user = get_userdatabylogin($username);
148
+ if ( $user || "yes" == $loginlockdownOptions['lockout_invalid_usernames'] ) {
149
  $insert = "INSERT INTO " . $table_name . " (user_id, lockdown_date, release_date, lockdown_IP) " .
150
  "VALUES ('" . $user->ID . "', now(), date_add(now(), INTERVAL " .
151
  $loginlockdownOptions['lockout_length'] . " MINUTE), '" . $ip . "')";
180
  $loginlockdownAdminOptions = array(
181
  'max_login_retries' => 3,
182
  'retries_within' => 5,
183
+ 'lockout_length' => 60,
184
+ 'lockout_invalid_usernames' => 'no',
185
+ 'mask_login_errors' => 'no');
186
  $loginlockdownOptions = get_option("loginlockdownAdminOptions");
187
  if ( !empty($loginlockdownOptions) ) {
188
  foreach ( $loginlockdownOptions as $key => $option ) {
208
  if (isset($_POST['ll_lockout_length'])) {
209
  $loginlockdownAdminOptions['lockout_length'] = $_POST['ll_lockout_length'];
210
  }
211
+ if (isset($_POST['ll_lockout_invalid_usernames'])) {
212
+ $loginlockdownAdminOptions['lockout_invalid_usernames'] = $_POST['ll_lockout_invalid_usernames'];
213
+ }
214
+ if (isset($_POST['ll_mask_login_errors'])) {
215
+ $loginlockdownAdminOptions['mask_login_errors'] = $_POST['ll_mask_login_errors'];
216
+ }
217
  update_option("loginlockdownAdminOptions", $loginlockdownAdminOptions);
218
  ?>
219
  <div class="updated"><p><strong><?php _e("Settings Updated.", "loginlockdown");?></strong></p></div>
238
  <form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
239
  <h2><?php _e('Login LockDown Options', 'loginlockdown') ?></h2>
240
  <h3><?php _e('Max Login Retries', 'loginlockdown') ?></h3>
241
+ <input type="text" name="ll_max_login_retries" size="8" value="<?php echo $loginlockdownAdminOptions['max_login_retries']; ?>">
242
  <h3><?php _e('Retry Time Period Restriction (minutes)', 'loginlockdown') ?></h3>
243
+ <input type="text" name="ll_retries_within" size="8" value="<?php echo $loginlockdownAdminOptions['retries_within']; ?>">
244
  <h3><?php _e('Lockout Length (minutes)', 'loginlockdown') ?></h3>
245
+ <input type="text" name="ll_lockout_length" size="8" value="<?php echo $loginlockdownAdminOptions['lockout_length']; ?>">
246
+ <h3><?php _e('Lockout Invalid Usernames?', 'loginlockdown') ?></h3>
247
+ <input type="radio" name="ll_lockout_invalid_usernames" value="yes" <?php if( $loginlockdownAdminOptions['lockout_invalid_usernames'] == "yes" ) echo "checked"; ?>>&nbsp;Yes&nbsp;&nbsp;&nbsp;<input type="radio" name="ll_lockout_invalid_usernames" value="no" <?php if( $loginlockdownAdminOptions['lockout_invalid_usernames'] == "no" ) echo "checked"; ?>>&nbsp;No
248
+ <h3><?php _e('Mask Login Errors?', 'loginlockdown') ?></h3>
249
+ <input type="radio" name="ll_mask_login_errors" value="yes" <?php if( $loginlockdownAdminOptions['mask_login_errors'] == "yes" ) echo "checked"; ?>>&nbsp;Yes&nbsp;&nbsp;&nbsp;<input type="radio" name="ll_mask_login_errors" value="no" <?php if( $loginlockdownAdminOptions['mask_login_errors'] == "no" ) echo "checked"; ?>>&nbsp;No
250
  <div class="submit">
251
  <input type="submit" name="update_loginlockdownSettings" value="<?php _e('Update Settings', 'loginlockdown') ?>" /></div>
252
  </form>
286
  if ( isset($loginlockdown_db_version) ) {
287
  //Actions
288
  add_action('admin_menu', 'loginlockdown_ap');
289
+ if(!defined('WP_PLUGIN_DIR')){
290
+ define('WP_PLUGIN_DIR', ABSPATH . 'wp-content/plugins');
291
  }
292
+ $activatestr = str_replace(WP_PLUGIN_DIR . "/", "activate_", __FILE__);
293
  add_action($activatestr, 'loginLockdown_install');
294
+ add_action('login_form', 'll_credit_link');
295
+
296
+ remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
297
+ add_filter('authenticate', 'll_wp_authenticate_username_password', 20, 3);
298
  //Filters
299
+ //Functions
300
+ function ll_wp_authenticate_username_password($user, $username, $password) {
301
+ if ( is_a($user, 'WP_User') ) { return $user; }
302
+
303
+ if ( empty($username) || empty($password) ) {
304
+ $error = new WP_Error();
305
+
306
+ if ( empty($username) )
307
+ $error->add('empty_username', __('<strong>ERROR</strong>: The username field is empty.'));
308
+
309
+ if ( empty($password) )
310
+ $error->add('empty_password', __('<strong>ERROR</strong>: The password field is empty.'));
311
+
312
+ return $error;
313
+ }
314
+
315
+ $userdata = get_userdatabylogin($username);
316
+
317
+ if ( !$userdata ) {
318
+ return new WP_Error('invalid_username', sprintf(__('<strong>ERROR</strong>: Invalid username. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), site_url('wp-login.php?action=lostpassword', 'login')));
319
+ }
320
+
321
+ $userdata = apply_filters('wp_authenticate_user', $userdata, $password);
322
+ if ( is_wp_error($userdata) ) {
323
+ return $userdata;
324
+ }
325
+
326
+ if ( !wp_check_password($password, $userdata->user_pass, $userdata->ID) ) {
327
+ return new WP_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: Incorrect password. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), site_url('wp-login.php?action=lostpassword', 'login')));
328
+ }
329
+
330
+ $user = new WP_User($userdata->ID);
331
+ return $user;
332
+ }
333
+
334
+
335
  if ( !function_exists('wp_authenticate') ) :
336
  function wp_authenticate($username, $password) {
337
  global $wpdb, $error;
338
+ global $loginlockdownOptions;
339
+
340
+ $username = sanitize_user($username);
341
+ $password = trim($password);
342
+
343
  if ( 0 < isLockedDown() ) {
344
  return new WP_Error('incorrect_password', "<strong>ERROR</strong>: We're sorry, but this IP range has been blocked due to too many recent " .
345
  "failed login attempts.<br /><br />Please try again later.");
346
  }
347
+
348
+ $user = apply_filters('authenticate', null, $username, $password);
349
+
350
+ if ( $user == null ) {
351
+ // TODO what should the error message be? (Or would these even happen?)
352
+ // Only needed if all authentication handlers fail to return anything.
353
+ $user = new WP_Error('authentication_failed', __('<strong>ERROR</strong>: Invalid username or incorrect password.'));
354
+ }
355
+
356
+ $ignore_codes = array('empty_username', 'empty_password');
357
+
358
+ if (is_wp_error($user) && !in_array($user->get_error_code(), $ignore_codes) ) {
 
 
 
 
 
359
  incrementFails($username);
360
  if ( $loginlockdownOptions['max_login_retries'] <= countFails($username) ) {
361
  lockDown($username);
362
  return new WP_Error('incorrect_password', __("<strong>ERROR</strong>: We're sorry, but this IP range has been blocked due to too many recent " .
363
  "failed login attempts.<br /><br />Please try again later."));
364
+ }
365
+ if ( 'yes' == $loginlockdownOptions['mask_login_errors'] ) {
366
+ return new WP_Error('authentication_failed', sprintf(__('<strong>ERROR</strong>: Invalid username or incorrect password. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), site_url('wp-login.php?action=lostpassword', 'login')));
367
+ } else {
368
+ do_action('wp_login_failed', $username);
369
+ }
370
+ }
371
+
372
+ return $user;
 
 
 
 
 
 
 
 
 
373
  }
374
  endif;
375
  }
376
 
377
 
378
+ ?>
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Developer: Michael VanDeMar (michael@endlesspoetry.com)
3
  Tags: security, login
4
  Requires at least: 2.5
5
- Tested up to: 2.7.1
6
- Stable Tag: 1.3
7
 
8
  Limits the number of login attempts from a given IP range within a certain time period.
9
 
@@ -22,4 +22,4 @@ via the Options panel. Admisitrators can release locked out IP ranges manually f
22
  2. Activate the plugin in the Plugin options.
23
  3. Customize the settings from the Options panel, if desired.
24
 
25
- Enjoy.
2
  Developer: Michael VanDeMar (michael@endlesspoetry.com)
3
  Tags: security, login
4
  Requires at least: 2.5
5
+ Tested up to: 2.8.4
6
+ Stable Tag: 1.4
7
 
8
  Limits the number of login attempts from a given IP range within a certain time period.
9
 
22
  2. Activate the plugin in the Plugin options.
23
  3. Customize the settings from the Options panel, if desired.
24
 
25
+ Enjoy.
version.txt CHANGED
@@ -1 +1 @@
1
- 1.3
1
+ 1.4