Version Description
Plugin returns the 403 Forbidden header after the limit of login attempts via XMLRPC is reached.
Added support of IP ranges in white/black lists.
Lockouts now can be released selectively.
Fixed the issue with encoding of special symbols in email notifications.
Download this release
Release Info
Developer | wpchefgadget |
Plugin | Limit Login Attempts Reloaded |
Version | 2.6.1 |
Comparing to | |
See all releases |
Code changes from version 2.5.0 to 2.6.1
- core/Helpers.php +3 -1
- core/LimitLoginAttempts.php +131 -60
- limit-login-attempts-reloaded.php +1 -1
- readme.txt +11 -2
- views/options-page.php +45 -6
core/Helpers.php
CHANGED
@@ -39,13 +39,15 @@ class LLA_Helpers {
|
|
39 |
'username' => $user_name,
|
40 |
'counter' => $info['counter'],
|
41 |
'gateway' => ( isset( $info['gateway'] ) ) ? $info['gateway'] : '-',
|
|
|
42 |
);
|
43 |
} else { // For old plugin version
|
44 |
$new_log[0] = array(
|
45 |
'ip' => $ip,
|
46 |
'username' => $user_name,
|
47 |
'counter' => $info,
|
48 |
-
'gateway' => '-'
|
|
|
49 |
);
|
50 |
}
|
51 |
|
39 |
'username' => $user_name,
|
40 |
'counter' => $info['counter'],
|
41 |
'gateway' => ( isset( $info['gateway'] ) ) ? $info['gateway'] : '-',
|
42 |
+
'unlocked' => !empty( $info['unlocked'] ),
|
43 |
);
|
44 |
} else { // For old plugin version
|
45 |
$new_log[0] = array(
|
46 |
'ip' => $ip,
|
47 |
'username' => $user_name,
|
48 |
'counter' => $info,
|
49 |
+
'gateway' => '-',
|
50 |
+
'unlocked' => false,
|
51 |
);
|
52 |
}
|
53 |
|
core/LimitLoginAttempts.php
CHANGED
@@ -66,7 +66,7 @@ class Limit_Login_Attempts
|
|
66 |
add_filter( 'limit_login_blacklist_ip', array( $this, 'check_blacklist_ips' ), 10, 2 );
|
67 |
add_filter( 'limit_login_blacklist_usernames', array( $this, 'check_blacklist_usernames' ), 10, 2 );
|
68 |
}
|
69 |
-
|
70 |
/**
|
71 |
* Hook 'plugins_loaded'
|
72 |
*/
|
@@ -77,13 +77,13 @@ class Limit_Login_Attempts
|
|
77 |
|
78 |
// Check if installed old plugin
|
79 |
$this->check_original_installed();
|
80 |
-
|
81 |
if ( is_multisite() )
|
82 |
require_once ABSPATH.'wp-admin/includes/plugin.php';
|
83 |
-
|
84 |
$this->network_mode = is_multisite() && is_plugin_active_for_network('limit-login-attempts-reloaded/limit-login-attempts-reloaded.php');
|
85 |
-
|
86 |
-
|
87 |
if ( $this->network_mode )
|
88 |
{
|
89 |
$this->allow_local_options = get_site_option( 'limit_login_allow_local_options', false );
|
@@ -94,7 +94,7 @@ class Limit_Login_Attempts
|
|
94 |
$this->allow_local_options = true;
|
95 |
$this->use_local_options = true;
|
96 |
}
|
97 |
-
|
98 |
|
99 |
// Setup default plugin options
|
100 |
//$this->sanitize_options();
|
@@ -105,10 +105,10 @@ class Limit_Login_Attempts
|
|
105 |
add_filter( 'shake_error_codes', array( $this, 'failure_shake' ) );
|
106 |
add_action( 'login_head', array( $this, 'add_error_message' ) );
|
107 |
add_action( 'login_errors', array( $this, 'fixup_error_messages' ) );
|
108 |
-
|
109 |
if ( $this->network_mode )
|
110 |
add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) );
|
111 |
-
|
112 |
if ( $this->allow_local_options )
|
113 |
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
114 |
|
@@ -125,10 +125,27 @@ class Limit_Login_Attempts
|
|
125 |
*/
|
126 |
add_action( 'wp_authenticate', array( $this, 'track_credentials' ), 10, 2 );
|
127 |
add_action( 'authenticate', array( $this, 'authenticate_filter' ), 5, 3 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
}
|
129 |
|
130 |
public function check_whitelist_ips( $allow, $ip ) {
|
131 |
-
return
|
132 |
}
|
133 |
|
134 |
public function check_whitelist_usernames( $allow, $username ) {
|
@@ -136,13 +153,44 @@ class Limit_Login_Attempts
|
|
136 |
}
|
137 |
|
138 |
public function check_blacklist_ips( $allow, $ip ) {
|
139 |
-
return
|
140 |
}
|
141 |
|
142 |
public function check_blacklist_usernames( $allow, $username ) {
|
143 |
return in_array( $username, (array) $this->get_option( 'blacklist_usernames' ) );
|
144 |
}
|
145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
/**
|
147 |
* @param $error IXR_Error
|
148 |
*
|
@@ -278,7 +326,7 @@ class Limit_Login_Attempts
|
|
278 |
{
|
279 |
add_submenu_page( 'settings.php', 'Limit Login Attempts', 'Limit Login Attempts', 'manage_options', $this->_options_page_slug, array( $this, 'options_page' ) );
|
280 |
}
|
281 |
-
|
282 |
public function admin_menu()
|
283 |
{
|
284 |
add_options_page( 'Limit Login Attempts', 'Limit Login Attempts', 'manage_options', $this->_options_page_slug, array( $this, 'options_page' ) );
|
@@ -293,7 +341,7 @@ class Limit_Login_Attempts
|
|
293 |
{
|
294 |
if ( is_network_admin() )
|
295 |
return network_admin_url( 'settings.php?page=limit-login-attempts' );
|
296 |
-
|
297 |
return menu_page_url( $this->_options_page_slug, false );
|
298 |
}
|
299 |
|
@@ -304,43 +352,43 @@ class Limit_Login_Attempts
|
|
304 |
*
|
305 |
* @return null
|
306 |
*/
|
307 |
-
public function get_option( $option_name, $local = null )
|
308 |
{
|
309 |
if ( is_null( $local ) )
|
310 |
$local = $this->use_local_options;
|
311 |
-
|
312 |
$option = 'limit_login_'.$option_name;
|
313 |
-
|
314 |
$func = $local ? 'get_option' : 'get_site_option';
|
315 |
$value = $func( $option, null );
|
316 |
-
|
317 |
if ( is_null( $value ) && isset( $this->default_options[ $option_name ] ) )
|
318 |
$value = $this->default_options[ $option_name ];
|
319 |
-
|
320 |
return $value;
|
321 |
}
|
322 |
-
|
323 |
public function update_option( $option_name, $value, $local = null )
|
324 |
{
|
325 |
if ( is_null( $local ) )
|
326 |
$local = $this->use_local_options;
|
327 |
-
|
328 |
$option = 'limit_login_'.$option_name;
|
329 |
-
|
330 |
$func = $local ? 'update_option' : 'update_site_option';
|
331 |
-
|
332 |
return $func( $option, $value );
|
333 |
}
|
334 |
-
|
335 |
public function add_option( $option_name, $value, $local=null )
|
336 |
{
|
337 |
if ( is_null( $local ) )
|
338 |
$local = $this->use_local_options;
|
339 |
-
|
340 |
$option = 'limit_login_'.$option_name;
|
341 |
-
|
342 |
$func = $local ? 'add_option' : 'add_site_option';
|
343 |
-
|
344 |
return $func( $option, $value, '', 'no' );
|
345 |
}
|
346 |
|
@@ -358,11 +406,11 @@ class Limit_Login_Attempts
|
|
358 |
}
|
359 |
if ( $this->get_option('notify_email_after') > $this->get_option( 'allowed_lockouts' ) )
|
360 |
$this->update_option( 'notify_email_after', $this->get_option( 'allowed_lockouts' ) );
|
361 |
-
|
362 |
$args = explode( ',', $this->get_option( 'lockout_notify' ) );
|
363 |
$args_allowed = explode( ',', LLA_LOCKOUT_NOTIFY_ALLOWED );
|
364 |
$new_args = array_intersect( $args, $args_allowed );
|
365 |
-
|
366 |
$this->update_option( 'lockout_notify', implode( ',', $new_args ) );
|
367 |
|
368 |
$ctype = $this->get_option( 'client_type' );
|
@@ -555,6 +603,7 @@ class Limit_Login_Attempts
|
|
555 |
}
|
556 |
|
557 |
$blogname = $this->use_local_options ? get_option( 'blogname' ) : get_site_option( 'site_name' );
|
|
|
558 |
|
559 |
if ( $whitelisted ) {
|
560 |
$subject = sprintf( __( "[%s] Failed login attempts from whitelisted IP"
|
@@ -581,9 +630,10 @@ class Limit_Login_Attempts
|
|
581 |
|
582 |
$admin_email = $this->use_local_options ? get_option( 'admin_email' ) : get_site_option( 'admin_email' );
|
583 |
|
|
|
584 |
@wp_mail( $admin_email, $subject, $message );
|
585 |
}
|
586 |
-
|
587 |
/**
|
588 |
* Logging of lockout (if configured)
|
589 |
*
|
@@ -604,30 +654,18 @@ class Limit_Login_Attempts
|
|
604 |
$ip = $this->get_address();
|
605 |
|
606 |
/* can be written much simpler, if you do not mind php warnings */
|
607 |
-
if ( isset( $log[ $ip ] ) )
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
);
|
617 |
-
}
|
618 |
-
} else {
|
619 |
-
$log[ $ip ][ $user_login ] = array(
|
620 |
-
'counter' => 1
|
621 |
-
);
|
622 |
-
}
|
623 |
-
} else {
|
624 |
-
$log[ $ip ] = array(
|
625 |
-
$user_login => array(
|
626 |
-
'counter' => 1
|
627 |
-
)
|
628 |
);
|
629 |
-
}
|
630 |
|
|
|
631 |
$log[ $ip ][ $user_login ]['date'] = time();
|
632 |
|
633 |
if ( isset( $_POST['woocommerce-login-nonce'] ) ) {
|
@@ -1024,14 +1062,14 @@ class Limit_Login_Attempts
|
|
1024 |
public function options_page() {
|
1025 |
$this->use_local_options = !is_network_admin();
|
1026 |
$this->cleanup();
|
1027 |
-
|
1028 |
if( !empty( $_POST ) )
|
1029 |
{
|
1030 |
check_admin_referer( 'limit-login-attempts-options' );
|
1031 |
-
|
1032 |
if ( is_network_admin() )
|
1033 |
$this->update_option( 'allow_local_options', !empty($_POST['allow_local_options']) );
|
1034 |
-
|
1035 |
elseif ( $this->network_mode )
|
1036 |
$this->update_option( 'use_local_options', empty($_POST['use_global_options']) );
|
1037 |
|
@@ -1064,7 +1102,7 @@ class Limit_Login_Attempts
|
|
1064 |
$this->update_option('valid_duration', (int)$_POST['valid_duration'] * 3600 );
|
1065 |
$this->update_option('allowed_lockouts', (int)$_POST['allowed_lockouts'] );
|
1066 |
$this->update_option('long_duration', (int)$_POST['long_duration'] * 3600 );
|
1067 |
-
$this->update_option('notify_email_after', (int)$_POST['email_after']
|
1068 |
|
1069 |
$white_list_ips = ( !empty( $_POST['lla_whitelist_ips'] ) ) ? explode("\n", str_replace("\r", "", $_POST['lla_whitelist_ips'] ) ) : array();
|
1070 |
|
@@ -1098,7 +1136,7 @@ class Limit_Login_Attempts
|
|
1098 |
}
|
1099 |
}
|
1100 |
$this->update_option('blacklist', $black_list_ips );
|
1101 |
-
|
1102 |
$black_list_usernames = ( !empty( $_POST['lla_blacklist_usernames'] ) ) ? explode("\n", str_replace("\r", "", $_POST['lla_blacklist_usernames'] ) ) : array();
|
1103 |
|
1104 |
if( !empty( $black_list_usernames ) ) {
|
@@ -1109,7 +1147,7 @@ class Limit_Login_Attempts
|
|
1109 |
}
|
1110 |
}
|
1111 |
$this->update_option('blacklist_usernames', $black_list_usernames );
|
1112 |
-
|
1113 |
$notify_methods = array();
|
1114 |
if( isset( $_POST[ 'lockout_notify_log' ] ) ) {
|
1115 |
$notify_methods[] = 'log';
|
@@ -1118,16 +1156,49 @@ class Limit_Login_Attempts
|
|
1118 |
$notify_methods[] = 'email';
|
1119 |
}
|
1120 |
$this->update_option('lockout_notify', implode( ',', $notify_methods ) );
|
1121 |
-
|
1122 |
$this->sanitize_options();
|
1123 |
-
|
1124 |
-
$this->show_error( __( 'Options
|
1125 |
}
|
1126 |
}
|
1127 |
-
|
1128 |
include_once( LLA_PLUGIN_DIR . '/views/options-page.php' );
|
1129 |
}
|
1130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1131 |
/**
|
1132 |
* Show error message
|
1133 |
*
|
66 |
add_filter( 'limit_login_blacklist_ip', array( $this, 'check_blacklist_ips' ), 10, 2 );
|
67 |
add_filter( 'limit_login_blacklist_usernames', array( $this, 'check_blacklist_usernames' ), 10, 2 );
|
68 |
}
|
69 |
+
|
70 |
/**
|
71 |
* Hook 'plugins_loaded'
|
72 |
*/
|
77 |
|
78 |
// Check if installed old plugin
|
79 |
$this->check_original_installed();
|
80 |
+
|
81 |
if ( is_multisite() )
|
82 |
require_once ABSPATH.'wp-admin/includes/plugin.php';
|
83 |
+
|
84 |
$this->network_mode = is_multisite() && is_plugin_active_for_network('limit-login-attempts-reloaded/limit-login-attempts-reloaded.php');
|
85 |
+
|
86 |
+
|
87 |
if ( $this->network_mode )
|
88 |
{
|
89 |
$this->allow_local_options = get_site_option( 'limit_login_allow_local_options', false );
|
94 |
$this->allow_local_options = true;
|
95 |
$this->use_local_options = true;
|
96 |
}
|
97 |
+
|
98 |
|
99 |
// Setup default plugin options
|
100 |
//$this->sanitize_options();
|
105 |
add_filter( 'shake_error_codes', array( $this, 'failure_shake' ) );
|
106 |
add_action( 'login_head', array( $this, 'add_error_message' ) );
|
107 |
add_action( 'login_errors', array( $this, 'fixup_error_messages' ) );
|
108 |
+
|
109 |
if ( $this->network_mode )
|
110 |
add_action( 'network_admin_menu', array( $this, 'network_admin_menu' ) );
|
111 |
+
|
112 |
if ( $this->allow_local_options )
|
113 |
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
114 |
|
125 |
*/
|
126 |
add_action( 'wp_authenticate', array( $this, 'track_credentials' ), 10, 2 );
|
127 |
add_action( 'authenticate', array( $this, 'authenticate_filter' ), 5, 3 );
|
128 |
+
|
129 |
+
if ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST )
|
130 |
+
add_action( 'init', array( $this, 'check_xmlrpc_lock' ) );
|
131 |
+
|
132 |
+
add_action('wp_ajax_limit-login-unlock', array( $this, 'ajax_unlock' ) );
|
133 |
+
}
|
134 |
+
|
135 |
+
public function check_xmlrpc_lock()
|
136 |
+
{
|
137 |
+
if ( is_user_logged_in() || $this->is_ip_whitelisted() )
|
138 |
+
return;
|
139 |
+
|
140 |
+
if ( $this->is_ip_blacklisted() || !$this->is_limit_login_ok() )
|
141 |
+
{
|
142 |
+
header('HTTP/1.0 403 Forbidden');
|
143 |
+
exit;
|
144 |
+
}
|
145 |
}
|
146 |
|
147 |
public function check_whitelist_ips( $allow, $ip ) {
|
148 |
+
return $this->ip_in_range( $ip, (array) $this->get_option( 'whitelist' ) );
|
149 |
}
|
150 |
|
151 |
public function check_whitelist_usernames( $allow, $username ) {
|
153 |
}
|
154 |
|
155 |
public function check_blacklist_ips( $allow, $ip ) {
|
156 |
+
return $this->ip_in_range( $ip, (array) $this->get_option( 'blacklist' ) );
|
157 |
}
|
158 |
|
159 |
public function check_blacklist_usernames( $allow, $username ) {
|
160 |
return in_array( $username, (array) $this->get_option( 'blacklist_usernames' ) );
|
161 |
}
|
162 |
|
163 |
+
public function ip_in_range( $ip, $list )
|
164 |
+
{
|
165 |
+
foreach ( $list as $range )
|
166 |
+
{
|
167 |
+
$range = array_map('trim', explode('-', $range) );
|
168 |
+
if ( count( $range ) == 1 )
|
169 |
+
{
|
170 |
+
if ( (string)$ip === (string)$range[0] )
|
171 |
+
return true;
|
172 |
+
}
|
173 |
+
else
|
174 |
+
{
|
175 |
+
$low = ip2long( $range[0] );
|
176 |
+
$high = ip2long( $range[1] );
|
177 |
+
$ip = ip2long( $ip );
|
178 |
+
|
179 |
+
if ( $low === false || $high === false || $ip === false )
|
180 |
+
continue;
|
181 |
+
|
182 |
+
$low = (float)sprintf("%u",$low);
|
183 |
+
$high = (float)sprintf("%u",$high);
|
184 |
+
$ip = (float)sprintf("%u",$ip);
|
185 |
+
|
186 |
+
if ( $ip >= $low && $ip <= $high )
|
187 |
+
return true;
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
/**
|
195 |
* @param $error IXR_Error
|
196 |
*
|
326 |
{
|
327 |
add_submenu_page( 'settings.php', 'Limit Login Attempts', 'Limit Login Attempts', 'manage_options', $this->_options_page_slug, array( $this, 'options_page' ) );
|
328 |
}
|
329 |
+
|
330 |
public function admin_menu()
|
331 |
{
|
332 |
add_options_page( 'Limit Login Attempts', 'Limit Login Attempts', 'manage_options', $this->_options_page_slug, array( $this, 'options_page' ) );
|
341 |
{
|
342 |
if ( is_network_admin() )
|
343 |
return network_admin_url( 'settings.php?page=limit-login-attempts' );
|
344 |
+
|
345 |
return menu_page_url( $this->_options_page_slug, false );
|
346 |
}
|
347 |
|
352 |
*
|
353 |
* @return null
|
354 |
*/
|
355 |
+
public function get_option( $option_name, $local = null )
|
356 |
{
|
357 |
if ( is_null( $local ) )
|
358 |
$local = $this->use_local_options;
|
359 |
+
|
360 |
$option = 'limit_login_'.$option_name;
|
361 |
+
|
362 |
$func = $local ? 'get_option' : 'get_site_option';
|
363 |
$value = $func( $option, null );
|
364 |
+
|
365 |
if ( is_null( $value ) && isset( $this->default_options[ $option_name ] ) )
|
366 |
$value = $this->default_options[ $option_name ];
|
367 |
+
|
368 |
return $value;
|
369 |
}
|
370 |
+
|
371 |
public function update_option( $option_name, $value, $local = null )
|
372 |
{
|
373 |
if ( is_null( $local ) )
|
374 |
$local = $this->use_local_options;
|
375 |
+
|
376 |
$option = 'limit_login_'.$option_name;
|
377 |
+
|
378 |
$func = $local ? 'update_option' : 'update_site_option';
|
379 |
+
|
380 |
return $func( $option, $value );
|
381 |
}
|
382 |
+
|
383 |
public function add_option( $option_name, $value, $local=null )
|
384 |
{
|
385 |
if ( is_null( $local ) )
|
386 |
$local = $this->use_local_options;
|
387 |
+
|
388 |
$option = 'limit_login_'.$option_name;
|
389 |
+
|
390 |
$func = $local ? 'add_option' : 'add_site_option';
|
391 |
+
|
392 |
return $func( $option, $value, '', 'no' );
|
393 |
}
|
394 |
|
406 |
}
|
407 |
if ( $this->get_option('notify_email_after') > $this->get_option( 'allowed_lockouts' ) )
|
408 |
$this->update_option( 'notify_email_after', $this->get_option( 'allowed_lockouts' ) );
|
409 |
+
|
410 |
$args = explode( ',', $this->get_option( 'lockout_notify' ) );
|
411 |
$args_allowed = explode( ',', LLA_LOCKOUT_NOTIFY_ALLOWED );
|
412 |
$new_args = array_intersect( $args, $args_allowed );
|
413 |
+
|
414 |
$this->update_option( 'lockout_notify', implode( ',', $new_args ) );
|
415 |
|
416 |
$ctype = $this->get_option( 'client_type' );
|
603 |
}
|
604 |
|
605 |
$blogname = $this->use_local_options ? get_option( 'blogname' ) : get_site_option( 'site_name' );
|
606 |
+
$blogname = htmlspecialchars_decode( $blogname, ENT_QUOTES );
|
607 |
|
608 |
if ( $whitelisted ) {
|
609 |
$subject = sprintf( __( "[%s] Failed login attempts from whitelisted IP"
|
630 |
|
631 |
$admin_email = $this->use_local_options ? get_option( 'admin_email' ) : get_site_option( 'admin_email' );
|
632 |
|
633 |
+
//var_dump( $blogname, $subject ); exit;
|
634 |
@wp_mail( $admin_email, $subject, $message );
|
635 |
}
|
636 |
+
|
637 |
/**
|
638 |
* Logging of lockout (if configured)
|
639 |
*
|
654 |
$ip = $this->get_address();
|
655 |
|
656 |
/* can be written much simpler, if you do not mind php warnings */
|
657 |
+
if ( !isset( $log[ $ip ] ) )
|
658 |
+
$log[ $ip ] = array();
|
659 |
+
|
660 |
+
if ( !isset( $log[ $ip ][ $user_login ] ) )
|
661 |
+
$log[ $ip ][ $user_login ] = array( 'counter' => 0 );
|
662 |
+
|
663 |
+
elseif ( !is_array( $log[ $ip ][ $user_login ] ) )
|
664 |
+
$log[ $ip ][ $user_login ] = array(
|
665 |
+
'counter' => $log[ $ip ][ $user_login ],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
666 |
);
|
|
|
667 |
|
668 |
+
$log[ $ip ][ $user_login ]['counter']++;
|
669 |
$log[ $ip ][ $user_login ]['date'] = time();
|
670 |
|
671 |
if ( isset( $_POST['woocommerce-login-nonce'] ) ) {
|
1062 |
public function options_page() {
|
1063 |
$this->use_local_options = !is_network_admin();
|
1064 |
$this->cleanup();
|
1065 |
+
|
1066 |
if( !empty( $_POST ) )
|
1067 |
{
|
1068 |
check_admin_referer( 'limit-login-attempts-options' );
|
1069 |
+
|
1070 |
if ( is_network_admin() )
|
1071 |
$this->update_option( 'allow_local_options', !empty($_POST['allow_local_options']) );
|
1072 |
+
|
1073 |
elseif ( $this->network_mode )
|
1074 |
$this->update_option( 'use_local_options', empty($_POST['use_global_options']) );
|
1075 |
|
1102 |
$this->update_option('valid_duration', (int)$_POST['valid_duration'] * 3600 );
|
1103 |
$this->update_option('allowed_lockouts', (int)$_POST['allowed_lockouts'] );
|
1104 |
$this->update_option('long_duration', (int)$_POST['long_duration'] * 3600 );
|
1105 |
+
$this->update_option('notify_email_after', (int)$_POST['email_after'] );
|
1106 |
|
1107 |
$white_list_ips = ( !empty( $_POST['lla_whitelist_ips'] ) ) ? explode("\n", str_replace("\r", "", $_POST['lla_whitelist_ips'] ) ) : array();
|
1108 |
|
1136 |
}
|
1137 |
}
|
1138 |
$this->update_option('blacklist', $black_list_ips );
|
1139 |
+
|
1140 |
$black_list_usernames = ( !empty( $_POST['lla_blacklist_usernames'] ) ) ? explode("\n", str_replace("\r", "", $_POST['lla_blacklist_usernames'] ) ) : array();
|
1141 |
|
1142 |
if( !empty( $black_list_usernames ) ) {
|
1147 |
}
|
1148 |
}
|
1149 |
$this->update_option('blacklist_usernames', $black_list_usernames );
|
1150 |
+
|
1151 |
$notify_methods = array();
|
1152 |
if( isset( $_POST[ 'lockout_notify_log' ] ) ) {
|
1153 |
$notify_methods[] = 'log';
|
1156 |
$notify_methods[] = 'email';
|
1157 |
}
|
1158 |
$this->update_option('lockout_notify', implode( ',', $notify_methods ) );
|
1159 |
+
|
1160 |
$this->sanitize_options();
|
1161 |
+
|
1162 |
+
$this->show_error( __( 'Options saved.', 'limit-login-attempts-reloaded' ) );
|
1163 |
}
|
1164 |
}
|
1165 |
+
|
1166 |
include_once( LLA_PLUGIN_DIR . '/views/options-page.php' );
|
1167 |
}
|
1168 |
|
1169 |
+
public function ajax_unlock()
|
1170 |
+
{
|
1171 |
+
check_ajax_referer('limit-login-unlock', 'sec');
|
1172 |
+
$ip = (string)@$_POST['ip'];
|
1173 |
+
|
1174 |
+
$lockouts = (array)$this->get_option('lockouts');
|
1175 |
+
|
1176 |
+
if ( isset( $lockouts[ $ip ] ) )
|
1177 |
+
{
|
1178 |
+
unset( $lockouts[ $ip ] );
|
1179 |
+
$this->update_option( 'lockouts', $lockouts );
|
1180 |
+
}
|
1181 |
+
|
1182 |
+
//save to log
|
1183 |
+
$user_login = @(string)$_POST['username'];
|
1184 |
+
$log = $this->get_option( 'logged' );
|
1185 |
+
|
1186 |
+
if ( @$log[ $ip ][ $user_login ] )
|
1187 |
+
{
|
1188 |
+
if ( !is_array( $log[ $ip ][ $user_login ] ) )
|
1189 |
+
$log[ $ip ][ $user_login ] = array(
|
1190 |
+
'counter' => $log[ $ip ][ $user_login ],
|
1191 |
+
);
|
1192 |
+
$log[ $ip ][ $user_login ]['unlocked'] = true;
|
1193 |
+
|
1194 |
+
$this->update_option( 'logged', $log );
|
1195 |
+
}
|
1196 |
+
|
1197 |
+
header('Content-Type: application/json');
|
1198 |
+
echo 'true';
|
1199 |
+
exit;
|
1200 |
+
}
|
1201 |
+
|
1202 |
/**
|
1203 |
* Show error message
|
1204 |
*
|
limit-login-attempts-reloaded.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
Description: Limit the rate of login attempts, including by way of cookies and for each IP address.
|
5 |
Author: wpchefgadget
|
6 |
Text Domain: limit-login-attempts-reloaded
|
7 |
-
Version: 2.
|
8 |
|
9 |
Copyright 2008 - 2012 Johan Eenfeldt, 2016 - 2017 WPChef
|
10 |
|
4 |
Description: Limit the rate of login attempts, including by way of cookies and for each IP address.
|
5 |
Author: wpchefgadget
|
6 |
Text Domain: limit-login-attempts-reloaded
|
7 |
+
Version: 2.6.1
|
8 |
|
9 |
Copyright 2008 - 2012 Johan Eenfeldt, 2016 - 2017 WPChef
|
10 |
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: wpchefgadget
|
3 |
Tags: login, security, authentication, Limit Login Attempts, Limit Login Attempts Reloaded, Limit Login Attempts Revamped, Limit Login Attempts Renovated, Limit Login Attempts Updated, Better Limit Login Attempts, Limit Login Attempts Renewed, Limit Login Attempts Upgraded
|
4 |
Requires at least: 3.0
|
5 |
-
Tested up to: 4.
|
6 |
-
Stable tag: 2.
|
7 |
|
8 |
Reloaded version of the original Limit Login Attempts plugin for Login Protection by a team of WordPress developers.
|
9 |
|
@@ -49,6 +49,15 @@ Based on the original code from Limit Login Attemps plugin by Johan Eenfeldt.
|
|
49 |
|
50 |
== Changelog ==
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
= 2.5.0 =
|
53 |
* Added Multi-site Compatibility and additional MU settings. https://wordpress.org/support/topic/multisite-compatibility-47/
|
54 |
|
2 |
Contributors: wpchefgadget
|
3 |
Tags: login, security, authentication, Limit Login Attempts, Limit Login Attempts Reloaded, Limit Login Attempts Revamped, Limit Login Attempts Renovated, Limit Login Attempts Updated, Better Limit Login Attempts, Limit Login Attempts Renewed, Limit Login Attempts Upgraded
|
4 |
Requires at least: 3.0
|
5 |
+
Tested up to: 4.8
|
6 |
+
Stable tag: 2.6.1
|
7 |
|
8 |
Reloaded version of the original Limit Login Attempts plugin for Login Protection by a team of WordPress developers.
|
9 |
|
49 |
|
50 |
== Changelog ==
|
51 |
|
52 |
+
= 2.6.1 =
|
53 |
+
Plugin returns the 403 Forbidden header after the limit of login attempts via XMLRPC is reached.
|
54 |
+
|
55 |
+
Added support of IP ranges in white/black lists.
|
56 |
+
|
57 |
+
Lockouts now can be released selectively.
|
58 |
+
|
59 |
+
Fixed the issue with encoding of special symbols in email notifications.
|
60 |
+
|
61 |
= 2.5.0 =
|
62 |
* Added Multi-site Compatibility and additional MU settings. https://wordpress.org/support/topic/multisite-compatibility-47/
|
63 |
|
views/options-page.php
CHANGED
@@ -74,12 +74,12 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
74 |
$('.use_global_options').change( function(){
|
75 |
var form = $(this).siblings('table');
|
76 |
form.stop();
|
77 |
-
|
78 |
if ( this.checked )
|
79 |
first ? form.hide() : form.fadeOut();
|
80 |
else
|
81 |
first ? form.show() : form.fadeIn();
|
82 |
-
|
83 |
first = false;
|
84 |
}).change();
|
85 |
});
|
@@ -89,7 +89,7 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
89 |
<tr>
|
90 |
<th scope="row" valign="top"><?php echo __( 'Lockout', 'limit-login-attempts-reloaded' ); ?></th>
|
91 |
<td>
|
92 |
-
|
93 |
<input type="text" size="3" maxlength="4"
|
94 |
value="<?php echo( $this->get_option( 'allowed_retries' ) ); ?>"
|
95 |
name="allowed_retries"/> <?php echo __( 'allowed retries', 'limit-login-attempts-reloaded' ); ?>
|
@@ -127,7 +127,7 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
127 |
valign="top"><?php echo __( 'Whitelist', 'limit-login-attempts-reloaded' ); ?></th>
|
128 |
<td>
|
129 |
<div class="field-col">
|
130 |
-
<p class="description"><?php _e( 'One IP per line', 'limit-login-attempts-reloaded' ); ?></p>
|
131 |
<textarea name="lla_whitelist_ips" rows="10" cols="50"><?php echo $white_list_ips; ?></textarea>
|
132 |
</div>
|
133 |
<div class="field-col">
|
@@ -141,7 +141,7 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
141 |
valign="top"><?php echo __( 'Blacklist', 'limit-login-attempts-reloaded' ); ?></th>
|
142 |
<td>
|
143 |
<div class="field-col">
|
144 |
-
<p class="description"><?php _e( 'One IP per line', 'limit-login-attempts-reloaded' ); ?></p>
|
145 |
<textarea name="lla_blacklist_ips" rows="10" cols="50"><?php echo $black_list_ips; ?></textarea>
|
146 |
</div>
|
147 |
<div class="field-col">
|
@@ -152,7 +152,7 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
152 |
</tr>
|
153 |
</table>
|
154 |
<p class="submit">
|
155 |
-
<input class="button button-primary" name="update_options" value="<?php echo __( '
|
156 |
type="submit"/>
|
157 |
</p>
|
158 |
</form>
|
@@ -160,6 +160,8 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
160 |
$log = $this->get_option( 'logged' );
|
161 |
$log = LLA_Helpers::sorted_log_by_date( $log );
|
162 |
|
|
|
|
|
163 |
if( is_array( $log ) && ! empty( $log ) ) { ?>
|
164 |
<h3><?php echo __( 'Lockout log', 'limit-login-attempts-reloaded' ); ?></h3>
|
165 |
<form action="<?php echo $this->get_options_page_uri(); ?>" method="post">
|
@@ -178,6 +180,7 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
178 |
<th scope="col"><?php echo _x( "IP", "Internet address", 'limit-login-attempts-reloaded' ); ?></th>
|
179 |
<th scope="col"><?php _e( 'Tried to log in as', 'limit-login-attempts-reloaded' ); ?></th>
|
180 |
<th scope="col"><?php _e( 'Gateway', 'limit-login-attempts-reloaded' ); ?></th>
|
|
|
181 |
</tr>
|
182 |
|
183 |
<?php foreach ( $log as $date => $user_info ) : ?>
|
@@ -186,11 +189,47 @@ $black_list_usernames = ( is_array( $black_list_usernames ) && !empty( $black_li
|
|
186 |
<td class="limit-login-ip"><?php echo $user_info['ip']; ?></td>
|
187 |
<td class="limit-login-max"><?php echo $user_info['username'] . ' (' . $user_info['counter'] .' lockouts)'; ?></td>
|
188 |
<td class="limit-login-gateway"><?php echo $user_info['gateway']; ?></td>
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
</tr>
|
190 |
<?php endforeach; ?>
|
191 |
|
192 |
</table>
|
193 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
<?php
|
195 |
} /* if showing $log */
|
196 |
?>
|
74 |
$('.use_global_options').change( function(){
|
75 |
var form = $(this).siblings('table');
|
76 |
form.stop();
|
77 |
+
|
78 |
if ( this.checked )
|
79 |
first ? form.hide() : form.fadeOut();
|
80 |
else
|
81 |
first ? form.show() : form.fadeIn();
|
82 |
+
|
83 |
first = false;
|
84 |
}).change();
|
85 |
});
|
89 |
<tr>
|
90 |
<th scope="row" valign="top"><?php echo __( 'Lockout', 'limit-login-attempts-reloaded' ); ?></th>
|
91 |
<td>
|
92 |
+
|
93 |
<input type="text" size="3" maxlength="4"
|
94 |
value="<?php echo( $this->get_option( 'allowed_retries' ) ); ?>"
|
95 |
name="allowed_retries"/> <?php echo __( 'allowed retries', 'limit-login-attempts-reloaded' ); ?>
|
127 |
valign="top"><?php echo __( 'Whitelist', 'limit-login-attempts-reloaded' ); ?></th>
|
128 |
<td>
|
129 |
<div class="field-col">
|
130 |
+
<p class="description"><?php _e( 'One IP or IP range (1.2.3.4-5.6.7.8) per line', 'limit-login-attempts-reloaded' ); ?></p>
|
131 |
<textarea name="lla_whitelist_ips" rows="10" cols="50"><?php echo $white_list_ips; ?></textarea>
|
132 |
</div>
|
133 |
<div class="field-col">
|
141 |
valign="top"><?php echo __( 'Blacklist', 'limit-login-attempts-reloaded' ); ?></th>
|
142 |
<td>
|
143 |
<div class="field-col">
|
144 |
+
<p class="description"><?php _e( 'One IP or IP range (1.2.3.4-5.6.7.8) per line', 'limit-login-attempts-reloaded' ); ?></p>
|
145 |
<textarea name="lla_blacklist_ips" rows="10" cols="50"><?php echo $black_list_ips; ?></textarea>
|
146 |
</div>
|
147 |
<div class="field-col">
|
152 |
</tr>
|
153 |
</table>
|
154 |
<p class="submit">
|
155 |
+
<input class="button button-primary" name="update_options" value="<?php echo __( 'Save Options', 'limit-login-attempts-reloaded' ); ?>"
|
156 |
type="submit"/>
|
157 |
</p>
|
158 |
</form>
|
160 |
$log = $this->get_option( 'logged' );
|
161 |
$log = LLA_Helpers::sorted_log_by_date( $log );
|
162 |
|
163 |
+
$lockouts = (array)$this->get_option('lockouts');
|
164 |
+
|
165 |
if( is_array( $log ) && ! empty( $log ) ) { ?>
|
166 |
<h3><?php echo __( 'Lockout log', 'limit-login-attempts-reloaded' ); ?></h3>
|
167 |
<form action="<?php echo $this->get_options_page_uri(); ?>" method="post">
|
180 |
<th scope="col"><?php echo _x( "IP", "Internet address", 'limit-login-attempts-reloaded' ); ?></th>
|
181 |
<th scope="col"><?php _e( 'Tried to log in as', 'limit-login-attempts-reloaded' ); ?></th>
|
182 |
<th scope="col"><?php _e( 'Gateway', 'limit-login-attempts-reloaded' ); ?></th>
|
183 |
+
<th>
|
184 |
</tr>
|
185 |
|
186 |
<?php foreach ( $log as $date => $user_info ) : ?>
|
189 |
<td class="limit-login-ip"><?php echo $user_info['ip']; ?></td>
|
190 |
<td class="limit-login-max"><?php echo $user_info['username'] . ' (' . $user_info['counter'] .' lockouts)'; ?></td>
|
191 |
<td class="limit-login-gateway"><?php echo $user_info['gateway']; ?></td>
|
192 |
+
<td>
|
193 |
+
<?php if ( !empty( $lockouts[ $user_info['ip'] ] ) && $lockouts[ $user_info['ip'] ] > time() ) : ?>
|
194 |
+
<a href="#" class="button limit-login-unlock" data-ip="<?=esc_attr($user_info['ip'])?>" data-username="<?=esc_attr($user_info['username'])?>">Unlock</a>
|
195 |
+
<?php elseif ( $user_info['unlocked'] ): ?>
|
196 |
+
Unlocked
|
197 |
+
<?php endif ?>
|
198 |
</tr>
|
199 |
<?php endforeach; ?>
|
200 |
|
201 |
</table>
|
202 |
</div>
|
203 |
+
<script>jQuery( function($) {
|
204 |
+
$('.limit-login-log .limit-login-unlock').click( function()
|
205 |
+
{
|
206 |
+
var btn = $(this);
|
207 |
+
|
208 |
+
if ( btn.hasClass('disabled') )
|
209 |
+
return false;
|
210 |
+
btn.addClass( 'disabled' );
|
211 |
+
|
212 |
+
$.post( ajaxurl, {
|
213 |
+
action: 'limit-login-unlock',
|
214 |
+
sec: '<?=wp_create_nonce('limit-login-unlock') ?>',
|
215 |
+
ip: btn.data('ip'),
|
216 |
+
username: btn.data('username')
|
217 |
+
} )
|
218 |
+
.done( function(data) {
|
219 |
+
if ( data === true )
|
220 |
+
btn.fadeOut( function(){ $(this).parent().text('Unlocked') });
|
221 |
+
else
|
222 |
+
fail();
|
223 |
+
}).fail( fail );
|
224 |
+
|
225 |
+
function fail() {
|
226 |
+
alert('Connection error');
|
227 |
+
btn.removeClass('disabled');
|
228 |
+
}
|
229 |
+
|
230 |
+
return false;
|
231 |
+
} );
|
232 |
+
} )</script>
|
233 |
<?php
|
234 |
} /* if showing $log */
|
235 |
?>
|