Version Description
Download this release
Release Info
Developer | mvandemar |
Plugin | Login LockDown |
Version | 1.4 |
Comparing to | |
See all releases |
Code changes from version 1.3 to 1.4
- loginlockdown.php +99 -53
- readme.txt +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.
|
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('
|
271 |
-
define('
|
272 |
}
|
273 |
-
$activatestr = str_replace(
|
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 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
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 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
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"; ?>> Yes <input type="radio" name="ll_lockout_invalid_usernames" value="no" <?php if( $loginlockdownAdminOptions['lockout_invalid_usernames'] == "no" ) echo "checked"; ?>> 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"; ?>> Yes <input type="radio" name="ll_mask_login_errors" value="no" <?php if( $loginlockdownAdminOptions['mask_login_errors'] == "no" ) echo "checked"; ?>> 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.
|
6 |
-
Stable Tag: 1.
|
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.
|
1 |
+
1.4
|