Shield Security for WordPress - Version 12.0.2

Version Description

Download this release

Release Info

Developer paultgoodchild
Plugin Icon 128x128 Shield Security for WordPress
Version 12.0.2
Comparing to
See all releases

Code changes from version 12.0.1 to 12.0.2

cl.json CHANGED
@@ -94,6 +94,24 @@
94
  "Traffic logs are no longer limited by amount.",
95
  "They are instead limited by age (in days). Updated configuration options are available."
96
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
  ]
99
  },
94
  "Traffic logs are no longer limited by amount.",
95
  "They are instead limited by age (in days). Updated configuration options are available."
96
  ]
97
+ },
98
+ {
99
+ "type": "changed",
100
+ "pro_only": false,
101
+ "title": "NotBot JS Is Always Loaded By Default",
102
+ "description": [
103
+ "Since many customers are using caching and optimisation plugins that interfere with NotBot JS, it is now loaded for all visitors by default.",
104
+ "An option within the plugin has been provided to revert to the normal optimised loading of the NotBot JS."
105
+ ]
106
+ },
107
+ {
108
+ "type": "changed",
109
+ "pro_only": true,
110
+ "title": "U2F 2-Factor Authentication Bypasses MFA",
111
+ "description": [
112
+ "U2F is a strong 2FA mechanism and so it doesn't really need to be used in conjunction with other factors.",
113
+ "When the Chained/MFA option is enabled, when U2F is supplied, this can be done alone without the need for other factors."
114
+ ]
115
  }
116
  ]
117
  },
config/deprecated/ips.php CHANGED
@@ -164,6 +164,19 @@
164
  "summary": "Prevent IPs/Visitors With High Reputation Scores From Being Blocked",
165
  "description": "Ensures that visitors with a high reputation are never blocked by Shield."
166
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  {
168
  "key": "transgression_limit",
169
  "section": "section_auto_black_list",
164
  "summary": "Prevent IPs/Visitors With High Reputation Scores From Being Blocked",
165
  "description": "Ensures that visitors with a high reputation are never blocked by Shield."
166
  },
167
+ {
168
+ "key": "force_notbot",
169
+ "section": "section_antibot",
170
+ "advanced": true,
171
+ "default": "Y",
172
+ "type": "checkbox",
173
+ "link_info": "https://shsec.io/jy",
174
+ "link_blog": "https://shsec.io/jz",
175
+ "beacon_id": 448,
176
+ "name": "Force NotBot JS",
177
+ "summary": "Force Loading Of NotBot JS",
178
+ "description": "Use this option if you're using an aggressive caching plugin or system to ensure NotBot JS is loaded for visitors."
179
+ },
180
  {
181
  "key": "transgression_limit",
182
  "section": "section_auto_black_list",
config/ips.json CHANGED
@@ -164,6 +164,19 @@
164
  "summary": "Prevent IPs/Visitors With High Reputation Scores From Being Blocked",
165
  "description": "Ensures that visitors with a high reputation are never blocked by Shield."
166
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  {
168
  "key": "transgression_limit",
169
  "section": "section_auto_black_list",
164
  "summary": "Prevent IPs/Visitors With High Reputation Scores From Being Blocked",
165
  "description": "Ensures that visitors with a high reputation are never blocked by Shield."
166
  },
167
+ {
168
+ "key": "force_notbot",
169
+ "section": "section_antibot",
170
+ "advanced": true,
171
+ "default": "Y",
172
+ "type": "checkbox",
173
+ "link_info": "https://shsec.io/jy",
174
+ "link_blog": "https://shsec.io/jz",
175
+ "beacon_id": 448,
176
+ "name": "Force NotBot JS",
177
+ "summary": "Force Loading Of NotBot JS",
178
+ "description": "Use this option if you're using an aggressive caching plugin or system to ensure NotBot JS is loaded for visitors."
179
+ },
180
  {
181
  "key": "transgression_limit",
182
  "section": "section_auto_black_list",
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 12.0.1
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 12.0.2
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
plugin-spec.php CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "12.0.1",
4
- "release_timestamp": 1632214137,
5
- "build": "202109.2101",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
1
  {
2
  "properties": {
3
+ "version": "12.0.2",
4
+ "release_timestamp": 1632300000,
5
+ "build": "202109.2201",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
plugin.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "12.0.1",
4
- "release_timestamp": 1632214137,
5
- "build": "202109.2101",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
1
  {
2
  "properties": {
3
+ "version": "12.0.2",
4
+ "release_timestamp": 1632300000,
5
+ "build": "202109.2201",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield Security",
readme.txt CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.7
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.8
11
- Stable tag: 12.0.1
12
 
13
  No-Nonsense Security Hardening that protects WordPress against hackers, malicious bots, and spammers (no captchas!). Now with exclusive ShieldNET Technology.
14
 
8
  Requires PHP: 7.0
9
  Recommended PHP: 7.4
10
  Tested up to: 5.8
11
+ Stable tag: 12.0.2
12
 
13
  No-Nonsense Security Hardening that protects WordPress against hackers, malicious bots, and spammers (no captchas!). Now with exclusive ShieldNET Technology.
14
 
resources/js/shield/audit_trail.js CHANGED
@@ -176,7 +176,7 @@
176
  }
177
  ],
178
  language: {
179
- emptyTable: "There are no items to display, or they've been set to be ignored."
180
  }
181
  }
182
  ) );
176
  }
