Version Description
Current Release = Released: 7th December, 2018 - Release Notes
(v.9) FIXED: Admin notices displaying to non-admins.
(v.7) ADDED: [PRO] New option to specify usernames for Security Admin role.
(v.7) IMPROVED: Idle user detection.
(v.7) IMPROVED: Support for redirect/cancel URLs in 2FA login page.
(v.7) CHANGED: Final release before Shield v7. Small warning shown on plugins page if PHP < 5.4
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 6.10.9 |
Comparing to | |
See all releases |
Code changes from version 6.10.4 to 6.10.9
- icwp-plugin-controller.php +80 -73
- icwp-wpsf.php +1 -1
- init.php +8 -11
- plugin-spec.php +2 -2
- readme.txt +16 -7
- resources/css/plugin.css +4 -5
- resources/images/flags/ad.png +0 -0
- resources/images/flags/ae.png +0 -0
- resources/images/flags/af.png +0 -0
- resources/images/flags/ag.png +0 -0
- resources/images/flags/al.png +0 -0
- resources/images/flags/am.png +0 -0
- resources/images/flags/ao.png +0 -0
- resources/images/flags/ar.png +0 -0
- resources/images/flags/at.png +0 -0
- resources/images/flags/au.png +0 -0
- resources/images/flags/az.png +0 -0
- resources/images/flags/ba.png +0 -0
- resources/images/flags/bb.png +0 -0
- resources/images/flags/bd.png +0 -0
- resources/images/flags/be.png +0 -0
- resources/images/flags/bf.png +0 -0
- resources/images/flags/bg.png +0 -0
- resources/images/flags/bh.png +0 -0
- resources/images/flags/bi.png +0 -0
- resources/images/flags/bj.png +0 -0
- resources/images/flags/bn.png +0 -0
- resources/images/flags/bo.png +0 -0
- resources/images/flags/br.png +0 -0
- resources/images/flags/bs.png +0 -0
- resources/images/flags/bt.png +0 -0
- resources/images/flags/bw.png +0 -0
- resources/images/flags/by.png +0 -0
- resources/images/flags/bz.png +0 -0
- resources/images/flags/ca.png +0 -0
- resources/images/flags/cd.png +0 -0
- resources/images/flags/cf.png +0 -0
- resources/images/flags/cg.png +0 -0
- resources/images/flags/ch.png +0 -0
- resources/images/flags/ci.png +0 -0
- resources/images/flags/cl.png +0 -0
- resources/images/flags/cm.png +0 -0
- resources/images/flags/cn.png +0 -0
- resources/images/flags/co.png +0 -0
- resources/images/flags/cr.png +0 -0
- resources/images/flags/cu.png +0 -0
- resources/images/flags/cv.png +0 -0
- resources/images/flags/cy.png +0 -0
- resources/images/flags/cz.png +0 -0
- resources/images/flags/de.png +0 -0
- resources/images/flags/dj.png +0 -0
- resources/images/flags/dk.png +0 -0
- resources/images/flags/dm.png +0 -0
- resources/images/flags/do.png +0 -0
- resources/images/flags/dz.png +0 -0
- resources/images/flags/ec.png +0 -0
- resources/images/flags/ee.png +0 -0
- resources/images/flags/eg.png +0 -0
- resources/images/flags/eh.png +0 -0
- resources/images/flags/er.png +0 -0
- resources/images/flags/es.png +0 -0
- resources/images/flags/et.png +0 -0
- resources/images/flags/fi.png +0 -0
- resources/images/flags/fj.png +0 -0
- resources/images/flags/fm.png +0 -0
- resources/images/flags/fr.png +0 -0
- resources/images/flags/ga.png +0 -0
- resources/images/flags/gb.png +0 -0
- resources/images/flags/gd.png +0 -0
- resources/images/flags/ge.png +0 -0
- resources/images/flags/gh.png +0 -0
- resources/images/flags/gm.png +0 -0
- resources/images/flags/gn.png +0 -0
- resources/images/flags/gq.png +0 -0
- resources/images/flags/gr.png +0 -0
- resources/images/flags/gt.png +0 -0
- resources/images/flags/gw.png +0 -0
- resources/images/flags/gy.png +0 -0
- resources/images/flags/hn.png +0 -0
- resources/images/flags/hr.png +0 -0
- resources/images/flags/ht.png +0 -0
- resources/images/flags/hu.png +0 -0
- resources/images/flags/id.png +0 -0
- resources/images/flags/ie.png +0 -0
- resources/images/flags/il.png +0 -0
- resources/images/flags/in.png +0 -0
- resources/images/flags/iq.png +0 -0
- resources/images/flags/ir.png +0 -0
- resources/images/flags/is.png +0 -0
- resources/images/flags/it.png +0 -0
- resources/images/flags/jm.png +0 -0
- resources/images/flags/jo.png +0 -0
- resources/images/flags/jp.png +0 -0
- resources/images/flags/ke.png +0 -0
- resources/images/flags/kg.png +0 -0
- resources/images/flags/kh.png +0 -0
- resources/images/flags/ki.png +0 -0
- resources/images/flags/km.png +0 -0
- resources/images/flags/kn.png +0 -0
- resources/images/flags/kp.png +0 -0
- resources/images/flags/kr.png +0 -0
- resources/images/flags/ks.png +0 -0
- resources/images/flags/kw.png +0 -0
- resources/images/flags/kz.png +0 -0
- resources/images/flags/la.png +0 -0
- resources/images/flags/lb.png +0 -0
- resources/images/flags/lc.png +0 -0
- resources/images/flags/li.png +0 -0
- resources/images/flags/lk.png +0 -0
- resources/images/flags/lr.png +0 -0
- resources/images/flags/ls.png +0 -0
- resources/images/flags/lt.png +0 -0
- resources/images/flags/lu.png +0 -0
- resources/images/flags/lv.png +0 -0
- resources/images/flags/ly.png +0 -0
- resources/images/flags/ma.png +0 -0
- resources/images/flags/mc.png +0 -0
- resources/images/flags/md.png +0 -0
- resources/images/flags/me.png +0 -0
- resources/images/flags/mg.png +0 -0
- resources/images/flags/mh.png +0 -0
- resources/images/flags/mk.png +0 -0
- resources/images/flags/ml.png +0 -0
- resources/images/flags/mm.png +0 -0
- resources/images/flags/mn.png +0 -0
- resources/images/flags/mr.png +0 -0
- resources/images/flags/mt.png +0 -0
- resources/images/flags/mu.png +0 -0
- resources/images/flags/mv.png +0 -0
- resources/images/flags/mw.png +0 -0
- resources/images/flags/mx.png +0 -0
- resources/images/flags/my.png +0 -0
- resources/images/flags/mz.png +0 -0
- resources/images/flags/na.png +0 -0
- resources/images/flags/ne.png +0 -0
- resources/images/flags/ng.png +0 -0
- resources/images/flags/ni.png +0 -0
- resources/images/flags/nl.png +0 -0
- resources/images/flags/no.png +0 -0
- resources/images/flags/np.png +0 -0
- resources/images/flags/nr.png +0 -0
- resources/images/flags/nz.png +0 -0
- resources/images/flags/om.png +0 -0
- resources/images/flags/pa.png +0 -0
- resources/images/flags/pe.png +0 -0
- resources/images/flags/pg.png +0 -0
- resources/images/flags/ph.png +0 -0
- resources/images/flags/pk.png +0 -0
- resources/images/flags/pl.png +0 -0
- resources/images/flags/pt.png +0 -0
- resources/images/flags/pw.png +0 -0
- resources/images/flags/py.png +0 -0
- resources/images/flags/qa.png +0 -0
- resources/images/flags/ro.png +0 -0
- resources/images/flags/rs.png +0 -0
- resources/images/flags/ru.png +0 -0
- resources/images/flags/rw.png +0 -0
- resources/images/flags/sa.png +0 -0
- resources/images/flags/sb.png +0 -0
- resources/images/flags/sc.png +0 -0
- resources/images/flags/sd.png +0 -0
- resources/images/flags/se.png +0 -0
- resources/images/flags/sg.png +0 -0
- resources/images/flags/si.png +0 -0
- resources/images/flags/sk.png +0 -0
- resources/images/flags/sl.png +0 -0
- resources/images/flags/sm.png +0 -0
- resources/images/flags/sn.png +0 -0
- resources/images/flags/so.png +0 -0
- resources/images/flags/sr.png +0 -0
- resources/images/flags/st.png +0 -0
- resources/images/flags/sv.png +0 -0
- resources/images/flags/sy.png +0 -0
- resources/images/flags/sz.png +0 -0
- resources/images/flags/td.png +0 -0
- resources/images/flags/tg.png +0 -0
- resources/images/flags/th.png +0 -0
- resources/images/flags/tj.png +0 -0
- resources/images/flags/tl.png +0 -0
- resources/images/flags/tm.png +0 -0
- resources/images/flags/tn.png +0 -0
- resources/images/flags/to.png +0 -0
- resources/images/flags/tr.png +0 -0
- resources/images/flags/tt.png +0 -0
- resources/images/flags/tv.png +0 -0
- resources/images/flags/tw.png +0 -0
- resources/images/flags/tz.png +0 -0
- resources/images/flags/ua.png +0 -0
- resources/images/flags/ug.png +0 -0
- resources/images/flags/us.png +0 -0
- resources/images/flags/uy.png +0 -0
- resources/images/flags/uz.png +0 -0
- resources/images/flags/va.png +0 -0
- resources/images/flags/vc.png +0 -0
- resources/images/flags/ve.png +0 -0
- resources/images/flags/vn.png +0 -0
- resources/images/flags/vu.png +0 -0
- resources/images/flags/ws.png +0 -0
- resources/images/flags/ye.png +0 -0
- resources/images/flags/za.png +0 -0
- resources/images/flags/zm.png +0 -0
- resources/images/flags/zw.png +0 -0
- resources/js/shield-antibot.js +5 -6
- src/common/icwp-wpfunctions.php +2 -1
- src/config/feature-admin_access_restriction.php +13 -0
- src/config/feature-autoupdates.php +25 -0
- src/config/feature-firewall.php +4 -1
- src/config/feature-license.php +2 -37
- src/config/feature-login_protect.php +2 -2
- src/config/feature-plugin.php +9 -9
- src/features/admin_access_restriction.php +99 -28
- src/features/audit_trail.php +1 -2
- src/features/autoupdates.php +29 -24
- src/features/base.php +34 -58
- src/features/hack_protect.php +1 -1
- src/features/ips.php +3 -2
- src/features/license.php +85 -50
- src/features/login_protect.php +33 -15
- src/features/plugin.php +47 -12
- src/features/traffic.php +1 -2
- src/processors/admin_access_restriction.php +43 -33
- src/processors/adminaccess_whitelabel.php +2 -2
- src/processors/autoupdates.php +11 -2
- src/processors/base.php +10 -10
- src/processors/base_wpsf.php +3 -1
- src/processors/basedb.php +1 -1
- src/processors/comments_filter.php +1 -1
- src/processors/commentsfilter_humanspam.php +1 -1
- src/processors/dbhandler.php +0 -7
- src/processors/hackprotect_pluginvulnerabilities.php +34 -34
- src/processors/ips.php +0 -1
- src/processors/license.php +1 -1
- src/processors/lockdown.php +1 -0
- src/processors/loginprotect_backupcodes.php +0 -209
- src/processors/loginprotect_cooldown.php +1 -1
- src/processors/loginprotect_googleauthenticator.php +0 -344
- src/processors/loginprotect_intent.php +37 -9
- src/processors/loginprotect_intentprovider_backup.php +1 -1
- src/processors/loginprotect_intentprovider_base.php +1 -1
- src/processors/loginprotect_intentprovider_email.php +1 -1
- src/processors/loginprotect_intentprovider_ga.php +2 -2
- src/processors/loginprotect_intentprovider_yubikey.php +1 -1
- src/processors/loginprotect_track.php +0 -166
- src/processors/loginprotect_twofactorauth.php +0 -239
- src/processors/loginprotect_yubikey.php +0 -378
- src/processors/plugin.php +1 -21
- src/processors/sessions.php +6 -0
- src/wizards/base_wpsf.php +1 -1
- templates/php/page/login_intent.php +1 -0
icwp-plugin-controller.php
CHANGED
@@ -91,7 +91,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
91 |
/**
|
92 |
* @var boolean
|
93 |
*/
|
94 |
-
|
95 |
|
96 |
/**
|
97 |
* @var string
|
@@ -127,7 +127,6 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
127 |
self::$sRootFile = $sRootFile;
|
128 |
$this->checkMinimumRequirements();
|
129 |
$this->doRegisterHooks();
|
130 |
-
$this->loadWpTrack();
|
131 |
$this->loadFactory(); // so we know it's loaded whenever we need it. Cuz we need it.
|
132 |
$this->doLoadTextDomain();
|
133 |
|
@@ -260,7 +259,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
260 |
/**
|
261 |
*/
|
262 |
public function onWpDeactivatePlugin() {
|
263 |
-
if (
|
264 |
do_action( $this->prefix( 'delete_plugin' ) );
|
265 |
$this->deletePluginControllerOptions();
|
266 |
}
|
@@ -277,7 +276,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
277 |
protected function doRegisterHooks() {
|
278 |
$this->registerActivationHooks();
|
279 |
|
280 |
-
add_action( 'init', array( $this, 'onWpInit' ),
|
281 |
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
282 |
add_action( 'wp_loaded', array( $this, 'onWpLoaded' ) );
|
283 |
|
@@ -337,8 +336,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
337 |
/**
|
338 |
*/
|
339 |
public function onWpInit() {
|
|
|
340 |
add_action( 'wp_enqueue_scripts', array( $this, 'onWpEnqueueFrontendCss' ), 99 );
|
341 |
-
$this->bMeetsBasePermissions = current_user_can( $this->getBasePermissions() );
|
342 |
}
|
343 |
|
344 |
/**
|
@@ -352,7 +351,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
352 |
/**
|
353 |
*/
|
354 |
public function onWpDashboardSetup() {
|
355 |
-
if ( $this->isValidAdminArea() ) {
|
356 |
wp_add_dashboard_widget(
|
357 |
$this->prefix( 'dashboard_widget' ),
|
358 |
apply_filters( $this->prefix( 'dashboard_widget_title' ), $this->getHumanName() ),
|
@@ -366,32 +365,6 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
366 |
echo implode( '', $aContent );
|
367 |
}
|
368 |
|
369 |
-
/**
|
370 |
-
* v5.4.1: Nasty looping bug in here where this function was called within the 'user_has_cap' filter
|
371 |
-
* so we removed the "current_user_can()" or any such sub-call within this function
|
372 |
-
* @return bool
|
373 |
-
*/
|
374 |
-
public function getHasPermissionToManage() {
|
375 |
-
if ( apply_filters( $this->prefix( 'bypass_permission_to_manage' ), false ) ) {
|
376 |
-
return true;
|
377 |
-
}
|
378 |
-
return ( $this->getMeetsBasePermissions() && apply_filters( $this->prefix( 'has_permission_to_manage' ), true ) );
|
379 |
-
}
|
380 |
-
|
381 |
-
/**
|
382 |
-
* Must be simple and cannot contain anything that would call filter "user_has_cap", e.g. current_user_can()
|
383 |
-
* @return boolean
|
384 |
-
*/
|
385 |
-
public function getMeetsBasePermissions() {
|
386 |
-
return (bool)$this->bMeetsBasePermissions;
|
387 |
-
}
|
388 |
-
|
389 |
-
/**
|
390 |
-
*/
|
391 |
-
public function getHasPermissionToView() {
|
392 |
-
return $this->getHasPermissionToManage(); // TODO: separate view vs manage
|
393 |
-
}
|
394 |
-
|
395 |
/**
|
396 |
* @uses die()
|
397 |
*/
|
@@ -557,6 +530,15 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
557 |
$sSettingsLink = sprintf( $sLinkTemplate, $aMetaLink[ 'href' ], "_blank", $aMetaLink[ 'name' ] );;
|
558 |
array_push( $aPluginMeta, $sSettingsLink );
|
559 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
560 |
}
|
561 |
return $aPluginMeta;
|
562 |
}
|
@@ -734,7 +716,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
734 |
$sFile = $this->getPluginBaseFile();
|
735 |
if ( !empty( $oUpdates->response ) && isset( $oUpdates->response[ $sFile ] ) ) {
|
736 |
if ( version_compare( $oUpdates->response[ $sFile ]->new_version, '7.0.0', '>=' )
|
737 |
-
&& !$this->loadDP()->getPhpVersionIsAtLeast( '5.
|
738 |
unset( $oUpdates->response[ $sFile ] );
|
739 |
}
|
740 |
}
|
@@ -1089,9 +1071,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1089 |
* @param bool $bCheckUserPerms - do we check the logged-in user permissions
|
1090 |
* @return bool
|
1091 |
*/
|
1092 |
-
public function isValidAdminArea( $bCheckUserPerms =
|
1093 |
-
if ( $bCheckUserPerms &&
|
1094 |
-
&& !$this->getMeetsBasePermissions() ) {
|
1095 |
return false;
|
1096 |
}
|
1097 |
|
@@ -1105,6 +1086,29 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1105 |
return false;
|
1106 |
}
|
1107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1108 |
/**
|
1109 |
* @param string
|
1110 |
* @return string
|
@@ -1303,7 +1307,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1303 |
* @return string
|
1304 |
*/
|
1305 |
public function getPath_Assets( $sAsset = '' ) {
|
1306 |
-
|
|
|
1307 |
}
|
1308 |
|
1309 |
/**
|
@@ -1311,7 +1316,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1311 |
* @return string
|
1312 |
*/
|
1313 |
public function getPath_Flags( $sFlag = '' ) {
|
1314 |
-
|
|
|
1315 |
}
|
1316 |
|
1317 |
/**
|
@@ -1319,12 +1325,14 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1319 |
* @return string
|
1320 |
*/
|
1321 |
public function getPath_Temp( $sTmpFile = '' ) {
|
|
|
1322 |
$oFs = $this->loadFS();
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
|
|
1326 |
}
|
1327 |
-
return
|
1328 |
}
|
1329 |
|
1330 |
/**
|
@@ -1351,35 +1359,28 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1351 |
return $this->getPath_Assets( 'images/'.$sAsset );
|
1352 |
}
|
1353 |
|
1354 |
-
/**
|
1355 |
-
* @return string
|
1356 |
-
*/
|
1357 |
-
public function getPath_Config() {
|
1358 |
-
return $this->getPath_Source().'config/';
|
1359 |
-
}
|
1360 |
-
|
1361 |
/**
|
1362 |
* @param string $sSlug
|
1363 |
* @return string
|
1364 |
*/
|
1365 |
public function getPath_ConfigFile( $sSlug ) {
|
1366 |
-
return $this->
|
1367 |
}
|
1368 |
|
1369 |
/**
|
1370 |
-
* get the root directory for the plugin with the trailing slash
|
1371 |
* @return string
|
1372 |
*/
|
1373 |
public function getPath_Languages() {
|
1374 |
-
return $this->getRootDir()
|
1375 |
}
|
1376 |
|
1377 |
/**
|
1378 |
-
*
|
|
|
1379 |
* @return string
|
1380 |
*/
|
1381 |
-
public function
|
1382 |
-
return $this->
|
1383 |
}
|
1384 |
|
1385 |
/**
|
@@ -1388,23 +1389,15 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1388 |
* @return string
|
1389 |
*/
|
1390 |
public function getPath_SourceFile( $sSourceFile = '' ) {
|
1391 |
-
|
1392 |
-
|
1393 |
-
|
1394 |
-
/**
|
1395 |
-
* Get the path to a library source file
|
1396 |
-
* @param string $sLibFile
|
1397 |
-
* @return string
|
1398 |
-
*/
|
1399 |
-
public function getPath_LibFile( $sLibFile = '' ) {
|
1400 |
-
return $this->getPath_Source().'lib/'.$sLibFile;
|
1401 |
}
|
1402 |
|
1403 |
/**
|
1404 |
* @return string
|
1405 |
*/
|
1406 |
public function getPath_Templates() {
|
1407 |
-
return $this->getRootDir()
|
1408 |
}
|
1409 |
|
1410 |
/**
|
@@ -1412,14 +1405,14 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1412 |
* @return string
|
1413 |
*/
|
1414 |
public function getPath_TemplatesFile( $sTemplate ) {
|
1415 |
-
return $this->getPath_Templates()
|
1416 |
}
|
1417 |
|
1418 |
/**
|
1419 |
* @return string
|
1420 |
*/
|
1421 |
private function getPathPluginSpec() {
|
1422 |
-
return $this->getRootDir()
|
1423 |
}
|
1424 |
|
1425 |
/**
|
@@ -1542,9 +1535,9 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1542 |
protected function saveCurrentPluginControllerOptions() {
|
1543 |
$oOptions = $this->getPluginControllerOptions();
|
1544 |
if ( $this->sConfigOptionsHashWhenLoaded != md5( serialize( $oOptions ) ) ) {
|
1545 |
-
add_filter( $this->prefix( '
|
1546 |
$this->loadWp()->updateOption( $this->getPluginControllerOptionsKey(), $oOptions );
|
1547 |
-
remove_filter( $this->prefix( '
|
1548 |
}
|
1549 |
}
|
1550 |
|
@@ -1576,7 +1569,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1576 |
/**
|
1577 |
*/
|
1578 |
public function deactivateSelf() {
|
1579 |
-
if ( $this->
|
1580 |
deactivate_plugins( $this->getPluginBaseFile() );
|
1581 |
}
|
1582 |
}
|
@@ -1641,7 +1634,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1641 |
public function getUniqueRequestId( $bSetIfNeeded = true ) {
|
1642 |
if ( !isset( self::$sRequestId ) ) {
|
1643 |
self::$sRequestId = md5(
|
1644 |
-
$this->getSessionId( $bSetIfNeeded ).$this->loadIpService()->getRequestIp().$this->loadRequest()
|
|
|
1645 |
);
|
1646 |
}
|
1647 |
return self::$sRequestId;
|
@@ -1710,7 +1704,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1710 |
$bSuccess = true;
|
1711 |
}
|
1712 |
catch ( Exception $oE ) {
|
1713 |
-
if ( $this->isValidAdminArea() ) {
|
1714 |
$this->sAdminNoticeError = $oE->getMessage();
|
1715 |
add_action( 'admin_notices', array( $this, 'adminNoticePluginFailedToLoad' ) );
|
1716 |
add_action( 'network_admin_notices', array( $this, 'adminNoticePluginFailedToLoad' ) );
|
@@ -1883,4 +1877,17 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
|
|
1883 |
}
|
1884 |
return $aResult;
|
1885 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1886 |
}
|
91 |
/**
|
92 |
* @var boolean
|
93 |
*/
|
94 |
+
private $bMeetsBasePermissions;
|
95 |
|
96 |
/**
|
97 |
* @var string
|
127 |
self::$sRootFile = $sRootFile;
|
128 |
$this->checkMinimumRequirements();
|
129 |
$this->doRegisterHooks();
|
|
|
130 |
$this->loadFactory(); // so we know it's loaded whenever we need it. Cuz we need it.
|
131 |
$this->doLoadTextDomain();
|
132 |
|
259 |
/**
|
260 |
*/
|
261 |
public function onWpDeactivatePlugin() {
|
262 |
+
if ( $this->isPluginAdmin() && apply_filters( $this->prefix( 'delete_on_deactivate' ), false ) ) {
|
263 |
do_action( $this->prefix( 'delete_plugin' ) );
|
264 |
$this->deletePluginControllerOptions();
|
265 |
}
|
276 |
protected function doRegisterHooks() {
|
277 |
$this->registerActivationHooks();
|
278 |
|
279 |
+
add_action( 'init', array( $this, 'onWpInit' ), -1000 );
|
280 |
add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
|
281 |
add_action( 'wp_loaded', array( $this, 'onWpLoaded' ) );
|
282 |
|
336 |
/**
|
337 |
*/
|
338 |
public function onWpInit() {
|
339 |
+
$this->getMeetsBasePermissions();
|
340 |
add_action( 'wp_enqueue_scripts', array( $this, 'onWpEnqueueFrontendCss' ), 99 );
|
|
|
341 |
}
|
342 |
|
343 |
/**
|
351 |
/**
|
352 |
*/
|
353 |
public function onWpDashboardSetup() {
|
354 |
+
if ( $this->isValidAdminArea() && $this->isPluginAdmin() ) {
|
355 |
wp_add_dashboard_widget(
|
356 |
$this->prefix( 'dashboard_widget' ),
|
357 |
apply_filters( $this->prefix( 'dashboard_widget_title' ), $this->getHumanName() ),
|
365 |
echo implode( '', $aContent );
|
366 |
}
|
367 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
/**
|
369 |
* @uses die()
|
370 |
*/
|
530 |
$sSettingsLink = sprintf( $sLinkTemplate, $aMetaLink[ 'href' ], "_blank", $aMetaLink[ 'name' ] );;
|
531 |
array_push( $aPluginMeta, $sSettingsLink );
|
532 |
}
|
533 |
+
|
534 |
+
if ( !$this->loadDP()->getPhpVersionIsAtLeast( '5.4' ) ) {
|
535 |
+
$aPluginMeta[] = sprintf(
|
536 |
+
'<a href="%s" target="_blank" title="%s" style="color: red;">%s</a>',
|
537 |
+
'https://icwp.io/dj',
|
538 |
+
'Upgrades Not Available',
|
539 |
+
'PHP Too Old!'
|
540 |
+
);
|
541 |
+
}
|
542 |
}
|
543 |
return $aPluginMeta;
|
544 |
}
|
716 |
$sFile = $this->getPluginBaseFile();
|
717 |
if ( !empty( $oUpdates->response ) && isset( $oUpdates->response[ $sFile ] ) ) {
|
718 |
if ( version_compare( $oUpdates->response[ $sFile ]->new_version, '7.0.0', '>=' )
|
719 |
+
&& !$this->loadDP()->getPhpVersionIsAtLeast( '5.4.0' ) ) {
|
720 |
unset( $oUpdates->response[ $sFile ] );
|
721 |
}
|
722 |
}
|
1071 |
* @param bool $bCheckUserPerms - do we check the logged-in user permissions
|
1072 |
* @return bool
|
1073 |
*/
|
1074 |
+
public function isValidAdminArea( $bCheckUserPerms = false ) {
|
1075 |
+
if ( $bCheckUserPerms && did_action( 'init' ) && !$this->isPluginAdmin() ) {
|
|
|
1076 |
return false;
|
1077 |
}
|
1078 |
|
1086 |
return false;
|
1087 |
}
|
1088 |
|
1089 |
+
/**
|
1090 |
+
* only ever consider after WP INIT (when a logged-in user is recognised)
|
1091 |
+
* @return bool
|
1092 |
+
*/
|
1093 |
+
public function isPluginAdmin() {
|
1094 |
+
return apply_filters( $this->prefix( 'bypass_is_plugin_admin' ), false )
|
1095 |
+
|| ( $this->getMeetsBasePermissions() // takes care of did_action('init)
|
1096 |
+
&& apply_filters( $this->prefix( 'is_plugin_admin' ), true )
|
1097 |
+
);
|
1098 |
+
}
|
1099 |
+
|
1100 |
+
/**
|
1101 |
+
* DO NOT CHANGE THIS IMPLEMENTATION. We call this as early as possible so that the
|
1102 |
+
* current_user_can() never gets caught up in an infinite loop of permissions checking
|
1103 |
+
* @return boolean
|
1104 |
+
*/
|
1105 |
+
public function getMeetsBasePermissions() {
|
1106 |
+
if ( did_action( 'init' ) && !isset( $this->bMeetsBasePermissions ) ) {
|
1107 |
+
$this->bMeetsBasePermissions = current_user_can( $this->getBasePermissions() );
|
1108 |
+
}
|
1109 |
+
return isset( $this->bMeetsBasePermissions ) ? $this->bMeetsBasePermissions : false;
|
1110 |
+
}
|
1111 |
+
|
1112 |
/**
|
1113 |
* @param string
|
1114 |
* @return string
|
1307 |
* @return string
|
1308 |
*/
|
1309 |
public function getPath_Assets( $sAsset = '' ) {
|
1310 |
+
$sBase = path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'assets' ) );
|
1311 |
+
return empty( $sAsset ) ? $sBase : path_join( $sBase, $sAsset );
|
1312 |
}
|
1313 |
|
1314 |
/**
|
1316 |
* @return string
|
1317 |
*/
|
1318 |
public function getPath_Flags( $sFlag = '' ) {
|
1319 |
+
$sBase = path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'flags' ) );
|
1320 |
+
return empty( $sFlag ) ? $sBase : path_join( $sBase, $sFlag );
|
1321 |
}
|
1322 |
|
1323 |
/**
|
1325 |
* @return string
|
1326 |
*/
|
1327 |
public function getPath_Temp( $sTmpFile = '' ) {
|
1328 |
+
$sTempPath = null;
|
1329 |
$oFs = $this->loadFS();
|
1330 |
+
|
1331 |
+
$sBase = path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'temp' ) );
|
1332 |
+
if ( $oFs->mkdir( $sBase ) ) {
|
1333 |
+
$sTempPath = $sBase;
|
1334 |
}
|
1335 |
+
return empty( $sTmpFile ) ? $sTempPath : path_join( $sTempPath, $sTmpFile );
|
1336 |
}
|
1337 |
|
1338 |
/**
|
1359 |
return $this->getPath_Assets( 'images/'.$sAsset );
|
1360 |
}
|
1361 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1362 |
/**
|
1363 |
* @param string $sSlug
|
1364 |
* @return string
|
1365 |
*/
|
1366 |
public function getPath_ConfigFile( $sSlug ) {
|
1367 |
+
return $this->getPath_SourceFile( sprintf( 'config/feature-%s.php', $sSlug ) );
|
1368 |
}
|
1369 |
|
1370 |
/**
|
|
|
1371 |
* @return string
|
1372 |
*/
|
1373 |
public function getPath_Languages() {
|
1374 |
+
return path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'languages' ) ).'/';
|
1375 |
}
|
1376 |
|
1377 |
/**
|
1378 |
+
* Get the path to a library source file
|
1379 |
+
* @param string $sLibFile
|
1380 |
* @return string
|
1381 |
*/
|
1382 |
+
public function getPath_LibFile( $sLibFile = '' ) {
|
1383 |
+
return $this->getPath_SourceFile( 'lib/'.$sLibFile );
|
1384 |
}
|
1385 |
|
1386 |
/**
|
1389 |
* @return string
|
1390 |
*/
|
1391 |
public function getPath_SourceFile( $sSourceFile = '' ) {
|
1392 |
+
$sBase = path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'source' ) ).'/';
|
1393 |
+
return empty( $sSourceFile ) ? $sBase : path_join( $sBase, $sSourceFile );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1394 |
}
|
1395 |
|
1396 |
/**
|
1397 |
* @return string
|
1398 |
*/
|
1399 |
public function getPath_Templates() {
|
1400 |
+
return path_join( $this->getRootDir(), $this->getPluginSpec_Path( 'templates' ) ).'/';
|
1401 |
}
|
1402 |
|
1403 |
/**
|
1405 |
* @return string
|
1406 |
*/
|
1407 |
public function getPath_TemplatesFile( $sTemplate ) {
|
1408 |
+
return path_join( $this->getPath_Templates(), $sTemplate );
|
1409 |
}
|
1410 |
|
1411 |
/**
|
1412 |
* @return string
|
1413 |
*/
|
1414 |
private function getPathPluginSpec() {
|
1415 |
+
return path_join( $this->getRootDir(), 'plugin-spec.php' );
|
1416 |
}
|
1417 |
|
1418 |
/**
|
1535 |
protected function saveCurrentPluginControllerOptions() {
|
1536 |
$oOptions = $this->getPluginControllerOptions();
|
1537 |
if ( $this->sConfigOptionsHashWhenLoaded != md5( serialize( $oOptions ) ) ) {
|
1538 |
+
add_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true' );
|
1539 |
$this->loadWp()->updateOption( $this->getPluginControllerOptionsKey(), $oOptions );
|
1540 |
+
remove_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true' );
|
1541 |
}
|
1542 |
}
|
1543 |
|
1569 |
/**
|
1570 |
*/
|
1571 |
public function deactivateSelf() {
|
1572 |
+
if ( $this->isPluginAdmin() && function_exists( 'deactivate_plugins' ) ) {
|
1573 |
deactivate_plugins( $this->getPluginBaseFile() );
|
1574 |
}
|
1575 |
}
|
1634 |
public function getUniqueRequestId( $bSetIfNeeded = true ) {
|
1635 |
if ( !isset( self::$sRequestId ) ) {
|
1636 |
self::$sRequestId = md5(
|
1637 |
+
$this->getSessionId( $bSetIfNeeded ).$this->loadIpService()->getRequestIp().$this->loadRequest()
|
1638 |
+
->ts().wp_rand()
|
1639 |
);
|
1640 |
}
|
1641 |
return self::$sRequestId;
|
1704 |
$bSuccess = true;
|
1705 |
}
|
1706 |
catch ( Exception $oE ) {
|
1707 |
+
if ( $this->isValidAdminArea() && $this->isPluginAdmin() ) {
|
1708 |
$this->sAdminNoticeError = $oE->getMessage();
|
1709 |
add_action( 'admin_notices', array( $this, 'adminNoticePluginFailedToLoad' ) );
|
1710 |
add_action( 'network_admin_notices', array( $this, 'adminNoticePluginFailedToLoad' ) );
|
1877 |
}
|
1878 |
return $aResult;
|
1879 |
}
|
1880 |
+
|
1881 |
+
/**
|
1882 |
+
* v5.4.1: Nasty looping bug in here where this function was called within the 'user_has_cap' filter
|
1883 |
+
* so we removed the "current_user_can()" or any such sub-call within this function
|
1884 |
+
* @deprecated v6.10.7
|
1885 |
+
* @return bool
|
1886 |
+
*/
|
1887 |
+
public function getHasPermissionToManage() {
|
1888 |
+
if ( apply_filters( $this->prefix( 'bypass_permission_to_manage' ), false ) ) {
|
1889 |
+
return true;
|
1890 |
+
}
|
1891 |
+
return ( $this->isPluginAdmin() && apply_filters( $this->prefix( 'is_plugin_admin' ), true ) );
|
1892 |
+
}
|
1893 |
}
|
icwp-wpsf.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Shield Security
|
4 |
* Plugin URI: https://icwp.io/2f
|
5 |
* Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
|
6 |
-
* Version: 6.10.
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Domain Path: /languages/
|
9 |
* Author: One Dollar Plugin
|
3 |
* Plugin Name: Shield Security
|
4 |
* Plugin URI: https://icwp.io/2f
|
5 |
* Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
|
6 |
+
* Version: 6.10.9
|
7 |
* Text Domain: wp-simple-firewall
|
8 |
* Domain Path: /languages/
|
9 |
* Author: One Dollar Plugin
|
init.php
CHANGED
@@ -56,21 +56,18 @@ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Foundation {
|
|
56 |
*/
|
57 |
public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
|
58 |
$oCon = $this->getController();
|
59 |
-
if ( !$oCon->isValidAdminArea() ) {
|
60 |
-
return $aActionLinks;
|
61 |
-
}
|
62 |
|
63 |
-
if ( $
|
64 |
-
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
}
|
72 |
}
|
73 |
}
|
|
|
74 |
return $aActionLinks;
|
75 |
}
|
76 |
}
|
56 |
*/
|
57 |
public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
|
58 |
$oCon = $this->getController();
|
|
|
|
|
|
|
59 |
|
60 |
+
if ( $oCon->isValidAdminArea() && !$oCon->isPluginAdmin()
|
61 |
+
&& $sPluginFile == $oCon->getPluginBaseFile() ) {
|
62 |
|
63 |
+
if ( array_key_exists( 'edit', $aActionLinks ) ) {
|
64 |
+
unset( $aActionLinks[ 'edit' ] );
|
65 |
+
}
|
66 |
+
if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
|
67 |
+
unset( $aActionLinks[ 'deactivate' ] );
|
|
|
68 |
}
|
69 |
}
|
70 |
+
|
71 |
return $aActionLinks;
|
72 |
}
|
73 |
}
|
plugin-spec.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"properties": {
|
3 |
-
"version": "6.10.
|
4 |
-
"release_timestamp":
|
5 |
"slug_parent": "icwp",
|
6 |
"slug_plugin": "wpsf",
|
7 |
"human_name": "Shield",
|
1 |
{
|
2 |
"properties": {
|
3 |
+
"version": "6.10.9",
|
4 |
+
"release_timestamp": 1544177090,
|
5 |
"slug_parent": "icwp",
|
6 |
"slug_plugin": "wpsf",
|
7 |
"human_name": "Shield",
|
readme.txt
CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.5.0
|
|
8 |
Requires PHP: 5.2.4
|
9 |
Recommended PHP: 5.4
|
10 |
Tested up to: 5.0
|
11 |
-
Stable tag: 6.10.
|
12 |
|
13 |
Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
|
14 |
|
@@ -354,9 +354,22 @@ You will always be able to use Shield Security and its free features in-full.
|
|
354 |
|
355 |
[Go Pro for just $1/month](https://icwp.io/aa).
|
356 |
|
357 |
-
= 6.10.
|
358 |
-
*Released:
|
359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
* **(v.4)** FIXED: Couldn't deactivate plugin.
|
361 |
* **(v.3)** ADDED: Support for Ultimate Member forms
|
362 |
* **(v.3)** ADDED: Support for LearnPress login/registration forms
|
@@ -364,10 +377,6 @@ You will always be able to use Shield Security and its free features in-full.
|
|
364 |
* **(v.3)** IMPROVED: Distinguish which sub-site (sub-domain) for WPMS installations on [Traffic Watcher](https://icwp.io/c1).
|
365 |
* **(v.3)** IMPROVED: Server's own IP lookup is only attempted once.
|
366 |
* **(v.3)** ADDED: Experimental feature to help with some custom 3rd party login/registration forms
|
367 |
-
|
368 |
-
= 6.10 - Series =
|
369 |
-
*Released: 15th October, 2018* - [Release Notes](https://icwp.io/dg)
|
370 |
-
|
371 |
* **(v.2)** IMPROVED: Visitor IP address detection
|
372 |
* **(v.2)** IMPROVED: Automatic whitelisting of Manage WP IP addresses
|
373 |
* **(v.2)** IMPROVED: SPAM Comments code enhanced and optimised
|
8 |
Requires PHP: 5.2.4
|
9 |
Recommended PHP: 5.4
|
10 |
Tested up to: 5.0
|
11 |
+
Stable tag: 6.10.9
|
12 |
|
13 |
Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
|
14 |
|
354 |
|
355 |
[Go Pro for just $1/month](https://icwp.io/aa).
|
356 |
|
357 |
+
= 6.10.9 - Current Release =
|
358 |
+
*Released: 7th December, 2018* - [Release Notes](https://icwp.io/dg)
|
359 |
|
360 |
+
* **(v.9)** FIXED: Admin notices displaying to non-admins.
|
361 |
+
* **(v.7)** ADDED: [**PRO**] New option to specify usernames for Security Admin role.
|
362 |
+
* **(v.7)** IMPROVED: Idle user detection.
|
363 |
+
* **(v.7)** IMPROVED: Support for redirect/cancel URLs in 2FA login page.
|
364 |
+
* **(v.7)** CHANGED: Final release before Shield v7. Small warning shown on plugins page if PHP < 5.4
|
365 |
+
|
366 |
+
= 6.10 - Series =
|
367 |
+
*Released: 15th October, 2018* - [Release Notes](https://icwp.io/dg)
|
368 |
+
|
369 |
+
* **(v.6)** ADDED: New option to control plugin automatic updates.
|
370 |
+
* **(v.6)** IMPROVED: Enhancements to the experimental bot JS.
|
371 |
+
* **(v.6)** IMPROVED: Support for Easy Digital Downloads forms.
|
372 |
+
* **(v.5)** Release skipped.
|
373 |
* **(v.4)** FIXED: Couldn't deactivate plugin.
|
374 |
* **(v.3)** ADDED: Support for Ultimate Member forms
|
375 |
* **(v.3)** ADDED: Support for LearnPress login/registration forms
|
377 |
* **(v.3)** IMPROVED: Distinguish which sub-site (sub-domain) for WPMS installations on [Traffic Watcher](https://icwp.io/c1).
|
378 |
* **(v.3)** IMPROVED: Server's own IP lookup is only attempted once.
|
379 |
* **(v.3)** ADDED: Experimental feature to help with some custom 3rd party login/registration forms
|
|
|
|
|
|
|
|
|
380 |
* **(v.2)** IMPROVED: Visitor IP address detection
|
381 |
* **(v.2)** IMPROVED: Automatic whitelisting of Manage WP IP addresses
|
382 |
* **(v.2)** IMPROVED: SPAM Comments code enhanced and optimised
|
resources/css/plugin.css
CHANGED
@@ -802,7 +802,9 @@ input:checked + .icwp-slider:before {
|
|
802 |
#IcwpWpsfSecurityAdmin {
|
803 |
background-color: white;
|
804 |
padding: 40px;
|
805 |
-
margin:
|
|
|
|
|
806 |
}
|
807 |
.card.gopro-card {
|
808 |
padding: 0; /* fix to override for bootstrap4 cuz WP has a .card style*/
|
@@ -857,10 +859,7 @@ input:checked + .icwp-slider:before {
|
|
857 |
}
|
858 |
|
859 |
.icon-flag {
|
860 |
-
|
861 |
-
height: 12px;
|
862 |
-
border: 1px solid black;
|
863 |
-
vertical-align: unset;
|
864 |
}
|
865 |
|
866 |
/** TABLE: Audit trail **/
|
802 |
#IcwpWpsfSecurityAdmin {
|
803 |
background-color: white;
|
804 |
padding: 40px;
|
805 |
+
margin: 120px 0 40px;
|
806 |
+
box-shadow: 6px 6px 0 rgba(0,0,0,0.2);
|
807 |
+
border: 1px solid rgba(0,0,0,0.2);
|
808 |
}
|
809 |
.card.gopro-card {
|
810 |
padding: 0; /* fix to override for bootstrap4 cuz WP has a .card style*/
|
859 |
}
|
860 |
|
861 |
.icon-flag {
|
862 |
+
vertical-align: bottom;
|
|
|
|
|
|
|
863 |
}
|
864 |
|
865 |
/** TABLE: Audit trail **/
|
resources/images/flags/ad.png
DELETED
Binary file
|
resources/images/flags/ae.png
DELETED
Binary file
|
resources/images/flags/af.png
DELETED
Binary file
|
resources/images/flags/ag.png
DELETED
Binary file
|
resources/images/flags/al.png
DELETED
Binary file
|
resources/images/flags/am.png
DELETED
Binary file
|
resources/images/flags/ao.png
DELETED
Binary file
|
resources/images/flags/ar.png
DELETED
Binary file
|
resources/images/flags/at.png
DELETED
Binary file
|
resources/images/flags/au.png
DELETED
Binary file
|
resources/images/flags/az.png
DELETED
Binary file
|
resources/images/flags/ba.png
DELETED
Binary file
|
resources/images/flags/bb.png
DELETED
Binary file
|
resources/images/flags/bd.png
DELETED
Binary file
|
resources/images/flags/be.png
DELETED
Binary file
|
resources/images/flags/bf.png
DELETED
Binary file
|
resources/images/flags/bg.png
DELETED
Binary file
|
resources/images/flags/bh.png
DELETED
Binary file
|
resources/images/flags/bi.png
DELETED
Binary file
|
resources/images/flags/bj.png
DELETED
Binary file
|
resources/images/flags/bn.png
DELETED
Binary file
|
resources/images/flags/bo.png
DELETED
Binary file
|
resources/images/flags/br.png
DELETED
Binary file
|
resources/images/flags/bs.png
DELETED
Binary file
|
resources/images/flags/bt.png
DELETED
Binary file
|
resources/images/flags/bw.png
DELETED
Binary file
|
resources/images/flags/by.png
DELETED
Binary file
|
resources/images/flags/bz.png
DELETED
Binary file
|
resources/images/flags/ca.png
DELETED
Binary file
|
resources/images/flags/cd.png
DELETED
Binary file
|
resources/images/flags/cf.png
DELETED
Binary file
|
resources/images/flags/cg.png
DELETED
Binary file
|
resources/images/flags/ch.png
DELETED
Binary file
|
resources/images/flags/ci.png
DELETED
Binary file
|
resources/images/flags/cl.png
DELETED
Binary file
|
resources/images/flags/cm.png
DELETED
Binary file
|
resources/images/flags/cn.png
DELETED
Binary file
|
resources/images/flags/co.png
DELETED
Binary file
|
resources/images/flags/cr.png
DELETED
Binary file
|
resources/images/flags/cu.png
DELETED
Binary file
|
resources/images/flags/cv.png
DELETED
Binary file
|
resources/images/flags/cy.png
DELETED
Binary file
|
resources/images/flags/cz.png
DELETED
Binary file
|
resources/images/flags/de.png
DELETED
Binary file
|
resources/images/flags/dj.png
DELETED
Binary file
|
resources/images/flags/dk.png
DELETED
Binary file
|
resources/images/flags/dm.png
DELETED
Binary file
|
resources/images/flags/do.png
DELETED
Binary file
|
resources/images/flags/dz.png
DELETED
Binary file
|
resources/images/flags/ec.png
DELETED
Binary file
|
resources/images/flags/ee.png
DELETED
Binary file
|
resources/images/flags/eg.png
DELETED
Binary file
|
resources/images/flags/eh.png
DELETED
Binary file
|
resources/images/flags/er.png
DELETED
Binary file
|
resources/images/flags/es.png
DELETED
Binary file
|
resources/images/flags/et.png
DELETED
Binary file
|
resources/images/flags/fi.png
DELETED
Binary file
|
resources/images/flags/fj.png
DELETED
Binary file
|
resources/images/flags/fm.png
DELETED
Binary file
|
resources/images/flags/fr.png
DELETED
Binary file
|
resources/images/flags/ga.png
DELETED
Binary file
|
resources/images/flags/gb.png
DELETED
Binary file
|
resources/images/flags/gd.png
DELETED
Binary file
|
resources/images/flags/ge.png
DELETED
Binary file
|
resources/images/flags/gh.png
DELETED
Binary file
|
resources/images/flags/gm.png
DELETED
Binary file
|
resources/images/flags/gn.png
DELETED
Binary file
|
resources/images/flags/gq.png
DELETED
Binary file
|
resources/images/flags/gr.png
DELETED
Binary file
|
resources/images/flags/gt.png
DELETED
Binary file
|
resources/images/flags/gw.png
DELETED
Binary file
|
resources/images/flags/gy.png
DELETED
Binary file
|
resources/images/flags/hn.png
DELETED
Binary file
|
resources/images/flags/hr.png
DELETED
Binary file
|
resources/images/flags/ht.png
DELETED
Binary file
|
resources/images/flags/hu.png
DELETED
Binary file
|
resources/images/flags/id.png
DELETED
Binary file
|
resources/images/flags/ie.png
DELETED
Binary file
|
resources/images/flags/il.png
DELETED
Binary file
|
resources/images/flags/in.png
DELETED
Binary file
|
resources/images/flags/iq.png
DELETED
Binary file
|
resources/images/flags/ir.png
DELETED
Binary file
|
resources/images/flags/is.png
DELETED
Binary file
|
resources/images/flags/it.png
DELETED
Binary file
|
resources/images/flags/jm.png
DELETED
Binary file
|
resources/images/flags/jo.png
DELETED
Binary file
|
resources/images/flags/jp.png
DELETED
Binary file
|
resources/images/flags/ke.png
DELETED
Binary file
|
resources/images/flags/kg.png
DELETED
Binary file
|
resources/images/flags/kh.png
DELETED
Binary file
|
resources/images/flags/ki.png
DELETED
Binary file
|
resources/images/flags/km.png
DELETED
Binary file
|
resources/images/flags/kn.png
DELETED
Binary file
|
resources/images/flags/kp.png
DELETED
Binary file
|
resources/images/flags/kr.png
DELETED
Binary file
|
resources/images/flags/ks.png
DELETED
Binary file
|
resources/images/flags/kw.png
DELETED
Binary file
|
resources/images/flags/kz.png
DELETED
Binary file
|
resources/images/flags/la.png
DELETED
Binary file
|
resources/images/flags/lb.png
DELETED
Binary file
|
resources/images/flags/lc.png
DELETED
Binary file
|
resources/images/flags/li.png
DELETED
Binary file
|
resources/images/flags/lk.png
DELETED
Binary file
|
resources/images/flags/lr.png
DELETED
Binary file
|
resources/images/flags/ls.png
DELETED
Binary file
|
resources/images/flags/lt.png
DELETED
Binary file
|
resources/images/flags/lu.png
DELETED
Binary file
|
resources/images/flags/lv.png
DELETED
Binary file
|
resources/images/flags/ly.png
DELETED
Binary file
|
resources/images/flags/ma.png
DELETED
Binary file
|
resources/images/flags/mc.png
DELETED
Binary file
|
resources/images/flags/md.png
DELETED
Binary file
|
resources/images/flags/me.png
DELETED
Binary file
|
resources/images/flags/mg.png
DELETED
Binary file
|
resources/images/flags/mh.png
DELETED
Binary file
|
resources/images/flags/mk.png
DELETED
Binary file
|
resources/images/flags/ml.png
DELETED
Binary file
|
resources/images/flags/mm.png
DELETED
Binary file
|
resources/images/flags/mn.png
DELETED
Binary file
|
resources/images/flags/mr.png
DELETED
Binary file
|
resources/images/flags/mt.png
DELETED
Binary file
|
resources/images/flags/mu.png
DELETED
Binary file
|
resources/images/flags/mv.png
DELETED
Binary file
|
resources/images/flags/mw.png
DELETED
Binary file
|
resources/images/flags/mx.png
DELETED
Binary file
|
resources/images/flags/my.png
DELETED
Binary file
|
resources/images/flags/mz.png
DELETED
Binary file
|
resources/images/flags/na.png
DELETED
Binary file
|
resources/images/flags/ne.png
DELETED
Binary file
|
resources/images/flags/ng.png
DELETED
Binary file
|
resources/images/flags/ni.png
DELETED
Binary file
|
resources/images/flags/nl.png
DELETED
Binary file
|
resources/images/flags/no.png
DELETED
Binary file
|
resources/images/flags/np.png
DELETED
Binary file
|
resources/images/flags/nr.png
DELETED
Binary file
|
resources/images/flags/nz.png
DELETED
Binary file
|
resources/images/flags/om.png
DELETED
Binary file
|
resources/images/flags/pa.png
DELETED
Binary file
|
resources/images/flags/pe.png
DELETED
Binary file
|
resources/images/flags/pg.png
DELETED
Binary file
|
resources/images/flags/ph.png
DELETED
Binary file
|
resources/images/flags/pk.png
DELETED
Binary file
|
resources/images/flags/pl.png
DELETED
Binary file
|
resources/images/flags/pt.png
DELETED
Binary file
|
resources/images/flags/pw.png
DELETED
Binary file
|
resources/images/flags/py.png
DELETED
Binary file
|
resources/images/flags/qa.png
DELETED
Binary file
|
resources/images/flags/ro.png
DELETED
Binary file
|
resources/images/flags/rs.png
DELETED
Binary file
|
resources/images/flags/ru.png
DELETED
Binary file
|
resources/images/flags/rw.png
DELETED
Binary file
|
resources/images/flags/sa.png
DELETED
Binary file
|
resources/images/flags/sb.png
DELETED
Binary file
|
resources/images/flags/sc.png
DELETED
Binary file
|
resources/images/flags/sd.png
DELETED
Binary file
|
resources/images/flags/se.png
DELETED
Binary file
|
resources/images/flags/sg.png
DELETED
Binary file
|
resources/images/flags/si.png
DELETED
Binary file
|
resources/images/flags/sk.png
DELETED
Binary file
|
resources/images/flags/sl.png
DELETED
Binary file
|
resources/images/flags/sm.png
DELETED
Binary file
|
resources/images/flags/sn.png
DELETED
Binary file
|
resources/images/flags/so.png
DELETED
Binary file
|
resources/images/flags/sr.png
DELETED
Binary file
|
resources/images/flags/st.png
DELETED
Binary file
|
resources/images/flags/sv.png
DELETED
Binary file
|
resources/images/flags/sy.png
DELETED
Binary file
|
resources/images/flags/sz.png
DELETED
Binary file
|
resources/images/flags/td.png
DELETED
Binary file
|
resources/images/flags/tg.png
DELETED
Binary file
|
resources/images/flags/th.png
DELETED
Binary file
|
resources/images/flags/tj.png
DELETED
Binary file
|
resources/images/flags/tl.png
DELETED
Binary file
|
resources/images/flags/tm.png
DELETED
Binary file
|
resources/images/flags/tn.png
DELETED
Binary file
|
resources/images/flags/to.png
DELETED
Binary file
|
resources/images/flags/tr.png
DELETED
Binary file
|
resources/images/flags/tt.png
DELETED
Binary file
|
resources/images/flags/tv.png
DELETED
Binary file
|
resources/images/flags/tw.png
DELETED
Binary file
|
resources/images/flags/tz.png
DELETED
Binary file
|
resources/images/flags/ua.png
DELETED
Binary file
|
resources/images/flags/ug.png
DELETED
Binary file
|
resources/images/flags/us.png
DELETED
Binary file
|
resources/images/flags/uy.png
DELETED
Binary file
|
resources/images/flags/uz.png
DELETED
Binary file
|
resources/images/flags/va.png
DELETED
Binary file
|
resources/images/flags/vc.png
DELETED
Binary file
|
resources/images/flags/ve.png
DELETED
Binary file
|
resources/images/flags/vn.png
DELETED
Binary file
|
resources/images/flags/vu.png
DELETED
Binary file
|
resources/images/flags/ws.png
DELETED
Binary file
|
resources/images/flags/ye.png
DELETED
Binary file
|
resources/images/flags/za.png
DELETED
Binary file
|
resources/images/flags/zm.png
DELETED
Binary file
|
resources/images/flags/zw.png
DELETED
Binary file
|
resources/js/shield-antibot.js
CHANGED
@@ -3,15 +3,14 @@ if ( typeof icwp_wpsf_vars_lpantibot !== 'undefined' ) {
|
|
3 |
|
4 |
this.initialise = function () {
|
5 |
jQuery( document ).ready( function () {
|
6 |
-
jQuery
|
7 |
-
function ( _
|
8 |
-
|
9 |
-
if ( form !== null ) {
|
10 |
if ( icwp_wpsf_vars_lpantibot.flags.recap ) {
|
11 |
-
insertPlaceHolder_Recap(
|
12 |
}
|
13 |
if ( icwp_wpsf_vars_lpantibot.flags.gasp ) {
|
14 |
-
insertPlaceHolder_Gasp(
|
15 |
}
|
16 |
}
|
17 |
}
|
3 |
|
4 |
this.initialise = function () {
|
5 |
jQuery( document ).ready( function () {
|
6 |
+
jQuery( icwp_wpsf_vars_lpantibot.form_selectors ).each(
|
7 |
+
function ( _ ) {
|
8 |
+
if ( this !== null ) {
|
|
|
9 |
if ( icwp_wpsf_vars_lpantibot.flags.recap ) {
|
10 |
+
insertPlaceHolder_Recap( this );
|
11 |
}
|
12 |
if ( icwp_wpsf_vars_lpantibot.flags.gasp ) {
|
13 |
+
insertPlaceHolder_Gasp( this );
|
14 |
}
|
15 |
}
|
16 |
}
|
src/common/icwp-wpfunctions.php
CHANGED
@@ -728,7 +728,8 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
|
|
728 |
public function isRest() {
|
729 |
$bIsRest = ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || !empty( $_REQUEST[ 'rest_route' ] );
|
730 |
|
731 |
-
|
|
|
732 |
$sRestUrlBase = get_rest_url( get_current_blog_id(), '/' );
|
733 |
$sRestPath = trim( parse_url( $sRestUrlBase, PHP_URL_PATH ), '/' );
|
734 |
$sRequestPath = trim( $this->loadRequest()->getPath(), '/' );
|
728 |
public function isRest() {
|
729 |
$bIsRest = ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || !empty( $_REQUEST[ 'rest_route' ] );
|
730 |
|
731 |
+
global $wp_rewrite;
|
732 |
+
if ( !$bIsRest && function_exists( 'rest_url' ) && is_object( $wp_rewrite ) ) {
|
733 |
$sRestUrlBase = get_rest_url( get_current_blog_id(), '/' );
|
734 |
$sRestPath = trim( parse_url( $sRestUrlBase, PHP_URL_PATH ), '/' );
|
735 |
$sRequestPath = trim( $this->loadRequest()->getPath(), '/' );
|
src/config/feature-admin_access_restriction.php
CHANGED
@@ -96,6 +96,19 @@
|
|
96 |
"summary": "Provide/Update Security Admin Access Key",
|
97 |
"description": "Careful: If you forget this, you could potentially lock yourself out from using this plugin."
|
98 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
{
|
100 |
"key": "admin_access_timeout",
|
101 |
"section": "section_admin_access_restriction_settings",
|
96 |
"summary": "Provide/Update Security Admin Access Key",
|
97 |
"description": "Careful: If you forget this, you could potentially lock yourself out from using this plugin."
|
98 |
},
|
99 |
+
{
|
100 |
+
"key": "sec_admin_users",
|
101 |
+
"section": "section_admin_access_restriction_settings",
|
102 |
+
"sensitive": true,
|
103 |
+
"premium": true,
|
104 |
+
"default": "",
|
105 |
+
"type": "array",
|
106 |
+
"link_info": "https://icwp.io/dk",
|
107 |
+
"link_blog": "",
|
108 |
+
"name": "Security Admins",
|
109 |
+
"summary": "Persistent Security Admins",
|
110 |
+
"description": "All emails, usernames, or user IDs entered here will always be Security Admins."
|
111 |
+
},
|
112 |
{
|
113 |
"key": "admin_access_timeout",
|
114 |
"section": "section_admin_access_restriction_settings",
|
src/config/feature-autoupdates.php
CHANGED
@@ -160,6 +160,31 @@
|
|
160 |
"summary": "Delay Automatic Updates For Period Of Stability",
|
161 |
"description": "Shield will delay upgrades until the new update has been available for the set number of days."
|
162 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
{
|
164 |
"key": "enable_upgrade_notification_email",
|
165 |
"section": "section_options",
|
160 |
"summary": "Delay Automatic Updates For Period Of Stability",
|
161 |
"description": "Shield will delay upgrades until the new update has been available for the set number of days."
|
162 |
},
|
163 |
+
{
|
164 |
+
"key": "autoupdate_plugin_self",
|
165 |
+
"section": "section_options",
|
166 |
+
"default": "auto",
|
167 |
+
"type": "select",
|
168 |
+
"value_options": [
|
169 |
+
{
|
170 |
+
"value_key": "auto",
|
171 |
+
"text": "Let Shield Decide"
|
172 |
+
},
|
173 |
+
{
|
174 |
+
"value_key": "disabled",
|
175 |
+
"text": "Disabled"
|
176 |
+
},
|
177 |
+
{
|
178 |
+
"value_key": "immediate",
|
179 |
+
"text": "As Soon As Possible"
|
180 |
+
}
|
181 |
+
],
|
182 |
+
"link_info": "https://icwp.io/3x",
|
183 |
+
"link_blog": "",
|
184 |
+
"name": "WordPress Core Updates",
|
185 |
+
"summary": "Decide how the WordPress Core will automatically update, if at all",
|
186 |
+
"description": "At least automatically upgrading minor versions is recommended (and is the WordPress default)."
|
187 |
+
},
|
188 |
{
|
189 |
"key": "enable_upgrade_notification_email",
|
190 |
"section": "section_options",
|
src/config/feature-firewall.php
CHANGED
@@ -253,6 +253,7 @@
|
|
253 |
{
|
254 |
"key": "text_firewalldie",
|
255 |
"section": "section_user_messages",
|
|
|
256 |
"premium": true,
|
257 |
"default": "default",
|
258 |
"type": "text",
|
@@ -306,7 +307,9 @@
|
|
306 |
"redirect_to",
|
307 |
"jetpack_sso_original_request",
|
308 |
"jetpack_sso_redirect_to",
|
309 |
-
"/^wordpress_logged_in_[0-9a-f]+$/"
|
|
|
|
|
310 |
]
|
311 |
},
|
312 |
"firewall_patterns": {
|
253 |
{
|
254 |
"key": "text_firewalldie",
|
255 |
"section": "section_user_messages",
|
256 |
+
"sensitive": true,
|
257 |
"premium": true,
|
258 |
"default": "default",
|
259 |
"type": "text",
|
307 |
"redirect_to",
|
308 |
"jetpack_sso_original_request",
|
309 |
"jetpack_sso_redirect_to",
|
310 |
+
"/^wordpress_logged_in_[0-9a-f]+$/",
|
311 |
+
"edd_action",
|
312 |
+
"edd_redirect"
|
313 |
]
|
314 |
},
|
315 |
"firewall_patterns": {
|
src/config/feature-license.php
CHANGED
@@ -51,46 +51,12 @@
|
|
51 |
"default": 0,
|
52 |
"section": "section_non_ui"
|
53 |
},
|
54 |
-
{
|
55 |
-
"key": "license_last_request_at",
|
56 |
-
"transferable": false,
|
57 |
-
"default": 0,
|
58 |
-
"section": "section_non_ui"
|
59 |
-
},
|
60 |
-
{
|
61 |
-
"key": "license_verified_at",
|
62 |
-
"sensitive": true,
|
63 |
-
"transferable": false,
|
64 |
-
"default": 0,
|
65 |
-
"section": "section_non_ui"
|
66 |
-
},
|
67 |
-
{
|
68 |
-
"key": "license_expires_at",
|
69 |
-
"sensitive": true,
|
70 |
-
"transferable": false,
|
71 |
-
"default": 0,
|
72 |
-
"section": "section_non_ui"
|
73 |
-
},
|
74 |
-
{
|
75 |
-
"key": "license_official_status",
|
76 |
-
"sensitive": true,
|
77 |
-
"transferable": false,
|
78 |
-
"default": "",
|
79 |
-
"section": "section_non_ui"
|
80 |
-
},
|
81 |
{
|
82 |
"key": "license_deactivated_reason",
|
83 |
"transferable": false,
|
84 |
"default": "",
|
85 |
"section": "section_non_ui"
|
86 |
},
|
87 |
-
{
|
88 |
-
"key": "license_registered_email",
|
89 |
-
"sensitive": true,
|
90 |
-
"transferable": false,
|
91 |
-
"default": "",
|
92 |
-
"section": "section_non_ui"
|
93 |
-
},
|
94 |
{
|
95 |
"key": "last_warning_email_sent_at",
|
96 |
"transferable": false,
|
@@ -98,10 +64,9 @@
|
|
98 |
"section": "section_non_ui"
|
99 |
},
|
100 |
{
|
101 |
-
"key": "
|
102 |
-
"sensitive": true,
|
103 |
"transferable": false,
|
104 |
-
"default":
|
105 |
"section": "section_non_ui"
|
106 |
},
|
107 |
{
|
51 |
"default": 0,
|
52 |
"section": "section_non_ui"
|
53 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
{
|
55 |
"key": "license_deactivated_reason",
|
56 |
"transferable": false,
|
57 |
"default": "",
|
58 |
"section": "section_non_ui"
|
59 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
{
|
61 |
"key": "last_warning_email_sent_at",
|
62 |
"transferable": false,
|
64 |
"section": "section_non_ui"
|
65 |
},
|
66 |
{
|
67 |
+
"key": "last_deactivated_email_sent_at",
|
|
|
68 |
"transferable": false,
|
69 |
+
"default": 0,
|
70 |
"section": "section_non_ui"
|
71 |
},
|
72 |
{
|
src/config/feature-login_protect.php
CHANGED
@@ -354,8 +354,8 @@
|
|
354 |
"section": "section_brute_force_login_protection",
|
355 |
"type": "array",
|
356 |
"default": [
|
357 |
-
"ihc_login_form",
|
358 |
-
"createuser"
|
359 |
],
|
360 |
"link_info": "",
|
361 |
"link_blog": "",
|
354 |
"section": "section_brute_force_login_protection",
|
355 |
"type": "array",
|
356 |
"default": [
|
357 |
+
"form#ihc_login_form",
|
358 |
+
"form#createuser"
|
359 |
],
|
360 |
"link_info": "",
|
361 |
"link_blog": "",
|
src/config/feature-plugin.php
CHANGED
@@ -319,9 +319,9 @@
|
|
319 |
"type": "text",
|
320 |
"link_info": "https://icwp.io/shld5",
|
321 |
"link_blog": "",
|
322 |
-
"name": "reCAPTCHA
|
323 |
-
"summary": "Google reCAPTCHA
|
324 |
-
"description": "Enter your Google reCAPTCHA
|
325 |
},
|
326 |
{
|
327 |
"key": "google_recaptcha_secret_key",
|
@@ -331,9 +331,9 @@
|
|
331 |
"type": "text",
|
332 |
"link_info": "https://icwp.io/shld5",
|
333 |
"link_blog": "",
|
334 |
-
"name": "reCAPTCHA
|
335 |
-
"summary": "Google reCAPTCHA
|
336 |
-
"description": "Enter your Google reCAPTCHA
|
337 |
},
|
338 |
{
|
339 |
"key": "tracking_last_sent_at",
|
@@ -377,19 +377,19 @@
|
|
377 |
"transferable": false,
|
378 |
"sensitive": true,
|
379 |
"section": "section_non_ui",
|
380 |
-
"
|
381 |
},
|
382 |
{
|
383 |
"key": "this_server_ip_last_check_at",
|
384 |
"transferable": false,
|
385 |
"section": "section_non_ui",
|
386 |
-
"
|
387 |
},
|
388 |
{
|
389 |
"key": "insights_test_cron_last_run_at",
|
390 |
"transferable": false,
|
391 |
"section": "section_non_ui",
|
392 |
-
"
|
393 |
}
|
394 |
],
|
395 |
"definitions": {
|
319 |
"type": "text",
|
320 |
"link_info": "https://icwp.io/shld5",
|
321 |
"link_blog": "",
|
322 |
+
"name": "reCAPTCHA Site Key",
|
323 |
+
"summary": "Google reCAPTCHA Site Key",
|
324 |
+
"description": "Enter your Google reCAPTCHA site key for use throughout the plugin."
|
325 |
},
|
326 |
{
|
327 |
"key": "google_recaptcha_secret_key",
|
331 |
"type": "text",
|
332 |
"link_info": "https://icwp.io/shld5",
|
333 |
"link_blog": "",
|
334 |
+
"name": "reCAPTCHA Secret",
|
335 |
+
"summary": "Google reCAPTCHA Secret Key",
|
336 |
+
"description": "Enter your Google reCAPTCHA secret key for use throughout the plugin."
|
337 |
},
|
338 |
{
|
339 |
"key": "tracking_last_sent_at",
|
377 |
"transferable": false,
|
378 |
"sensitive": true,
|
379 |
"section": "section_non_ui",
|
380 |
+
"default": ""
|
381 |
},
|
382 |
{
|
383 |
"key": "this_server_ip_last_check_at",
|
384 |
"transferable": false,
|
385 |
"section": "section_non_ui",
|
386 |
+
"default": 0
|
387 |
},
|
388 |
{
|
389 |
"key": "insights_test_cron_last_run_at",
|
390 |
"transferable": false,
|
391 |
"section": "section_non_ui",
|
392 |
+
"default": 0
|
393 |
}
|
394 |
],
|
395 |
"definitions": {
|
src/features/admin_access_restriction.php
CHANGED
@@ -10,13 +10,11 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
10 |
|
11 |
const HASH_DELETE = '32f68a60cef40faedbc6af20298c1a1e';
|
12 |
|
13 |
-
private $bHasPermissionToSubmit;
|
14 |
-
|
15 |
/**
|
16 |
* @return bool
|
17 |
*/
|
18 |
protected function isReadyToExecute() {
|
19 |
-
return $this->hasAccessKey() && parent::isReadyToExecute();
|
20 |
}
|
21 |
|
22 |
/**
|
@@ -31,6 +29,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
31 |
case 'sec_admin_check':
|
32 |
$aAjaxResponse = $this->ajaxExec_SecAdminCheck();
|
33 |
break;
|
|
|
34 |
case 'sec_admin_login':
|
35 |
case 'restricted_access':
|
36 |
$aAjaxResponse = $this->ajaxExec_SecAdminLogin();
|
@@ -110,22 +109,6 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
110 |
return $this->renderTemplate( 'snippets/admin_access_login', $aData );
|
111 |
}
|
112 |
|
113 |
-
/**
|
114 |
-
* @param bool $bHasPermission
|
115 |
-
* @return bool
|
116 |
-
*/
|
117 |
-
public function doCheckHasPermissionToSubmit( $bHasPermission = true ) {
|
118 |
-
|
119 |
-
$this->bHasPermissionToSubmit = $bHasPermission;
|
120 |
-
if ( $this->isModuleEnabled() ) {
|
121 |
-
$sAccessKey = $this->getAccessKeyHash();
|
122 |
-
if ( !empty( $sAccessKey ) ) {
|
123 |
-
$this->bHasPermissionToSubmit = $this->isSecAdminSessionValid() || $this->checkAdminAccessKeySubmission();
|
124 |
-
}
|
125 |
-
}
|
126 |
-
return $this->bHasPermissionToSubmit;
|
127 |
-
}
|
128 |
-
|
129 |
/**
|
130 |
* @return string
|
131 |
*/
|
@@ -178,6 +161,14 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
178 |
return is_array( $aOptions ) ? $aOptions : array();
|
179 |
}
|
180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
/**
|
182 |
* TODO: Bug where if $sType is defined, it'll be set to 'wp' anyway
|
183 |
* @param string $sType - wp or wpms
|
@@ -207,6 +198,23 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
207 |
return !empty( $sKey ) && strlen( $sKey ) == 32;
|
208 |
}
|
209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
/**
|
211 |
* @return bool
|
212 |
*/
|
@@ -236,11 +244,50 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
236 |
}
|
237 |
}
|
238 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
}
|
240 |
|
241 |
protected function setSaveUserResponse() {
|
242 |
if ( $this->isAccessKeyRequest() ) {
|
243 |
-
$bSuccess = $this->
|
244 |
|
245 |
if ( $bSuccess ) {
|
246 |
$sMessage = _wpsf__( 'Security Admin key accepted.' );
|
@@ -268,8 +315,15 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
268 |
*/
|
269 |
public function getSecAdminTimeLeft() {
|
270 |
$nLeft = 0;
|
271 |
-
if ( $this->
|
272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
}
|
274 |
return max( 0, $nLeft );
|
275 |
}
|
@@ -295,7 +349,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
295 |
/**
|
296 |
* @return bool
|
297 |
*/
|
298 |
-
|
299 |
$sAccessKeyRequest = $this->loadRequest()->post( 'admin_access_key_request', '' );
|
300 |
$bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
|
301 |
if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
|
@@ -389,12 +443,12 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
389 |
* @throws Exception
|
390 |
*/
|
391 |
public function setNewAccessKeyManually( $sKey ) {
|
392 |
-
if ( !$this->doCheckHasPermissionToSubmit() ) {
|
393 |
-
throw new Exception( 'User does not have permission to update the Security Admin Access Key.' );
|
394 |
-
}
|
395 |
if ( empty( $sKey ) ) {
|
396 |
throw new Exception( 'Attempting to set an empty Security Admin Access Key.' );
|
397 |
}
|
|
|
|
|
|
|
398 |
|
399 |
$this->setIsMainFeatureEnabled( true )
|
400 |
->setOpt( 'admin_access_key', md5( $sKey ) )
|
@@ -421,7 +475,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
421 |
);
|
422 |
|
423 |
{//sec admin
|
424 |
-
if ( !( $this->isModuleEnabled() && $this->hasAccessKey() ) ) {
|
425 |
$aNotices[ 'messages' ][ 'sec_admin' ] = array(
|
426 |
'title' => 'Security Plugin Unprotected',
|
427 |
'message' => sprintf(
|
@@ -445,7 +499,8 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
445 |
* @return bool
|
446 |
*/
|
447 |
protected function isEnabledForUiSummary() {
|
448 |
-
return parent::isEnabledForUiSummary() &&
|
|
|
449 |
}
|
450 |
|
451 |
/**
|
@@ -538,6 +593,14 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
538 |
.( $this->hasAccessKey() ? '<br/>'.sprintf( _wpsf__( 'To delete the current security key, type exactly "%s" and save.' ), '<strong>DELETE</strong>' ) : '' );
|
539 |
break;
|
540 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
case 'admin_access_timeout' :
|
542 |
$sName = _wpsf__( 'Security Admin Timeout' );
|
543 |
$sSummary = _wpsf__( 'Specify An Automatic Timeout Interval For Security Admin Access' );
|
@@ -702,4 +765,12 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
|
|
702 |
);
|
703 |
}
|
704 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
705 |
}
|
10 |
|
11 |
const HASH_DELETE = '32f68a60cef40faedbc6af20298c1a1e';
|
12 |
|
|
|
|
|
13 |
/**
|
14 |
* @return bool
|
15 |
*/
|
16 |
protected function isReadyToExecute() {
|
17 |
+
return ( $this->hasAccessKey() || $this->hasSecAdminUsers() ) && parent::isReadyToExecute();
|
18 |
}
|
19 |
|
20 |
/**
|
29 |
case 'sec_admin_check':
|
30 |
$aAjaxResponse = $this->ajaxExec_SecAdminCheck();
|
31 |
break;
|
32 |
+
|
33 |
case 'sec_admin_login':
|
34 |
case 'restricted_access':
|
35 |
$aAjaxResponse = $this->ajaxExec_SecAdminLogin();
|
109 |
return $this->renderTemplate( 'snippets/admin_access_login', $aData );
|
110 |
}
|
111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
/**
|
113 |
* @return string
|
114 |
*/
|
161 |
return is_array( $aOptions ) ? $aOptions : array();
|
162 |
}
|
163 |
|
164 |
+
/**
|
165 |
+
* @return array
|
166 |
+
*/
|
167 |
+
public function getSecurityAdminUsers() {
|
168 |
+
$aU = $this->getOpt( 'sec_admin_users', array() );
|
169 |
+
return ( is_array( $aU ) && $this->isPremium() ) ? $aU : array();
|
170 |
+
}
|
171 |
+
|
172 |
/**
|
173 |
* TODO: Bug where if $sType is defined, it'll be set to 'wp' anyway
|
174 |
* @param string $sType - wp or wpms
|
198 |
return !empty( $sKey ) && strlen( $sKey ) == 32;
|
199 |
}
|
200 |
|
201 |
+
/**
|
202 |
+
* @return bool
|
203 |
+
*/
|
204 |
+
public function hasSecAdminUsers() {
|
205 |
+
$aUsers = $this->getSecurityAdminUsers();
|
206 |
+
return !empty( $aUsers );
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* No checking of admin capabilities in-case of infinite loop with admin access caps check
|
211 |
+
* @return bool
|
212 |
+
*/
|
213 |
+
public function isRegisteredSecAdminUser() {
|
214 |
+
$sUser = $this->loadWpUsers()->getCurrentWpUsername();
|
215 |
+
return !empty( $sUser ) && in_array( $sUser, $this->getSecurityAdminUsers() );
|
216 |
+
}
|
217 |
+
|
218 |
/**
|
219 |
* @return bool
|
220 |
*/
|
244 |
}
|
245 |
}
|
246 |
}
|
247 |
+
|
248 |
+
$this->setOpt( 'sec_admin_users', $this->verifySecAdminUsers( $this->getSecurityAdminUsers() ) );
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Ensures that all entries are valid users.
|
253 |
+
* @param string[] $aSecUsers
|
254 |
+
* @return string[]
|
255 |
+
*/
|
256 |
+
private function verifySecAdminUsers( $aSecUsers ) {
|
257 |
+
$oDP = $this->loadDP();
|
258 |
+
$oWpUsers = $this->loadWpUsers();
|
259 |
+
|
260 |
+
$aFiltered = array();
|
261 |
+
foreach ( $aSecUsers as $nCurrentKey => $sUsernameOrEmail ) {
|
262 |
+
if ( $oDP->validEmail( $sUsernameOrEmail ) ) {
|
263 |
+
$oUser = $oWpUsers->getUserByEmail( $sUsernameOrEmail );
|
264 |
+
}
|
265 |
+
else {
|
266 |
+
$oUser = $oWpUsers->getUserByUsername( $sUsernameOrEmail );
|
267 |
+
if ( is_null( $oUser ) && is_numeric( $sUsernameOrEmail ) ) {
|
268 |
+
$oUser = $oWpUsers->getUserById( $sUsernameOrEmail );
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
if ( $oUser instanceof WP_User && $oUser->ID > 0 && $oWpUsers->isUserAdmin( $oUser ) ) {
|
273 |
+
$aFiltered[] = $oUser->user_login;
|
274 |
+
}
|
275 |
+
}
|
276 |
+
|
277 |
+
// We now run a bit of a sanity check to ensure that the current user is
|
278 |
+
// not adding users here that aren't themselves without a key to still gain access
|
279 |
+
$oCurrent = $oWpUsers->getCurrentWpUser();
|
280 |
+
if ( !empty( $aFiltered ) && !$this->hasAccessKey() && !in_array( $oCurrent->user_login, $aFiltered ) ) {
|
281 |
+
$aFiltered[] = $oCurrent->user_login;
|
282 |
+
}
|
283 |
+
|
284 |
+
natsort( $aFiltered );
|
285 |
+
return array_unique( $aFiltered );
|
286 |
}
|
287 |
|
288 |
protected function setSaveUserResponse() {
|
289 |
if ( $this->isAccessKeyRequest() ) {
|
290 |
+
$bSuccess = $this->checkAdminAccessKeySubmission();
|
291 |
|
292 |
if ( $bSuccess ) {
|
293 |
$sMessage = _wpsf__( 'Security Admin key accepted.' );
|
315 |
*/
|
316 |
public function getSecAdminTimeLeft() {
|
317 |
$nLeft = 0;
|
318 |
+
if ( $this->hasSession() ) {
|
319 |
+
|
320 |
+
$nSecAdminAt = $this->getSession()->getSecAdminAt();
|
321 |
+
if ( $this->isRegisteredSecAdminUser() ) {
|
322 |
+
$nLeft = 0;
|
323 |
+
}
|
324 |
+
else if ( $nSecAdminAt > 0 ) {
|
325 |
+
$nLeft = $this->getSecAdminTimeout() - ( $this->loadRequest()->ts() - $nSecAdminAt );
|
326 |
+
}
|
327 |
}
|
328 |
return max( 0, $nLeft );
|
329 |
}
|
349 |
/**
|
350 |
* @return bool
|
351 |
*/
|
352 |
+
public function checkAdminAccessKeySubmission() {
|
353 |
$sAccessKeyRequest = $this->loadRequest()->post( 'admin_access_key_request', '' );
|
354 |
$bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
|
355 |
if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
|
443 |
* @throws Exception
|
444 |
*/
|
445 |
public function setNewAccessKeyManually( $sKey ) {
|
|
|
|
|
|
|
446 |
if ( empty( $sKey ) ) {
|
447 |
throw new Exception( 'Attempting to set an empty Security Admin Access Key.' );
|
448 |
}
|
449 |
+
if ( !$this->getConn()->isPluginAdmin() ) {
|
450 |
+
throw new Exception( 'User does not have permission to update the Security Admin Access Key.' );
|
451 |
+
}
|
452 |
|
453 |
$this->setIsMainFeatureEnabled( true )
|
454 |
->setOpt( 'admin_access_key', md5( $sKey ) )
|
475 |
);
|
476 |
|
477 |
{//sec admin
|
478 |
+
if ( !( $this->isModuleEnabled() && ( $this->hasAccessKey() || $this->hasSecAdminUsers() ) ) ) {
|
479 |
$aNotices[ 'messages' ][ 'sec_admin' ] = array(
|
480 |
'title' => 'Security Plugin Unprotected',
|
481 |
'message' => sprintf(
|
499 |
* @return bool
|
500 |
*/
|
501 |
protected function isEnabledForUiSummary() {
|
502 |
+
return parent::isEnabledForUiSummary() && ( $this->getSecAdminTimeout() > 0 )
|
503 |
+
&& ( $this->hasAccessKey() || $this->hasSecAdminUsers() );
|
504 |
}
|
505 |
|
506 |
/**
|
593 |
.( $this->hasAccessKey() ? '<br/>'.sprintf( _wpsf__( 'To delete the current security key, type exactly "%s" and save.' ), '<strong>DELETE</strong>' ) : '' );
|
594 |
break;
|
595 |
|
596 |
+
case 'sec_admin_users' :
|
597 |
+
$sName = _wpsf__( 'Security Admins' );
|
598 |
+
$sSummary = _wpsf__( 'Persistent Security Admins' );
|
599 |
+
$sDescription = _wpsf__( "Users provided will be security admins automatically, without needing the security key." )
|
600 |
+
.'<br/>'._wpsf__( 'Enter admin username, email or ID.' ).' '._wpsf__( '1 entry per-line.' )
|
601 |
+
.'<br/>'.sprintf( '%s: %s', _wpsf__( 'Note' ), _wpsf__( 'Verified users will be converted to usernames.' ) );
|
602 |
+
break;
|
603 |
+
|
604 |
case 'admin_access_timeout' :
|
605 |
$sName = _wpsf__( 'Security Admin Timeout' );
|
606 |
$sSummary = _wpsf__( 'Specify An Automatic Timeout Interval For Security Admin Access' );
|
765 |
);
|
766 |
}
|
767 |
}
|
768 |
+
|
769 |
+
/**
|
770 |
+
* @deprecated v6.10.7
|
771 |
+
* @return bool
|
772 |
+
*/
|
773 |
+
public function doCheckHasPermissionToSubmit() {
|
774 |
+
return $this->getConn()->isPluginAdmin();
|
775 |
+
}
|
776 |
}
|
src/features/audit_trail.php
CHANGED
@@ -331,8 +331,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
|
|
331 |
* @throws Exception
|
332 |
*/
|
333 |
protected function loadStrings_Options( $aOptionsParams ) {
|
334 |
-
|
335 |
-
$oCon = self::getConn();
|
336 |
|
337 |
$sKey = $aOptionsParams[ 'key' ];
|
338 |
switch ( $sKey ) {
|
331 |
* @throws Exception
|
332 |
*/
|
333 |
protected function loadStrings_Options( $aOptionsParams ) {
|
334 |
+
$oCon = $this->getConn();
|
|
|
335 |
|
336 |
$sKey = $aOptionsParams[ 'key' ];
|
337 |
switch ( $sKey ) {
|
src/features/autoupdates.php
CHANGED
@@ -112,9 +112,7 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
|
|
112 |
switch ( $this->loadRequest()->request( 'exec' ) ) {
|
113 |
|
114 |
case 'toggle_plugin_autoupdate':
|
115 |
-
|
116 |
-
$aAjaxResponse = $this->ajaxExec_TogglePluginAutoupdate();
|
117 |
-
}
|
118 |
break;
|
119 |
|
120 |
default:
|
@@ -128,24 +126,26 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
|
|
128 |
* @return array
|
129 |
*/
|
130 |
public function ajaxExec_TogglePluginAutoupdate() {
|
131 |
-
|
132 |
$bSuccess = false;
|
133 |
-
|
134 |
-
|
135 |
-
$
|
136 |
-
|
137 |
-
$this->
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
$aPlugin
|
142 |
-
$
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
|
|
|
|
|
|
149 |
}
|
150 |
|
151 |
return array(
|
@@ -180,6 +180,7 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
|
|
180 |
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
181 |
|
182 |
$sSectionSlug = $aOptionsParams[ 'slug' ];
|
|
|
183 |
switch ( $sSectionSlug ) {
|
184 |
|
185 |
case 'section_enable_plugin_feature_automatic_updates_control' :
|
@@ -203,8 +204,10 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
|
|
203 |
case 'section_automatic_plugin_self_update' :
|
204 |
$sTitle = _wpsf__( 'Automatic Plugin Self-Update' );
|
205 |
$aSummary = array(
|
206 |
-
sprintf( '%s - %s',
|
207 |
-
|
|
|
|
|
208 |
sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'Keep this option turned on.' ) )
|
209 |
);
|
210 |
$sTitleShort = _wpsf__( 'Self-Update' );
|
@@ -262,8 +265,10 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
|
|
262 |
case 'autoupdate_plugin_self' :
|
263 |
$sName = _wpsf__( 'Auto Update Plugin' );
|
264 |
$sSummary = _wpsf__( 'Always Automatically Update This Plugin' );
|
265 |
-
$sDescription = sprintf(
|
266 |
-
|
|
|
|
|
267 |
break;
|
268 |
|
269 |
case 'autoupdate_core' :
|
112 |
switch ( $this->loadRequest()->request( 'exec' ) ) {
|
113 |
|
114 |
case 'toggle_plugin_autoupdate':
|
115 |
+
$aAjaxResponse = $this->ajaxExec_TogglePluginAutoupdate();
|
|
|
|
|
116 |
break;
|
117 |
|
118 |
default:
|
126 |
* @return array
|
127 |
*/
|
128 |
public function ajaxExec_TogglePluginAutoupdate() {
|
|
|
129 |
$bSuccess = false;
|
130 |
+
$sMessage = _wpsf__( 'You do not have permissions to perform this action.' );
|
131 |
+
|
132 |
+
if ( $this->isAutoupdateIndividualPlugins() && $this->getConn()->isPluginAdmin() ) {
|
133 |
+
$oWpPlugins = $this->loadWpPlugins();
|
134 |
+
$sFile = $this->loadRequest()->post( 'pluginfile' );
|
135 |
+
if ( $oWpPlugins->isInstalled( $sFile ) ) {
|
136 |
+
$this->setPluginToAutoUpdate( $sFile );
|
137 |
+
|
138 |
+
$aPlugin = $oWpPlugins->getPlugin( $sFile );
|
139 |
+
$sMessage = sprintf( _wpsf__( 'Plugin "%s" will %s.' ),
|
140 |
+
$aPlugin[ 'Name' ],
|
141 |
+
$this->loadWp()
|
142 |
+
->getIsPluginAutomaticallyUpdated( $sFile ) ? _wpsf__( 'update automatically' ) : _wpsf__( 'not update automatically' )
|
143 |
+
);
|
144 |
+
$bSuccess = true;
|
145 |
+
}
|
146 |
+
else {
|
147 |
+
$sMessage = _wpsf__( 'Failed to change the update status of the plugin.' );
|
148 |
+
}
|
149 |
}
|
150 |
|
151 |
return array(
|
180 |
protected function loadStrings_SectionTitles( $aOptionsParams ) {
|
181 |
|
182 |
$sSectionSlug = $aOptionsParams[ 'slug' ];
|
183 |
+
$sPlugName = $this->getConn()->getHumanName();
|
184 |
switch ( $sSectionSlug ) {
|
185 |
|
186 |
case 'section_enable_plugin_feature_automatic_updates_control' :
|
204 |
case 'section_automatic_plugin_self_update' :
|
205 |
$sTitle = _wpsf__( 'Automatic Plugin Self-Update' );
|
206 |
$aSummary = array(
|
207 |
+
sprintf( '%s - %s',
|
208 |
+
_wpsf__( 'Purpose' ),
|
209 |
+
sprintf( _wpsf__( 'Allows the %s plugin to automatically update itself when an update is available.' ), $sPlugName )
|
210 |
+
),
|
211 |
sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'Keep this option turned on.' ) )
|
212 |
);
|
213 |
$sTitleShort = _wpsf__( 'Self-Update' );
|
265 |
case 'autoupdate_plugin_self' :
|
266 |
$sName = _wpsf__( 'Auto Update Plugin' );
|
267 |
$sSummary = _wpsf__( 'Always Automatically Update This Plugin' );
|
268 |
+
$sDescription = sprintf(
|
269 |
+
_wpsf__( 'Regardless of any other settings, automatically update the "%s" plugin.' ),
|
270 |
+
$sPlugName
|
271 |
+
);
|
272 |
break;
|
273 |
|
274 |
case 'autoupdate_core' :
|
src/features/base.php
CHANGED
@@ -274,7 +274,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
274 |
if ( $this->getOptionsVo()->getFeatureProperty( 'auto_load_processor' ) ) {
|
275 |
$this->loadProcessor();
|
276 |
}
|
277 |
-
if ( $this->isModuleEnabled() && $this->isReadyToExecute() ) {
|
278 |
$this->doExecuteProcessor();
|
279 |
}
|
280 |
}
|
@@ -297,7 +297,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
297 |
protected function importOptions() {
|
298 |
// So we don't poll for the file every page load.
|
299 |
if ( $this->loadRequest()->query( 'icwp_shield_import' ) == 1 ) {
|
300 |
-
$aOptions =
|
301 |
if ( !empty( $aOptions ) && is_array( $aOptions ) && array_key_exists( $this->getOptionsStorageKey(), $aOptions ) ) {
|
302 |
$this->getOptionsVo()->setMultipleOptions( $aOptions[ $this->getOptionsStorageKey() ] );
|
303 |
$this
|
@@ -356,8 +356,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
356 |
*/
|
357 |
protected function loadProcessor() {
|
358 |
if ( !isset( $this->oProcessor ) ) {
|
359 |
-
include_once(
|
360 |
-
|
361 |
$sClassName = $this->getProcessorClassName();
|
362 |
if ( !class_exists( $sClassName, false ) ) {
|
363 |
return null;
|
@@ -372,7 +372,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
372 |
* @return string
|
373 |
*/
|
374 |
protected function getProcessorClassName() {
|
375 |
-
return ucwords(
|
376 |
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getSlug() ) ) );
|
377 |
}
|
378 |
|
@@ -381,7 +381,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
381 |
* @return string
|
382 |
*/
|
383 |
protected function getWizardClassName() {
|
384 |
-
return ucwords(
|
385 |
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getSlug() ) ) );
|
386 |
}
|
387 |
|
@@ -390,7 +390,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
390 |
*/
|
391 |
protected function getOptionsVo() {
|
392 |
if ( !isset( $this->oOptions ) ) {
|
393 |
-
$oCon =
|
394 |
$this->oOptions = ICWP_WPSF_Factory::OptionsVo();
|
395 |
$this->oOptions
|
396 |
->setPathToConfig( $oCon->getPath_ConfigFile( $this->getSlug() ) )
|
@@ -414,8 +414,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
414 |
* @return bool
|
415 |
*/
|
416 |
public function isUpgrading() {
|
417 |
-
// return $this->getVersion() !=
|
418 |
-
return
|
419 |
}
|
420 |
|
421 |
/**
|
@@ -460,7 +460,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
460 |
return $this->loadWp()
|
461 |
->getUrl_AdminPage(
|
462 |
$this->getModSlug(),
|
463 |
-
|
464 |
);
|
465 |
}
|
466 |
|
@@ -470,7 +470,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
470 |
*/
|
471 |
public function getEmailHandler() {
|
472 |
if ( is_null( self::$oEmailHandler ) ) {
|
473 |
-
self::$oEmailHandler =
|
474 |
}
|
475 |
return self::$oEmailHandler;
|
476 |
}
|
@@ -505,7 +505,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
505 |
else if ( apply_filters( $this->prefix( 'globally_disabled' ), false ) ) {
|
506 |
$bEnabled = false;
|
507 |
}
|
508 |
-
else if (
|
509 |
$bEnabled = false;
|
510 |
}
|
511 |
else if ( $oOpts->getFeatureProperty( 'premium' ) === true && !$this->isPremium() ) {
|
@@ -550,23 +550,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
550 |
return $this->sModSlug;
|
551 |
}
|
552 |
|
553 |
-
/**
|
554 |
-
* @return int
|
555 |
-
*/
|
556 |
-
public function getPluginInstallationTime() {
|
557 |
-
return $this->getOpt( 'installation_time', 0 );
|
558 |
-
}
|
559 |
-
|
560 |
-
/**
|
561 |
-
* With trailing slash
|
562 |
-
* @param string $sSourceFile
|
563 |
-
* @return string
|
564 |
-
*/
|
565 |
-
public function getResourcesDir( $sSourceFile = '' ) {
|
566 |
-
return self::getConn()
|
567 |
-
->getRootDir().'resources/'.ltrim( $sSourceFile, '/' );
|
568 |
-
}
|
569 |
-
|
570 |
/**
|
571 |
* @param array $aItems
|
572 |
* @return array
|
@@ -578,7 +561,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
578 |
}
|
579 |
if ( !empty( $sMenuTitleName ) ) {
|
580 |
|
581 |
-
$sHumanName =
|
582 |
|
583 |
$bMenuHighlighted = $this->getOptionsVo()->getFeatureProperty( 'highlight_menu_item' );
|
584 |
if ( $bMenuHighlighted ) {
|
@@ -887,7 +870,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
887 |
*/
|
888 |
protected function getWizardHandler() {
|
889 |
if ( !isset( $this->oWizard ) ) {
|
890 |
-
include_once(
|
891 |
$sClassName = $this->getWizardClassName();
|
892 |
if ( !class_exists( $sClassName, false ) ) {
|
893 |
return null;
|
@@ -916,9 +899,9 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
916 |
}
|
917 |
|
918 |
private function store() {
|
919 |
-
add_filter( $this->prefix( '
|
920 |
-
$this->getOptionsVo()->doOptionsSave(
|
921 |
-
remove_filter( $this->prefix( '
|
922 |
}
|
923 |
|
924 |
/**
|
@@ -937,7 +920,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
937 |
*/
|
938 |
public function buildOptions() {
|
939 |
|
940 |
-
$bPremiumEnabled =
|
941 |
|
942 |
$oOptsVo = $this->getOptionsVo();
|
943 |
$aOptions = $oOptsVo->getOptionsForPluginUse();
|
@@ -1087,10 +1070,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1087 |
* Deletes all the options including direct save.
|
1088 |
*/
|
1089 |
public function deletePluginOptions() {
|
1090 |
-
|
1091 |
-
|
1092 |
-
$this->bPluginDeleting = true;
|
1093 |
-
}
|
1094 |
}
|
1095 |
|
1096 |
/**
|
@@ -1115,7 +1096,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1115 |
*/
|
1116 |
protected function ajaxExec_ModOptions() {
|
1117 |
|
1118 |
-
$sName =
|
1119 |
|
1120 |
try {
|
1121 |
$this->saveOptionsSubmit();
|
@@ -1163,7 +1144,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1163 |
* @throws Exception
|
1164 |
*/
|
1165 |
protected function saveOptionsSubmit() {
|
1166 |
-
if (
|
1167 |
throw new Exception( _wpsf__( "You don't currently have permission to save settings." ) );
|
1168 |
}
|
1169 |
$this->doSaveStandardOptions();
|
@@ -1171,13 +1152,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1171 |
}
|
1172 |
|
1173 |
protected function verifyFormSubmit() {
|
1174 |
-
|
1175 |
-
|
1176 |
-
return false;
|
1177 |
-
}
|
1178 |
-
|
1179 |
-
// Now verify this is really a valid submission.
|
1180 |
-
return check_admin_referer( self::getConn()->getPluginPrefix() );
|
1181 |
}
|
1182 |
|
1183 |
/**
|
@@ -1203,7 +1179,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1203 |
*/
|
1204 |
public function setFlashAdminNotice( $sMsg, $bError = false ) {
|
1205 |
$this->loadWpNotices()
|
1206 |
-
->addFlashUserMessage( sprintf( '[%s] %s',
|
1207 |
return $this;
|
1208 |
}
|
1209 |
|
@@ -1385,7 +1361,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1385 |
* @return string
|
1386 |
*/
|
1387 |
public function prefix( $sSuffix = '', $sGlue = '-' ) {
|
1388 |
-
return
|
1389 |
}
|
1390 |
|
1391 |
/**
|
@@ -1393,7 +1369,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1393 |
* @return string
|
1394 |
*/
|
1395 |
public function getOptionStoragePrefix() {
|
1396 |
-
return
|
1397 |
}
|
1398 |
|
1399 |
/**
|
@@ -1437,7 +1413,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1437 |
* @return array
|
1438 |
*/
|
1439 |
protected function getBaseDisplayData( $bRenderEmbeddedContent = false ) {
|
1440 |
-
$oCon =
|
1441 |
self::$sActivelyDisplayedModuleOptions = $this->getSlug();
|
1442 |
|
1443 |
$aData = array(
|
@@ -1693,7 +1669,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1693 |
|
1694 |
// Get the same Base Data as normal display
|
1695 |
try {
|
1696 |
-
return $this->loadRenderer(
|
1697 |
->setTemplate( $sTemplate )
|
1698 |
->setRenderVars( $this->getBaseDisplayData( true ) )
|
1699 |
->render();
|
@@ -1707,8 +1683,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1707 |
* @return bool
|
1708 |
*/
|
1709 |
protected function canDisplayOptionsForm() {
|
1710 |
-
return $this->getOptionsVo()->isAccessRestricted() ?
|
1711 |
-
->getHasPermissionToView() : true;
|
1712 |
}
|
1713 |
|
1714 |
/**
|
@@ -1779,7 +1754,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1779 |
$aData[ 'unique_render_id' ] = substr( md5( mt_rand() ), 0, 5 );
|
1780 |
}
|
1781 |
try {
|
1782 |
-
$oRndr = $this->loadRenderer(
|
1783 |
if ( $bUseTwig ) {
|
1784 |
$oRndr->setTemplateEngineTwig();
|
1785 |
}
|
@@ -1990,7 +1965,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
1990 |
* @return $this
|
1991 |
*/
|
1992 |
protected function setOptAt( $sOpt, $nAt = null ) {
|
1993 |
-
|
|
|
1994 |
}
|
1995 |
|
1996 |
/**
|
@@ -2023,7 +1999,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
|
|
2023 |
* @return string
|
2024 |
*/
|
2025 |
public function getVersion() {
|
2026 |
-
return
|
2027 |
}
|
2028 |
|
2029 |
/**
|
274 |
if ( $this->getOptionsVo()->getFeatureProperty( 'auto_load_processor' ) ) {
|
275 |
$this->loadProcessor();
|
276 |
}
|
277 |
+
if ( !$this->isUpgrading() && $this->isModuleEnabled() && $this->isReadyToExecute() ) {
|
278 |
$this->doExecuteProcessor();
|
279 |
}
|
280 |
}
|
297 |
protected function importOptions() {
|
298 |
// So we don't poll for the file every page load.
|
299 |
if ( $this->loadRequest()->query( 'icwp_shield_import' ) == 1 ) {
|
300 |
+
$aOptions = $this->getConn()->getOptionsImportFromFile();
|
301 |
if ( !empty( $aOptions ) && is_array( $aOptions ) && array_key_exists( $this->getOptionsStorageKey(), $aOptions ) ) {
|
302 |
$this->getOptionsVo()->setMultipleOptions( $aOptions[ $this->getOptionsStorageKey() ] );
|
303 |
$this
|
356 |
*/
|
357 |
protected function loadProcessor() {
|
358 |
if ( !isset( $this->oProcessor ) ) {
|
359 |
+
include_once( $this->getConn()
|
360 |
+
->getPath_SourceFile( sprintf( 'processors/%s.php', $this->getSlug() ) ) );
|
361 |
$sClassName = $this->getProcessorClassName();
|
362 |
if ( !class_exists( $sClassName, false ) ) {
|
363 |
return null;
|
372 |
* @return string
|
373 |
*/
|
374 |
protected function getProcessorClassName() {
|
375 |
+
return ucwords( $this->getConn()->getOptionStoragePrefix() ).'Processor_'.
|
376 |
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getSlug() ) ) );
|
377 |
}
|
378 |
|
381 |
* @return string
|
382 |
*/
|
383 |
protected function getWizardClassName() {
|
384 |
+
return ucwords( $this->getConn()->getOptionStoragePrefix() ).'Wizard_'.
|
385 |
str_replace( ' ', '', ucwords( str_replace( '_', ' ', $this->getSlug() ) ) );
|
386 |
}
|
387 |
|
390 |
*/
|
391 |
protected function getOptionsVo() {
|
392 |
if ( !isset( $this->oOptions ) ) {
|
393 |
+
$oCon = $this->getConn();
|
394 |
$this->oOptions = ICWP_WPSF_Factory::OptionsVo();
|
395 |
$this->oOptions
|
396 |
->setPathToConfig( $oCon->getPath_ConfigFile( $this->getSlug() ) )
|
414 |
* @return bool
|
415 |
*/
|
416 |
public function isUpgrading() {
|
417 |
+
// return $this->getVersion() != $this->getController()->getVersion();
|
418 |
+
return $this->getConn()->getIsRebuildOptionsFromFile() || $this->getOptionsVo()->getRebuildFromFile();
|
419 |
}
|
420 |
|
421 |
/**
|
460 |
return $this->loadWp()
|
461 |
->getUrl_AdminPage(
|
462 |
$this->getModSlug(),
|
463 |
+
$this->getConn()->getIsWpmsNetworkAdminOnly()
|
464 |
);
|
465 |
}
|
466 |
|
470 |
*/
|
471 |
public function getEmailHandler() {
|
472 |
if ( is_null( self::$oEmailHandler ) ) {
|
473 |
+
self::$oEmailHandler = $this->getConn()->loadFeatureHandler( array( 'slug' => 'email' ) );
|
474 |
}
|
475 |
return self::$oEmailHandler;
|
476 |
}
|
505 |
else if ( apply_filters( $this->prefix( 'globally_disabled' ), false ) ) {
|
506 |
$bEnabled = false;
|
507 |
}
|
508 |
+
else if ( $this->getConn()->getIfForceOffActive() ) {
|
509 |
$bEnabled = false;
|
510 |
}
|
511 |
else if ( $oOpts->getFeatureProperty( 'premium' ) === true && !$this->isPremium() ) {
|
550 |
return $this->sModSlug;
|
551 |
}
|
552 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
553 |
/**
|
554 |
* @param array $aItems
|
555 |
* @return array
|
561 |
}
|
562 |
if ( !empty( $sMenuTitleName ) ) {
|
563 |
|
564 |
+
$sHumanName = $this->getConn()->getHumanName();
|
565 |
|
566 |
$bMenuHighlighted = $this->getOptionsVo()->getFeatureProperty( 'highlight_menu_item' );
|
567 |
if ( $bMenuHighlighted ) {
|
870 |
*/
|
871 |
protected function getWizardHandler() {
|
872 |
if ( !isset( $this->oWizard ) ) {
|
873 |
+
include_once( $this->getConn()->getPath_SourceFile( sprintf( 'wizards/%s.php', $this->getSlug() ) ) );
|
874 |
$sClassName = $this->getWizardClassName();
|
875 |
if ( !class_exists( $sClassName, false ) ) {
|
876 |
return null;
|
899 |
}
|
900 |
|
901 |
private function store() {
|
902 |
+
add_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true', 1000 );
|
903 |
+
$bSuccess = $this->getOptionsVo()->doOptionsSave( $this->getConn()->getIsResetPlugin() );
|
904 |
+
remove_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true', 1000 );
|
905 |
}
|
906 |
|
907 |
/**
|
920 |
*/
|
921 |
public function buildOptions() {
|
922 |
|
923 |
+
$bPremiumEnabled = $this->getConn()->isPremiumExtensionsEnabled();
|
924 |
|
925 |
$oOptsVo = $this->getOptionsVo();
|
926 |
$aOptions = $oOptsVo->getOptionsForPluginUse();
|
1070 |
* Deletes all the options including direct save.
|
1071 |
*/
|
1072 |
public function deletePluginOptions() {
|
1073 |
+
$this->getOptionsVo()->doOptionsDelete();
|
1074 |
+
$this->bPluginDeleting = true;
|
|
|
|
|
1075 |
}
|
1076 |
|
1077 |
/**
|
1096 |
*/
|
1097 |
protected function ajaxExec_ModOptions() {
|
1098 |
|
1099 |
+
$sName = $this->getConn()->getHumanName();
|
1100 |
|
1101 |
try {
|
1102 |
$this->saveOptionsSubmit();
|
1144 |
* @throws Exception
|
1145 |
*/
|
1146 |
protected function saveOptionsSubmit() {
|
1147 |
+
if ( !$this->getConn()->isPluginAdmin() ) {
|
1148 |
throw new Exception( _wpsf__( "You don't currently have permission to save settings." ) );
|
1149 |
}
|
1150 |
$this->doSaveStandardOptions();
|
1152 |
}
|
1153 |
|
1154 |
protected function verifyFormSubmit() {
|
1155 |
+
return $this->getConn()->isPluginAdmin()
|
1156 |
+
&& check_admin_referer( $this->getConn()->getPluginPrefix() );
|
|
|
|
|
|
|
|
|
|
|
1157 |
}
|
1158 |
|
1159 |
/**
|
1179 |
*/
|
1180 |
public function setFlashAdminNotice( $sMsg, $bError = false ) {
|
1181 |
$this->loadWpNotices()
|
1182 |
+
->addFlashUserMessage( sprintf( '[%s] %s', $this->getConn()->getHumanName(), $sMsg ), $bError );
|
1183 |
return $this;
|
1184 |
}
|
1185 |
|
1361 |
* @return string
|
1362 |
*/
|
1363 |
public function prefix( $sSuffix = '', $sGlue = '-' ) {
|
1364 |
+
return $this->getConn()->prefix( $sSuffix, $sGlue );
|
1365 |
}
|
1366 |
|
1367 |
/**
|
1369 |
* @return string
|
1370 |
*/
|
1371 |
public function getOptionStoragePrefix() {
|
1372 |
+
return $this->getConn()->getOptionStoragePrefix();
|
1373 |
}
|
1374 |
|
1375 |
/**
|
1413 |
* @return array
|
1414 |
*/
|
1415 |
protected function getBaseDisplayData( $bRenderEmbeddedContent = false ) {
|
1416 |
+
$oCon = $this->getConn();
|
1417 |
self::$sActivelyDisplayedModuleOptions = $this->getSlug();
|
1418 |
|
1419 |
$aData = array(
|
1669 |
|
1670 |
// Get the same Base Data as normal display
|
1671 |
try {
|
1672 |
+
return $this->loadRenderer( $this->getConn()->getPath_Templates() )
|
1673 |
->setTemplate( $sTemplate )
|
1674 |
->setRenderVars( $this->getBaseDisplayData( true ) )
|
1675 |
->render();
|
1683 |
* @return bool
|
1684 |
*/
|
1685 |
protected function canDisplayOptionsForm() {
|
1686 |
+
return $this->getOptionsVo()->isAccessRestricted() ? $this->getConn()->isPluginAdmin() : true;
|
|
|
1687 |
}
|
1688 |
|
1689 |
/**
|
1754 |
$aData[ 'unique_render_id' ] = substr( md5( mt_rand() ), 0, 5 );
|
1755 |
}
|
1756 |
try {
|
1757 |
+
$oRndr = $this->loadRenderer( $this->getConn()->getPath_Templates() );
|
1758 |
if ( $bUseTwig ) {
|
1759 |
$oRndr->setTemplateEngineTwig();
|
1760 |
}
|
1965 |
* @return $this
|
1966 |
*/
|
1967 |
protected function setOptAt( $sOpt, $nAt = null ) {
|
1968 |
+
$nAt = is_null( $nAt ) ? $this->loadRequest()->ts() : max( 0, (int)$nAt );
|
1969 |
+
return $this->setOpt( $sOpt, $nAt );
|
1970 |
}
|
1971 |
|
1972 |
/**
|
1999 |
* @return string
|
2000 |
*/
|
2001 |
public function getVersion() {
|
2002 |
+
return $this->getConn()->getVersion();
|
2003 |
}
|
2004 |
|
2005 |
/**
|
src/features/hack_protect.php
CHANGED
@@ -384,7 +384,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
|
|
384 |
public function isWpvulnPluginsHighlightEnabled() {
|
385 |
$sOpt = $this->getWpvulnPluginsHighlightOption();
|
386 |
return ( $sOpt != 'disabled' ) && $this->loadWpUsers()->isUserAdmin()
|
387 |
-
&& ( ( $sOpt != 'enabled_securityadmin' ) || $this->getConn()->
|
388 |
}
|
389 |
|
390 |
/**
|
384 |
public function isWpvulnPluginsHighlightEnabled() {
|
385 |
$sOpt = $this->getWpvulnPluginsHighlightOption();
|
386 |
return ( $sOpt != 'disabled' ) && $this->loadWpUsers()->isUserAdmin()
|
387 |
+
&& ( ( $sOpt != 'enabled_securityadmin' ) || $this->getConn()->isPluginAdmin() );
|
388 |
}
|
389 |
|
390 |
/**
|
src/features/ips.php
CHANGED
@@ -347,6 +347,8 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
|
|
347 |
* @throws Exception
|
348 |
*/
|
349 |
protected function loadStrings_Options( $aOptionsParams ) {
|
|
|
|
|
350 |
switch ( $aOptionsParams[ 'key' ] ) {
|
351 |
|
352 |
case 'enable_ips' :
|
@@ -358,8 +360,7 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
|
|
358 |
case 'transgression_limit' :
|
359 |
$sName = _wpsf__( 'Transgression Limit' );
|
360 |
$sSummary = _wpsf__( 'Visitor IP address will be Black Listed after X bad actions on your site' );
|
361 |
-
$sDescription = sprintf( _wpsf__( 'A black mark is set against an IP address each time a visitor trips the defenses of the %s plugin.' ),
|
362 |
-
->getHumanName() )
|
363 |
.'<br />'._wpsf__( 'When the number of these transgressions exceeds specified limit, they are automatically blocked from accessing the site.' )
|
364 |
.'<br />'.sprintf( _wpsf__( 'Set this to "0" to turn off the %s feature.' ), _wpsf__( 'Automatic IP Black List' ) );
|
365 |
break;
|
347 |
* @throws Exception
|
348 |
*/
|
349 |
protected function loadStrings_Options( $aOptionsParams ) {
|
350 |
+
|
351 |
+
$sPlugName = $this->getConn()->getHumanName();
|
352 |
switch ( $aOptionsParams[ 'key' ] ) {
|
353 |
|
354 |
case 'enable_ips' :
|
360 |
case 'transgression_limit' :
|
361 |
$sName = _wpsf__( 'Transgression Limit' );
|
362 |
$sSummary = _wpsf__( 'Visitor IP address will be Black Listed after X bad actions on your site' );
|
363 |
+
$sDescription = sprintf( _wpsf__( 'A black mark is set against an IP address each time a visitor trips the defenses of the %s plugin.' ), $sPlugName )
|
|
|
364 |
.'<br />'._wpsf__( 'When the number of these transgressions exceeds specified limit, they are automatically blocked from accessing the site.' )
|
365 |
.'<br />'.sprintf( _wpsf__( 'Set this to "0" to turn off the %s feature.' ), _wpsf__( 'Automatic IP Black List' ) );
|
366 |
break;
|
src/features/license.php
CHANGED
@@ -9,7 +9,10 @@ require_once( dirname( __FILE__ ).'/base_wpsf.php' );
|
|
9 |
class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf {
|
10 |
|
11 |
protected function doPostConstruction() {
|
12 |
-
add_filter( $this->getConn()->getPremiumLicenseFilterName(), array(
|
|
|
|
|
|
|
13 |
}
|
14 |
|
15 |
public function action_doFeatureShutdown() {
|
@@ -266,19 +269,16 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
266 |
* @return $this
|
267 |
*/
|
268 |
public function verifyLicense( $bForceCheck = true ) {
|
269 |
-
|
270 |
-
$
|
271 |
-
|
272 |
-
// If your last license verification has expired and it's been 4hrs since your last check.
|
273 |
-
$bCheck = $bForceCheck
|
274 |
-
|| ( $this->isLicenseActive() && !$oCurrent->isReady() && $this->getIsLicenseNotCheckedFor( HOUR_IN_SECONDS ) )
|
275 |
-
|| ( $this->hasValidWorkingLicense() && $this->isLastVerifiedExpired()
|
276 |
-
&& $this->getIsLicenseNotCheckedFor( HOUR_IN_SECONDS*4 ) );
|
277 |
|
278 |
// 1 check in 20 seconds
|
279 |
-
if ( $
|
|
|
|
|
280 |
|
281 |
-
$this->
|
|
|
282 |
->savePluginOptions();
|
283 |
|
284 |
/** @var ICWP_WPSF_Processor_License $oPro */
|
@@ -293,16 +293,15 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
293 |
$oPro->addToAuditEntry( 'Pro License check succeeded.', 1, 'license_check_success' );
|
294 |
}
|
295 |
else {
|
296 |
-
$oCurrent->setLastRequestAt( $nNow );
|
297 |
if ( $oCurrent->isValid() ) { // we have something valid previously stored
|
298 |
|
299 |
if ( !$bForceCheck && $this->isWithinVerifiedGraceExpired() ) {
|
300 |
$this->sendLicenseWarningEmail();
|
301 |
$oPro->addToAuditEntry( 'License check failed. Sending Warning Email.', 2, 'license_check_failed' );
|
302 |
}
|
303 |
-
else if ( $bForceCheck || $this->isLastVerifiedGraceExpired() ) {
|
304 |
$oCurrent = $oLookupLicense;
|
305 |
-
$this->deactivate(
|
306 |
$this->sendLicenseDeactivatedEmail();
|
307 |
$oPro->addToAuditEntry( 'License check failed. Deactivating Pro.', 3, 'license_check_failed' );
|
308 |
}
|
@@ -316,19 +315,64 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
316 |
}
|
317 |
}
|
318 |
|
|
|
319 |
$this->setLicenseData( $oCurrent )
|
320 |
->savePluginOptions();
|
321 |
-
|
322 |
-
try {
|
323 |
-
}
|
324 |
-
catch ( Exception $oE ) {
|
325 |
-
// $oCurrent->setLastErrors( 'Could not find a valid license' );
|
326 |
-
}
|
327 |
}
|
328 |
|
329 |
return $this;
|
330 |
}
|
331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
/**
|
333 |
* @return $this
|
334 |
*/
|
@@ -347,6 +391,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
347 |
$bCanSend = $nNow - $this->getOpt( 'last_warning_email_sent_at' ) > DAY_IN_SECONDS;
|
348 |
|
349 |
if ( $bCanSend ) {
|
|
|
350 |
$aMessage = array(
|
351 |
_wpsf__( 'Attempts to verify Shield Pro license has just failed.' ),
|
352 |
sprintf( _wpsf__( 'Please check your license on-site: %s' ), $this->getUrl_AdminPage() ),
|
@@ -364,17 +409,22 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
364 |
/**
|
365 |
*/
|
366 |
private function sendLicenseDeactivatedEmail() {
|
367 |
-
$
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
|
|
|
|
|
|
|
|
|
|
378 |
}
|
379 |
|
380 |
/**
|
@@ -541,15 +591,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
541 |
* @return bool
|
542 |
*/
|
543 |
protected function isWithinVerifiedGraceExpired() {
|
544 |
-
return
|
545 |
-
}
|
546 |
-
|
547 |
-
/**
|
548 |
-
* @param string $sEmail
|
549 |
-
* @return string
|
550 |
-
*/
|
551 |
-
protected function setOfficialLicenseRegisteredEmail( $sEmail ) {
|
552 |
-
return $this->setOpt( 'license_registered_email', $sEmail );
|
553 |
}
|
554 |
|
555 |
/**
|
@@ -560,14 +602,6 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
560 |
return $this->setOptAt( 'license_last_checked_at', $nAt );
|
561 |
}
|
562 |
|
563 |
-
/**
|
564 |
-
* @param int $nAt
|
565 |
-
* @return $this
|
566 |
-
*/
|
567 |
-
protected function setLicenseLastRequestedAt( $nAt = null ) {
|
568 |
-
return $this->setOptAt( 'license_last_request_at', $nAt );
|
569 |
-
}
|
570 |
-
|
571 |
/**
|
572 |
* @param string $sKey
|
573 |
* @return string|null
|
@@ -609,8 +643,9 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
609 |
* @return boolean
|
610 |
*/
|
611 |
public function getIfShowModuleMenuItem() {
|
612 |
-
|
613 |
-
|
|
|
614 |
}
|
615 |
|
616 |
/**
|
9 |
class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf {
|
10 |
|
11 |
protected function doPostConstruction() {
|
12 |
+
add_filter( $this->getConn()->getPremiumLicenseFilterName(), array(
|
13 |
+
$this,
|
14 |
+
'hasValidWorkingLicense'
|
15 |
+
), PHP_INT_MAX );
|
16 |
}
|
17 |
|
18 |
public function action_doFeatureShutdown() {
|
269 |
* @return $this
|
270 |
*/
|
271 |
public function verifyLicense( $bForceCheck = true ) {
|
272 |
+
// Is a check actually required and permitted
|
273 |
+
$bCheckReq = $this->isLicenseCheckRequired() && $this->canLicenseCheck();
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
|
275 |
// 1 check in 20 seconds
|
276 |
+
if ( ( $bForceCheck || $bCheckReq ) && $this->getIsLicenseNotCheckedFor( 20 ) ) {
|
277 |
+
|
278 |
+
$oCurrent = $this->loadLicense();
|
279 |
|
280 |
+
$this->touchLicenseCheckFileFlag()
|
281 |
+
->setLicenseLastCheckedAt()
|
282 |
->savePluginOptions();
|
283 |
|
284 |
/** @var ICWP_WPSF_Processor_License $oPro */
|
293 |
$oPro->addToAuditEntry( 'Pro License check succeeded.', 1, 'license_check_success' );
|
294 |
}
|
295 |
else {
|
|
|
296 |
if ( $oCurrent->isValid() ) { // we have something valid previously stored
|
297 |
|
298 |
if ( !$bForceCheck && $this->isWithinVerifiedGraceExpired() ) {
|
299 |
$this->sendLicenseWarningEmail();
|
300 |
$oPro->addToAuditEntry( 'License check failed. Sending Warning Email.', 2, 'license_check_failed' );
|
301 |
}
|
302 |
+
else if ( $bForceCheck || $oCurrent->isExpired() || $this->isLastVerifiedGraceExpired() ) {
|
303 |
$oCurrent = $oLookupLicense;
|
304 |
+
$this->deactivate( _wpsf__( 'Automatic license verification failed.' ) );
|
305 |
$this->sendLicenseDeactivatedEmail();
|
306 |
$oPro->addToAuditEntry( 'License check failed. Deactivating Pro.', 3, 'license_check_failed' );
|
307 |
}
|
315 |
}
|
316 |
}
|
317 |
|
318 |
+
$oCurrent->setLastRequestAt( $this->loadRequest()->ts() );
|
319 |
$this->setLicenseData( $oCurrent )
|
320 |
->savePluginOptions();
|
|
|
|
|
|
|
|
|
|
|
|
|
321 |
}
|
322 |
|
323 |
return $this;
|
324 |
}
|
325 |
|
326 |
+
/**
|
327 |
+
* @return bool
|
328 |
+
*/
|
329 |
+
private function isLicenseCheckRequired() {
|
330 |
+
return ( $this->isLicenseMaybeExpiring() && $this->getIsLicenseNotCheckedFor( HOUR_IN_SECONDS*4 ) )
|
331 |
+
|| ( $this->isLicenseActive()
|
332 |
+
&& !$this->loadLicense()->isReady() && $this->getIsLicenseNotCheckedFor( HOUR_IN_SECONDS ) )
|
333 |
+
|| ( $this->hasValidWorkingLicense() && $this->isLastVerifiedExpired()
|
334 |
+
&& $this->getIsLicenseNotCheckedFor( HOUR_IN_SECONDS*4 ) );
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* @return bool
|
339 |
+
*/
|
340 |
+
private function canLicenseCheck() {
|
341 |
+
$sShieldAction = $this->loadRequest()->query( 'shield_action' );
|
342 |
+
return !in_array( $sShieldAction, array( 'keyless_handshake', 'license_check' ) )
|
343 |
+
&& $this->canLicenseCheck_FileFlag();
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* @return bool
|
348 |
+
*/
|
349 |
+
private function canLicenseCheck_FileFlag() {
|
350 |
+
$oFs = $this->loadFS();
|
351 |
+
$sFileFlag = $this->getConn()->getPath_Flags( 'license_check' );
|
352 |
+
$nMtime = $oFs->exists( $sFileFlag ) ? $oFs->getModifiedTime( $sFileFlag ) : 0;
|
353 |
+
return ( $this->loadRequest()->ts() - $nMtime ) > MINUTE_IN_SECONDS;
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* @return $this
|
358 |
+
*/
|
359 |
+
private function touchLicenseCheckFileFlag() {
|
360 |
+
$this->loadFS()->touch( $this->getConn()->getPath_Flags( 'license_check' ) );
|
361 |
+
return $this;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* @return bool
|
366 |
+
*/
|
367 |
+
protected function isLicenseMaybeExpiring() {
|
368 |
+
$bNearly = $this->isLicenseActive() &&
|
369 |
+
(
|
370 |
+
abs( $this->loadRequest()->ts() - $this->loadLicense()->getExpiresAt() )
|
371 |
+
< ( DAY_IN_SECONDS/2 )
|
372 |
+
);
|
373 |
+
return $bNearly;
|
374 |
+
}
|
375 |
+
|
376 |
/**
|
377 |
* @return $this
|
378 |
*/
|
391 |
$bCanSend = $nNow - $this->getOpt( 'last_warning_email_sent_at' ) > DAY_IN_SECONDS;
|
392 |
|
393 |
if ( $bCanSend ) {
|
394 |
+
$this->setOptAt( 'last_warning_email_sent_at' )->savePluginOptions();
|
395 |
$aMessage = array(
|
396 |
_wpsf__( 'Attempts to verify Shield Pro license has just failed.' ),
|
397 |
sprintf( _wpsf__( 'Please check your license on-site: %s' ), $this->getUrl_AdminPage() ),
|
409 |
/**
|
410 |
*/
|
411 |
private function sendLicenseDeactivatedEmail() {
|
412 |
+
$nNow = $this->loadRequest()->ts();
|
413 |
+
|
414 |
+
if ( ( $nNow - $this->getOpt( 'last_deactivated_email_sent_at' ) ) > DAY_IN_SECONDS ) {
|
415 |
+
$this->setOptAt( 'last_deactivated_email_sent_at' )->savePluginOptions();
|
416 |
+
$aMessage = array(
|
417 |
+
_wpsf__( 'All attempts to verify Shield Pro license have failed.' ),
|
418 |
+
sprintf( _wpsf__( 'Please check your license on-site: %s' ), $this->getUrl_AdminPage() ),
|
419 |
+
sprintf( _wpsf__( 'If this problem persists, please contact support: %s' ), 'https://support.onedollarplugin.com/' )
|
420 |
+
);
|
421 |
+
$this->getEmailProcessor()
|
422 |
+
->sendEmailWithWrap(
|
423 |
+
$this->getPluginDefaultRecipientAddress(),
|
424 |
+
'[Action May Be Required] Pro License Has Been Deactivated',
|
425 |
+
$aMessage
|
426 |
+
);
|
427 |
+
}
|
428 |
}
|
429 |
|
430 |
/**
|
591 |
* @return bool
|
592 |
*/
|
593 |
protected function isWithinVerifiedGraceExpired() {
|
594 |
+
return $this->isLastVerifiedExpired() && !$this->isLastVerifiedGraceExpired();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
595 |
}
|
596 |
|
597 |
/**
|
602 |
return $this->setOptAt( 'license_last_checked_at', $nAt );
|
603 |
}
|
604 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
/**
|
606 |
* @param string $sKey
|
607 |
* @return string|null
|
643 |
* @return boolean
|
644 |
*/
|
645 |
public function getIfShowModuleMenuItem() {
|
646 |
+
$oCon = $this->getConn();
|
647 |
+
return parent::getIfShowModuleMenuItem() && $oCon->isPremiumExtensionsEnabled()
|
648 |
+
&& $oCon->isPluginAdmin();
|
649 |
}
|
650 |
|
651 |
/**
|
src/features/login_protect.php
CHANGED
@@ -57,9 +57,9 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
57 |
$this->getOptionsVo()->resetOptToDefault( 'login_limit_interval' );
|
58 |
}
|
59 |
|
60 |
-
$aIds = $this->
|
61 |
foreach ( $aIds as $nKey => $sId ) {
|
62 |
-
$sId =
|
63 |
if ( empty( $sId ) ) {
|
64 |
unset( $aIds[ $nKey ] );
|
65 |
}
|
@@ -160,7 +160,10 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
160 |
$aRoles = $this->getOptEmailTwoFactorRolesDefaults();
|
161 |
$this->setOpt( 'two_factor_auth_user_roles', $aRoles );
|
162 |
}
|
163 |
-
|
|
|
|
|
|
|
164 |
}
|
165 |
|
166 |
/**
|
@@ -256,9 +259,21 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
256 |
}
|
257 |
else if ( $this->getIfSupport3rdParty() && class_exists( 'WC_Social_Login' ) ) {
|
258 |
// custom support for WooCommerce Social login
|
259 |
-
$oMeta = $this->
|
260 |
$bCanSkip = isset( $oMeta->wc_social_login_valid ) ? $oMeta->wc_social_login_valid : false;
|
261 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
return $bCanSkip;
|
263 |
}
|
264 |
|
@@ -279,7 +294,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
279 |
* @return array
|
280 |
*/
|
281 |
public function getMfaLoginHashes( $oUser ) {
|
282 |
-
$oMeta = $this->
|
283 |
$aHashes = $oMeta->hash_loginmfa;
|
284 |
if ( !is_array( $aHashes ) ) {
|
285 |
$aHashes = array();
|
@@ -499,7 +514,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
499 |
$aWarnings[] =
|
500 |
_wpsf__( '2FA by email demands that your WP site is properly configured to send email.' )
|
501 |
.'<br/>'._wpsf__( 'This is a common problem and you may get locked out in the future if you ignore this.' )
|
502 |
-
.' '.sprintf( '<a href="%s" target="_blank"
|
503 |
}
|
504 |
|
505 |
return $aWarnings;
|
@@ -590,14 +605,14 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
590 |
*/
|
591 |
public function isEnabledBotJs() {
|
592 |
return $this->isPremium() && $this->isOpt( 'enable_antibot_js', 'Y' )
|
593 |
-
&& count( $this->
|
594 |
&& ( $this->isEnabledGaspCheck() || $this->isGoogleRecaptchaEnabled() );
|
595 |
}
|
596 |
|
597 |
/**
|
598 |
* @return array
|
599 |
*/
|
600 |
-
public function
|
601 |
$aIds = $this->getOpt( 'antibot_form_ids', array() );
|
602 |
return is_array( $aIds ) ? $aIds : array();
|
603 |
}
|
@@ -623,14 +638,14 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
623 |
$sUnique,
|
624 |
'icwp_wpsf_vars_lpantibot',
|
625 |
array(
|
626 |
-
'
|
627 |
-
'uniq'
|
628 |
-
'cbname'
|
629 |
-
'strings'
|
630 |
'label' => $this->getTextImAHuman(),
|
631 |
'alert' => $this->getTextPleaseCheckBox(),
|
632 |
),
|
633 |
-
'flags'
|
634 |
'gasp' => $this->isEnabledGaspCheck(),
|
635 |
'recap' => $this->isGoogleRecaptchaEnabled(),
|
636 |
)
|
@@ -869,8 +884,11 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
|
|
869 |
|
870 |
case 'antibot_form_ids' :
|
871 |
$sName = _wpsf__( 'AntiBot Forms' );
|
872 |
-
$sSummary = _wpsf__( 'Enter The
|
873 |
-
$sDescription = _wpsf__( 'For use with the AntiBot JS option.' )
|
|
|
|
|
|
|
874 |
break;
|
875 |
|
876 |
case 'login_limit_interval' :
|
57 |
$this->getOptionsVo()->resetOptToDefault( 'login_limit_interval' );
|
58 |
}
|
59 |
|
60 |
+
$aIds = $this->getAntiBotFormSelectors();
|
61 |
foreach ( $aIds as $nKey => $sId ) {
|
62 |
+
$sId = trim( strip_tags( $sId ) );
|
63 |
if ( empty( $sId ) ) {
|
64 |
unset( $aIds[ $nKey ] );
|
65 |
}
|
160 |
$aRoles = $this->getOptEmailTwoFactorRolesDefaults();
|
161 |
$this->setOpt( 'two_factor_auth_user_roles', $aRoles );
|
162 |
}
|
163 |
+
if ( $this->isPremium() ) {
|
164 |
+
$aRoles = apply_filters( 'odp-shield-2fa_email_user_roles', $aRoles );
|
165 |
+
}
|
166 |
+
return is_array( $aRoles ) ? $aRoles : $this->getOptEmailTwoFactorRolesDefaults();
|
167 |
}
|
168 |
|
169 |
/**
|
259 |
}
|
260 |
else if ( $this->getIfSupport3rdParty() && class_exists( 'WC_Social_Login' ) ) {
|
261 |
// custom support for WooCommerce Social login
|
262 |
+
$oMeta = $this->getConn()->getUserMeta( $oUser );
|
263 |
$bCanSkip = isset( $oMeta->wc_social_login_valid ) ? $oMeta->wc_social_login_valid : false;
|
264 |
}
|
265 |
+
else {
|
266 |
+
/**
|
267 |
+
* TODO: remove the HTTP_REFERER bit once iCWP plugin is updated.
|
268 |
+
* We want logins from iCWP to skip 2FA. To achieve this, iCWP plugin needs
|
269 |
+
* to add a TRUE filter on 'odp-shield-2fa_skip' at the point of login.
|
270 |
+
* Until then, we'll use the HTTP referrer as an indicator
|
271 |
+
*/
|
272 |
+
$bCanSkip = apply_filters(
|
273 |
+
'odp-shield-2fa_skip',
|
274 |
+
strpos( $this->loadRequest()->server( 'HTTP_REFERER' ), 'https://app.icontrolwp.com/' ) === 0
|
275 |
+
);
|
276 |
+
}
|
277 |
return $bCanSkip;
|
278 |
}
|
279 |
|
294 |
* @return array
|
295 |
*/
|
296 |
public function getMfaLoginHashes( $oUser ) {
|
297 |
+
$oMeta = $this->getConn()->getUserMeta( $oUser );
|
298 |
$aHashes = $oMeta->hash_loginmfa;
|
299 |
if ( !is_array( $aHashes ) ) {
|
300 |
$aHashes = array();
|
514 |
$aWarnings[] =
|
515 |
_wpsf__( '2FA by email demands that your WP site is properly configured to send email.' )
|
516 |
.'<br/>'._wpsf__( 'This is a common problem and you may get locked out in the future if you ignore this.' )
|
517 |
+
.' '.sprintf( '<a href="%s" target="_blank" class="alert-link">%s</a>', 'https://icwp.io/dd', _wpsf__( 'Learn More.' ) );
|
518 |
}
|
519 |
|
520 |
return $aWarnings;
|
605 |
*/
|
606 |
public function isEnabledBotJs() {
|
607 |
return $this->isPremium() && $this->isOpt( 'enable_antibot_js', 'Y' )
|
608 |
+
&& count( $this->getAntiBotFormSelectors() ) > 0
|
609 |
&& ( $this->isEnabledGaspCheck() || $this->isGoogleRecaptchaEnabled() );
|
610 |
}
|
611 |
|
612 |
/**
|
613 |
* @return array
|
614 |
*/
|
615 |
+
public function getAntiBotFormSelectors() {
|
616 |
$aIds = $this->getOpt( 'antibot_form_ids', array() );
|
617 |
return is_array( $aIds ) ? $aIds : array();
|
618 |
}
|
638 |
$sUnique,
|
639 |
'icwp_wpsf_vars_lpantibot',
|
640 |
array(
|
641 |
+
'form_selectors' => implode( ',', $this->getAntiBotFormSelectors() ),
|
642 |
+
'uniq' => preg_replace( '#[^a-zA-Z0-9]#', '', apply_filters( 'icwp_shield_lp_gasp_uniqid', uniqid() ) ),
|
643 |
+
'cbname' => $this->getGaspKey(),
|
644 |
+
'strings' => array(
|
645 |
'label' => $this->getTextImAHuman(),
|
646 |
'alert' => $this->getTextPleaseCheckBox(),
|
647 |
),
|
648 |
+
'flags' => array(
|
649 |
'gasp' => $this->isEnabledGaspCheck(),
|
650 |
'recap' => $this->isGoogleRecaptchaEnabled(),
|
651 |
)
|
884 |
|
885 |
case 'antibot_form_ids' :
|
886 |
$sName = _wpsf__( 'AntiBot Forms' );
|
887 |
+
$sSummary = _wpsf__( 'Enter The Selectors Of The 3rd Party Login Forms For Use With AntiBot JS' );
|
888 |
+
$sDescription = _wpsf__( 'For use with the AntiBot JS option.' )
|
889 |
+
.' '._wpsf__( 'IDs are prefixed with "#".' )
|
890 |
+
.' '._wpsf__( 'Classes are prefixed with ".".' )
|
891 |
+
.'<br />'._wpsf__( 'IDs are preferred over classes.' );
|
892 |
break;
|
893 |
|
894 |
case 'login_limit_interval' :
|
src/features/plugin.php
CHANGED
@@ -316,9 +316,9 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
316 |
* @param string $sPlugin
|
317 |
*/
|
318 |
public function onWpHookDeactivatePlugin( $sPlugin ) {
|
319 |
-
$oCon =
|
320 |
if ( strpos( $oCon->getRootFile(), $sPlugin ) !== false ) {
|
321 |
-
if ( !$oCon->
|
322 |
$this->loadWp()->wpDie(
|
323 |
_wpsf__( 'Sorry, you do not have permission to disable this plugin.' )
|
324 |
.' '._wpsf__( 'You need to authenticate first.' )
|
@@ -385,10 +385,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
385 |
*/
|
386 |
protected function doPrePluginOptionsSave() {
|
387 |
|
388 |
-
$
|
389 |
-
if ( empty( $nInstalledAt ) || $nInstalledAt <= 0 ) {
|
390 |
-
$this->setOpt( 'installation_time', $this->loadRequest()->ts() );
|
391 |
-
}
|
392 |
|
393 |
if ( $this->isTrackingEnabled() && !$this->isTrackingPermissionSet() ) {
|
394 |
$this->setOpt( 'tracking_permission_set_at', $this->loadRequest()->ts() );
|
@@ -403,6 +400,46 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
403 |
$this->setPluginInstallationId();
|
404 |
}
|
405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
406 |
/**
|
407 |
* @param string $sOptionKey
|
408 |
*/
|
@@ -451,7 +488,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
451 |
*/
|
452 |
protected function genInstallId() {
|
453 |
return sha1(
|
454 |
-
$this->
|
455 |
.$this->loadWp()->getWpUrl()
|
456 |
.$this->loadDbProcessor()->getPrefix()
|
457 |
);
|
@@ -720,9 +757,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
720 |
* @return $this
|
721 |
*/
|
722 |
public function updateTestCronLastRunAt() {
|
723 |
-
$this->setOptInsightsAt( 'test_cron_last_run_at' )
|
724 |
-
->savePluginOptions();
|
725 |
-
return $this;
|
726 |
}
|
727 |
|
728 |
/**
|
@@ -837,13 +872,13 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
837 |
protected function loadStrings_Options( $aOptionsParams ) {
|
838 |
|
839 |
$sKey = $aOptionsParams[ 'key' ];
|
|
|
840 |
switch ( $sKey ) {
|
841 |
|
842 |
case 'global_enable_plugin_features' :
|
843 |
$sName = _wpsf__( 'Enable/Disable Plugin Modules' );
|
844 |
$sSummary = _wpsf__( 'Enable/Disable All Plugin Modules' );
|
845 |
-
$sDescription = sprintf( _wpsf__( 'Uncheck this option to disable all %s features.' ),
|
846 |
-
->getHumanName() );
|
847 |
break;
|
848 |
|
849 |
case 'enable_notes' :
|
316 |
* @param string $sPlugin
|
317 |
*/
|
318 |
public function onWpHookDeactivatePlugin( $sPlugin ) {
|
319 |
+
$oCon = $this->getConn();
|
320 |
if ( strpos( $oCon->getRootFile(), $sPlugin ) !== false ) {
|
321 |
+
if ( !$oCon->isPluginAdmin() ) {
|
322 |
$this->loadWp()->wpDie(
|
323 |
_wpsf__( 'Sorry, you do not have permission to disable this plugin.' )
|
324 |
.' '._wpsf__( 'You need to authenticate first.' )
|
385 |
*/
|
386 |
protected function doPrePluginOptionsSave() {
|
387 |
|
388 |
+
$this->storeRealInstallDate();
|
|
|
|
|
|
|
389 |
|
390 |
if ( $this->isTrackingEnabled() && !$this->isTrackingPermissionSet() ) {
|
391 |
$this->setOpt( 'tracking_permission_set_at', $this->loadRequest()->ts() );
|
400 |
$this->setPluginInstallationId();
|
401 |
}
|
402 |
|
403 |
+
/**
|
404 |
+
* @return int
|
405 |
+
*/
|
406 |
+
public function getFirstInstallDate() {
|
407 |
+
return $this->loadWp()->getOption( $this->prefixOptionKey( 'install_date' ) );
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* @return int
|
412 |
+
*/
|
413 |
+
public function getInstallDate() {
|
414 |
+
return $this->getOpt( 'installation_time', 0 );
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* @return int - the real install timestamp
|
419 |
+
*/
|
420 |
+
public function storeRealInstallDate() {
|
421 |
+
$oWP = $this->loadWp();
|
422 |
+
$nNow = $this->loadRequest()->ts();
|
423 |
+
|
424 |
+
$sOptKey = $this->prefixOptionKey( 'install_date' );
|
425 |
+
|
426 |
+
$nWpDate = $oWP->getOption( $sOptKey );
|
427 |
+
if ( empty( $nWpDate ) ) {
|
428 |
+
$nWpDate = $nNow;
|
429 |
+
}
|
430 |
+
|
431 |
+
$nPluginDate = $this->getInstallDate();
|
432 |
+
if ( $nPluginDate == 0 ) {
|
433 |
+
$nPluginDate = $nNow;
|
434 |
+
}
|
435 |
+
|
436 |
+
$nFinal = min( $nPluginDate, $nWpDate );
|
437 |
+
$oWP->updateOption( $sOptKey, $nFinal );
|
438 |
+
$this->setOpt( 'installation_time', $nPluginDate );
|
439 |
+
|
440 |
+
return $nFinal;
|
441 |
+
}
|
442 |
+
|
443 |
/**
|
444 |
* @param string $sOptionKey
|
445 |
*/
|
488 |
*/
|
489 |
protected function genInstallId() {
|
490 |
return sha1(
|
491 |
+
$this->getInstallDate()
|
492 |
.$this->loadWp()->getWpUrl()
|
493 |
.$this->loadDbProcessor()->getPrefix()
|
494 |
);
|
757 |
* @return $this
|
758 |
*/
|
759 |
public function updateTestCronLastRunAt() {
|
760 |
+
return $this->setOptInsightsAt( 'test_cron_last_run_at' );
|
|
|
|
|
761 |
}
|
762 |
|
763 |
/**
|
872 |
protected function loadStrings_Options( $aOptionsParams ) {
|
873 |
|
874 |
$sKey = $aOptionsParams[ 'key' ];
|
875 |
+
$sPlugName = $this->getConn()->getHumanName();
|
876 |
switch ( $sKey ) {
|
877 |
|
878 |
case 'global_enable_plugin_features' :
|
879 |
$sName = _wpsf__( 'Enable/Disable Plugin Modules' );
|
880 |
$sSummary = _wpsf__( 'Enable/Disable All Plugin Modules' );
|
881 |
+
$sDescription = sprintf( _wpsf__( 'Uncheck this option to disable all %s features.' ), $sPlugName );
|
|
|
882 |
break;
|
883 |
|
884 |
case 'enable_notes' :
|
src/features/traffic.php
CHANGED
@@ -322,7 +322,6 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
322 |
public function formatEntriesForDisplay( $aEntries ) {
|
323 |
|
324 |
if ( is_array( $aEntries ) ) {
|
325 |
-
$oCon = $this->getController();
|
326 |
$oWpUsers = $this->loadWpUsers();
|
327 |
$oGeo = $this->loadGeoIp2();
|
328 |
$sYou = $this->loadIpService()->getRequestIp();
|
@@ -371,7 +370,7 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
|
|
371 |
$sCountry = _wpsf__( 'Unknown' );
|
372 |
}
|
373 |
else {
|
374 |
-
$sFlag =
|
375 |
$sCountry = sprintf( '<img class="icon-flag" src="%s"/> %s', $sFlag, $sCountry );
|
376 |
}
|
377 |
|
322 |
public function formatEntriesForDisplay( $aEntries ) {
|
323 |
|
324 |
if ( is_array( $aEntries ) ) {
|
|
|
325 |
$oWpUsers = $this->loadWpUsers();
|
326 |
$oGeo = $this->loadGeoIp2();
|
327 |
$sYou = $this->loadIpService()->getRequestIp();
|
370 |
$sCountry = _wpsf__( 'Unknown' );
|
371 |
}
|
372 |
else {
|
373 |
+
$sFlag = sprintf( 'https://www.countryflags.io/%s/flat/16.png', strtolower( $oGeo->countryIso( $sIp ) ) );
|
374 |
$sCountry = sprintf( '<img class="icon-flag" src="%s"/> %s', $sFlag, $sCountry );
|
375 |
}
|
376 |
|
src/processors/admin_access_restriction.php
CHANGED
@@ -17,25 +17,37 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
17 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
18 |
$oFO = $this->getMod();
|
19 |
|
20 |
-
add_filter( $oFO->prefix( '
|
21 |
-
add_filter( $oFO->prefix( 'has_permission_to_view' ), array( $oFO, 'doCheckHasPermissionToSubmit' ) );
|
22 |
-
|
23 |
-
if ( !$oFO->isUpgrading() && !$this->loadWp()->isRequestUserLogin() ) {
|
24 |
-
add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
|
25 |
-
}
|
26 |
|
27 |
if ( $oFO->isWlEnabled() ) {
|
28 |
$this->runWhiteLabel();
|
29 |
}
|
30 |
}
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
public function onWpInit() {
|
33 |
parent::onWpInit();
|
34 |
|
35 |
-
|
|
|
36 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
37 |
$oFO = $this->getMod();
|
38 |
|
|
|
|
|
|
|
|
|
39 |
if ( $oFO->isAdminAccessAdminUsersEnabled() ) {
|
40 |
add_filter( 'editable_roles', array( $this, 'restrictEditableRoles' ), 100, 1 );
|
41 |
add_filter( 'user_has_cap', array( $this, 'restrictAdminUserChanges' ), 100, 3 );
|
@@ -107,13 +119,6 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
107 |
return $aData;
|
108 |
}
|
109 |
|
110 |
-
/**
|
111 |
-
* @return bool
|
112 |
-
*/
|
113 |
-
protected function isSecurityAdmin() {
|
114 |
-
return self::getController()->getHasPermissionToManage();
|
115 |
-
}
|
116 |
-
|
117 |
/**
|
118 |
* @param int $nUserId
|
119 |
* @param string $sRole
|
@@ -276,7 +281,7 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
276 |
public function addNotice_certain_options_restricted( $aNoticeAttributes ) {
|
277 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
278 |
$oFO = $this->getMod();
|
279 |
-
if ( $
|
280 |
return;
|
281 |
}
|
282 |
|
@@ -312,7 +317,8 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
312 |
* @throws Exception
|
313 |
*/
|
314 |
public function addNotice_admin_users_restricted( $aNoticeAttributes ) {
|
315 |
-
|
|
|
316 |
return;
|
317 |
}
|
318 |
|
@@ -324,7 +330,7 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
324 |
return;
|
325 |
}
|
326 |
|
327 |
-
$sName = $
|
328 |
$aRenderData = array(
|
329 |
'notice_attributes' => $aNoticeAttributes,
|
330 |
'strings' => array(
|
@@ -357,8 +363,11 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
357 |
}
|
358 |
|
359 |
/**
|
360 |
-
*
|
361 |
-
*
|
|
|
|
|
|
|
362 |
* @param mixed $mNewOptionValue
|
363 |
* @param string $sOptionKey
|
364 |
* @param mixed $mOldValue
|
@@ -366,17 +375,13 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
366 |
*/
|
367 |
public function blockOptionsSaves( $mNewOptionValue, $sOptionKey, $mOldValue ) {
|
368 |
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
$
|
373 |
-
|
374 |
-
if ( !$bSavingIsPermitted ) {
|
375 |
-
$this->doStatIncrement( 'option.save.blocked' );
|
376 |
-
}
|
377 |
}
|
378 |
|
379 |
-
return $
|
380 |
}
|
381 |
|
382 |
/**
|
@@ -447,8 +452,7 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
447 |
*/
|
448 |
public function disableThemeManipulation( $aAllCaps, $cap, $aArgs ) {
|
449 |
// If we're registered with Admin Access we don't modify anything
|
450 |
-
|
451 |
-
if ( $bHasAdminAccess ) {
|
452 |
return $aAllCaps;
|
453 |
}
|
454 |
|
@@ -482,9 +486,7 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
482 |
* @return array
|
483 |
*/
|
484 |
public function disablePostsManipulation( $aAllCaps, $cap, $aArgs ) {
|
485 |
-
|
486 |
-
$bHasAdminAccess = self::getController()->getHasPermissionToManage();
|
487 |
-
if ( $bHasAdminAccess ) {
|
488 |
return $aAllCaps;
|
489 |
}
|
490 |
|
@@ -572,4 +574,12 @@ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Bas
|
|
572 |
$sLinkText
|
573 |
);
|
574 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
575 |
}
|
17 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
18 |
$oFO = $this->getMod();
|
19 |
|
20 |
+
add_filter( $oFO->prefix( 'is_plugin_admin' ), array( $this, 'adjustUserAdminPermissions' ) );
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
if ( $oFO->isWlEnabled() ) {
|
23 |
$this->runWhiteLabel();
|
24 |
}
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @param bool $bHasPermission
|
29 |
+
* @return bool
|
30 |
+
*/
|
31 |
+
public function adjustUserAdminPermissions( $bHasPermission = true ) {
|
32 |
+
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
33 |
+
$oFO = $this->getMod();
|
34 |
+
return $bHasPermission &&
|
35 |
+
( $oFO->isRegisteredSecAdminUser() || $oFO->isSecAdminSessionValid()
|
36 |
+
|| $oFO->checkAdminAccessKeySubmission() );
|
37 |
+
}
|
38 |
+
|
39 |
public function onWpInit() {
|
40 |
parent::onWpInit();
|
41 |
|
42 |
+
$oCon = $this->getController();
|
43 |
+
if ( !$oCon->isPluginAdmin() ) {
|
44 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
45 |
$oFO = $this->getMod();
|
46 |
|
47 |
+
if ( !$oFO->isUpgrading() && !$this->loadWp()->isRequestUserLogin() ) {
|
48 |
+
add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
|
49 |
+
}
|
50 |
+
|
51 |
if ( $oFO->isAdminAccessAdminUsersEnabled() ) {
|
52 |
add_filter( 'editable_roles', array( $this, 'restrictEditableRoles' ), 100, 1 );
|
53 |
add_filter( 'user_has_cap', array( $this, 'restrictAdminUserChanges' ), 100, 3 );
|
119 |
return $aData;
|
120 |
}
|
121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
/**
|
123 |
* @param int $nUserId
|
124 |
* @param string $sRole
|
281 |
public function addNotice_certain_options_restricted( $aNoticeAttributes ) {
|
282 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
283 |
$oFO = $this->getMod();
|
284 |
+
if ( $this->getController()->isPluginAdmin() ) {
|
285 |
return;
|
286 |
}
|
287 |
|
317 |
* @throws Exception
|
318 |
*/
|
319 |
public function addNotice_admin_users_restricted( $aNoticeAttributes ) {
|
320 |
+
$oCon = $this->getController();
|
321 |
+
if ( $oCon->isPluginAdmin() ) {
|
322 |
return;
|
323 |
}
|
324 |
|
330 |
return;
|
331 |
}
|
332 |
|
333 |
+
$sName = $oCon->getHumanName();
|
334 |
$aRenderData = array(
|
335 |
'notice_attributes' => $aNoticeAttributes,
|
336 |
'strings' => array(
|
363 |
}
|
364 |
|
365 |
/**
|
366 |
+
* Need to always re-test isPluginAdmin() because there's a dynamic filter in there to
|
367 |
+
* permit saving by the plugin itself.
|
368 |
+
*
|
369 |
+
* Right before a plugin option is due to update it will check that we have permissions to do so
|
370 |
+
* and if not, will * revert the option to save to the previous one.
|
371 |
* @param mixed $mNewOptionValue
|
372 |
* @param string $sOptionKey
|
373 |
* @param mixed $mOldValue
|
375 |
*/
|
376 |
public function blockOptionsSaves( $mNewOptionValue, $sOptionKey, $mOldValue ) {
|
377 |
|
378 |
+
if ( !$this->getController()->isPluginAdmin()
|
379 |
+
&& ( $this->isOptionForThisPlugin( $sOptionKey ) || $this->isOptionRestricted( $sOptionKey ) ) ) {
|
380 |
+
$this->doStatIncrement( 'option.save.blocked' );
|
381 |
+
$mNewOptionValue = $mOldValue;
|
|
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
+
return $mNewOptionValue;
|
385 |
}
|
386 |
|
387 |
/**
|
452 |
*/
|
453 |
public function disableThemeManipulation( $aAllCaps, $cap, $aArgs ) {
|
454 |
// If we're registered with Admin Access we don't modify anything
|
455 |
+
if ( $this->getController()->isPluginAdmin() ) {
|
|
|
456 |
return $aAllCaps;
|
457 |
}
|
458 |
|
486 |
* @return array
|
487 |
*/
|
488 |
public function disablePostsManipulation( $aAllCaps, $cap, $aArgs ) {
|
489 |
+
if ( $this->getController()->isPluginAdmin() ) {
|
|
|
|
|
490 |
return $aAllCaps;
|
491 |
}
|
492 |
|
574 |
$sLinkText
|
575 |
);
|
576 |
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* @deprecated
|
580 |
+
* @return bool
|
581 |
+
*/
|
582 |
+
protected function isSecurityAdmin() {
|
583 |
+
return $this->getController()->isPluginAdmin();
|
584 |
+
}
|
585 |
}
|
src/processors/adminaccess_whitelabel.php
CHANGED
@@ -21,12 +21,12 @@ class ICWP_WPSF_Processor_AdminAccess_Whitelabel extends ICWP_WPSF_Processor_Bas
|
|
21 |
|
22 |
public function onWpInit() {
|
23 |
parent::onWpInit();
|
|
|
24 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
25 |
$oFO = $this->getMod();
|
26 |
$oCon = $this->getController();
|
27 |
|
28 |
-
if ( $oFO->isWlHideUpdates() && $this->isNeedToHideUpdates()
|
29 |
-
&& !$oCon->getHasPermissionToManage() ) {
|
30 |
$this->hideUpdates();
|
31 |
}
|
32 |
}
|
21 |
|
22 |
public function onWpInit() {
|
23 |
parent::onWpInit();
|
24 |
+
|
25 |
/** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFO */
|
26 |
$oFO = $this->getMod();
|
27 |
$oCon = $this->getController();
|
28 |
|
29 |
+
if ( $oFO->isWlHideUpdates() && $this->isNeedToHideUpdates() && !$oCon->isPluginAdmin() ) {
|
|
|
30 |
$this->hideUpdates();
|
31 |
}
|
32 |
}
|
src/processors/autoupdates.php
CHANGED
@@ -70,7 +70,7 @@ class ICWP_WPSF_Processor_Autoupdates extends ICWP_WPSF_Processor_BaseWpsf {
|
|
70 |
$this->loadWp()->doForceRunAutomaticUpdates();
|
71 |
}
|
72 |
|
73 |
-
if ( $oFO->isAutoupdateIndividualPlugins()
|
74 |
// Adds automatic update indicator column to all plugins in plugin listing.
|
75 |
add_filter( 'manage_plugins_columns', array( $this, 'fAddPluginsListAutoUpdateColumn' ) );
|
76 |
}
|
@@ -275,6 +275,15 @@ class ICWP_WPSF_Processor_Autoupdates extends ICWP_WPSF_Processor_BaseWpsf {
|
|
275 |
else if ( $oFO->isPluginSetToAutoupdate( $sFile ) ) {
|
276 |
$bDoAutoUpdate = true;
|
277 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
|
279 |
return $bDoAutoUpdate;
|
280 |
}
|
@@ -406,7 +415,7 @@ class ICWP_WPSF_Processor_Autoupdates extends ICWP_WPSF_Processor_BaseWpsf {
|
|
406 |
* @return array
|
407 |
*/
|
408 |
public function fAddPluginsListAutoUpdateColumn( $aColumns ) {
|
409 |
-
if ( !isset( $aColumns[ 'icwp_autoupdate' ] ) ) {
|
410 |
$aColumns[ 'icwp_autoupdate' ] = 'Auto Update';
|
411 |
add_action( 'manage_plugins_custom_column',
|
412 |
array( $this, 'aPrintPluginsListAutoUpdateColumnContent' ),
|
70 |
$this->loadWp()->doForceRunAutomaticUpdates();
|
71 |
}
|
72 |
|
73 |
+
if ( $oFO->isAutoupdateIndividualPlugins() ) {
|
74 |
// Adds automatic update indicator column to all plugins in plugin listing.
|
75 |
add_filter( 'manage_plugins_columns', array( $this, 'fAddPluginsListAutoUpdateColumn' ) );
|
76 |
}
|
275 |
else if ( $oFO->isPluginSetToAutoupdate( $sFile ) ) {
|
276 |
$bDoAutoUpdate = true;
|
277 |
}
|
278 |
+
else if ( $sFile === $this->getController()->getPluginBaseFile() ) {
|
279 |
+
$sAuto = $oFO->getOpt( 'autoupdate_plugin_self' );
|
280 |
+
if ( $sAuto === 'immediate' ) {
|
281 |
+
$bDoAutoUpdate = true;
|
282 |
+
}
|
283 |
+
else if ( $sAuto === 'disabled' ) {
|
284 |
+
$bDoAutoUpdate = false;
|
285 |
+
}
|
286 |
+
}
|
287 |
|
288 |
return $bDoAutoUpdate;
|
289 |
}
|
415 |
* @return array
|
416 |
*/
|
417 |
public function fAddPluginsListAutoUpdateColumn( $aColumns ) {
|
418 |
+
if ( $this->getController()->isPluginAdmin() && !isset( $aColumns[ 'icwp_autoupdate' ] ) ) {
|
419 |
$aColumns[ 'icwp_autoupdate' ] = 'Auto Update';
|
420 |
add_action( 'manage_plugins_custom_column',
|
421 |
array( $this, 'aPrintPluginsListAutoUpdateColumnContent' ),
|
src/processors/base.php
CHANGED
@@ -31,20 +31,24 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
|
|
31 |
*/
|
32 |
public function __construct( $oModCon ) {
|
33 |
$this->oModCon = $oModCon;
|
34 |
-
add_action( $oModCon->prefix( 'plugin_shutdown' ), array( $this, 'onModuleShutdown' ) );
|
35 |
-
add_action( $oModCon->prefix( 'generate_admin_notices' ), array( $this, 'autoAddToAdminNotices' ) );
|
36 |
-
if ( method_exists( $this, 'addToAdminNotices' ) ) {
|
37 |
-
add_action( $oModCon->prefix( 'generate_admin_notices' ), array( $this, 'addToAdminNotices' ) );
|
38 |
-
}
|
39 |
|
40 |
add_action( 'init', array( $this, 'onWpInit' ) );
|
41 |
add_action( 'wp_login', array( $this, 'onWpLogin' ), 10, 2 );
|
42 |
add_action( 'set_logged_in_cookie', array( $this, 'onWpSetLoggedInCookie' ), 5, 4 );
|
|
|
43 |
|
44 |
$this->init();
|
45 |
}
|
46 |
|
47 |
public function onWpInit() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
@@ -106,8 +110,6 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
|
|
106 |
}
|
107 |
|
108 |
public function autoAddToAdminNotices() {
|
109 |
-
$oCon = $this->getController();
|
110 |
-
|
111 |
foreach ( $this->getMod()->getAdminNotices() as $sNoticeId => $aAttrs ) {
|
112 |
|
113 |
if ( !$this->getIfDisplayAdminNotice( $aAttrs ) ) {
|
@@ -115,9 +117,7 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
|
|
115 |
}
|
116 |
|
117 |
$sMethodName = 'addNotice_'.str_replace( '-', '_', $sNoticeId );
|
118 |
-
if ( method_exists( $this, $sMethodName )
|
119 |
-
&& $aAttrs[ 'valid_admin' ] && $oCon->isValidAdminArea() ) {
|
120 |
-
|
121 |
$aAttrs[ 'id' ] = $sNoticeId;
|
122 |
$aAttrs[ 'notice_id' ] = $sNoticeId;
|
123 |
call_user_func( array( $this, $sMethodName ), $aAttrs );
|
31 |
*/
|
32 |
public function __construct( $oModCon ) {
|
33 |
$this->oModCon = $oModCon;
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
add_action( 'init', array( $this, 'onWpInit' ) );
|
36 |
add_action( 'wp_login', array( $this, 'onWpLogin' ), 10, 2 );
|
37 |
add_action( 'set_logged_in_cookie', array( $this, 'onWpSetLoggedInCookie' ), 5, 4 );
|
38 |
+
add_action( $oModCon->prefix( 'plugin_shutdown' ), array( $this, 'onModuleShutdown' ) );
|
39 |
|
40 |
$this->init();
|
41 |
}
|
42 |
|
43 |
public function onWpInit() {
|
44 |
+
$oMod = $this->getMod();
|
45 |
+
$oCon = $oMod->getConn();
|
46 |
+
if ( $oCon->isValidAdminArea() && $oCon->isPluginAdmin() ) {
|
47 |
+
add_action( $oMod->prefix( 'generate_admin_notices' ), array( $this, 'autoAddToAdminNotices' ) );
|
48 |
+
if ( method_exists( $this, 'addToAdminNotices' ) ) {
|
49 |
+
add_action( $oMod->prefix( 'generate_admin_notices' ), array( $this, 'addToAdminNotices' ) );
|
50 |
+
}
|
51 |
+
}
|
52 |
}
|
53 |
|
54 |
/**
|
110 |
}
|
111 |
|
112 |
public function autoAddToAdminNotices() {
|
|
|
|
|
113 |
foreach ( $this->getMod()->getAdminNotices() as $sNoticeId => $aAttrs ) {
|
114 |
|
115 |
if ( !$this->getIfDisplayAdminNotice( $aAttrs ) ) {
|
117 |
}
|
118 |
|
119 |
$sMethodName = 'addNotice_'.str_replace( '-', '_', $sNoticeId );
|
120 |
+
if ( method_exists( $this, $sMethodName ) ) {
|
|
|
|
|
121 |
$aAttrs[ 'id' ] = $sNoticeId;
|
122 |
$aAttrs[ 'notice_id' ] = $sNoticeId;
|
123 |
call_user_func( array( $this, $sMethodName ), $aAttrs );
|
src/processors/base_wpsf.php
CHANGED
@@ -45,7 +45,9 @@ abstract class ICWP_WPSF_Processor_BaseWpsf extends ICWP_WPSF_Processor_Base {
|
|
45 |
* @return int
|
46 |
*/
|
47 |
protected function getInstallationDays() {
|
48 |
-
$nTimeInstalled = $this->
|
|
|
|
|
49 |
if ( empty( $nTimeInstalled ) ) {
|
50 |
return 0;
|
51 |
}
|
45 |
* @return int
|
46 |
*/
|
47 |
protected function getInstallationDays() {
|
48 |
+
$nTimeInstalled = $this->getController()
|
49 |
+
->loadCorePluginFeatureHandler()
|
50 |
+
->getInstallDate();
|
51 |
if ( empty( $nTimeInstalled ) ) {
|
52 |
return 0;
|
53 |
}
|
src/processors/basedb.php
CHANGED
@@ -51,7 +51,7 @@ abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_BaseWpsf {
|
|
51 |
/**
|
52 |
*/
|
53 |
public function deleteTable() {
|
54 |
-
if (
|
55 |
$this->deleteCleanupCron();
|
56 |
$this->loadDbProcessor()->doDropTable( $this->getTableName() );
|
57 |
}
|
51 |
/**
|
52 |
*/
|
53 |
public function deleteTable() {
|
54 |
+
if ( $this->getTableExists() ) {
|
55 |
$this->deleteCleanupCron();
|
56 |
$this->loadDbProcessor()->doDropTable( $this->getTableName() );
|
57 |
}
|
src/processors/comments_filter.php
CHANGED
@@ -54,7 +54,7 @@ class ICWP_WPSF_Processor_CommentsFilter extends ICWP_WPSF_Processor_BaseWpsf {
|
|
54 |
$oFO = $this->getMod();
|
55 |
|
56 |
// We only warn when the human spam filter is running
|
57 |
-
if ( $oFO->isOpt( 'enable_comments_human_spam_filter', 'Y' )
|
58 |
|
59 |
$oWpPlugins = $this->loadWpPlugins();
|
60 |
$sPluginFile = $oWpPlugins->findPluginBy( 'Akismet', 'Name' );
|
54 |
$oFO = $this->getMod();
|
55 |
|
56 |
// We only warn when the human spam filter is running
|
57 |
+
if ( $oFO->isOpt( 'enable_comments_human_spam_filter', 'Y' ) ) {
|
58 |
|
59 |
$oWpPlugins = $this->loadWpPlugins();
|
60 |
$sPluginFile = $oWpPlugins->findPluginBy( 'Akismet', 'Name' );
|
src/processors/commentsfilter_humanspam.php
CHANGED
@@ -210,6 +210,6 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_C
|
|
210 |
* @return string
|
211 |
*/
|
212 |
protected function getSpamBlacklistFile() {
|
213 |
-
return $this->
|
214 |
}
|
215 |
}
|
210 |
* @return string
|
211 |
*/
|
212 |
protected function getSpamBlacklistFile() {
|
213 |
+
return $this->getController()->getPath_Assets( 'spamblacklist.txt' );
|
214 |
}
|
215 |
}
|
src/processors/dbhandler.php
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Created by PhpStorm.
|
4 |
-
* User: paulg
|
5 |
-
* Date: 19/02/2016
|
6 |
-
* Time: 13:48
|
7 |
-
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/processors/hackprotect_pluginvulnerabilities.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', false ) ):
|
4 |
|
5 |
-
require_once( dirname(__FILE__ ).'/base_wpsf.php' );
|
6 |
|
7 |
class ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities extends ICWP_WPSF_Processor_BaseWpsf {
|
8 |
|
@@ -32,18 +32,16 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
32 |
// For display on the Plugins page
|
33 |
add_filter( 'manage_plugins_columns', array( $this, 'fCountColumns' ), 1000 );
|
34 |
add_action( 'admin_init', array( $this, 'addPluginVulnerabilityRows' ), 10, 2 );
|
35 |
-
|
36 |
}
|
37 |
|
38 |
protected function setupNotificationsCron() {
|
39 |
-
$
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
);
|
46 |
-
add_action( $this->getMod()->prefix( 'delete_plugin' ), array( $this, 'deleteCron' ) );
|
47 |
}
|
48 |
|
49 |
/**
|
@@ -56,7 +54,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
56 |
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
57 |
$oFO = $this->getMod();
|
58 |
|
59 |
-
foreach( $this->loadWpPlugins()->getPlugins() as $sPluginFile => $aPluginData ) {
|
60 |
$aPluginVulnerabilityData = $this->getPluginVulnerabilityData( $sPluginFile, $aPluginData );
|
61 |
if ( is_array( $aPluginVulnerabilityData ) ) {
|
62 |
$this->addPluginVulnerabilityToEmail( $aPluginData, $aPluginVulnerabilityData );
|
@@ -77,10 +75,10 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
77 |
$this->aEmailContents = array_merge(
|
78 |
$this->aEmailContents,
|
79 |
array(
|
80 |
-
'- '
|
81 |
-
'- '
|
82 |
-
'- '
|
83 |
-
'- '
|
84 |
'',
|
85 |
)
|
86 |
);
|
@@ -97,13 +95,14 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
97 |
}
|
98 |
|
99 |
$aPreamble = array(
|
100 |
-
sprintf( _wpsf__( '%s has detected a plugin with a known security vulnerability on your site.' ), $this->getController()
|
|
|
101 |
_wpsf__( 'Details for the plugin(s) are below:' ),
|
102 |
'',
|
103 |
);
|
104 |
|
105 |
$this->aEmailContents = array_merge( $aPreamble, $this->aEmailContents );
|
106 |
-
$this->aEmailContents[
|
107 |
|
108 |
$sEmailSubject = sprintf( '%s - %s', _wpsf__( 'Warning' ), _wpsf__( 'Plugin(s) Discovered With Known Security Vulnerabilities.' ) );
|
109 |
|
@@ -120,7 +119,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
120 |
}
|
121 |
|
122 |
public function addPluginVulnerabilityRows() {
|
123 |
-
foreach( $this->loadWpPlugins()->getInstalledBaseFiles() as $sPluginFile ) {
|
124 |
add_action( "after_plugin_row_$sPluginFile", array( $this, 'attachVulnerabilityWarning' ), 100, 2 );
|
125 |
}
|
126 |
}
|
@@ -138,23 +137,24 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
138 |
|
139 |
/**
|
140 |
* @param string $sPluginFile
|
141 |
-
* @param array
|
142 |
*/
|
143 |
public function attachVulnerabilityWarning( $sPluginFile, $aPluginData ) {
|
144 |
|
145 |
$aPluginVulnerabilityData = $this->getPluginVulnerabilityData( $sPluginFile, $aPluginData );
|
146 |
if ( is_array( $aPluginVulnerabilityData ) ) {
|
147 |
$aRenderData = array(
|
148 |
-
'strings'
|
149 |
-
'known_vuln'
|
150 |
-
|
151 |
-
'
|
152 |
-
'
|
153 |
-
'
|
154 |
-
'
|
155 |
-
'
|
|
|
156 |
),
|
157 |
-
'hrefs'
|
158 |
'more_info' => $aPluginVulnerabilityData[ 'URL' ]
|
159 |
),
|
160 |
'nColspan' => $this->nColumnsCount
|
@@ -165,8 +165,8 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
165 |
|
166 |
/**
|
167 |
* @param string $sPluginFile
|
168 |
-
* @param array
|
169 |
-
* @return false|array
|
170 |
*/
|
171 |
protected function getPluginVulnerabilityData( $sPluginFile, $aPluginData ) {
|
172 |
|
@@ -175,12 +175,12 @@ if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', fal
|
|
175 |
return false;
|
176 |
}
|
177 |
|
178 |
-
$sSlug = !empty( $aPluginData['slug'] ) ? $aPluginData['slug'] : substr( $sPluginFile, 0, strpos( $sPluginFile, DIRECTORY_SEPARATOR ) );
|
179 |
if ( array_key_exists( $sSlug, $aPV ) ) {
|
180 |
-
foreach( $aPV[$sSlug] as $aVulnerabilityItem ) {
|
181 |
|
182 |
-
if ( version_compare( $aPluginData['Version'], $aVulnerabilityItem['FirstVersion'], '>=' )
|
183 |
-
&& version_compare( $aPluginData['Version'], $aVulnerabilityItem['LastVersion'], '<=' ) ) {
|
184 |
|
185 |
return $aVulnerabilityItem;
|
186 |
}
|
2 |
|
3 |
if ( !class_exists( 'ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities', false ) ):
|
4 |
|
5 |
+
require_once( dirname( __FILE__ ).'/base_wpsf.php' );
|
6 |
|
7 |
class ICWP_WPSF_Processor_HackProtect_PluginVulnerabilities extends ICWP_WPSF_Processor_BaseWpsf {
|
8 |
|
32 |
// For display on the Plugins page
|
33 |
add_filter( 'manage_plugins_columns', array( $this, 'fCountColumns' ), 1000 );
|
34 |
add_action( 'admin_init', array( $this, 'addPluginVulnerabilityRows' ), 10, 2 );
|
|
|
35 |
}
|
36 |
|
37 |
protected function setupNotificationsCron() {
|
38 |
+
$this->loadWpCronProcessor()
|
39 |
+
->setRecurrence( 'daily' )
|
40 |
+
->createCronJob(
|
41 |
+
$this->getCronName(),
|
42 |
+
array( $this, 'cron_dailyPluginVulnerabilitiesScan' )
|
43 |
+
);
|
44 |
+
add_action( $this->getMod()->prefix( 'delete_plugin' ), array( $this, 'deleteCron' ) );
|
|
|
45 |
}
|
46 |
|
47 |
/**
|
54 |
/** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
|
55 |
$oFO = $this->getMod();
|
56 |
|
57 |
+
foreach ( $this->loadWpPlugins()->getPlugins() as $sPluginFile => $aPluginData ) {
|
58 |
$aPluginVulnerabilityData = $this->getPluginVulnerabilityData( $sPluginFile, $aPluginData );
|
59 |
if ( is_array( $aPluginVulnerabilityData ) ) {
|
60 |
$this->addPluginVulnerabilityToEmail( $aPluginData, $aPluginVulnerabilityData );
|
75 |
$this->aEmailContents = array_merge(
|
76 |
$this->aEmailContents,
|
77 |
array(
|
78 |
+
'- '.sprintf( _wpsf__( 'Plugin Name: %s' ), $aPluginData[ 'Name' ] ),
|
79 |
+
'- '.sprintf( _wpsf__( 'Vulnerability Type: %s' ), $aVulnerabilityData[ 'TypeOfVulnerability' ] ),
|
80 |
+
'- '.sprintf( _wpsf__( 'Vulnerable Plugin Version Range: %s' ), $aVulnerabilityData[ 'FirstVersion' ].' - '.$aVulnerabilityData[ 'LastVersion' ] ),
|
81 |
+
'- '.sprintf( _wpsf__( 'Further Information: %s' ), $aVulnerabilityData[ 'URL' ] ),
|
82 |
'',
|
83 |
)
|
84 |
);
|
95 |
}
|
96 |
|
97 |
$aPreamble = array(
|
98 |
+
sprintf( _wpsf__( '%s has detected a plugin with a known security vulnerability on your site.' ), $this->getController()
|
99 |
+
->getHumanName() ),
|
100 |
_wpsf__( 'Details for the plugin(s) are below:' ),
|
101 |
'',
|
102 |
);
|
103 |
|
104 |
$this->aEmailContents = array_merge( $aPreamble, $this->aEmailContents );
|
105 |
+
$this->aEmailContents[] = _wpsf__( 'You should update or remove these plugins at your earliest convenience.' );
|
106 |
|
107 |
$sEmailSubject = sprintf( '%s - %s', _wpsf__( 'Warning' ), _wpsf__( 'Plugin(s) Discovered With Known Security Vulnerabilities.' ) );
|
108 |
|
119 |
}
|
120 |
|
121 |
public function addPluginVulnerabilityRows() {
|
122 |
+
foreach ( $this->loadWpPlugins()->getInstalledBaseFiles() as $sPluginFile ) {
|
123 |
add_action( "after_plugin_row_$sPluginFile", array( $this, 'attachVulnerabilityWarning' ), 100, 2 );
|
124 |
}
|
125 |
}
|
137 |
|
138 |
/**
|
139 |
* @param string $sPluginFile
|
140 |
+
* @param array $aPluginData
|
141 |
*/
|
142 |
public function attachVulnerabilityWarning( $sPluginFile, $aPluginData ) {
|
143 |
|
144 |
$aPluginVulnerabilityData = $this->getPluginVulnerabilityData( $sPluginFile, $aPluginData );
|
145 |
if ( is_array( $aPluginVulnerabilityData ) ) {
|
146 |
$aRenderData = array(
|
147 |
+
'strings' => array(
|
148 |
+
'known_vuln' => sprintf( _wpsf__( '%s has discovered that the currently installed version of the "%s" plugin has a known security vulnerability.' ), $this->getController()
|
149 |
+
->getHumanName(), $aPluginData[ 'Name' ] ),
|
150 |
+
'vuln_type' => _wpsf__( 'Vulnerability Type' ),
|
151 |
+
'vuln_type_explanation' => ucfirst( $aPluginVulnerabilityData[ 'TypeOfVulnerability' ] ),
|
152 |
+
'vuln_versions' => _wpsf__( 'Vulnerable Versions' ),
|
153 |
+
'more_info' => _wpsf__( 'More Info' ),
|
154 |
+
'first_version' => $aPluginVulnerabilityData[ 'FirstVersion' ],
|
155 |
+
'last_version' => $aPluginVulnerabilityData[ 'LastVersion' ],
|
156 |
),
|
157 |
+
'hrefs' => array(
|
158 |
'more_info' => $aPluginVulnerabilityData[ 'URL' ]
|
159 |
),
|
160 |
'nColspan' => $this->nColumnsCount
|
165 |
|
166 |
/**
|
167 |
* @param string $sPluginFile
|
168 |
+
* @param array $aPluginData
|
169 |
+
* @return false|array - array if a vulnerability exists
|
170 |
*/
|
171 |
protected function getPluginVulnerabilityData( $sPluginFile, $aPluginData ) {
|
172 |
|
175 |
return false;
|
176 |
}
|
177 |
|
178 |
+
$sSlug = !empty( $aPluginData[ 'slug' ] ) ? $aPluginData[ 'slug' ] : substr( $sPluginFile, 0, strpos( $sPluginFile, DIRECTORY_SEPARATOR ) );
|
179 |
if ( array_key_exists( $sSlug, $aPV ) ) {
|
180 |
+
foreach ( $aPV[ $sSlug ] as $aVulnerabilityItem ) {
|
181 |
|
182 |
+
if ( version_compare( $aPluginData[ 'Version' ], $aVulnerabilityItem[ 'FirstVersion' ], '>=' )
|
183 |
+
&& version_compare( $aPluginData[ 'Version' ], $aVulnerabilityItem[ 'LastVersion' ], '<=' ) ) {
|
184 |
|
185 |
return $aVulnerabilityItem;
|
186 |
}
|
src/processors/ips.php
CHANGED
@@ -43,7 +43,6 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
|
|
43 |
}
|
44 |
|
45 |
add_filter( 'authenticate', array( $this, 'addLoginFailedWarningMessage' ), 10000, 1 );
|
46 |
-
// add_filter( $oFO->prefix( 'has_permission_to_manage' ), array( $this, 'isCurrentIpWhitelisted' ), 30, 0 );
|
47 |
add_action( 'template_redirect', array( $this, 'doTrack404' ) );
|
48 |
}
|
49 |
|
43 |
}
|
44 |
|
45 |
add_filter( 'authenticate', array( $this, 'addLoginFailedWarningMessage' ), 10000, 1 );
|
|
|
46 |
add_action( 'template_redirect', array( $this, 'doTrack404' ) );
|
47 |
}
|
48 |
|
src/processors/license.php
CHANGED
@@ -33,7 +33,7 @@ class ICWP_WPSF_Processor_License extends ICWP_WPSF_Processor_BaseWpsf {
|
|
33 |
|
34 |
case 'license_check':
|
35 |
if ( !wp_next_scheduled( $oFO->prefix( 'adhoc_cron_license_check' ) ) ) {
|
36 |
-
wp_schedule_single_event( $oReq->ts() +
|
37 |
}
|
38 |
break;
|
39 |
}
|
33 |
|
34 |
case 'license_check':
|
35 |
if ( !wp_next_scheduled( $oFO->prefix( 'adhoc_cron_license_check' ) ) ) {
|
36 |
+
wp_schedule_single_event( $oReq->ts() + 20, $oFO->prefix( 'adhoc_cron_license_check' ), array( true ) );
|
37 |
}
|
38 |
break;
|
39 |
}
|
src/processors/lockdown.php
CHANGED
@@ -68,6 +68,7 @@ class ICWP_WPSF_Processor_Lockdown extends ICWP_WPSF_Processor_BaseWpsf {
|
|
68 |
|
69 |
public function onWpInit() {
|
70 |
parent::onWpInit();
|
|
|
71 |
if ( $this->loadWp()->isRest() ) {
|
72 |
$this->processRestApi();
|
73 |
}
|
68 |
|
69 |
public function onWpInit() {
|
70 |
parent::onWpInit();
|
71 |
+
|
72 |
if ( $this->loadWp()->isRest() ) {
|
73 |
$this->processRestApi();
|
74 |
}
|
src/processors/loginprotect_backupcodes.php
DELETED
@@ -1,209 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_BackupCodes', false ) ) {
|
4 |
-
return;
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname( __FILE__ ).'/loginprotect_intentprovider_base.php' );
|
8 |
-
|
9 |
-
class ICWP_WPSF_Processor_LoginProtect_BackupCodes extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
13 |
-
* functions. Otherwise we need to be careful of mixing up users.
|
14 |
-
* @param WP_User $oUser
|
15 |
-
*/
|
16 |
-
public function addOptionsToUserProfile( $oUser ) {
|
17 |
-
$oCon = $this->getController();
|
18 |
-
|
19 |
-
$bValidatedProfile = $this->hasValidatedProfile( $oUser );
|
20 |
-
$aData = array(
|
21 |
-
'has_mfa' => $this->isUserSubjectToLoginIntent( $oUser ),
|
22 |
-
'has_validated_profile' => $bValidatedProfile,
|
23 |
-
'user_google_authenticator_secret' => $this->getSecret( $oUser ),
|
24 |
-
'is_my_user_profile' => ( $oUser->ID == $this->loadWpUsers()->getCurrentWpUserId() ),
|
25 |
-
'i_am_valid_admin' => $oCon->getHasPermissionToManage(),
|
26 |
-
'user_to_edit_is_admin' => $this->loadWpUsers()->isUserAdmin( $oUser ),
|
27 |
-
'strings' => array(
|
28 |
-
'button_gen_code' => _wpsf__( 'Generate ONE-Time Backup 2FA Login Code' ),
|
29 |
-
'button_del_code' => _wpsf__( 'Delete Login Backup Code' ),
|
30 |
-
'not_available' => _wpsf__( 'Backup login codes are not available if you do not have any other two-factor authentication modes active.' ),
|
31 |
-
'description_code' => _wpsf__( 'Click to generate a backup login code for your two-factor authentication.' ),
|
32 |
-
'description_code_ext1' => sprintf( '%s: %s',
|
33 |
-
_wpsf__( 'Important' ),
|
34 |
-
_wpsf__( 'This code will be displayed only once and you may use it to verify your login only once.' )
|
35 |
-
.' '._wpsf__( 'Store it somewhere safe.' ) ),
|
36 |
-
'description_code_ext2' => _wpsf__( 'Generating a new code will replace your existing code.' ),
|
37 |
-
'description_chart_url' => _wpsf__( 'Use your Google Authenticator app to scan this QR code and enter the one time password below.' ),
|
38 |
-
'description_ga_secret' => _wpsf__( 'If you have a problem with scanning the QR code enter this code manually into the app.' ),
|
39 |
-
'desc_remove' => _wpsf__( 'Check the box to remove Google Authenticator login authentication.' ),
|
40 |
-
'label_check_to_remove' => sprintf( _wpsf__( 'Remove %s' ), _wpsf__( 'Google Authenticator' ) ),
|
41 |
-
'label_enter_code' => _wpsf__( 'Create Backup 2FA Login Code' ),
|
42 |
-
'label_ga_secret' => _wpsf__( 'Manual Code' ),
|
43 |
-
'label_scan_qr_code' => _wpsf__( 'Scan This QR Code' ),
|
44 |
-
'title' => _wpsf__( 'Backup Login Code' ),
|
45 |
-
'cant_add_other_user' => sprintf( _wpsf__( "Sorry, %s may not be added to another user's account." ), 'Backup Codes' ),
|
46 |
-
'cant_remove_admins' => sprintf( _wpsf__( "Sorry, %s may only be removed from another user's account by a Security Administrator." ), _wpsf__( 'Backup Codes' ) ),
|
47 |
-
'provided_by' => sprintf( _wpsf__( 'Provided by %s' ), $oCon->getHumanName() ),
|
48 |
-
'remove_more_info' => sprintf( _wpsf__( 'Understand how to remove Google Authenticator' ) )
|
49 |
-
),
|
50 |
-
'data' => array(
|
51 |
-
'otp_field_name' => $this->getLoginFormParameter()
|
52 |
-
)
|
53 |
-
);
|
54 |
-
|
55 |
-
echo $this->getMod()->renderTemplate( 'snippets/user_profile_backupcode.php', $aData );
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* @param WP_User $oUser
|
60 |
-
*/
|
61 |
-
public function addOptionsToUserEditProfile( $oUser ) {
|
62 |
-
// Allow no actions to be taken on other user profiles
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* @param array $aFields
|
67 |
-
* @return array
|
68 |
-
*/
|
69 |
-
public function addLoginIntentField( $aFields ) {
|
70 |
-
if ( $this->getCurrentUserHasValidatedProfile() ) {
|
71 |
-
$aFields[] = array(
|
72 |
-
'name' => $this->getLoginFormParameter(),
|
73 |
-
'type' => 'text',
|
74 |
-
'value' => '',
|
75 |
-
'placeholder' => _wpsf__( 'Please use your Backup Code to login.' ),
|
76 |
-
'text' => _wpsf__( 'Login Backup Code' ),
|
77 |
-
'help_link' => '',
|
78 |
-
);
|
79 |
-
}
|
80 |
-
return $aFields;
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Backup codes shouldn't make a user subject to login intent, but only be presented as required
|
85 |
-
* - i.e. they have other MFA options but they can't be used at the moment. So no MFA options =
|
86 |
-
* no need for backup codes
|
87 |
-
* @param bool $bIsSubjectTo
|
88 |
-
* @param WP_User $oUser
|
89 |
-
* @return bool
|
90 |
-
*/
|
91 |
-
public function filterUserSubjectToIntent( $bIsSubjectTo, $oUser ) {
|
92 |
-
return $bIsSubjectTo;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* @param WP_User $oUser
|
97 |
-
* @return bool
|
98 |
-
*/
|
99 |
-
protected function hasValidatedProfile( $oUser ) {
|
100 |
-
return $this->hasValidSecret( $oUser );
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* Backup Code are 1-time only and if you have MFA, then we need to remove all the other tracking factors
|
105 |
-
* @param WP_User $oUser
|
106 |
-
* @param string $sOtpCode
|
107 |
-
* @return bool
|
108 |
-
*/
|
109 |
-
protected function processOtp( $oUser, $sOtpCode ) {
|
110 |
-
$bValid = $this->validateBackupCode( $oUser, $sOtpCode );
|
111 |
-
if ( $bValid ) {
|
112 |
-
$this->deleteSecret( $oUser );
|
113 |
-
}
|
114 |
-
return $bValid;
|
115 |
-
}
|
116 |
-
|
117 |
-
/**
|
118 |
-
* @param WP_User $oUser
|
119 |
-
* @param string $sOtpCode
|
120 |
-
* @return bool
|
121 |
-
*/
|
122 |
-
private function validateBackupCode( $oUser, $sOtpCode ) {
|
123 |
-
return wp_check_password( str_replace( '-', '', $sOtpCode ), $this->getSecret( $oUser ) );
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* @param WP_User $oUser
|
128 |
-
* @param bool $bIsSuccess
|
129 |
-
*/
|
130 |
-
protected function auditLogin( $oUser, $bIsSuccess ) {
|
131 |
-
if ( $bIsSuccess ) {
|
132 |
-
$this->addToAuditEntry(
|
133 |
-
sprintf( _wpsf__( 'User "%s" verified their identity using %s method.' ),
|
134 |
-
$oUser->user_login, _wpsf__( 'Backup Code' )
|
135 |
-
), 2, 'login_protect_bc_verified'
|
136 |
-
);
|
137 |
-
$this->doStatIncrement( 'login.backupcode.verified' );
|
138 |
-
}
|
139 |
-
else {
|
140 |
-
$this->addToAuditEntry(
|
141 |
-
sprintf( _wpsf__( 'User "%s" failed to verify their identity using %s method.' ),
|
142 |
-
$oUser->user_login, _wpsf__( 'Backup Code' )
|
143 |
-
), 2, 'login_protect_bc_failed'
|
144 |
-
);
|
145 |
-
$this->doStatIncrement( 'login.backupcode.fail' );
|
146 |
-
}
|
147 |
-
}
|
148 |
-
|
149 |
-
/**
|
150 |
-
* @param WP_User $oUser
|
151 |
-
* @param bool $bIsOtpSuccess
|
152 |
-
* @param bool $bOtpProvided - whether a OTP was actually provided
|
153 |
-
* @return $this
|
154 |
-
*/
|
155 |
-
protected function postOtpProcessAction( $oUser, $bIsOtpSuccess, $bOtpProvided ) {
|
156 |
-
parent::postOtpProcessAction( $oUser, $bIsOtpSuccess, $bOtpProvided );
|
157 |
-
|
158 |
-
if ( $bOtpProvided && $bIsOtpSuccess ) {
|
159 |
-
$this->sendBackupCodeUsedEmail( $oUser );
|
160 |
-
}
|
161 |
-
return $this;
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* @param WP_User $oUser
|
166 |
-
*/
|
167 |
-
private function sendBackupCodeUsedEmail( $oUser ) {
|
168 |
-
$aEmailContent = array(
|
169 |
-
_wpsf__( 'This is a quick notice to inform you that your Backup Login code was just used.' ),
|
170 |
-
_wpsf__( "Your WordPress account had only 1 backup login code." )
|
171 |
-
.' '._wpsf__( "You must go to your profile and regenerate a new code if you want to use this method again." ),
|
172 |
-
'',
|
173 |
-
sprintf( '<strong>%s</strong>', _wpsf__( 'Login Details' ) ),
|
174 |
-
sprintf( '%s: %s', _wpsf__( 'URL' ), $this->loadWp()->getHomeUrl() ),
|
175 |
-
sprintf( '%s: %s', _wpsf__( 'Username' ), $oUser->user_login ),
|
176 |
-
sprintf( '%s: %s', _wpsf__( 'IP Address' ), $this->ip() ),
|
177 |
-
'',
|
178 |
-
_wpsf__( 'Thank You.' ),
|
179 |
-
);
|
180 |
-
|
181 |
-
$sTitle = sprintf( _wpsf__( "Notice: %s" ), _wpsf__( "Backup Login Code Just Used" ) );
|
182 |
-
$this->getEmailProcessor()
|
183 |
-
->sendEmailWithWrap( $oUser->user_email, $sTitle, $aEmailContent );
|
184 |
-
}
|
185 |
-
|
186 |
-
/**
|
187 |
-
* @return string
|
188 |
-
*/
|
189 |
-
protected function genNewSecret() {
|
190 |
-
return wp_generate_password( 25, false );
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* @param WP_User $oUser
|
195 |
-
* @param string $sNewSecret
|
196 |
-
* @return $this
|
197 |
-
*/
|
198 |
-
protected function setSecret( $oUser, $sNewSecret ) {
|
199 |
-
parent::setSecret( $oUser, wp_hash_password( $sNewSecret ) );
|
200 |
-
return $this;
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* @return string
|
205 |
-
*/
|
206 |
-
protected function getStub() {
|
207 |
-
return ICWP_WPSF_Processor_LoginProtect_Track::Factor_BackupCode;
|
208 |
-
}
|
209 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/processors/loginprotect_cooldown.php
CHANGED
@@ -58,7 +58,7 @@ class ICWP_WPSF_Processor_LoginProtect_Cooldown extends ICWP_WPSF_Processor_Logi
|
|
58 |
* @return string
|
59 |
*/
|
60 |
protected function getLastLoginTimeFilePath() {
|
61 |
-
return
|
62 |
}
|
63 |
|
64 |
/**
|
58 |
* @return string
|
59 |
*/
|
60 |
protected function getLastLoginTimeFilePath() {
|
61 |
+
return path_join( $this->getController()->getRootDir(), 'mode.login_throttled' );
|
62 |
}
|
63 |
|
64 |
/**
|
src/processors/loginprotect_googleauthenticator.php
DELETED
@@ -1,344 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator', false ) ) {
|
4 |
-
return;
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname( __FILE__ ).'/loginprotect_intentprovider_base.php' );
|
8 |
-
|
9 |
-
class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
|
10 |
-
|
11 |
-
/**
|
12 |
-
*/
|
13 |
-
public function run() {
|
14 |
-
parent::run();
|
15 |
-
if ( $this->loadRequest()->query( 'shield_action' ) == 'garemovalconfirm' ) {
|
16 |
-
add_action( 'wp_loaded', array( $this, 'validateUserGaRemovalLink' ), 10 );
|
17 |
-
}
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
22 |
-
* functions. Otherwise we need to be careful of mixing up users.
|
23 |
-
* @param WP_User $oUser
|
24 |
-
*/
|
25 |
-
public function addOptionsToUserProfile( $oUser ) {
|
26 |
-
$oCon = $this->getController();
|
27 |
-
|
28 |
-
$bValidatedProfile = $this->hasValidatedProfile( $oUser );
|
29 |
-
$aData = array(
|
30 |
-
'has_validated_profile' => $bValidatedProfile,
|
31 |
-
'user_google_authenticator_secret' => $this->getSecret( $oUser ),
|
32 |
-
'is_my_user_profile' => ( $oUser->ID == $this->loadWpUsers()->getCurrentWpUserId() ),
|
33 |
-
'i_am_valid_admin' => $oCon->getHasPermissionToManage(),
|
34 |
-
'user_to_edit_is_admin' => $this->loadWpUsers()->isUserAdmin( $oUser ),
|
35 |
-
'strings' => array(
|
36 |
-
'description_otp_code' => _wpsf__( 'Provide the current code generated by your Google Authenticator app.' ),
|
37 |
-
'description_otp_code_ext' => _wpsf__( 'To reset this QR Code enter fake data here.' ),
|
38 |
-
'description_chart_url' => _wpsf__( 'Use your Google Authenticator app to scan this QR code and enter the one time password below.' ),
|
39 |
-
'description_ga_secret' => _wpsf__( 'If you have a problem with scanning the QR code enter this code manually into the app.' ),
|
40 |
-
'desc_remove' => _wpsf__( 'Check the box to remove Google Authenticator login authentication.' ),
|
41 |
-
'label_check_to_remove' => sprintf( _wpsf__( 'Remove %s' ), _wpsf__( 'Google Authenticator' ) ),
|
42 |
-
'label_enter_code' => _wpsf__( 'Google Authenticator Code' ),
|
43 |
-
'label_ga_secret' => _wpsf__( 'Manual Code' ),
|
44 |
-
'label_scan_qr_code' => _wpsf__( 'Scan This QR Code' ),
|
45 |
-
'title' => _wpsf__( 'Google Authenticator' ),
|
46 |
-
'cant_add_other_user' => sprintf( _wpsf__( "Sorry, %s may not be added to another user's account." ), 'Google Authenticator' ),
|
47 |
-
'cant_remove_admins' => sprintf( _wpsf__( "Sorry, %s may only be removed from another user's account by a Security Administrator." ), _wpsf__( 'Google Authenticator' ) ),
|
48 |
-
'provided_by' => sprintf( _wpsf__( 'Provided by %s' ), $oCon->getHumanName() ),
|
49 |
-
'remove_more_info' => sprintf( _wpsf__( 'Understand how to remove Google Authenticator' ) )
|
50 |
-
),
|
51 |
-
'data' => array(
|
52 |
-
'otp_field_name' => $this->getLoginFormParameter()
|
53 |
-
)
|
54 |
-
);
|
55 |
-
|
56 |
-
if ( !$bValidatedProfile ) {
|
57 |
-
$aData[ 'chart_url' ] = $this->getGaRegisterChartUrl( $oUser );
|
58 |
-
}
|
59 |
-
|
60 |
-
echo $this->getMod()->renderTemplate( 'snippets/user_profile_googleauthenticator.php', $aData );
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* @param WP_User $oUser
|
65 |
-
* @return string
|
66 |
-
*/
|
67 |
-
public function getGaRegisterChartUrl( $oUser ) {
|
68 |
-
if ( empty( $oUser ) ) {
|
69 |
-
$sUrl = '';
|
70 |
-
}
|
71 |
-
else {
|
72 |
-
$sUrl = $this->loadGoogleAuthenticatorProcessor()
|
73 |
-
->getGoogleQrChartUrl(
|
74 |
-
$this->getSecret( $oUser ),
|
75 |
-
preg_replace( '#[^0-9a-z]#i', '', $oUser->user_login )
|
76 |
-
.'@'.preg_replace( '#[^0-9a-z]#i', '', $this->loadWp()->getSiteName() )
|
77 |
-
);
|
78 |
-
}
|
79 |
-
return $sUrl;
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* The only thing we can do is REMOVE Google Authenticator from an account that is not our own
|
84 |
-
* But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
|
85 |
-
* @param int $nSavingUserId
|
86 |
-
*/
|
87 |
-
public function handleEditOtherUserProfileSubmit( $nSavingUserId ) {
|
88 |
-
|
89 |
-
// Can only edit other users if you're admin/security-admin
|
90 |
-
if ( $this->getController()->getHasPermissionToManage() ) {
|
91 |
-
$oWpUsers = $this->loadWpUsers();
|
92 |
-
$oSavingUser = $oWpUsers->getUserById( $nSavingUserId );
|
93 |
-
|
94 |
-
$sShieldTurnOff = $this->loadRequest()->post( 'shield_turn_off_google_authenticator' );
|
95 |
-
if ( !empty( $sShieldTurnOff ) && $sShieldTurnOff == 'Y' ) {
|
96 |
-
|
97 |
-
$bPermissionToRemoveGa = true;
|
98 |
-
// if the current user has Google Authenticator on THEIR account, process their OTP.
|
99 |
-
$oCurrentUser = $oWpUsers->getCurrentWpUser();
|
100 |
-
if ( $this->hasValidatedProfile( $oCurrentUser ) ) {
|
101 |
-
$bPermissionToRemoveGa = $this->processOtp( $oCurrentUser, $this->fetchCodeFromRequest() );
|
102 |
-
}
|
103 |
-
|
104 |
-
if ( $bPermissionToRemoveGa ) {
|
105 |
-
$this->processRemovalFromAccount( $oSavingUser );
|
106 |
-
$sMsg = _wpsf__( 'Google Authenticator was successfully removed from the account.' );
|
107 |
-
}
|
108 |
-
else {
|
109 |
-
$sMsg = _wpsf__( 'Google Authenticator could not be removed from the account - ensure your code is correct.' );
|
110 |
-
}
|
111 |
-
$this->getMod()->setFlashAdminNotice( $sMsg, $bPermissionToRemoveGa );
|
112 |
-
}
|
113 |
-
}
|
114 |
-
else {
|
115 |
-
// DO NOTHING EVER
|
116 |
-
}
|
117 |
-
}
|
118 |
-
|
119 |
-
/**
|
120 |
-
* @param WP_User $oUser
|
121 |
-
* @return $this
|
122 |
-
*/
|
123 |
-
protected function processRemovalFromAccount( $oUser ) {
|
124 |
-
$this->setProfileValidated( $oUser, false )
|
125 |
-
->resetSecret( $oUser );
|
126 |
-
return $this;
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile,
|
131 |
-
* so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
|
132 |
-
* @param int $nSavingUserId
|
133 |
-
*/
|
134 |
-
public function handleUserProfileSubmit( $nSavingUserId ) {
|
135 |
-
$oWpUsers = $this->loadWpUsers();
|
136 |
-
|
137 |
-
$oSavingUser = $oWpUsers->getUserById( $nSavingUserId );
|
138 |
-
|
139 |
-
// If it's your own account, you CANT do anything without your OTP (except turn off via email).
|
140 |
-
$sOtp = $this->fetchCodeFromRequest();
|
141 |
-
$bValidOtp = $this->processOtp( $oSavingUser, $sOtp );
|
142 |
-
|
143 |
-
$sMessageOtpInvalid = _wpsf__( 'One Time Password (OTP) was not valid.' ).' '._wpsf__( 'Please try again.' );
|
144 |
-
|
145 |
-
$sShieldTurnOff = $this->loadRequest()->post( 'shield_turn_off_google_authenticator' );
|
146 |
-
if ( !empty( $sShieldTurnOff ) && $sShieldTurnOff == 'Y' ) {
|
147 |
-
|
148 |
-
$bError = false;
|
149 |
-
if ( $bValidOtp ) {
|
150 |
-
$this->processRemovalFromAccount( $oSavingUser );
|
151 |
-
$sFlash = _wpsf__( 'Google Authenticator was successfully removed from the account.' );
|
152 |
-
}
|
153 |
-
else if ( empty( $sOtp ) ) {
|
154 |
-
|
155 |
-
if ( $this->sendEmailConfirmationGaRemoval( $oSavingUser ) ) {
|
156 |
-
$sFlash = _wpsf__( 'An email has been sent to you in order to confirm Google Authenticator removal' );
|
157 |
-
}
|
158 |
-
else {
|
159 |
-
$bError = true;
|
160 |
-
$sFlash = _wpsf__( 'We tried to send an email for you to confirm Google Authenticator removal but it failed.' );
|
161 |
-
}
|
162 |
-
}
|
163 |
-
else {
|
164 |
-
$bError = true;
|
165 |
-
$sFlash = $sMessageOtpInvalid;
|
166 |
-
}
|
167 |
-
$this->getMod()->setFlashAdminNotice( $sFlash, $bError );
|
168 |
-
return;
|
169 |
-
}
|
170 |
-
|
171 |
-
// At this stage, if the OTP was empty, then we have no further processing to do.
|
172 |
-
if ( empty( $sOtp ) ) {
|
173 |
-
return;
|
174 |
-
}
|
175 |
-
|
176 |
-
// We're trying to validate our OTP to activate our GA
|
177 |
-
if ( !$this->hasValidatedProfile( $oSavingUser ) ) {
|
178 |
-
|
179 |
-
if ( $bValidOtp ) {
|
180 |
-
$this->setProfileValidated( $oSavingUser );
|
181 |
-
$sFlash = sprintf(
|
182 |
-
_wpsf__( '%s was successfully added to your account.' ),
|
183 |
-
_wpsf__( 'Google Authenticator' )
|
184 |
-
);
|
185 |
-
}
|
186 |
-
else {
|
187 |
-
$this->resetSecret( $oSavingUser );
|
188 |
-
$sFlash = $sMessageOtpInvalid;
|
189 |
-
}
|
190 |
-
$this->getMod()->setFlashAdminNotice( $sFlash, !$bValidOtp );
|
191 |
-
}
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* @param array $aFields
|
196 |
-
* @return array
|
197 |
-
*/
|
198 |
-
public function addLoginIntentField( $aFields ) {
|
199 |
-
if ( $this->getCurrentUserHasValidatedProfile() ) {
|
200 |
-
$aFields[] = array(
|
201 |
-
'name' => $this->getLoginFormParameter(),
|
202 |
-
'type' => 'text',
|
203 |
-
'value' => '',
|
204 |
-
'placeholder' => _wpsf__( 'Please use your Google Authenticator App to retrieve your code.' ),
|
205 |
-
'text' => _wpsf__( 'Google Authenticator Code' ),
|
206 |
-
'help_link' => 'https://icwp.io/wpsf42',
|
207 |
-
'extras' => array(
|
208 |
-
'onkeyup' => "this.value=this.value.replace(/[^\d]/g,'')"
|
209 |
-
)
|
210 |
-
);
|
211 |
-
}
|
212 |
-
return $aFields;
|
213 |
-
}
|
214 |
-
|
215 |
-
/**
|
216 |
-
* @param WP_User $oUser
|
217 |
-
* @return bool
|
218 |
-
*/
|
219 |
-
protected function sendEmailConfirmationGaRemoval( $oUser ) {
|
220 |
-
$bSendSuccess = false;
|
221 |
-
|
222 |
-
$aEmailContent = array();
|
223 |
-
$aEmailContent[] = _wpsf__( 'You have requested the removal of Google Authenticator from your WordPress account.' )
|
224 |
-
._wpsf__( 'Please click the link below to confirm.' );
|
225 |
-
$aEmailContent[] = $this->generateGaRemovalConfirmationLink();
|
226 |
-
|
227 |
-
$sRecipient = $oUser->get( 'user_email' );
|
228 |
-
if ( $this->loadDP()->validEmail( $sRecipient ) ) {
|
229 |
-
$sEmailSubject = _wpsf__( 'Google Authenticator Removal Confirmation' );
|
230 |
-
$bSendSuccess = $this->getEmailProcessor()
|
231 |
-
->sendEmailWithWrap( $sRecipient, $sEmailSubject, $aEmailContent );
|
232 |
-
}
|
233 |
-
return $bSendSuccess;
|
234 |
-
}
|
235 |
-
|
236 |
-
/**
|
237 |
-
*/
|
238 |
-
public function validateUserGaRemovalLink() {
|
239 |
-
// Must be already logged in for this link to work.
|
240 |
-
$oWpCurrentUser = $this->loadWpUsers()->getCurrentWpUser();
|
241 |
-
if ( empty( $oWpCurrentUser ) ) {
|
242 |
-
return;
|
243 |
-
}
|
244 |
-
|
245 |
-
// Session IDs must be the same
|
246 |
-
$sSessionId = $this->loadRequest()->query( 'sessionid' );
|
247 |
-
if ( empty( $sSessionId ) || ( $sSessionId !== $this->getController()->getSessionId() ) ) {
|
248 |
-
return;
|
249 |
-
}
|
250 |
-
|
251 |
-
$this->processRemovalFromAccount( $oWpCurrentUser );
|
252 |
-
$this->getMod()
|
253 |
-
->setFlashAdminNotice( _wpsf__( 'Google Authenticator was successfully removed from this account.' ) );
|
254 |
-
$this->loadWp()->redirectToAdmin();
|
255 |
-
}
|
256 |
-
|
257 |
-
/**
|
258 |
-
* @param WP_User $oUser
|
259 |
-
* @param string $sOtpCode
|
260 |
-
* @return bool
|
261 |
-
*/
|
262 |
-
protected function processOtp( $oUser, $sOtpCode ) {
|
263 |
-
return $this->validateGaCode( $oUser, $sOtpCode );
|
264 |
-
}
|
265 |
-
|
266 |
-
/**
|
267 |
-
* @param WP_User $oUser
|
268 |
-
* @param string $sOtpCode
|
269 |
-
* @return bool
|
270 |
-
*/
|
271 |
-
public function validateGaCode( $oUser, $sOtpCode ) {
|
272 |
-
$bValidOtp = false;
|
273 |
-
if ( !empty( $sOtpCode ) && preg_match( '#^[0-9]{6}$#', $sOtpCode ) ) {
|
274 |
-
$bValidOtp = $this->loadGoogleAuthenticatorProcessor()
|
275 |
-
->verifyOtp( $this->getSecret( $oUser ), $sOtpCode );
|
276 |
-
}
|
277 |
-
return $bValidOtp;
|
278 |
-
}
|
279 |
-
|
280 |
-
/**
|
281 |
-
* @param WP_User $oUser
|
282 |
-
* @param bool $bIsSuccess
|
283 |
-
*/
|
284 |
-
protected function auditLogin( $oUser, $bIsSuccess ) {
|
285 |
-
if ( $bIsSuccess ) {
|
286 |
-
$this->addToAuditEntry(
|
287 |
-
sprintf( _wpsf__( 'User "%s" verified their identity using %s method.' ),
|
288 |
-
$oUser->user_login, _wpsf__( 'Google Authenticator' )
|
289 |
-
), 2, 'login_protect_ga_verified'
|
290 |
-
);
|
291 |
-
$this->doStatIncrement( 'login.googleauthenticator.verified' );
|
292 |
-
}
|
293 |
-
else {
|
294 |
-
$this->addToAuditEntry(
|
295 |
-
sprintf( _wpsf__( 'User "%s" failed to verify their identity using %s method.' ),
|
296 |
-
$oUser->user_login, _wpsf__( 'Google Authenticator' )
|
297 |
-
), 2, 'login_protect_ga_failed'
|
298 |
-
);
|
299 |
-
$this->doStatIncrement( 'login.googleauthenticator.fail' );
|
300 |
-
}
|
301 |
-
}
|
302 |
-
|
303 |
-
/**
|
304 |
-
* @return string
|
305 |
-
*/
|
306 |
-
protected function generateGaRemovalConfirmationLink() {
|
307 |
-
$aQueryArgs = array(
|
308 |
-
'shield_action' => 'garemovalconfirm',
|
309 |
-
'sessionid' => $this->getController()->getSessionId()
|
310 |
-
);
|
311 |
-
return add_query_arg( $aQueryArgs, $this->loadWp()->getUrl_WpAdmin() );
|
312 |
-
}
|
313 |
-
|
314 |
-
/**
|
315 |
-
* @return string
|
316 |
-
*/
|
317 |
-
protected function genNewSecret() {
|
318 |
-
return $this->loadGoogleAuthenticatorProcessor()->generateNewSecret();
|
319 |
-
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
* @param WP_User $oUser
|
323 |
-
* @return string
|
324 |
-
*/
|
325 |
-
protected function getSecret( WP_User $oUser ) {
|
326 |
-
$sSec = parent::getSecret( $oUser );
|
327 |
-
return empty( $sSec ) ? $this->resetSecret( $oUser ) : $sSec;
|
328 |
-
}
|
329 |
-
|
330 |
-
/**
|
331 |
-
* @return string
|
332 |
-
*/
|
333 |
-
protected function getStub() {
|
334 |
-
return ICWP_WPSF_Processor_LoginProtect_Track::Factor_Google_Authenticator;
|
335 |
-
}
|
336 |
-
|
337 |
-
/**
|
338 |
-
* @param string $sSecret
|
339 |
-
* @return bool
|
340 |
-
*/
|
341 |
-
protected function isSecretValid( $sSecret ) {
|
342 |
-
return parent::isSecretValid( $sSecret ) && ( strlen( $sSecret ) == 16 );
|
343 |
-
}
|
344 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/processors/loginprotect_intent.php
CHANGED
@@ -45,6 +45,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
45 |
|
46 |
public function onWpInit() {
|
47 |
parent::onWpInit();
|
|
|
48 |
$this->setupLoginIntent();
|
49 |
}
|
50 |
|
@@ -110,6 +111,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
110 |
* @param WP_User|WP_Error $oUser
|
111 |
*/
|
112 |
protected function initLoginIntent( $oUser ) {
|
|
|
113 |
if ( !$this->isLoginCaptured() && $oUser instanceof WP_User
|
114 |
&& $this->getLoginTrack()->hasFactorsRemainingToTrack() ) {
|
115 |
|
@@ -129,6 +131,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
129 |
* hooked to 'init' and only run if a user is logged-in (not on the login request)
|
130 |
*/
|
131 |
private function processLoginIntent() {
|
|
|
132 |
$oWpUsers = $this->loadWpUsers();
|
133 |
|
134 |
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
@@ -137,16 +140,16 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
137 |
if ( $this->hasValidLoginIntent() ) { // ie. valid login intent present
|
138 |
$oReq = $this->loadRequest();
|
139 |
|
140 |
-
|
141 |
-
if ( $
|
142 |
|
143 |
if ( $oReq->post( 'cancel' ) == 1 ) {
|
144 |
$oWpUsers->logoutUser(); // clears the login and login intent
|
145 |
-
$
|
146 |
-
|
147 |
}
|
|
|
148 |
|
149 |
-
if ( $this->isLoginIntentValid() ) {
|
150 |
if ( $oReq->post( 'skip_mfa' ) === 'Y' ) { // store the browser hash
|
151 |
$oFO->addMfaLoginHash( $oWpUsers->getCurrentWpUser() );
|
152 |
}
|
@@ -160,11 +163,15 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
160 |
|
161 |
$oFO->setFlashAdminNotice( $sFlash )
|
162 |
->setOptInsightsAt( 'last_2fa_login_at' );
|
|
|
|
|
|
|
163 |
}
|
164 |
else {
|
165 |
$oFO->setFlashAdminNotice( _wpsf__( 'One or more of your authentication codes failed or was missing' ), true );
|
|
|
166 |
}
|
167 |
-
|
168 |
}
|
169 |
if ( $this->printLoginIntentForm() ) {
|
170 |
die();
|
@@ -185,7 +192,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
185 |
* Use this ONLY when the login intent has been successfully verified.
|
186 |
* @return $this
|
187 |
*/
|
188 |
-
|
189 |
return $this->setLoginIntentExpiresAt( 0 );
|
190 |
}
|
191 |
|
@@ -248,6 +255,7 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
248 |
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
249 |
$oFO = $this->getMod();
|
250 |
$oCon = $this->getController();
|
|
|
251 |
$aLoginIntentFields = apply_filters( $oFO->prefix( 'login-intent-form-fields' ), array() );
|
252 |
|
253 |
if ( empty( $aLoginIntentFields ) ) {
|
@@ -271,7 +279,26 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
271 |
$sMessageType = 'warning';
|
272 |
}
|
273 |
|
274 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
|
276 |
$aLabels = $oCon->getPluginLabels();
|
277 |
$sBannerUrl = empty( $aLabels[ 'url_login2fa_logourl' ] ) ? $oCon->getPluginUrl_Image( 'pluginlogo_banner-772x250.png' ) : $aLabels[ 'url_login2fa_logourl' ];
|
@@ -300,12 +327,13 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
|
|
300 |
'login_intent_flag' => $oFO->getLoginIntentRequestFlag()
|
301 |
),
|
302 |
'hrefs' => array(
|
303 |
-
'form_action' => $
|
304 |
'css_bootstrap' => $oCon->getPluginUrl_Css( 'bootstrap4.min.css' ),
|
305 |
'js_bootstrap' => $oCon->getPluginUrl_Js( 'bootstrap4.min.js' ),
|
306 |
'shield_logo' => 'https://ps.w.org/wp-simple-firewall/assets/banner-772x250.png',
|
307 |
'redirect_to' => $sRedirectTo,
|
308 |
'what_is_this' => 'https://icontrolwp.freshdesk.com/support/solutions/articles/3000064840',
|
|
|
309 |
),
|
310 |
'imgs' => array(
|
311 |
'banner' => $sBannerUrl,
|
45 |
|
46 |
public function onWpInit() {
|
47 |
parent::onWpInit();
|
48 |
+
|
49 |
$this->setupLoginIntent();
|
50 |
}
|
51 |
|
111 |
* @param WP_User|WP_Error $oUser
|
112 |
*/
|
113 |
protected function initLoginIntent( $oUser ) {
|
114 |
+
|
115 |
if ( !$this->isLoginCaptured() && $oUser instanceof WP_User
|
116 |
&& $this->getLoginTrack()->hasFactorsRemainingToTrack() ) {
|
117 |
|
131 |
* hooked to 'init' and only run if a user is logged-in (not on the login request)
|
132 |
*/
|
133 |
private function processLoginIntent() {
|
134 |
+
$oWp = $this->loadWp();
|
135 |
$oWpUsers = $this->loadWpUsers();
|
136 |
|
137 |
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
140 |
if ( $this->hasValidLoginIntent() ) { // ie. valid login intent present
|
141 |
$oReq = $this->loadRequest();
|
142 |
|
143 |
+
// Is 2FA/login-intent submit
|
144 |
+
if ( $oReq->request( $oFO->getLoginIntentRequestFlag() ) == 1 ) {
|
145 |
|
146 |
if ( $oReq->post( 'cancel' ) == 1 ) {
|
147 |
$oWpUsers->logoutUser(); // clears the login and login intent
|
148 |
+
$sRedirectHref = $oReq->post( 'cancel_href' );
|
149 |
+
empty( $sRedirectHref ) ? $oWp->redirectToLogin() : $oWp->doRedirect( rawurldecode( $sRedirectHref ) );
|
150 |
}
|
151 |
+
else if ( $this->isLoginIntentValid() ) {
|
152 |
|
|
|
153 |
if ( $oReq->post( 'skip_mfa' ) === 'Y' ) { // store the browser hash
|
154 |
$oFO->addMfaLoginHash( $oWpUsers->getCurrentWpUser() );
|
155 |
}
|
163 |
|
164 |
$oFO->setFlashAdminNotice( $sFlash )
|
165 |
->setOptInsightsAt( 'last_2fa_login_at' );
|
166 |
+
|
167 |
+
$sRedirectHref = $oReq->post( 'redirect_to' );
|
168 |
+
empty( $sRedirectHref ) ? $oWp->redirectHere() : $oWp->doRedirect( rawurldecode( $sRedirectHref ) );
|
169 |
}
|
170 |
else {
|
171 |
$oFO->setFlashAdminNotice( _wpsf__( 'One or more of your authentication codes failed or was missing' ), true );
|
172 |
+
$this->loadWp()->redirectHere();
|
173 |
}
|
174 |
+
return; // we've redirected anyway.
|
175 |
}
|
176 |
if ( $this->printLoginIntentForm() ) {
|
177 |
die();
|
192 |
* Use this ONLY when the login intent has been successfully verified.
|
193 |
* @return $this
|
194 |
*/
|
195 |
+
private function removeLoginIntent() {
|
196 |
return $this->setLoginIntentExpiresAt( 0 );
|
197 |
}
|
198 |
|
255 |
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
256 |
$oFO = $this->getMod();
|
257 |
$oCon = $this->getController();
|
258 |
+
$oReq = $this->loadRequest();
|
259 |
$aLoginIntentFields = apply_filters( $oFO->prefix( 'login-intent-form-fields' ), array() );
|
260 |
|
261 |
if ( empty( $aLoginIntentFields ) ) {
|
279 |
$sMessageType = 'warning';
|
280 |
}
|
281 |
|
282 |
+
$sReferUrl = $oReq->server( 'HTTP_REFERER', '' );
|
283 |
+
if ( strpos( $sReferUrl, '?' ) ) {
|
284 |
+
list( $sReferUrl, $sReferQuery ) = explode( '?', $sReferUrl, 2 );
|
285 |
+
}
|
286 |
+
else {
|
287 |
+
$sReferQuery = '';
|
288 |
+
}
|
289 |
+
|
290 |
+
$sRedirectTo = $oReq->post( 'redirect_to', '' );
|
291 |
+
if ( !empty( $sReferQuery ) ) {
|
292 |
+
parse_str( $sReferQuery, $aReferQueryItems );
|
293 |
+
if ( !empty( $aReferQueryItems[ 'redirect_to' ] ) ) {
|
294 |
+
$sRedirectTo = rawurlencode( $aReferQueryItems[ 'redirect_to' ] );
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
$sCancelHref = $oReq->post( 'cancel_href', '' );
|
299 |
+
if ( empty( $sCancelHref ) && $this->loadDP()->isValidUrl( $sReferUrl ) ) {
|
300 |
+
$sCancelHref = rawurlencode( parse_url( $sReferUrl, PHP_URL_PATH ) );
|
301 |
+
}
|
302 |
|
303 |
$aLabels = $oCon->getPluginLabels();
|
304 |
$sBannerUrl = empty( $aLabels[ 'url_login2fa_logourl' ] ) ? $oCon->getPluginUrl_Image( 'pluginlogo_banner-772x250.png' ) : $aLabels[ 'url_login2fa_logourl' ];
|
327 |
'login_intent_flag' => $oFO->getLoginIntentRequestFlag()
|
328 |
),
|
329 |
'hrefs' => array(
|
330 |
+
'form_action' => $oReq->getUri(),
|
331 |
'css_bootstrap' => $oCon->getPluginUrl_Css( 'bootstrap4.min.css' ),
|
332 |
'js_bootstrap' => $oCon->getPluginUrl_Js( 'bootstrap4.min.js' ),
|
333 |
'shield_logo' => 'https://ps.w.org/wp-simple-firewall/assets/banner-772x250.png',
|
334 |
'redirect_to' => $sRedirectTo,
|
335 |
'what_is_this' => 'https://icontrolwp.freshdesk.com/support/solutions/articles/3000064840',
|
336 |
+
'cancel_href' => $sCancelHref
|
337 |
),
|
338 |
'imgs' => array(
|
339 |
'banner' => $sBannerUrl,
|
src/processors/loginprotect_intentprovider_backup.php
CHANGED
@@ -22,7 +22,7 @@ class ICWP_WPSF_Processor_LoginProtect_BackupCodes extends ICWP_WPSF_Processor_L
|
|
22 |
'has_validated_profile' => $bValidatedProfile,
|
23 |
'user_google_authenticator_secret' => $this->getSecret( $oUser ),
|
24 |
'is_my_user_profile' => ( $oUser->ID == $this->loadWpUsers()->getCurrentWpUserId() ),
|
25 |
-
'i_am_valid_admin' => $oCon->
|
26 |
'user_to_edit_is_admin' => $this->loadWpUsers()->isUserAdmin( $oUser ),
|
27 |
'strings' => array(
|
28 |
'button_gen_code' => _wpsf__( 'Generate ONE-Time Backup 2FA Login Code' ),
|
22 |
'has_validated_profile' => $bValidatedProfile,
|
23 |
'user_google_authenticator_secret' => $this->getSecret( $oUser ),
|
24 |
'is_my_user_profile' => ( $oUser->ID == $this->loadWpUsers()->getCurrentWpUserId() ),
|
25 |
+
'i_am_valid_admin' => $oCon->isPluginAdmin(),
|
26 |
'user_to_edit_is_admin' => $this->loadWpUsers()->isUserAdmin( $oUser ),
|
27 |
'strings' => array(
|
28 |
'button_gen_code' => _wpsf__( 'Generate ONE-Time Backup 2FA Login Code' ),
|
src/processors/loginprotect_intentprovider_base.php
CHANGED
@@ -36,7 +36,7 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentProviderBase extends ICWP_
|
|
36 |
add_action( 'show_user_profile', array( $this, 'addOptionsToUserProfile' ) );
|
37 |
add_action( 'personal_options_update', array( $this, 'handleUserProfileSubmit' ) );
|
38 |
|
39 |
-
if ( $this->getController()->
|
40 |
add_action( 'edit_user_profile', array( $this, 'addOptionsToUserEditProfile' ) );
|
41 |
add_action( 'edit_user_profile_update', array( $this, 'handleEditOtherUserProfileSubmit' ) );
|
42 |
}
|
36 |
add_action( 'show_user_profile', array( $this, 'addOptionsToUserProfile' ) );
|
37 |
add_action( 'personal_options_update', array( $this, 'handleUserProfileSubmit' ) );
|
38 |
|
39 |
+
if ( $this->getController()->isPluginAdmin() ) {
|
40 |
add_action( 'edit_user_profile', array( $this, 'addOptionsToUserEditProfile' ) );
|
41 |
add_action( 'edit_user_profile_update', array( $this, 'handleEditOtherUserProfileSubmit' ) );
|
42 |
}
|
src/processors/loginprotect_intentprovider_email.php
CHANGED
@@ -203,7 +203,7 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor
|
|
203 |
'user_has_email_authentication_active' => $bValidatedProfile,
|
204 |
'user_has_email_authentication_enforced' => $this->isSubjectToEmailAuthentication( $oUser ),
|
205 |
'is_my_user_profile' => ( $oUser->ID == $oWp->getCurrentWpUserId() ),
|
206 |
-
'i_am_valid_admin' => $this->getController()->
|
207 |
'user_to_edit_is_admin' => $oWp->isUserAdmin( $oUser ),
|
208 |
'strings' => array(
|
209 |
'label_email_authentication' => _wpsf__( 'Email Authentication' ),
|
203 |
'user_has_email_authentication_active' => $bValidatedProfile,
|
204 |
'user_has_email_authentication_enforced' => $this->isSubjectToEmailAuthentication( $oUser ),
|
205 |
'is_my_user_profile' => ( $oUser->ID == $oWp->getCurrentWpUserId() ),
|
206 |
+
'i_am_valid_admin' => $this->getController()->isPluginAdmin(),
|
207 |
'user_to_edit_is_admin' => $oWp->isUserAdmin( $oUser ),
|
208 |
'strings' => array(
|
209 |
'label_email_authentication' => _wpsf__( 'Email Authentication' ),
|
src/processors/loginprotect_intentprovider_ga.php
CHANGED
@@ -30,7 +30,7 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
|
|
30 |
'has_validated_profile' => $bValidatedProfile,
|
31 |
'user_google_authenticator_secret' => $this->getSecret( $oUser ),
|
32 |
'is_my_user_profile' => ( $oUser->ID == $this->loadWpUsers()->getCurrentWpUserId() ),
|
33 |
-
'i_am_valid_admin' => $oCon->
|
34 |
'user_to_edit_is_admin' => $this->loadWpUsers()->isUserAdmin( $oUser ),
|
35 |
'strings' => array(
|
36 |
'description_otp_code' => _wpsf__( 'Provide the current code generated by your Google Authenticator app.' ),
|
@@ -87,7 +87,7 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
|
|
87 |
public function handleEditOtherUserProfileSubmit( $nSavingUserId ) {
|
88 |
|
89 |
// Can only edit other users if you're admin/security-admin
|
90 |
-
if ( $this->getController()->
|
91 |
$oWpUsers = $this->loadWpUsers();
|
92 |
$oSavingUser = $oWpUsers->getUserById( $nSavingUserId );
|
93 |
|
30 |
'has_validated_profile' => $bValidatedProfile,
|
31 |
'user_google_authenticator_secret' => $this->getSecret( $oUser ),
|
32 |
'is_my_user_profile' => ( $oUser->ID == $this->loadWpUsers()->getCurrentWpUserId() ),
|
33 |
+
'i_am_valid_admin' => $oCon->isPluginAdmin(),
|
34 |
'user_to_edit_is_admin' => $this->loadWpUsers()->isUserAdmin( $oUser ),
|
35 |
'strings' => array(
|
36 |
'description_otp_code' => _wpsf__( 'Provide the current code generated by your Google Authenticator app.' ),
|
87 |
public function handleEditOtherUserProfileSubmit( $nSavingUserId ) {
|
88 |
|
89 |
// Can only edit other users if you're admin/security-admin
|
90 |
+
if ( $this->getController()->isPluginAdmin() ) {
|
91 |
$oWpUsers = $this->loadWpUsers();
|
92 |
$oSavingUser = $oWpUsers->getUserById( $nSavingUserId );
|
93 |
|
src/processors/loginprotect_intentprovider_yubikey.php
CHANGED
@@ -27,7 +27,7 @@ class ICWP_WPSF_Processor_LoginProtect_Yubikey extends ICWP_WPSF_Processor_Login
|
|
27 |
$aData = array(
|
28 |
'has_validated_profile' => $bValidatedProfile,
|
29 |
'is_my_user_profile' => ( $oUser->ID == $oWpUsers->getCurrentWpUserId() ),
|
30 |
-
'i_am_valid_admin' => $oCon->
|
31 |
'user_to_edit_is_admin' => $oWpUsers->isUserAdmin( $oUser ),
|
32 |
'strings' => array(
|
33 |
'description_otp_code' => _wpsf__( 'This is your unique Yubikey Device ID.' ),
|
27 |
$aData = array(
|
28 |
'has_validated_profile' => $bValidatedProfile,
|
29 |
'is_my_user_profile' => ( $oUser->ID == $oWpUsers->getCurrentWpUserId() ),
|
30 |
+
'i_am_valid_admin' => $oCon->isPluginAdmin(),
|
31 |
'user_to_edit_is_admin' => $oWpUsers->isUserAdmin( $oUser ),
|
32 |
'strings' => array(
|
33 |
'description_otp_code' => _wpsf__( 'This is your unique Yubikey Device ID.' ),
|
src/processors/loginprotect_track.php
DELETED
@@ -1,166 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_Track', false ) ) {
|
4 |
-
return;
|
5 |
-
}
|
6 |
-
|
7 |
-
class ICWP_WPSF_Processor_LoginProtect_Track {
|
8 |
-
|
9 |
-
const Factor_Google_Authenticator = 'ga';
|
10 |
-
const Factor_Yubikey = 'yubi';
|
11 |
-
const Factor_Email = 'email';
|
12 |
-
const Factor_BackupCode = 'backupcode';
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @var array
|
16 |
-
*/
|
17 |
-
private $aFactorsTracked;
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @var array
|
21 |
-
*/
|
22 |
-
private $aFactorsToTrack;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @param string $sFactor
|
26 |
-
* @return $this
|
27 |
-
*/
|
28 |
-
public function addFactorToTrack( $sFactor ) {
|
29 |
-
$aFactorsToTrack = $this->getAuthFactorsToTrack();
|
30 |
-
$aFactorsToTrack[ $sFactor ] = true;
|
31 |
-
$this->aFactorsToTrack = $aFactorsToTrack;
|
32 |
-
return $this;
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @param string $sFactor
|
37 |
-
* @return $this
|
38 |
-
*/
|
39 |
-
public function addSuccessfulFactor( $sFactor ) {
|
40 |
-
return $this->setFactorState( $sFactor, true );
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* @param string $sFactor
|
45 |
-
* @return $this
|
46 |
-
*/
|
47 |
-
public function addUnSuccessfulFactor( $sFactor ) {
|
48 |
-
return $this->setFactorState( $sFactor, false );
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @return array
|
53 |
-
*/
|
54 |
-
public function getAuthFactorsTracked() {
|
55 |
-
if ( !isset( $this->aFactorsTracked ) ) {
|
56 |
-
$this->aFactorsTracked = array();
|
57 |
-
}
|
58 |
-
return $this->aFactorsTracked;
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* @return array
|
63 |
-
*/
|
64 |
-
public function getAuthFactorsToTrack() {
|
65 |
-
if ( !is_array( $this->aFactorsToTrack ) ) {
|
66 |
-
$this->aFactorsToTrack = array();
|
67 |
-
}
|
68 |
-
return array_unique( $this->aFactorsToTrack );
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* @return int
|
73 |
-
*/
|
74 |
-
public function getCountAuthFactorsTrackedTotal() {
|
75 |
-
return count( $this->getAuthFactorsTracked() );
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Works by using array_filter() with no callback, so only those values in the
|
80 |
-
* array that don't evaluate as false are returned. #SuperOmgElegant :)
|
81 |
-
* @return int
|
82 |
-
*/
|
83 |
-
public function getCountFactorsSuccessful() {
|
84 |
-
return count( $this->getFactorsSuccessful() );
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* @return array
|
89 |
-
*/
|
90 |
-
public function getFactorsSuccessful() {
|
91 |
-
return array_keys( array_filter( $this->getAuthFactorsTracked() ) ); // filter out the 'falses'
|
92 |
-
}
|
93 |
-
|
94 |
-
/**
|
95 |
-
* @return array
|
96 |
-
*/
|
97 |
-
public function getFactorsUnsuccessful() {
|
98 |
-
return array_diff( array_keys( $this->getAuthFactorsTracked() ), $this->getFactorsSuccessful() );
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* @return int
|
103 |
-
*/
|
104 |
-
public function getCountFactorsUnsuccessful() {
|
105 |
-
return ( $this->getCountAuthFactorsTrackedTotal() - $this->getCountFactorsSuccessful() );
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* @return int
|
110 |
-
*/
|
111 |
-
public function getCountFactorsRemainingToTrack() {
|
112 |
-
return count( $this->getAuthFactorsToTrack() );
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* @return bool
|
117 |
-
*/
|
118 |
-
public function hasFactorsRemainingToTrack() {
|
119 |
-
return ( $this->getCountFactorsRemainingToTrack() > 0 );
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* @return bool
|
124 |
-
*/
|
125 |
-
public function hasSuccessfulFactor() {
|
126 |
-
return ( $this->getCountFactorsSuccessful() > 0 );
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* @return bool
|
131 |
-
*/
|
132 |
-
public function hasUnSuccessfulFactor() {
|
133 |
-
return ( $this->getCountFactorsUnsuccessful() > 0 );
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* @return bool
|
138 |
-
*/
|
139 |
-
public function isFinalFactorRemainingToTrack() {
|
140 |
-
return ( $this->getCountFactorsRemainingToTrack() === 1 );
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* @param string $sFactor
|
145 |
-
* @return $this
|
146 |
-
*/
|
147 |
-
public function removeFactorToTrack( $sFactor ) {
|
148 |
-
$aFactorsToTrack = $this->getAuthFactorsToTrack();
|
149 |
-
unset( $aFactorsToTrack[ $sFactor ] );
|
150 |
-
$this->aFactorsToTrack = $aFactorsToTrack;
|
151 |
-
return $this;
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Also remove remaining factors to track
|
156 |
-
* @param string $sFactor
|
157 |
-
* @param bool $bState
|
158 |
-
* @return $this
|
159 |
-
*/
|
160 |
-
protected function setFactorState( $sFactor, $bState ) {
|
161 |
-
$aFactors = $this->getAuthFactorsTracked();
|
162 |
-
$aFactors[ $sFactor ] = $bState;
|
163 |
-
$this->aFactorsTracked = $aFactors;
|
164 |
-
return $this->removeFactorToTrack( $sFactor );
|
165 |
-
}
|
166 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/processors/loginprotect_twofactorauth.php
DELETED
@@ -1,239 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth', false ) ) {
|
4 |
-
return;
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname( __FILE__ ).'/loginprotect_intentprovider_base.php' );
|
8 |
-
|
9 |
-
class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* @param WP_User|WP_Error|null $oUser
|
13 |
-
* @return WP_Error|WP_User|null - WP_User when the login success AND the IP is authenticated. null when login
|
14 |
-
* not successful but IP is valid. WP_Error otherwise.
|
15 |
-
*/
|
16 |
-
public function processLoginAttempt_Filter( $oUser ) {
|
17 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
18 |
-
$oFO = $this->getMod();
|
19 |
-
|
20 |
-
if ( !$this->isLoginCaptured() && $oUser instanceof WP_User
|
21 |
-
&& $this->hasValidatedProfile( $oUser ) && !$oFO->canUserMfaSkip( $oUser ) ) {
|
22 |
-
|
23 |
-
$oFO->getSessionsProcessor()
|
24 |
-
->getQueryUpdater()
|
25 |
-
->setLoginIntentCodeEmail( $oFO->getSession(), $this->getSecret( $oUser ) );
|
26 |
-
|
27 |
-
// Now send email with authentication link for user.
|
28 |
-
$this->doStatIncrement( 'login.twofactor.started' )
|
29 |
-
->sendEmailTwoFactorVerify( $oUser )
|
30 |
-
->setLoginCaptured();
|
31 |
-
}
|
32 |
-
return $oUser;
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @param WP_User $oUser
|
37 |
-
* @param bool $bIsSuccess
|
38 |
-
*/
|
39 |
-
protected function auditLogin( $oUser, $bIsSuccess ) {
|
40 |
-
if ( $bIsSuccess ) {
|
41 |
-
$this->addToAuditEntry(
|
42 |
-
sprintf( _wpsf__( 'User "%s" verified their identity using %s method.' ),
|
43 |
-
$oUser->user_login, _wpsf__( 'Email Auth' )
|
44 |
-
), 2, 'login_protect_emailauth_verified'
|
45 |
-
);
|
46 |
-
$this->doStatIncrement( 'login.emailauth.verified' );
|
47 |
-
}
|
48 |
-
else {
|
49 |
-
$this->addToAuditEntry(
|
50 |
-
sprintf( _wpsf__( 'User "%s" failed to verify their identity using %s method.' ),
|
51 |
-
$oUser->user_login, _wpsf__( 'Email Auth' )
|
52 |
-
), 2, 'login_protect_emailauth_failed'
|
53 |
-
);
|
54 |
-
$this->doStatIncrement( 'login.emailauth.failed' );
|
55 |
-
}
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* @param WP_User $oUser
|
60 |
-
* @param string $sOtpCode
|
61 |
-
* @return bool
|
62 |
-
*/
|
63 |
-
protected function processOtp( $oUser, $sOtpCode ) {
|
64 |
-
$bValid = !empty( $sOtpCode ) && ( $sOtpCode == $this->getStoredSessionHashCode() );
|
65 |
-
if ( $bValid ) {
|
66 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
67 |
-
$oFO = $this->getMod();
|
68 |
-
$oFO->getSessionsProcessor()
|
69 |
-
->getQueryUpdater()
|
70 |
-
->clearLoginIntentCodeEmail( $oFO->getSession() );
|
71 |
-
}
|
72 |
-
return $bValid;
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* @param array $aFields
|
77 |
-
* @return array
|
78 |
-
*/
|
79 |
-
public function addLoginIntentField( $aFields ) {
|
80 |
-
if ( $this->getCurrentUserHasValidatedProfile() ) {
|
81 |
-
$aFields[] = array(
|
82 |
-
'name' => $this->getLoginFormParameter(),
|
83 |
-
'type' => 'text',
|
84 |
-
'value' => $this->fetchCodeFromRequest(),
|
85 |
-
'placeholder' => _wpsf__( 'This code was just sent to your registered Email address.' ),
|
86 |
-
'text' => _wpsf__( 'Email OTP' ),
|
87 |
-
'help_link' => 'https://icwp.io/3t'
|
88 |
-
);
|
89 |
-
}
|
90 |
-
return $aFields;
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* @param WP_User $oUser
|
95 |
-
* @return bool
|
96 |
-
*/
|
97 |
-
protected function hasValidatedProfile( $oUser ) {
|
98 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
99 |
-
$oFO = $this->getMod();
|
100 |
-
// Currently it's a global setting but this will evolve to be like Google Authenticator so that it's a user meta
|
101 |
-
return ( $oFO->isEmailAuthenticationActive() && $this->isSubjectToEmailAuthentication( $oUser ) );
|
102 |
-
}
|
103 |
-
|
104 |
-
/**
|
105 |
-
* @param WP_User $oUser
|
106 |
-
* @return bool
|
107 |
-
*/
|
108 |
-
private function isSubjectToEmailAuthentication( $oUser ) {
|
109 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
110 |
-
$oFO = $this->getMod();
|
111 |
-
return count( array_intersect( $oFO->getEmail2FaRoles(), $oUser->roles ) ) > 0;
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* @return string
|
116 |
-
*/
|
117 |
-
protected function genSessionHash() {
|
118 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
119 |
-
$oFO = $this->getMod();
|
120 |
-
return hash_hmac(
|
121 |
-
'sha1',
|
122 |
-
$this->getController()->getUniqueRequestId(),
|
123 |
-
$oFO->getTwoAuthSecretKey()
|
124 |
-
);
|
125 |
-
}
|
126 |
-
|
127 |
-
/**
|
128 |
-
* We don't use user meta as it's dependent on the particular user sessions in-use
|
129 |
-
* @param WP_User $oUser
|
130 |
-
* @return string
|
131 |
-
*/
|
132 |
-
protected function getSecret( WP_User $oUser ) {
|
133 |
-
return strtoupper( substr( $this->genSessionHash(), 0, 6 ) );
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* @return string The unique 2FA 6-digit code
|
138 |
-
*/
|
139 |
-
protected function getStoredSessionHashCode() {
|
140 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
141 |
-
$oFO = $this->getMod();
|
142 |
-
return $oFO->hasSession() ? $oFO->getSession()->getLoginIntentCodeEmail() : '';
|
143 |
-
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
* @param string $sSecret
|
147 |
-
* @return bool
|
148 |
-
*/
|
149 |
-
protected function isSecretValid( $sSecret ) {
|
150 |
-
$sHash = $this->getStoredSessionHashCode();
|
151 |
-
return !empty( $sHash );
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* @param WP_User $oUser
|
156 |
-
* @return $this
|
157 |
-
*/
|
158 |
-
protected function sendEmailTwoFactorVerify( WP_User $oUser ) {
|
159 |
-
$sIpAddress = $this->ip();
|
160 |
-
|
161 |
-
$aMessage = array(
|
162 |
-
_wpsf__( 'Someone attempted to login into this WordPress site using your account.' ),
|
163 |
-
_wpsf__( 'Login requires verification with the following code.' ),
|
164 |
-
'',
|
165 |
-
sprintf( _wpsf__( 'Verification Code: %s' ), sprintf( '<strong>%s</strong>', $this->getSecret( $oUser ) ) ),
|
166 |
-
'',
|
167 |
-
sprintf( '<strong>%s</strong>', _wpsf__( 'Login Details' ) ),
|
168 |
-
sprintf( '%s: %s', _wpsf__( 'URL' ), $this->loadWp()->getHomeUrl() ),
|
169 |
-
sprintf( '%s: %s', _wpsf__( 'Username' ), $oUser->user_login ),
|
170 |
-
sprintf( '%s: %s', _wpsf__( 'IP Address' ), $sIpAddress ),
|
171 |
-
'',
|
172 |
-
);
|
173 |
-
|
174 |
-
if ( !$this->getController()->isRelabelled() ) {
|
175 |
-
$aMessage[] = sprintf( '- <a href="%s" target="_blank">%s</a>', 'https://icwp.io/96', _wpsf__( 'Why no login link?' ) );
|
176 |
-
$aContent[] = '';
|
177 |
-
}
|
178 |
-
|
179 |
-
$sEmailSubject = _wpsf__( 'Two-Factor Login Verification' );
|
180 |
-
|
181 |
-
$bResult = $this->getEmailProcessor()
|
182 |
-
->sendEmailWithWrap( $oUser->user_email, $sEmailSubject, $aMessage );
|
183 |
-
if ( $bResult ) {
|
184 |
-
$sAuditMessage = sprintf( _wpsf__( 'User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".' ), $oUser->user_login, $sIpAddress );
|
185 |
-
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_two_factor_email_send' );
|
186 |
-
}
|
187 |
-
else {
|
188 |
-
$sAuditMessage = sprintf( _wpsf__( 'Tried to send email to User "%s" to verify their identity using Two-Factor Login Auth for IP address "%s", but email sending failed.' ), $oUser->user_login, $sIpAddress );
|
189 |
-
$this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_two_factor_email_send_fail' );
|
190 |
-
}
|
191 |
-
return $this;
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
196 |
-
* functions. Otherwise we need to be careful of mixing up users.
|
197 |
-
* @param WP_User $oUser
|
198 |
-
*/
|
199 |
-
public function addOptionsToUserProfile( $oUser ) {
|
200 |
-
$oWp = $this->loadWpUsers();
|
201 |
-
$bValidatedProfile = $this->hasValidatedProfile( $oUser );
|
202 |
-
$aData = array(
|
203 |
-
'user_has_email_authentication_active' => $bValidatedProfile,
|
204 |
-
'user_has_email_authentication_enforced' => $this->isSubjectToEmailAuthentication( $oUser ),
|
205 |
-
'is_my_user_profile' => ( $oUser->ID == $oWp->getCurrentWpUserId() ),
|
206 |
-
'i_am_valid_admin' => $this->getController()->isValidAdminArea( true ),
|
207 |
-
'user_to_edit_is_admin' => $oWp->isUserAdmin( $oUser ),
|
208 |
-
'strings' => array(
|
209 |
-
'label_email_authentication' => _wpsf__( 'Email Authentication' ),
|
210 |
-
'title' => _wpsf__( 'Email Authentication' ),
|
211 |
-
'description_email_authentication_checkbox' => _wpsf__( 'Check the box to enable email-based login authentication.' ),
|
212 |
-
'provided_by' => sprintf( _wpsf__( 'Provided by %s' ), $this->getController()
|
213 |
-
->getHumanName() )
|
214 |
-
)
|
215 |
-
);
|
216 |
-
|
217 |
-
$aData[ 'bools' ] = array(
|
218 |
-
'checked' => $bValidatedProfile || $aData[ 'user_has_email_authentication_enforced' ],
|
219 |
-
'disabled' => true || $aData[ 'user_has_email_authentication_enforced' ]
|
220 |
-
//TODO: Make email authentication a per-user setting
|
221 |
-
);
|
222 |
-
|
223 |
-
echo $this->getMod()->renderTemplate( 'snippets/user_profile_emailauthentication.php', $aData );
|
224 |
-
}
|
225 |
-
|
226 |
-
/**
|
227 |
-
* @return string
|
228 |
-
*/
|
229 |
-
protected function getStub() {
|
230 |
-
return ICWP_WPSF_Processor_LoginProtect_Track::Factor_Email;
|
231 |
-
}
|
232 |
-
|
233 |
-
/**
|
234 |
-
* @return string
|
235 |
-
*/
|
236 |
-
protected function get2FaCodeUserMetaKey() {
|
237 |
-
return $this->getMod()->prefix( 'tfaemail_reqid' );
|
238 |
-
}
|
239 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/processors/loginprotect_yubikey.php
DELETED
@@ -1,378 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( class_exists( 'ICWP_WPSF_Processor_LoginProtect_Yubikey', false ) ) {
|
4 |
-
return;
|
5 |
-
}
|
6 |
-
|
7 |
-
require_once( dirname( __FILE__ ).'/loginprotect_intentprovider_base.php' );
|
8 |
-
|
9 |
-
class ICWP_WPSF_Processor_LoginProtect_Yubikey extends ICWP_WPSF_Processor_LoginProtect_IntentProviderBase {
|
10 |
-
|
11 |
-
const OTP_LENGTH = 12;
|
12 |
-
/**
|
13 |
-
* @const string
|
14 |
-
*/
|
15 |
-
const URL_YUBIKEY_VERIFY = 'https://api.yubico.com/wsapi/2.0/verify';
|
16 |
-
|
17 |
-
/**
|
18 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
19 |
-
* functions. Otherwise we need to be careful of mixing up users.
|
20 |
-
* @param WP_User $oUser
|
21 |
-
*/
|
22 |
-
public function addOptionsToUserProfile( $oUser ) {
|
23 |
-
$oCon = $this->getController();
|
24 |
-
$oWpUsers = $this->loadWpUsers();
|
25 |
-
|
26 |
-
$bValidatedProfile = $this->hasValidatedProfile( $oUser );
|
27 |
-
$aData = array(
|
28 |
-
'has_validated_profile' => $bValidatedProfile,
|
29 |
-
'is_my_user_profile' => ( $oUser->ID == $oWpUsers->getCurrentWpUserId() ),
|
30 |
-
'i_am_valid_admin' => $oCon->getHasPermissionToManage(),
|
31 |
-
'user_to_edit_is_admin' => $oWpUsers->isUserAdmin( $oUser ),
|
32 |
-
'strings' => array(
|
33 |
-
'description_otp_code' => _wpsf__( 'This is your unique Yubikey Device ID.' ),
|
34 |
-
'description_otp_code_ext' => '['._wpsf__( 'Pro Only' ).'] '
|
35 |
-
._wpsf__( 'Multiple Yubikey Device IDs are separated by a comma.' ),
|
36 |
-
'description_otp' => _wpsf__( 'Provide a One Time Password from your Yubikey.' ),
|
37 |
-
'description_otp_ext' => $bValidatedProfile ?
|
38 |
-
_wpsf__( 'This will remove the Yubikey Device ID from your profile.' )
|
39 |
-
: _wpsf__( 'This will add the Yubikey Device ID to your profile.' ),
|
40 |
-
'description_otp_ext_2' => $bValidatedProfile ?
|
41 |
-
'['._wpsf__( 'Pro Only' ).'] '._wpsf__( 'If you provide a OTP from an alternative Yubikey device, it will also be added to your profile.' )
|
42 |
-
: '',
|
43 |
-
'label_enter_code' => _wpsf__( 'Yubikey ID' ),
|
44 |
-
'label_enter_otp' => _wpsf__( 'Yubikey OTP' ),
|
45 |
-
'title' => _wpsf__( 'Yubikey Authentication' ),
|
46 |
-
'cant_add_other_user' => sprintf( _wpsf__( "Sorry, %s may not be added to another user's account." ), 'Yubikey' ),
|
47 |
-
'cant_remove_admins' => sprintf( _wpsf__( "Sorry, %s may only be removed from another user's account by a Security Administrator." ), _wpsf__( 'Yubikey' ) ),
|
48 |
-
'provided_by' => sprintf( _wpsf__( 'Provided by %s' ), $oCon->getHumanName() ),
|
49 |
-
'remove_more_info' => sprintf( _wpsf__( 'Understand how to remove Google Authenticator' ) )
|
50 |
-
),
|
51 |
-
'data' => array(
|
52 |
-
'otp_field_name' => $this->getLoginFormParameter(),
|
53 |
-
'secret' => str_replace( ',', ', ', $this->getSecret( $oUser ) ),
|
54 |
-
)
|
55 |
-
);
|
56 |
-
|
57 |
-
echo $this->getMod()->renderTemplate( 'snippets/user_profile_yubikey.php', $aData );
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile,
|
62 |
-
* so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
|
63 |
-
* @param int $nSavingUserId
|
64 |
-
*/
|
65 |
-
public function handleUserProfileSubmit( $nSavingUserId ) {
|
66 |
-
|
67 |
-
// If it's your own account, you CANT do anything without your OTP (except turn off via email).
|
68 |
-
$sOtp = $this->fetchCodeFromRequest();
|
69 |
-
|
70 |
-
// At this stage, if the OTP was empty, then we have no further processing to do.
|
71 |
-
if ( empty( $sOtp ) ) {
|
72 |
-
return;
|
73 |
-
}
|
74 |
-
|
75 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
76 |
-
$oFO = $this->getMod();
|
77 |
-
|
78 |
-
if ( !$this->sendYubiOtpRequest( $sOtp ) ) {
|
79 |
-
$oFO->setFlashAdminNotice(
|
80 |
-
_wpsf__( 'One Time Password (OTP) was not valid.' ).' '._wpsf__( 'Please try again.' ),
|
81 |
-
true
|
82 |
-
);
|
83 |
-
return;
|
84 |
-
}
|
85 |
-
|
86 |
-
/*
|
87 |
-
* How we proceed depends on :
|
88 |
-
* 1) Is the OTP for a registered ID - if so, remove it; If not, add it;
|
89 |
-
* 2) Is this a premium Shield installation - if so, multiple yubikeys are permitted
|
90 |
-
*/
|
91 |
-
|
92 |
-
$oSavingUser = $this->loadWpUsers()->getUserById( $nSavingUserId );
|
93 |
-
$sYubiId = $this->getYubiIdFromOtp( $sOtp );
|
94 |
-
|
95 |
-
$bError = false;
|
96 |
-
if ( $this->hasYubiIdInProfile( $oSavingUser, $sYubiId ) ) {
|
97 |
-
$this->removeYubiIdFromProfile( $oSavingUser, $sYubiId );
|
98 |
-
$sMsg = sprintf(
|
99 |
-
_wpsf__( '%s was removed from your profile.' ),
|
100 |
-
_wpsf__( 'Yubikey Device' ).sprintf( ' "%s"', $sYubiId )
|
101 |
-
);
|
102 |
-
}
|
103 |
-
else if ( count( $this->getYubiIds( $oSavingUser ) ) == 0 || $oFO->isPremium() ) {
|
104 |
-
$this->addYubiIdToProfile( $oSavingUser, $sYubiId );
|
105 |
-
$sMsg = sprintf(
|
106 |
-
_wpsf__( '%s was added to your profile.' ),
|
107 |
-
_wpsf__( 'Yubikey Device' ).sprintf( ' (%s)', $sYubiId )
|
108 |
-
);
|
109 |
-
}
|
110 |
-
else {
|
111 |
-
$bError = true;
|
112 |
-
$sMsg = _wpsf__( 'No changes were made to your Yubikey configuration' );
|
113 |
-
}
|
114 |
-
|
115 |
-
$this->setProfileValidated( $oSavingUser, $this->hasValidSecret( $oSavingUser ) );
|
116 |
-
$oFO->setFlashAdminNotice( $sMsg, $bError );
|
117 |
-
}
|
118 |
-
|
119 |
-
/**
|
120 |
-
* @param WP_User $oUser
|
121 |
-
* @return array
|
122 |
-
*/
|
123 |
-
protected function getYubiIds( WP_User $oUser ) {
|
124 |
-
return explode( ',', parent::getSecret( $oUser ) );
|
125 |
-
}
|
126 |
-
|
127 |
-
/**
|
128 |
-
* @param string $sOTP
|
129 |
-
* @return string
|
130 |
-
*/
|
131 |
-
protected function getYubiIdFromOtp( $sOTP ) {
|
132 |
-
return substr( $sOTP, 0, $this->getYubiOtpLength() );
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* @param WP_User $oUser
|
137 |
-
* @param string $sKey
|
138 |
-
* @return bool
|
139 |
-
*/
|
140 |
-
protected function hasYubiIdInProfile( WP_User $oUser, $sKey ) {
|
141 |
-
return in_array( $sKey, $this->getYubiIds( $oUser ) );
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* @param WP_User $oUser
|
146 |
-
* @param string $sOneTimePassword
|
147 |
-
* @return bool
|
148 |
-
*/
|
149 |
-
protected function processOtp( $oUser, $sOneTimePassword ) {
|
150 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
151 |
-
$oFO = $this->getMod();
|
152 |
-
$bSuccess = false;
|
153 |
-
|
154 |
-
$aYubiKeys = $this->getYubiIds( $oUser );
|
155 |
-
|
156 |
-
// Only process the 1st secret if premium
|
157 |
-
if ( !$oFO->isPremium() ) {
|
158 |
-
$aYubiKeys = array_slice( $aYubiKeys, 0, 1 );
|
159 |
-
}
|
160 |
-
|
161 |
-
foreach ( $aYubiKeys as $sKey ) {
|
162 |
-
$bSuccess = strpos( $sOneTimePassword, $sKey ) === 0
|
163 |
-
&& $this->sendYubiOtpRequest( $sOneTimePassword );
|
164 |
-
if ( $bSuccess ) {
|
165 |
-
break;
|
166 |
-
}
|
167 |
-
}
|
168 |
-
|
169 |
-
return $bSuccess;
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* @param string $sOTP
|
174 |
-
* @return bool
|
175 |
-
*/
|
176 |
-
private function sendYubiOtpRequest( $sOTP ) {
|
177 |
-
$sOTP = trim( $sOTP );
|
178 |
-
$bSuccess = preg_match( '#^[a-z]{44}$#', $sOTP );
|
179 |
-
|
180 |
-
if ( $bSuccess ) {
|
181 |
-
$aParts = array(
|
182 |
-
'otp' => $sOTP,
|
183 |
-
'nonce' => md5( uniqid( rand() ) ),
|
184 |
-
'id' => $this->getOption( 'yubikey_app_id' )
|
185 |
-
);
|
186 |
-
$sYubiResponse = trim( $this->loadFS()
|
187 |
-
->getUrlContent( add_query_arg( $aParts, self::URL_YUBIKEY_VERIFY ) ) );
|
188 |
-
|
189 |
-
unset( $aParts[ 'id' ] );
|
190 |
-
$aParts[ 'status' ] = 'OK';
|
191 |
-
|
192 |
-
$bSuccess = true;
|
193 |
-
foreach ( $aParts as $sKey => $mVal ) {
|
194 |
-
$bSuccess = $bSuccess && preg_match( sprintf( '#%s=%s#', $sKey, $mVal ), $sYubiResponse );
|
195 |
-
}
|
196 |
-
}
|
197 |
-
|
198 |
-
return $bSuccess;
|
199 |
-
}
|
200 |
-
|
201 |
-
/**
|
202 |
-
* @param WP_User $oUser
|
203 |
-
* @param string $sNewKey
|
204 |
-
* @return $this
|
205 |
-
*/
|
206 |
-
protected function addYubiIdToProfile( $oUser, $sNewKey ) {
|
207 |
-
$aKeys = $this->getYubiIds( $oUser );
|
208 |
-
$aKeys[] = $sNewKey;
|
209 |
-
return $this->storeYubiIdInProfile( $oUser, $aKeys );
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* @param WP_User $oUser
|
214 |
-
* @param string $sKey
|
215 |
-
* @return $this
|
216 |
-
*/
|
217 |
-
protected function removeYubiIdFromProfile( $oUser, $sKey ) {
|
218 |
-
$aKeys = $this->loadDP()->removeFromArrayByValue( $this->getYubiIds( $oUser ), $sKey );
|
219 |
-
return $this->storeYubiIdInProfile( $oUser, $aKeys );
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* @param WP_User $oUser
|
224 |
-
* @param array $aKeys
|
225 |
-
* @return $this
|
226 |
-
*/
|
227 |
-
private function storeYubiIdInProfile( $oUser, $aKeys ) {
|
228 |
-
parent::setSecret( $oUser, implode( ',', array_unique( array_filter( $aKeys ) ) ) );
|
229 |
-
return $this;
|
230 |
-
}
|
231 |
-
|
232 |
-
/**
|
233 |
-
* @param WP_User $oUser
|
234 |
-
* @param bool $bIsSuccess
|
235 |
-
*/
|
236 |
-
protected function auditLogin( $oUser, $bIsSuccess ) {
|
237 |
-
if ( $bIsSuccess ) {
|
238 |
-
$this->addToAuditEntry(
|
239 |
-
sprintf( _wpsf__( 'User "%s" verified their identity using %s method.' ),
|
240 |
-
$oUser->user_login, _wpsf__( 'Yubikey OTP' )
|
241 |
-
), 2, 'login_protect_yubikey_login_success'
|
242 |
-
);
|
243 |
-
$this->doStatIncrement( 'login.yubikey.verified' );
|
244 |
-
}
|
245 |
-
else {
|
246 |
-
$this->addToAuditEntry(
|
247 |
-
sprintf( _wpsf__( 'User "%s" failed to verify their identity using %s method.' ),
|
248 |
-
$oUser->user_login, _wpsf__( 'Yubikey OTP' )
|
249 |
-
),2, 'login_protect_yubikey_failed'
|
250 |
-
);
|
251 |
-
$this->doStatIncrement( 'login.yubikey.failed' );
|
252 |
-
}
|
253 |
-
}
|
254 |
-
|
255 |
-
/**
|
256 |
-
* @param array $aFields
|
257 |
-
* @return array
|
258 |
-
*/
|
259 |
-
public function addLoginIntentField( $aFields ) {
|
260 |
-
if ( $this->getCurrentUserHasValidatedProfile() ) {
|
261 |
-
$aFields[] = array(
|
262 |
-
'name' => $this->getLoginFormParameter(),
|
263 |
-
'type' => 'text',
|
264 |
-
'placeholder' => _wpsf__( 'Use your Yubikey to generate a new code.' ),
|
265 |
-
'value' => '',
|
266 |
-
'text' => _wpsf__( 'Yubikey OTP' ),
|
267 |
-
'help_link' => 'https://icwp.io/4i'
|
268 |
-
);
|
269 |
-
}
|
270 |
-
return $aFields;
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* @return string
|
275 |
-
*/
|
276 |
-
protected function getStub() {
|
277 |
-
return ICWP_WPSF_Processor_LoginProtect_Track::Factor_Yubikey;
|
278 |
-
}
|
279 |
-
|
280 |
-
/**
|
281 |
-
* @param string $sSecret
|
282 |
-
* @return bool
|
283 |
-
*/
|
284 |
-
protected function isSecretValid( $sSecret ) {
|
285 |
-
$bValid = parent::isSecretValid( $sSecret );
|
286 |
-
if ( $bValid ) {
|
287 |
-
foreach ( explode( ',', $sSecret ) as $sId ) {
|
288 |
-
$bValid = $bValid && preg_match( sprintf( '#^[a-z]{%s}$#', $this->getYubiOtpLength() ), $sId );
|
289 |
-
}
|
290 |
-
}
|
291 |
-
return $bValid;
|
292 |
-
}
|
293 |
-
|
294 |
-
/**
|
295 |
-
* @return int
|
296 |
-
*/
|
297 |
-
protected function getYubiOtpLength() {
|
298 |
-
return self::OTP_LENGTH;
|
299 |
-
}
|
300 |
-
|
301 |
-
/**
|
302 |
-
* @param WP_User $oUser
|
303 |
-
* @return WP_User|WP_Error
|
304 |
-
*/
|
305 |
-
public function processLoginAttempt_Filter( $oUser ) {
|
306 |
-
return $oUser;
|
307 |
-
/** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
|
308 |
-
$oFO = $this->getMod();
|
309 |
-
$oLoginTrack = $this->getLoginTrack();
|
310 |
-
|
311 |
-
$bNeedToCheckThisFactor = $oFO->isChainedAuth() || !$oLoginTrack->hasSuccessfulFactor();
|
312 |
-
$bErrorOnFailure = $bNeedToCheckThisFactor && $oLoginTrack->isFinalFactorRemainingToTrack();
|
313 |
-
$oLoginTrack->addUnSuccessfulFactor( ICWP_WPSF_Processor_LoginProtect_Track::Factor_Yubikey );
|
314 |
-
|
315 |
-
if ( !$bNeedToCheckThisFactor || empty( $oUser ) || is_wp_error( $oUser ) ) {
|
316 |
-
return $oUser;
|
317 |
-
}
|
318 |
-
|
319 |
-
$oError = new WP_Error();
|
320 |
-
$sUsername = $oUser->user_login;
|
321 |
-
|
322 |
-
$sOneTimePassword = $this->fetchCodeFromRequest();
|
323 |
-
// $sApiKey = $this->getOption('yubikey_api_key');
|
324 |
-
|
325 |
-
// check that if we have a list of permitted keys, that the one used is on that list connected with the username.
|
326 |
-
$sYubikey12 = $this->getYubiIdFromOtp( $sOneTimePassword );
|
327 |
-
$fUsernameFound = false; // if username is never found, it means there's no yubikey specified which means we can bypass this authentication method.
|
328 |
-
$fFoundMatch = false;
|
329 |
-
foreach ( $this->getOption( 'yubikey_unique_keys' ) as $aUsernameYubikeyPair ) {
|
330 |
-
if ( isset( $aUsernameYubikeyPair[ $sUsername ] ) ) {
|
331 |
-
$fUsernameFound = true;
|
332 |
-
if ( $aUsernameYubikeyPair[ $sUsername ] == $sYubikey12 ) {
|
333 |
-
$fFoundMatch = true;
|
334 |
-
break;
|
335 |
-
}
|
336 |
-
}
|
337 |
-
}
|
338 |
-
|
339 |
-
// If no yubikey-username pair found for given username, we by-pass Yubikey auth.
|
340 |
-
if ( !$fUsernameFound ) {
|
341 |
-
$sAuditMessage = sprintf( _wpsf__( 'User "%s" logged in without a Yubikey One Time Password because no username-yubikey pair was found for this user.' ), $sUsername );
|
342 |
-
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_bypass' );
|
343 |
-
return $oUser;
|
344 |
-
}
|
345 |
-
|
346 |
-
// Username was found in the list of key pairs, but the yubikey provided didn't match that username.
|
347 |
-
if ( !$fFoundMatch ) {
|
348 |
-
$sAuditMessage = sprintf( _wpsf__( 'User "%s" attempted to login but Yubikey ID "%s" used was not in list of authorised keys.' ), $sUsername, $sYubikey12 );
|
349 |
-
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_fail_permitted_id' );
|
350 |
-
|
351 |
-
if ( $bErrorOnFailure ) {
|
352 |
-
$oError->add(
|
353 |
-
'yubikey_not_allowed',
|
354 |
-
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__( 'The Yubikey provided is not on the list of permitted keys for this user.' ) )
|
355 |
-
);
|
356 |
-
return $oError;
|
357 |
-
}
|
358 |
-
}
|
359 |
-
|
360 |
-
if ( $this->processOtp( null, $sOneTimePassword ) ) {
|
361 |
-
$sAuditMessage = sprintf( _wpsf__( 'User "%s" successfully logged in using a validated Yubikey One Time Password.' ), $sUsername );
|
362 |
-
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_login_success' );
|
363 |
-
$this->getLoginTrack()->addSuccessfulFactor( ICWP_WPSF_Processor_LoginProtect_Track::Factor_Yubikey );
|
364 |
-
}
|
365 |
-
else {
|
366 |
-
|
367 |
-
$sAuditMessage = sprintf( _wpsf__( 'User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API response.".' ), $sUsername );
|
368 |
-
$this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_fail_invalid_api_response' );
|
369 |
-
|
370 |
-
$oError->add(
|
371 |
-
'yubikey_validate_fail',
|
372 |
-
sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__( 'The Yubikey authentication was not validated successfully.' ) )
|
373 |
-
);
|
374 |
-
}
|
375 |
-
|
376 |
-
return $bErrorOnFailure ? $oError : $oUser;
|
377 |
-
}
|
378 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/processors/plugin.php
CHANGED
@@ -147,33 +147,13 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
|
|
147 |
/**
|
148 |
*/
|
149 |
public function dumpTrackingData() {
|
150 |
-
if ( $this->getController()->
|
151 |
echo sprintf( '<pre><code>%s</code></pre>', print_r( $this->getTrackingProcessor()
|
152 |
->collectTrackingData(), true ) );
|
153 |
die();
|
154 |
}
|
155 |
}
|
156 |
|
157 |
-
/**
|
158 |
-
*/
|
159 |
-
public function printTrackingDataBox() {
|
160 |
-
/** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
|
161 |
-
$oFO = $this->getMod();
|
162 |
-
|
163 |
-
if ( !$this->getController()->isValidAdminArea() ) {
|
164 |
-
return;
|
165 |
-
}
|
166 |
-
|
167 |
-
$aRenderData = array(
|
168 |
-
'strings' => array(
|
169 |
-
'tracking_data' => print_r( $this->getTrackingProcessor()->collectTrackingData(), true ),
|
170 |
-
),
|
171 |
-
'js_snippets' => array()
|
172 |
-
);
|
173 |
-
add_thickbox();
|
174 |
-
echo $oFO->renderTemplate( 'snippets/plugin_tracking_data_dump.php', $aRenderData );
|
175 |
-
}
|
176 |
-
|
177 |
protected function setupTestCron() {
|
178 |
try {
|
179 |
$this->loadWpCronProcessor()
|
147 |
/**
|
148 |
*/
|
149 |
public function dumpTrackingData() {
|
150 |
+
if ( $this->getController()->isPluginAdmin() ) {
|
151 |
echo sprintf( '<pre><code>%s</code></pre>', print_r( $this->getTrackingProcessor()
|
152 |
->collectTrackingData(), true ) );
|
153 |
die();
|
154 |
}
|
155 |
}
|
156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
protected function setupTestCron() {
|
158 |
try {
|
159 |
$this->loadWpCronProcessor()
|
src/processors/sessions.php
CHANGED
@@ -65,7 +65,11 @@ class ICWP_WPSF_Processor_Sessions extends ICWP_WPSF_BaseDbProcessor {
|
|
65 |
public function onWpLoaded() {
|
66 |
if ( $this->loadWpUsers()->isUserLoggedIn() && !$this->loadWp()->isRest() ) {
|
67 |
$this->autoAddSession();
|
|
|
|
|
68 |
|
|
|
|
|
69 |
/** @var ICWP_WPSF_FeatureHandler_Sessions $oFO */
|
70 |
$oFO = $this->getMod();
|
71 |
if ( $oFO->hasSession() ) {
|
@@ -73,6 +77,8 @@ class ICWP_WPSF_Processor_Sessions extends ICWP_WPSF_BaseDbProcessor {
|
|
73 |
->updateLastActivity( $this->getCurrentSession() );
|
74 |
}
|
75 |
}
|
|
|
|
|
76 |
}
|
77 |
|
78 |
private function autoAddSession() {
|
65 |
public function onWpLoaded() {
|
66 |
if ( $this->loadWpUsers()->isUserLoggedIn() && !$this->loadWp()->isRest() ) {
|
67 |
$this->autoAddSession();
|
68 |
+
}
|
69 |
+
}
|
70 |
|
71 |
+
public function onModuleShutdown() {
|
72 |
+
if ( !$this->loadWp()->isRest() ) {
|
73 |
/** @var ICWP_WPSF_FeatureHandler_Sessions $oFO */
|
74 |
$oFO = $this->getMod();
|
75 |
if ( $oFO->hasSession() ) {
|
77 |
->updateLastActivity( $this->getCurrentSession() );
|
78 |
}
|
79 |
}
|
80 |
+
|
81 |
+
parent::onModuleShutdown();
|
82 |
}
|
83 |
|
84 |
private function autoAddSession() {
|
src/wizards/base_wpsf.php
CHANGED
@@ -18,7 +18,7 @@ abstract class ICWP_WPSF_Wizard_BaseWpsf extends ICWP_WPSF_Wizard_Base {
|
|
18 |
protected function getUserCanSlide( $sSlide ) {
|
19 |
$aSlide = $this->getStepsDefinition()[ $sSlide ];
|
20 |
$bRestricted = !isset( $aSlide[ 'security_admin' ] ) || $aSlide[ 'security_admin' ];
|
21 |
-
return !$bRestricted || $this->getPluginCon()->
|
22 |
}
|
23 |
|
24 |
/**
|
18 |
protected function getUserCanSlide( $sSlide ) {
|
19 |
$aSlide = $this->getStepsDefinition()[ $sSlide ];
|
20 |
$bRestricted = !isset( $aSlide[ 'security_admin' ] ) || $aSlide[ 'security_admin' ];
|
21 |
+
return !$bRestricted || $this->getPluginCon()->isPluginAdmin();
|
22 |
}
|
23 |
|
24 |
/**
|
templates/php/page/login_intent.php
CHANGED
@@ -93,6 +93,7 @@
|
|
93 |
<form action="<?php echo $hrefs[ 'form_action' ]; ?>" method="post" class="form-horizontal">
|
94 |
<input type="hidden" name="<?php echo $data[ 'login_intent_flag' ]; ?>" value="1" />
|
95 |
<input type="hidden" name="redirect_to" value="<?php echo $hrefs[ 'redirect_to' ]; ?>" />
|
|
|
96 |
|
97 |
<?php foreach ( $data[ 'login_fields' ] as $aField ) : ?>
|
98 |
<div class="form-row">
|
93 |
<form action="<?php echo $hrefs[ 'form_action' ]; ?>" method="post" class="form-horizontal">
|
94 |
<input type="hidden" name="<?php echo $data[ 'login_intent_flag' ]; ?>" value="1" />
|
95 |
<input type="hidden" name="redirect_to" value="<?php echo $hrefs[ 'redirect_to' ]; ?>" />
|
96 |
+
<input type="hidden" name="cancel_href" value="<?php echo $hrefs[ 'cancel_href' ]; ?>" />
|
97 |
|
98 |
<?php foreach ( $data[ 'login_fields' ] as $aField ) : ?>
|
99 |
<div class="form-row">
|