Limit Login Attempts Reloaded - Version 2.22.0

Version Description

  • Added support of CIDR notation for specifying IP ranges.
  • Texts updated.
  • Refactoring.
Download this release

Release Info

Developer wpchefgadget
Plugin Icon 128x128 Limit Login Attempts Reloaded
Version 2.22.0
Comparing to
See all releases

Code changes from version 2.21.1 to 2.22.0

core/App.php CHANGED
@@ -77,10 +77,9 @@ class LLAR_App {
77
 
78
  /**
79
  * @param $link
80
- * @param bool $is_update
81
  * @return false[]
82
  */
83
- public static function setup( $link, $is_update = false ) {
84
 
85
  $return = array(
86
  'success' => false,
@@ -99,10 +98,6 @@ class LLAR_App {
99
  $plugin_data = get_plugin_data( LLA_PLUGIN_DIR . '/limit-login-attempts-reloaded.php' );
100
  $link = add_query_arg( 'version', $plugin_data['Version'], $link );
101
 
102
- if( $is_update ) {
103
- $link = add_query_arg( 'is_update', 1, $link );
104
- }
105
-
106
  $setup_response = wp_remote_get( $link );
107
  $setup_response_body = json_decode( wp_remote_retrieve_body( $setup_response ), true );
108
 
77
 
78
  /**
79
  * @param $link
 
80
  * @return false[]
81
  */
82
+ public static function setup( $link ) {
83
 
84
  $return = array(
85
  'success' => false,
98
  $plugin_data = get_plugin_data( LLA_PLUGIN_DIR . '/limit-login-attempts-reloaded.php' );
99
  $link = add_query_arg( 'version', $plugin_data['Version'], $link );
100
 
 
 
 
 
101
  $setup_response = wp_remote_get( $link );
102
  $setup_response_body = json_decode( wp_remote_retrieve_body( $setup_response ), true );
103
 
core/Helpers.php CHANGED
@@ -72,4 +72,27 @@ class LLA_Helpers {
72
 
73
  return $countries;
74
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
72
 
73
  return $countries;
74
  }
75
+
76
+ /**
77
+ * @param $ip
78
+ * @param $cidr
79
+ * @return bool
80
+ */
81
+ public static function check_ip_cidr($ip, $cidr) {
82
+
83
+ if( !$ip || !$cidr ) return false;
84
+
85
+ $cidr_checker = new LLAR_cidr_check();
86
+ return $cidr_checker->match( $ip, $cidr );
87
+ }
88
+
89
+ /**
90
+ * Checks if the plugin is installed as Must Use plugin
91
+ *
92
+ * @return bool
93
+ */
94
+ public static function is_mu() {
95
+
96
+ return ( strpos( LLA_PLUGIN_DIR, 'mu-plugins' ) !== false );
97
+ }
98
  }
core/LimitLoginAttempts.php CHANGED
@@ -300,18 +300,26 @@ class Limit_Login_Attempts {
300
  return in_array( $username, (array) $this->get_option( 'blacklist_usernames' ) );
301
  }
302
 
303
- public function ip_in_range( $ip, $list )
304
- {
305
- foreach ( $list as $range )
306
- {
307
  $range = array_map('trim', explode('-', $range) );
308
- if ( count( $range ) == 1 )
309
- {
310
- if ( (string)$ip === (string)$range[0] )
311
- return true;
312
- }
313
- else
314
- {
 
 
 
 
 
 
 
 
315
  $low = ip2long( $range[0] );
316
  $high = ip2long( $range[1] );
317
  $needle = ip2long( $ip );
@@ -978,17 +986,17 @@ class Limit_Login_Attempts {
978
  $blogname = $this->use_local_options ? get_option( 'blogname' ) : get_site_option( 'site_name' );
979
  $blogname = htmlspecialchars_decode( $blogname, ENT_QUOTES );
980
 
981
- $subject = sprintf( __( "[%s] Failed login attempt alert", 'limit-login-attempts-reloaded' ), $blogname );
982
 
983
- $message = __( '<p>Hello%1$s,</p>' .
984
- '<p>%2$d failed login attempts (%3$d lockout(s)) from IP <b>%4$s</b><br>' .
985
- 'Last user attempted: <b>%5$s</b><br>'.
986
- 'IP was blocked for %6$s</p>'.
987
- '<p>This notification was sent automatically via Limit Login Attempts Reloaded Plugin. ' .
988
- '<b>This is installed on your %7$s WordPress site.</b></p>'.
989
- '<p>Under Attack? Try our <a href="%8$s" target="_blank">advanced protection</a>. ' .
990
- 'Have Questions? Visit our <a href="%9$s" target="_blank">help section</a>.</p>' .
991
- '<hr><a href="%10$s">Unsubscribe</a> from these notifications.', 'limit-login-attempts-reloaded' );
992
 
993
  $plugin_data = get_plugin_data( LLA_PLUGIN_DIR . '/limit-login-attempts-reloaded.php' );
994
 
@@ -1002,8 +1010,22 @@ class Limit_Login_Attempts {
1002
  $when,
1003
  $site_domain,
1004
  'https://www.limitloginattempts.com/info.php?from=plugin-lockout-email&v='.$plugin_data['Version'],
1005
- 'https://www.limitloginattempts.com/resources/?from=plugin-lockout-email',
1006
- admin_url( 'options-general.php?page=limit-login-attempts&tab=settings' )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1007
  );
1008
 
1009
  @wp_mail( $admin_email, $subject, $message, array( 'content-type: text/html' ) );
@@ -1115,9 +1137,9 @@ class Limit_Login_Attempts {
1115
  $ip = $this->get_address();
1116
  }
1117
 
1118
- $whitelisted = apply_filters( 'limit_login_blacklist_ip', false, $ip );
1119
 
1120
- return ( $whitelisted === true );
1121
  }
1122
 
1123
  public function is_username_blacklisted( $username ) {
@@ -1647,7 +1669,7 @@ class Limit_Login_Attempts {
1647
 
1648
  if( !empty( $_POST['llar_app_settings'] ) && $this->app ) {
1649
 
1650
- if( ( $app_setup_code = $this->get_option( 'app_setup_code' ) ) && $setup_result = LLAR_App::setup( strrev( $app_setup_code ), true ) ) {
1651
 
1652
  if( $setup_result['success'] && $active_app_config = $setup_result['app_config'] ) {
1653
 
300
  return in_array( $username, (array) $this->get_option( 'blacklist_usernames' ) );
301
  }
302
 
303
+ public function ip_in_range( $ip, $list ) {
304
+
305
+ foreach ( $list as $range ) {
306
+
307
  $range = array_map('trim', explode('-', $range) );
308
+ if ( count( $range ) == 1 ) {
309
+
310
+ // CIDR
311
+ if( strpos( $range[0], '/' ) !== false && LLA_Helpers::check_ip_cidr( $ip, $range[0] ) ) {
312
+
313
+ return true;
314
+ }
315
+ // Single IP
316
+ else if ( (string)$ip === (string)$range[0] ) {
317
+
318
+ return true;
319
+ }
320
+
321
+ } else {
322
+
323
  $low = ip2long( $range[0] );
324
  $high = ip2long( $range[1] );
325
  $needle = ip2long( $ip );
986
  $blogname = $this->use_local_options ? get_option( 'blogname' ) : get_site_option( 'site_name' );
987
  $blogname = htmlspecialchars_decode( $blogname, ENT_QUOTES );
988
 
989
+ $subject = sprintf( __( "[%s] Failed WordPress login attempt", 'limit-login-attempts-reloaded' ), $blogname );
990
 
991
+ $message = __(
992
+ '<p>Hello%1$s,</p>
993
+ <p>%2$d failed login attempts (%3$d lockout(s)) from IP <b>%4$s</b><br>
994
+ Last user attempted: <b>%5$s</b><br>
995
+ IP was blocked for %6$s</p>
996
+ <p>This notification was sent automatically via Limit Login Attempts Reloaded Plugin.
997
+ <b>This is installed on your %7$s WordPress site. Please login to your WordPress dashboard to view more info.</b></p>
998
+ <p>Under Attack? Try our <a href="%8$s" target="_blank">advanced protection</a>.
999
+ Have Questions? Visit our <a href="%9$s" target="_blank">help section</a>.</p>', 'limit-login-attempts-reloaded' );
1000
 
1001
  $plugin_data = get_plugin_data( LLA_PLUGIN_DIR . '/limit-login-attempts-reloaded.php' );
1002
 
1010
  $when,
1011
  $site_domain,
1012
  'https://www.limitloginattempts.com/info.php?from=plugin-lockout-email&v='.$plugin_data['Version'],
1013
+ 'https://www.limitloginattempts.com/resources/?from=plugin-lockout-email'
1014
+ );
1015
+
1016
+ if( LLA_Helpers::is_mu() ) {
1017
+
1018
+ $message .= sprintf( __(
1019
+ '<p><i>This alert was sent by your website where Limit Login Attempts Reloaded free version
1020
+ is installed and you are listed as the admin. If you are a GoDaddy customer, the plugin is installed
1021
+ into a must-use (MU) folder. You can read more <a href="%s" target="_blank">here</a>.</i></p>', 'limit-login-attempts-reloaded' ),
1022
+ 'https://www.limitloginattempts.com/how-to-tell-if-i-have-limit-login-attempts-reloaded-on-my-site-a-survival-guide-for-godaddy-customers/'
1023
+ );
1024
+ }
1025
+
1026
+ $message .= sprintf( __(
1027
+ '<hr><a href="%s">Unsubscribe</a> from these notifications.', 'limit-login-attempts-reloaded' ),
1028
+ admin_url( 'options-general.php?page=limit-login-attempts&tab=settings' )
1029
  );
1030
 
1031
  @wp_mail( $admin_email, $subject, $message, array( 'content-type: text/html' ) );
1137
  $ip = $this->get_address();
1138
  }
1139
 
1140
+ $blacklisted = apply_filters( 'limit_login_blacklist_ip', false, $ip );
1141
 
1142
+ return ( $blacklisted === true );
1143
  }
1144
 
1145
  public function is_username_blacklisted( $username ) {
1669
 
1670
  if( !empty( $_POST['llar_app_settings'] ) && $this->app ) {
1671
 
1672
+ if( ( $app_setup_code = $this->get_option( 'app_setup_code' ) ) && $setup_result = LLAR_App::setup( strrev( $app_setup_code ) ) ) {
1673
 
1674
  if( $setup_result['success'] && $active_app_config = $setup_result['app_config'] ) {
1675
 
lib/CidrCheck.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class LLAR_cidr_check {
4
+
5
+ public function match($ip, $cidr) {
6
+
7
+ if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
8
+
9
+ return false;
10
+ }
11
+
12
+ $c = explode('/', $cidr);
13
+ $subnet = isset($c[0]) ? $c[0] : NULL;
14
+ $mask = isset($c[1]) ? $c[1] : NULL;
15
+ if ($mask === null) {
16
+ $mask = 32;
17
+ }
18
+
19
+ return $this->IPv4Match($ip, $subnet, $mask);
20
+ }
21
+
22
+ private function IPv4Match($address, $subnetAddress, $subnetMask) {
23
+
24
+ if (!filter_var($subnetAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || $subnetMask === NULL || $subnetMask === "" || $subnetMask < 0 || $subnetMask > 32) {
25
+ return false;
26
+ }
27
+
28
+ $address = ip2long($address);
29
+ $subnetAddress = ip2long($subnetAddress);
30
+ $mask = -1 << (32 - $subnetMask);
31
+ $subnetAddress &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
32
+ return ($address & $mask) == $subnetAddress;
33
+ }
34
+
35
+ }
limit-login-attempts-reloaded.php CHANGED
@@ -5,7 +5,7 @@ Description: Limit the rate of login attempts for each IP address.
5
  Author: Limit Login Attempts Reloaded
6
  Author URI: https://www.limitloginattempts.com/
7
  Text Domain: limit-login-attempts-reloaded
8
- Version: 2.21.1
9
 
10
  Copyright 2008 - 2012 Johan Eenfeldt, 2016 - 2021 Limit Login Attempts Reloaded
11
  */
@@ -34,6 +34,7 @@ $limit_login_nonempty_credentials = false; /* user and pwd nonempty */
34
  /***************************************************************************************
35
  * Include files
36
  **************************************************************************************/
 
37
  require_once( LLA_PLUGIN_DIR . '/core/Helpers.php' );
38
  require_once( LLA_PLUGIN_DIR . '/core/App.php' );
39
  require_once( LLA_PLUGIN_DIR . '/core/LimitLoginAttempts.php' );
5
  Author: Limit Login Attempts Reloaded
6
  Author URI: https://www.limitloginattempts.com/
7
  Text Domain: limit-login-attempts-reloaded
8
+ Version: 2.22.0
9
 
10
  Copyright 2008 - 2012 Johan Eenfeldt, 2016 - 2021 Limit Login Attempts Reloaded
11
  */
34
  /***************************************************************************************
35
  * Include files
36
  **************************************************************************************/
37
+ require_once( LLA_PLUGIN_DIR . '/lib/CidrCheck.php' );
38
  require_once( LLA_PLUGIN_DIR . '/core/Helpers.php' );
39
  require_once( LLA_PLUGIN_DIR . '/core/App.php' );
40
  require_once( LLA_PLUGIN_DIR . '/core/LimitLoginAttempts.php' );
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/donate?hosted_button_id=FKD4MYFCMNVQQ
4
  Tags: brute force, login, security, firewall, protection
5
  Requires at least: 3.0
6
  Tested up to: 5.7
7
- Stable tag: 2.21.1
8
 
9
  Reloaded version of the original Limit Login Attempts plugin for Login Protection by a team of WordPress developers. GDPR compliant.
10
 
@@ -18,9 +18,9 @@ WordPress by default allows unlimited login attempts. This can lead to passwords
18
 
19
  Limit Login Attempts Reloaded
20
  > <strong>Limit Login Attempts Reloaded Premium Cloud App</strong><br>
21
- > Enables cloud protection for Limit Login Attempts Reloaded plugin. It comes with all the great features you'll need to stop hackers and bots from brute-force attacks. The cloud app <a href="https://www.limitloginattempts.com/features/">offers several features</a> including advanced protection out of the box, and the ability for site admins and agencies to sync safelists/blocklists across multiple domains. <a href="https://app.limitloginattempts.com/network/create">Click here to activate the cloud app for the best WordPress security plugin now!</a>
22
 
23
- https://www.youtube.com/watch?v=IsotthPWCPA
24
 
25
  = Features: =
26
  * Limit the number of retry attempts when logging in (per each IP).
@@ -98,6 +98,11 @@ Please follow this link: <a href="https://www.limitloginattempts.com/resources/"
98
 
99
  == Changelog ==
100
 
 
 
 
 
 
101
  = 2.21.1 =
102
  * Fixed: Uncaught Error: Call to a member function stats()
103
  * Cloud API: added block by country.
4
  Tags: brute force, login, security, firewall, protection
5
  Requires at least: 3.0
6
  Tested up to: 5.7
7
+ Stable tag: 2.22.0
8
 
9
  Reloaded version of the original Limit Login Attempts plugin for Login Protection by a team of WordPress developers. GDPR compliant.
10
 
18
 
19
  Limit Login Attempts Reloaded
20
  > <strong>Limit Login Attempts Reloaded Premium Cloud App</strong><br>
21
+ > Enables cloud protection for Limit Login Attempts Reloaded plugin. It comes with all the great features you'll need to stop hackers and bots from brute-force attacks. The cloud app <a href="https://www.limitloginattempts.com/features/?from=wp-details">offers several features</a> including advanced protection out of the box, and the ability for site admins and agencies to sync safelists/blocklists across multiple domains. <a href="https://www.limitloginattempts.com/features/?from=wp-details-cta">Click here to activate the cloud app for the best WordPress security plugin now!</a>
22
 
23
+ https://www.youtube.com/watch?v=wzmPXu55zLU
24
 
25
  = Features: =
26
  * Limit the number of retry attempts when logging in (per each IP).
98
 
99
  == Changelog ==
100
 
101
+ = 2.22.0 =
102
+ * Added support of CIDR notation for specifying IP ranges.
103
+ * Texts updated.
104
+ * Refactoring.
105
+
106
  = 2.21.1 =
107
  * Fixed: Uncaught Error: Call to a member function stats()
108
  * Cloud API: added block by country.
views/tab-dashboard.php CHANGED
@@ -327,6 +327,15 @@ if( $active_app === 'local' ) {
327
  <div class="desc"><?php _e( 'Many options such as notifications, alerts, premium status, and more.', 'limit-login-attempts-reloaded' ); ?></div>
328
  </div>
329
  </div>
 
 
 
 
 
 
 
 
 
330
  </div>
331
  <?php if( $stats_global = LLAR_App::stats_global() ) : ?>
332
  <div class="dashboard-section-4">
327
  <div class="desc"><?php _e( 'Many options such as notifications, alerts, premium status, and more.', 'limit-login-attempts-reloaded' ); ?></div>
328
  </div>
329
  </div>
330
+ <div class="info-box-1">
331
+ <div class="info-box-icon">
332
+ <span class="dashicons dashicons-groups"></span>
333
+ </div>
334
+ <div class="info-box-content">
335
+ <div class="title"><a href="https://limitloginattempts.tapfiliate.com/" target="_blank"><?php _e( 'Refer A Friend', 'limit-login-attempts-reloaded' ); ?></a></div>
336
+ <div class="desc"><?php _e( 'Earn $20 for every friend or client that signs up for our premium service.', 'limit-login-attempts-reloaded' ); ?></div>
337
+ </div>
338
+ </div>
339
  </div>
340
  <?php if( $stats_global = LLAR_App::stats_global() ) : ?>
341
  <div class="dashboard-section-4">
views/tab-settings.php CHANGED
@@ -117,7 +117,7 @@ $active_app_config = $this->get_custom_app_config();
117
  </table>
118
 
119
  <h3><?php echo __( 'App Settings', 'limit-login-attempts-reloaded' ); ?></h3>
120
- <p><?php echo __( 'The apps absorb the main load caused by brute-force attacks, analyse login attempts and block unwanted visitors. They might provide other service functions as well.', 'limit-login-attempts-reloaded' ); ?></p>
121
 
122
  <div id="llar-apps-accordion" class="llar-accordion">
123
  <h3><?php echo __( 'Local App', 'limit-login-attempts-reloaded' ); ?></h3>
117
  </table>
118
 
119
  <h3><?php echo __( 'App Settings', 'limit-login-attempts-reloaded' ); ?></h3>
120
+ <p><?php echo __( 'The app absorbs the main load caused by brute-force attacks, analyzes login attempts, and blocks unwanted visitors. It provides other service functions as well.', 'limit-login-attempts-reloaded' ); ?></p>
121
 
122
  <div id="llar-apps-accordion" class="llar-accordion">
123
  <h3><?php echo __( 'Local App', 'limit-login-attempts-reloaded' ); ?></h3>