177
  ],
178
  language: {
179
+ emptyTable: "There are no items to display."
180
  }
181
  }
182
  ) );
resources/js/shield/traffic.js CHANGED
@@ -138,7 +138,7 @@
138
  }
139
  ],
140
  language: {
141
- emptyTable: "There are no items to display, or they've been set to be ignored."
142
  }
143
  }
144
  ) );
138
  }
139
  ],
140
  language: {
141
+ emptyTable: "There are no items to display."
142
  }
143
  }
144
  ) );
src/lib/src/Modules/{GeoIp → Data/Lib/GeoIP}/Lookup.php RENAMED
@@ -1,10 +1,12 @@
1
  <?php
2
 
3
- namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\GeoIp;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\IPs\IPGeoVO;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\IPs\IPRecords;
 
 
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\IpAddressConsumer;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
10
  use FernleafSystems\Wordpress\Services\Services;
@@ -17,6 +19,8 @@ class Lookup {
17
 
18
  private $ips = [];
19
 
 
 
20
  public function lookupIp() :IPGeoVO {
21
  $ip = $this->getIP();
22
  // Small optimization so we don't SQL it every time.
@@ -35,6 +39,11 @@ class Lookup {
35
 
36
  if ( is_null( $ipRecord->geo )
37
  || Services::Request()->carbon()->subMonth()->timestamp > @$ipRecord->geo[ 'ts' ] ) {
 
 
 
 
 
38
  $ipRecord->geo = $this->redirectliIpLookup();
39
  $this->getCon()
40
  ->getModule_Data()
@@ -54,6 +63,9 @@ class Lookup {
54
  return $this->ips[ $ip ] = ( new IPGeoVO() )->applyFromArray( $geoData );
55
  }
56
 
 
 
 
57
  private function redirectliIpLookup() :array {
58
  $data = @json_decode(
59
  Services::HttpRequest()->getContent( self::URL_REDIRECTLI.$this->getIP() ), true
1
  <?php
2
 
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\Lib\GeoIP;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Databases;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\{
7
+ DB\IPs\IPGeoVO,
8
+ DB\IPs\IPRecords
9
+ };
10
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\IpAddressConsumer;
11
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
12
  use FernleafSystems\Wordpress\Services\Services;
19
 
20
  private $ips = [];
21
 
22
+ private $reqCount = 0;
23
+
24
  public function lookupIp() :IPGeoVO {
25
  $ip = $this->getIP();
26
  // Small optimization so we don't SQL it every time.
39
 
40
  if ( is_null( $ipRecord->geo )
41
  || Services::Request()->carbon()->subMonth()->timestamp > @$ipRecord->geo[ 'ts' ] ) {
42
+
43
+ if ( $this->reqCount++ > 30 ) {
44
+ throw new \Exception( 'Lookup limit reached.' );
45
+ }
46
+
47
  $ipRecord->geo = $this->redirectliIpLookup();
48
  $this->getCon()
49
  ->getModule_Data()
63
  return $this->ips[ $ip ] = ( new IPGeoVO() )->applyFromArray( $geoData );
64
  }
65
 
66
+ /**
67
+ * @throws \Exception
68
+ */
69
  private function redirectliIpLookup() :array {
70
  $data = @json_decode(
71
  Services::HttpRequest()->getContent( self::URL_REDIRECTLI.$this->getIP() ), true
src/lib/src/Modules/IPs/Lib/Bots/NotBot/InsertNotBotJs.php CHANGED
@@ -25,9 +25,12 @@ class InsertNotBotJs extends ExecOnceModConsumer {
25
  private function isForcedForOptimisationPlugins() :bool {
26
  return (bool)apply_filters(
27
  'shield/notbot_force_load',
 
 
28
  !empty( array_intersect(
29
  array_map( 'basename', Services::WpPlugins()->getActivePlugins() ),
30
  [
 
31
  'wpFastestCache.php',
32
  'wp-cache.php', // Super Cache
33
  'wp-hummingbird.php',
25
  private function isForcedForOptimisationPlugins() :bool {
26
  return (bool)apply_filters(
27
  'shield/notbot_force_load',
28
+ $this->getOptions()->isOpt( 'force_notbot', 'Y' )
29
+ ||
30
  !empty( array_intersect(
31
  array_map( 'basename', Services::WpPlugins()->getActivePlugins() ),
32
  [
33
+ 'breeze.php',
34
  'wpFastestCache.php',
35
  'wp-cache.php', // Super Cache
36
  'wp-hummingbird.php',
src/lib/src/Modules/IPs/ModCon.php CHANGED
@@ -43,11 +43,8 @@ class ModCon extends BaseShield\ModCon {
43
  return $this->oBlacklistHandler;
44
  }
45
 
46
- protected function doPostConstruction() {
47
- $this->getDbH_BotSignal();
48
- }
49
-
50
  public function getDbH_BotSignal() :DB\BotSignal\Ops\Handler {
 
51
  return $this->getDbHandler()->loadDbH( 'botsignal' );
52
  }
53
 
43
  return $this->oBlacklistHandler;
44
  }
45
 
 
 
 
 
46
  public function getDbH_BotSignal() :DB\BotSignal\Ops\Handler {
47
+ $this->getCon()->getModule_Data()->getDbH_IPs();
48
  return $this->getDbHandler()->loadDbH( 'botsignal' );
49
  }
50
 
src/lib/src/Modules/IPs/Strings.php CHANGED
@@ -248,22 +248,22 @@ class Strings extends Base\Strings {
248
  */
249
  public function getOptionStrings( string $key ) :array {
250
 
251
- $sPlugName = $this->getCon()->getHumanName();
252
- $sModName = $this->getMod()->getMainFeatureName();
253
 
254
  switch ( $key ) {
255
 
256
  case 'enable_ips' :
257
- $name = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
258
- $summary = sprintf( __( 'Enable (or Disable) The %s Module', 'wp-simple-firewall' ), $sModName );
259
- $desc = sprintf( __( 'Un-Checking this option will completely disable the %s module.', 'wp-simple-firewall' ), $sModName );
260
  break;
261
 
262
  case 'transgression_limit' :
263
  $name = __( 'Offense Limit', 'wp-simple-firewall' );
264
  $summary = __( 'The number of permitted offenses before an IP address will be blocked', 'wp-simple-firewall' );
265
  $desc = [
266
- sprintf( __( 'An offense is registered against an IP address each time a visitor trips the defenses of the %s plugin.', 'wp-simple-firewall' ), $sPlugName ),
267
  __( 'When the number of these offenses exceeds the limit, they are automatically blocked from accessing the site.', 'wp-simple-firewall' ),
268
  sprintf( __( 'Set this to "0" to turn off the %s feature.', 'wp-simple-firewall' ), __( 'Automatic IP Black List', 'wp-simple-firewall' ) )
269
  ];
@@ -320,6 +320,20 @@ class Strings extends Base\Strings {
320
  ];
321
  break;
322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  case 'text_loginfailed' :
324
  $name = __( 'Login Failed', 'wp-simple-firewall' );
325
  $summary = __( 'Visitor Triggers The IP Offense System Through A Failed Login', 'wp-simple-firewall' );
248
  */
249
  public function getOptionStrings( string $key ) :array {
250
 
251
+ $pluginName = $this->getCon()->getHumanName();
252
+ $modName = $this->getMod()->getMainFeatureName();
253
 
254
  switch ( $key ) {
255
 
256
  case 'enable_ips' :
257
+ $name = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $modName );
258
+ $summary = sprintf( __( 'Enable (or Disable) The %s Module', 'wp-simple-firewall' ), $modName );
259
+ $desc = sprintf( __( 'Un-Checking this option will completely disable the %s module.', 'wp-simple-firewall' ), $modName );
260
  break;
261
 
262
  case 'transgression_limit' :
263
  $name = __( 'Offense Limit', 'wp-simple-firewall' );
264
  $summary = __( 'The number of permitted offenses before an IP address will be blocked', 'wp-simple-firewall' );
265
  $desc = [
266
+ sprintf( __( 'An offense is registered against an IP address each time a visitor trips the defenses of the %s plugin.', 'wp-simple-firewall' ), $pluginName ),
267
  __( 'When the number of these offenses exceeds the limit, they are automatically blocked from accessing the site.', 'wp-simple-firewall' ),
268
  sprintf( __( 'Set this to "0" to turn off the %s feature.', 'wp-simple-firewall' ), __( 'Automatic IP Black List', 'wp-simple-firewall' ) )
269
  ];
320
  ];
321
  break;
322
 
323
+ case 'force_notbot' :
324
+ $name = __( 'Force NotBot JS', 'wp-simple-firewall' );
325
+ $summary = __( 'Force Loading Of NotBot JS', 'wp-simple-firewall' );
326
+ $desc = [
327
+ sprintf( __( '%s uses Javascript to help identify bots versus legitimate visitors.', 'wp-simple-firewall' ),
328
+ $pluginName )
329
+ .' '.__( "However, caching plugins often interfere, preventing it loading for your visitors.", 'wp-simple-firewall' ),
330
+ __( "This may cause some of your legitimate users to be identified as bots, when they're not.", 'wp-simple-firewall' ),
331
+ __( "Turn this option on if you're using an aggressive caching system, to ensure NotBot JS is loaded for all visitors.", 'wp-simple-firewall' ),
332
+ __( "When this option is disabled we'll automatically optimise loading of the Javascript so it's only loaded where it's required.", 'wp-simple-firewall' )
333
+ .' '.__( "You should test your site and keep a lookout for user login issues after disabling this option.", 'wp-simple-firewall' )
334
+ ];
335
+ break;
336
+
337
  case 'text_loginfailed' :
338
  $name = __( 'Login Failed', 'wp-simple-firewall' );
339
  $summary = __( 'Visitor Triggers The IP Offense System Through A Failed Login', 'wp-simple-firewall' );
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php CHANGED
@@ -185,7 +185,7 @@ class MfaController {
185
  }
186
  );
187
 
188
- // Neither BackupCode NOR U2F should EVER be the only 1 provider available.
189
  if ( count( $Ps ) === 1 ) {
190
  /** @var Provider\BaseProvider $first */
191
  $first = reset( $Ps );
185
  }
186
  );
187
 
188
+ // BackupCode should NEVER be the only 1 provider available.
189
  if ( count( $Ps ) === 1 ) {
190
  /** @var Provider\BaseProvider $first */
191
  $first = reset( $Ps );
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BackupCodes.php CHANGED
@@ -8,6 +8,7 @@ use FernleafSystems\Wordpress\Services\Services;
8
  class BackupCodes extends BaseProvider {
9
 
10
  const SLUG = 'backupcode';
 
11
  const STANDALONE = false;
12
 
13
  public function getProviderName() :string {
@@ -84,11 +85,11 @@ class BackupCodes extends BaseProvider {
84
 
85
  /**
86
  * @param \WP_User $user
87
- * @param string $sOtpCode
88
  * @return bool
89
  */
90
- private function validateBackupCode( \WP_User $user, $sOtpCode ) :bool {
91
- return (bool)wp_check_password( str_replace( '-', '', $sOtpCode ), $this->getSecret( $user ) );
92
  }
93
 
94
  /**
8
  class BackupCodes extends BaseProvider {
9
 
10
  const SLUG = 'backupcode';
11
+ const BYPASS_MFA = true;
12
  const STANDALONE = false;
13
 
14
  public function getProviderName() :string {
85
 
86
  /**
87
  * @param \WP_User $user
88
+ * @param string $OTP
89
  * @return bool
90
  */
91
+ private function validateBackupCode( \WP_User $user, $OTP ) :bool {
92
+ return (bool)wp_check_password( str_replace( '-', '', $OTP ), $this->getSecret( $user ) );
93
  }
94
 
95
  /**
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php CHANGED
@@ -10,9 +10,15 @@ abstract class BaseProvider {
10
  use Modules\ModConsumer;
11
 
12
  const SLUG = '';
 
 
 
 
 
 
13
  /**
14
  * Set to true if this provider can be used in isolation. False if there
15
- * must be at least 1 other 2FA provider active.
16
  */
17
  const STANDALONE = true;
18
  /**
@@ -31,17 +37,15 @@ abstract class BaseProvider {
31
 
32
  /**
33
  * Assumes this is only called on active profiles
34
- * @param \WP_User $user
35
- * @return bool
36
  */
37
- public function validateLoginIntent( \WP_User $user ) {
38
- $bOtpSuccess = false;
39
- $sReqOtpCode = $this->fetchCodeFromRequest();
40
- if ( !empty( $sReqOtpCode ) ) {
41
- $bOtpSuccess = $this->processOtp( $user, $sReqOtpCode );
42
- $this->postOtpProcessAction( $user, $bOtpSuccess );
43
  }
44
- return $bOtpSuccess;
45
  }
46
 
47
  /**
10
  use Modules\ModConsumer;
11
 
12
  const SLUG = '';
13
+
14
+ /**
15
+ * Set to true if this provider can be used to validate 2FA even if MFA is active.
16
+ */
17
+ const BYPASS_MFA = false;
18
+
19
  /**
20
  * Set to true if this provider can be used in isolation. False if there
21
+ * must be at least 1 other 2FA provider active alongside it.
22
  */
23
  const STANDALONE = true;
24
  /**
37
 
38
  /**
39
  * Assumes this is only called on active profiles
 
 
40
  */
41
+ public function validateLoginIntent( \WP_User $user ) :bool {
42
+ $otpSuccess = false;
43
+ $OTP = $this->fetchCodeFromRequest();
44
+ if ( !empty( $OTP ) ) {
45
+ $otpSuccess = $this->processOtp( $user, $OTP );
46
+ $this->postOtpProcessAction( $user, $otpSuccess );
47
  }
48
+ return $otpSuccess;
49
  }
50
 
51
  /**
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/U2F.php CHANGED
@@ -12,6 +12,7 @@ use u2flib_server\SignRequest;
12
  class U2F extends BaseProvider {
13
 
14
  const SLUG = 'u2f';
 
15
  const DEFAULT_SECRET = '[]';
16
 
17
  public function isProfileActive( \WP_User $user ) :bool {
12
  class U2F extends BaseProvider {
13
 
14
  const SLUG = 'u2f';
15
+ const BYPASS_MFA = true;
16
  const DEFAULT_SECRET = '[]';
17
 
18
  public function isProfileActive( \WP_User $user ) :bool {
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/ValidateLoginIntentRequest.php CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFact
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
7
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
8
  use FernleafSystems\Wordpress\Services\Services;
9
 
10
  class ValidateLoginIntentRequest {
@@ -16,48 +15,49 @@ class ValidateLoginIntentRequest {
16
  * @throws \Exception
17
  */
18
  public function run() :bool {
19
- $oMfaCon = $this->getMfaCon();
20
  /** @var LoginGuard\Options $opts */
21
- $opts = $oMfaCon->getOptions();
22
 
23
  $user = Services::WpUsers()->getCurrentWpUser();
24
  if ( !$user instanceof \WP_User ) {
25
  throw new \Exception( 'No user logged-in.' );
26
  }
27
- $providers = $oMfaCon->getProvidersForUser( $user, true );
 
28
  if ( empty( $providers ) ) {
29
  throw new \Exception( 'No valid providers' );
30
  }
31
 
32
- $aSuccessfulProviders = [];
 
 
 
 
 
 
 
33
 
34
  $validated = false;
35
- { // Backup code is special case
36
- if ( isset( $providers[ Provider\BackupCodes::SLUG ] ) ) {
37
- if ( $providers[ Provider\BackupCodes::SLUG ]->validateLoginIntent( $user ) ) {
 
38
  $validated = true;
39
- $aSuccessfulProviders[] = $providers[ Provider\BackupCodes::SLUG ];
40
  }
41
- unset( $providers[ Provider\BackupCodes::SLUG ] );
 
42
  }
43
  }
44
 
45
- if ( !$validated ) {
46
- $aStates = [];
47
- foreach ( $providers as $sSlug => $provider ) {
48
- $aStates[ $sSlug ] = $provider->validateLoginIntent( $user );
49
- if ( $aStates[ $sSlug ] ) {
50
- $aSuccessfulProviders[] = $provider;
51
- }
52
- }
53
-
54
- $nSuccessful = count( array_filter( $aStates ) );
55
- $validated = $opts->isChainedAuth() ? $nSuccessful == count( $providers ) : $nSuccessful > 0;
56
  }
57
 
58
  if ( $validated ) {
59
  // Some cleanup can only run if login is completely tested and completely valid.
60
- foreach ( $aSuccessfulProviders as $provider ) {
61
  $provider->postSuccessActions( $user );
62
  }
63
  }
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
 
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
  class ValidateLoginIntentRequest {
15
  * @throws \Exception
16
  */
17
  public function run() :bool {
18
+ $mfaCon = $this->getMfaCon();
19
  /** @var LoginGuard\Options $opts */
20
+ $opts = $mfaCon->getOptions();
21
 
22
  $user = Services::WpUsers()->getCurrentWpUser();
23
  if ( !$user instanceof \WP_User ) {
24
  throw new \Exception( 'No user logged-in.' );
25
  }
26
+
27
+ $providers = $mfaCon->getProvidersForUser( $user, true );
28
  if ( empty( $providers ) ) {
29
  throw new \Exception( 'No valid providers' );
30
  }
31
 
32
+ $providerStates = [];
33
+ $successfulProviders = [];
34
+ foreach ( $providers as $slug => $provider ) {
35
+ $providerStates[ $slug ] = $provider->validateLoginIntent( $user );
36
+ if ( $providerStates[ $slug ] ) {
37
+ $successfulProviders[ $slug ] = $provider;
38
+ }
39
+ }
40
 
41
  $validated = false;
42
+
43
+ foreach ( $providers as $slug => $provider ) {
44
+ if ( $provider::BYPASS_MFA ) {
45
+ if ( $providerStates[ $slug ] ) {
46
  $validated = true;
 
47
  }
48
+ unset( $providers[ $slug ] );
49
+ unset( $providerStates[ $slug ] );
50
  }
51
  }
52
 
53
+ if ( !$validated ) {
54
+ $countSuccessful = count( array_filter( $providerStates ) );
55
+ $validated = $opts->isChainedAuth() ? $countSuccessful == count( $providers ) : $countSuccessful > 0;
 
 
 
 
 
 
 
 
56
  }
57
 
58
  if ( $validated ) {
59
  // Some cleanup can only run if login is completely tested and completely valid.
60
+ foreach ( $successfulProviders as $provider ) {
61
  $provider->postSuccessActions( $user );
62
  }
63
  }
src/lib/src/Modules/Traffic/Lib/TrafficTable/LoadRawTableData.php CHANGED
@@ -2,7 +2,8 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\TrafficTable;
4
 
5
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\GeoIp\Lookup;
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LoadLogs;
@@ -40,7 +41,7 @@ class LoadRawTableData extends BaseLoadTableData {
40
  return array_values( array_filter( array_map(
41
  function ( $log ) {
42
  /**
43
- * @deprecated 12.0 - this just removes dud entries from the conversion.
44
  */
45
  if ( empty( @$log->meta[ 'path' ] ) ) {
46
  return null;
@@ -199,7 +200,7 @@ class LoadRawTableData extends BaseLoadTableData {
199
  return $this->ipInfo[ $ip ];
200
  }
201
 
202
- private function getCountryIP( string $ip ) {
203
  if ( empty( $this->geoLookup ) ) {
204
  $this->geoLookup = ( new Lookup() )->setCon( $this->getCon() );
205
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Lib\TrafficTable;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\IPs\IPGeoVO;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\Lib\GeoIP\Lookup;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
9
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Data\DB\ReqLogs\LoadLogs;
41
  return array_values( array_filter( array_map(
42
  function ( $log ) {
43
  /**
44
+ * @deprecated 12.0 - this just removes dud entries from after the conversion.
45
  */
46
  if ( empty( @$log->meta[ 'path' ] ) ) {
47
  return null;
200
  return $this->ipInfo[ $ip ];
201
  }
202
 
203
+ private function getCountryIP( string $ip ) :IPGeoVO {
204
  if ( empty( $this->geoLookup ) ) {
205
  $this->geoLookup = ( new Lookup() )->setCon( $this->getCon() );
206
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/ApiBase.php CHANGED
@@ -118,7 +118,7 @@ abstract class ApiBase {
118
 
119
  $url = add_query_arg( $this->getQueryData(), $this->getApiUrl() );
120
  $sig = md5( $url );
121
- error_log( $url );
122
  if ( $this->isUseQueryCache() && isset( self::$QueryCache[ $sig ] ) ) {
123
  $response = self::$QueryCache[ $sig ];
124
  }
118
 
119
  $url = add_query_arg( $this->getQueryData(), $this->getApiUrl() );
120
  $sig = md5( $url );
121
+
122
  if ( $this->isUseQueryCache() && isset( self::$QueryCache[ $sig ] ) ) {
123
  $response = self::$QueryCache[ $sig ];
124
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Integrations/WpHashes/Malware/Confidence/Retrieve.php CHANGED
@@ -40,15 +40,6 @@ class Retrieve extends Base {
40
  return $this->query();
41
  }
42
 
43
- /**
44
- * @return array|null - null on failure
45
- */
46
- protected function fireRequestDecodeResponse() {
47
- $sResponse = $this->fireRequest();
48
- error_log( 'HTTP: '.$sResponse );
49
- return empty( $sResponse ) ? null : json_decode( $sResponse, true );
50
- }
51
-
52
  /**
53
  * @param string $sFullPath
54
  * @param string $sLine
40
  return $this->query();
41
  }
42
 
 
 
 
 
 
 
 
 
 
43
  /**
44
  * @param string $sFullPath
45
  * @param string $sLine
templates/twig/notices/base.twig CHANGED
@@ -28,7 +28,7 @@
28
  </div>
29
 
30
  <div class="dismiss-p" style="margin-bottom: 15px">
31
- <a class="icwp-notice-dismiss" href="#">{{ strings.dismiss|default('Dismss') }}</a>
32
  </div>
33
 
34
  <div style="clear:both;"></div>
28
  </div>
29
 
30
  <div class="dismiss-p" style="margin-bottom: 15px">
31
+ <a class="icwp-notice-dismiss" href="#">{{ strings.dismiss|default('Dismiss') }}</a>
32
  </div>
33
 
34
  <div style="clear:both;"></div>