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