PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.0.1
Defender Security – Malware Scanner, Login Security & Firewall v6.0.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / controller / class-hub.php

class-hub.php in Defender Security – Malware Scanner, Login Security & Firewall 6.0.1, at src/controller/class-hub.php

861 lines 25.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle various actions and interactions with the WPMUDEV Hub.
4 *
5 * @package WP_Defender\Controller
6 */
7
8 namespace WP_Defender\Controller;
9
10 use WP_Defender\Event;
11 use WP_Defender\Traits\IO;
12 use WP_Defender\Traits\Formats;
13 use WP_Defender\Behavior\WPMUDEV;
14 use WP_Defender\Model\Lockout_Log;
15 use WP_Defender\Model\Setting\Two_Fa;
16 use WP_Defender\Component\IP\Antibot_Global_Firewall;
17 use WP_Defender\Component\IP\Global_IP;
18 use WP_Defender\Component\Backup_Settings;
19 use WP_Defender\Model\Setting\Login_Lockout;
20 use WP_Defender\Model\Setting\Notfound_Lockout;
21 use WP_Defender\Model\Notification\Audit_Report;
22 use WP_Defender\Model\Setting\Blacklist_Lockout;
23 use WP_Defender\Model\Setting\Global_Ip_Lockout;
24 use WP_Defender\Component\Config\Config_Adapter;
25 use WP_Defender\Model\Setting\User_Agent_Lockout;
26 use WP_Defender\Model\Notification\Malware_Report;
27 use WP_Defender\Model\Notification\Tweak_Reminder;
28 use WP_Defender\Component\Config\Config_Hub_Helper;
29 use WP_Defender\Model\Notification\Firewall_Report;
30 use WP_Defender\Model\Notification\Malware_Notification;
31 use WP_Defender\Model\Notification\Firewall_Notification;
32 use WP_Defender\Model\Setting\Audit_Logging as Model_Audit_Logging;
33 use WP_Defender\Model\Setting\Security_Tweaks as Model_Security_Tweaks;
34 use WP_Defender\Model\Setting\Antibot_Global_Firewall_Setting;
35
36 /**
37 * Handles various actions and interactions with the WPMUDEV Hub.
38 */
39 class HUB extends Event {
40
41 use IO;
42 use Formats;
43
44 /**
45 * Flag indicating whether to display the onboarding view or not.
46 *
47 * @var bool
48 */
49 private $view_onboard = false;
50
51 /**
52 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
53 */
54 public function __construct() {
55 $this->attach_behavior( WPMUDEV::class, WPMUDEV::class );
56 add_filter( 'wdp_register_hub_action', array( $this, 'add_hub_endpoint' ) );
57 add_action( 'defender_hub_sync', array( $this, 'hub_sync' ) );
58 }
59
60 /**
61 * Add various hub endpoints to the actions array.
62 *
63 * @param array $actions An array of actions.
64 *
65 * @return array The updated actions array with hub endpoints added.
66 */
67 public function add_hub_endpoint( $actions ) {
68 $actions['defender_new_scan'] = array( $this, 'new_scan' );
69 $actions['defender_get_quarantined_files'] = array( $this, 'get_quarantined_files' );
70 $actions['defender_restore_quarantined_file'] = array( $this, 'restore_quarantined_file' );
71
72 $actions['defender_manage_lockout'] = array( $this, 'manage_lockout' );
73 $actions['defender_whitelist_ip'] = array( $this, 'whitelist_ip' );
74 $actions['defender_blacklist_ip'] = array( $this, 'blacklist_ip' );
75 $actions['defender_get_scan_progress'] = array( $this, 'get_scan_progress' );
76 $actions['defender_manage_recaptcha'] = array( $this, 'manage_recaptcha' );
77 $actions['defender_manage_2fa'] = array( $this, 'manage_2fa' );
78 $actions['defender_manage_global_ip_list'] = array( $this, 'manage_global_ip_list' );
79 $actions['defender_set_global_ip_list'] = array( $this, 'set_global_ips' );
80 $actions['defender_set_antibot_status'] = array( $this, 'set_antibot_status' );
81 // Backup/restore settings.
82 $actions['defender_export_settings'] = array( $this, 'export_settings' );
83 $actions['defender_import_settings'] = array( $this, 'import_settings' );
84 // Get stats, version#1.
85 $actions['defender_get_stats'] = array( $this, 'get_stats' );
86 // Version#2.
87 $actions['defender_get_stats_v2'] = array( $this, 'defender_get_stats_v2' );
88
89 return $actions;
90 }
91
92 /**
93 * Create new scan, triggered from HUB.
94 */
95 public function new_scan() {
96 $scan = \WP_Defender\Model\Scan::create();
97 if ( is_wp_error( $scan ) ) {
98 wp_send_json_error(
99 array(
100 'message' => $scan->get_error_message(),
101 )
102 );
103 }
104
105 wd_di()->get( Scan::class )->run_scan_mechanisms_from( 'hub' );
106
107 wp_send_json_success();
108 }
109
110 /**
111 * Track a feature activation or deactivation from the Hub.
112 *
113 * @param bool $is_active Whether the feature is being activated or deactivated.
114 * @param string $feature_title The title of the feature being tracked.
115 */
116 protected function track_feature_from_hub( bool $is_active, string $feature_title ) {
117 $event = $is_active ? 'def_feature_activated' : 'def_feature_deactivated';
118 $data = array(
119 'Feature' => $feature_title,
120 'Triggered From' => 'Hub',
121 );
122
123 $this->track_feature( $event, $data );
124 }
125
126 /**
127 * Get recent quarantined files.
128 */
129 public function get_quarantined_files(): void {
130 if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
131 $result = array(
132 'message' => defender_quarantine_pro_only(),
133 'success' => false,
134 );
135
136 wp_send_json_error( $result );
137 }
138
139 $quarantine_obj = wd_di()->get( \WP_Defender\Component\Quarantine::class );
140
141 $quarantined_files = $quarantine_obj->hub_list();
142
143 wp_send_json_success(
144 array( 'quarantined_files' => $quarantined_files )
145 );
146 }
147
148 /**
149 * Restores a quarantined file based on the provided parameters.
150 *
151 * @param object $params The parameters for restoring the quarantined file.
152 * Requires the 'id' property to be set.
153 *
154 * @return void
155 */
156 public function restore_quarantined_file( object $params ): void {
157 if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) {
158 $result = array(
159 'message' => defender_quarantine_pro_only(),
160 'success' => false,
161 );
162
163 wp_send_json_error( $result );
164 }
165
166 if ( isset( $params->id ) ) {
167 $id = (int) $params->id;
168
169 $quarantine_obj = wd_di()->get( \WP_Defender\Component\Quarantine::class );
170
171 $result = $quarantine_obj->restore_file( $id );
172
173 if ( isset( $result['success'] ) && false === $result['success'] ) {
174 wp_send_json_error( $result );
175 }
176
177 wp_send_json_success( $result );
178 }
179
180 wp_send_json_error(
181 array(
182 'message' => esc_html__( 'Missing parameter: id.', 'defender-security' ),
183 )
184 );
185 }
186
187 /**
188 * Manages the lockout feature based on the given parameters.
189 *
190 * @param array $params The parameters for managing the lockout.
191 * - type (string): The type of lockout to manage. Possible values: 'login', '404', 'ua-lockout'.
192 * @param string $action The action to perform on the lockout.
193 *
194 * @return void
195 */
196 public function manage_lockout( $params, $action ) {
197 $type = $params['type'];
198 $response = array();
199 if ( 'login' === $type ) {
200 $settings = new Login_Lockout();
201 if ( $settings->enabled ) {
202 $settings->enabled = false;
203 $response[ $type ] = 'disabled';
204 } else {
205 $settings->enabled = true;
206 $response[ $type ] = 'enabled';
207 }
208 $settings->save();
209 $feature = 'Login Protection';
210 } elseif ( '404' === $type ) {
211 $settings = new Notfound_Lockout();
212 if ( $settings->enabled ) {
213 $settings->enabled = false;
214 $response[ $type ] = 'disabled';
215 } else {
216 $settings->enabled = true;
217 $response[ $type ] = 'enabled';
218 }
219 $settings->save();
220 $feature = '404 Detection';
221 } elseif ( User_Agent_Lockout::get_module_slug() === $type ) {
222 $settings = new User_Agent_Lockout();
223 if ( $settings->enabled ) {
224 $settings->enabled = false;
225 $response[ $type ] = 'disabled';
226 } else {
227 $settings->enabled = true;
228 $response[ $type ] = 'enabled';
229 }
230 $settings->save();
231 } else {
232 $response[ $type ] = 'invalid';
233 }
234 // Track. Only for Login & NF Lockouts. Ignoring phpcs error due to all possible types.
235 if ( $this->is_tracking_active() && in_array( $type, array( 'login', '404' ), true ) ) {
236 $event = $settings->enabled ? 'def_feature_deactivated' : 'def_feature_activated';
237 $data = array(
238 'Feature' => $feature,
239 'Triggered From' => 'Hub',
240 );
241
242 $this->track_feature( $event, $data );
243 }
244
245 wp_send_json_success( $response );
246 }
247
248 /**
249 * Whitelists an IP address by removing it from the block list and adding it to the allow list.
250 *
251 * @param array $params An array containing the IP address to whitelist.
252 * @param string $action The action to perform.
253 *
254 * @return void
255 */
256 public function whitelist_ip( $params, $action ) {
257 $settings = new Blacklist_Lockout();
258 $ip = $params['ip'];
259 if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
260 $settings->remove_from_list( $ip, 'blocklist' );
261 $settings->add_to_list( $ip, 'allowlist' );
262 } else {
263 wp_send_json_error();
264 }
265 wp_send_json_success();
266 }
267
268 /**
269 * Blacklist an IP address by removing it from the allow list and adding it to the block list.
270 *
271 * @param array $params An array containing the IP address to blacklist.
272 * @param string $action The action to perform.
273 */
274 public function blacklist_ip( $params, $action ) {
275 $settings = new Blacklist_Lockout();
276 $ip = $params['ip'];
277 if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
278 $settings->remove_from_list( $ip, 'allowlist' );
279 $settings->add_to_list( $ip, 'blocklist' );
280 } else {
281 wp_send_json_error();
282 }
283 wp_send_json_success();
284 }
285
286 /**
287 * Push data into HUB. It's without timezone.
288 *
289 * @param array $params An array containing the data to push.
290 * @param string $action The action to perform.
291 */
292 public function get_stats( $params, $action ) {
293 $data = $this->build_stats_to_hub();
294 wp_send_json_success(
295 array( 'stats' => $data )
296 );
297 }
298
299 /**
300 * Push scan data into HUB.
301 */
302 public function get_scan_progress() {
303 $model = \WP_Defender\Model\Scan::get_active();
304 if ( ! is_object( $model ) ) {
305 wp_send_json_success(
306 array( 'progress' => - 1 )
307 );
308 }
309 $percent = $model->percent;
310 if ( $percent > 100 ) {
311 $percent = 100;
312 }
313 wp_send_json_success(
314 array( 'progress' => $percent )
315 );
316 }
317
318 /**
319 * Export settings to HUB.
320 * Analog to export_strings but return not array. So separated method.
321 */
322 public function export_settings() {
323 $config_component = wd_di()->get( Backup_Settings::class );
324 $data = $config_component->parse_data_for_hub();
325 // Replace all the new line in configs.
326 $configs = $data['configs'];
327 foreach ( $configs as $module => $mdata ) {
328 foreach ( $mdata as $key => $value ) {
329 if ( is_string( $value ) ) {
330 $value = str_replace( array( "\r", "\n" ), '{nl}', $value );
331 $mdata[ $key ] = $value;
332 }
333 }
334 $configs[ $module ] = $mdata;
335 }
336 $data['configs'] = $configs;
337 wp_send_json_success( $data );
338 }
339
340 /**
341 * Import settings from HUB.
342 * Analog to import_data but with object $params. So separated method.
343 *
344 * @param object object $params Request parameters.
345 */
346 public function import_settings( $params ) {
347 // Dirty but quick.
348 if (
349 ! isset( $params->configs )
350 || ! ( is_array( $params->configs ) || is_object( $params->configs ) )
351 || ( is_array( $params->configs ) && array() === $params->configs )
352 || ( is_object( $params->configs ) && 0 === count( get_object_vars( $params->configs ) ) )
353 ) {
354 wp_send_json_error(
355 array( 'message' => esc_html__( 'Invalid config', 'defender-security' ) )
356 );
357 }
358
359 $configs = json_decode( wp_json_encode( $params->configs ), true );
360 if ( array() === $configs ) {
361 wp_send_json_error(
362 array( 'message' => esc_html__( 'Empty data', 'defender-security' ) )
363 );
364 }
365
366 $config_component = wd_di()->get( Backup_Settings::class );
367 $lockout_service = wd_di()->get( \WP_Defender\Component\Blacklist_Lockout::class );
368 foreach ( $configs as $module => $mdata ) {
369 foreach ( $mdata as $key => $value ) {
370 // Todo: update logic to import/export whitelisted/blocklisted countries via maxmind_license_key.
371 if ( in_array( $key, array( 'geoIP_db', 'geodb_path' ), true ) ) {
372 if ( is_string( $value ) && '' !== trim( $value ) ) {
373 // Download it.
374 $lockout_service->is_geodb_downloaded();
375 } else {
376 // Reset it.
377 $mdata[ $key ] = '';
378 }
379 } elseif ( is_string( $value ) ) {
380 $value = str_replace( '{nl}', PHP_EOL, $value );
381 $mdata[ $key ] = $value;
382 }
383 }
384 $configs[ $module ] = $mdata;
385 }
386
387 // If it's old config structure then we upgrade configs to new format.
388 if ( array() !== $configs && ! $config_component->check_for_new_structure( $configs ) ) {
389 $adapter = wd_di()->get( Config_Adapter::class );
390 $configs = $adapter->upgrade( $configs );
391 }
392 $restore_result = $config_component->restore_data( $configs, 'hub' );
393 if ( is_string( $restore_result ) ) {
394 wp_send_json_error(
395 array( 'message' => $restore_result )
396 );
397 }
398
399 // Active config.
400 Config_Hub_Helper::active_config_from_hub_id( (int) $params->hub_config_id );
401
402 wp_send_json_success();
403 }
404
405 /**
406 * Build the json data for HUB 2.0.
407 */
408 public function defender_get_stats_v2() {
409 global $wp_version;
410
411 $audit_log = wd_di()->get( Audit_Logging::class );
412 $audit = $audit_log->summary_data( true );
413
414 $scan = \WP_Defender\Model\Scan::get_last();
415 $total = 0;
416 if ( is_object( $scan ) ) {
417 $total += count( $scan->get_issues() );
418 }
419 // Total number of Scan issues and Ignored items.
420 $scan_total_issues = $total;
421 // Exclude direct call of data_frontend().
422 $tweak_arr = wd_di()->get( Model_Security_Tweaks::class )->get_tweak_types();
423
424 $total += $tweak_arr['count_issues'];
425 // Get statuses of login/404/ua-request if Firewall Notification is enabled.
426 $firewall_notification = wd_di()->get( Firewall_Notification::class );
427
428 if ( 'enabled' === $firewall_notification->status ) {
429 $login_lockout = $firewall_notification->configs['login_lockout'];
430 $nf_lockout = $firewall_notification->configs['nf_lockout'];
431 // since 3.3.0.
432 $ua_lockout = $firewall_notification->configs['ua_lockout'] ?? false;
433 } else {
434 $login_lockout = false;
435 $nf_lockout = false;
436 $ua_lockout = false;
437 }
438
439 $status_active = \WP_Defender\Model\Notification::STATUS_ACTIVE;
440 $model_sec_headers = wd_di()->get( \WP_Defender\Model\Setting\Security_Headers::class );
441 $scan_report = wd_di()->get( Malware_Report::class );
442 $two_fa = wd_di()->get( Two_Fa::class );
443 if ( class_exists( 'WP_Defender\Component\Quarantine' ) ) {
444 $quarantined_files = wd_di()->get( \WP_Defender\Component\Quarantine::class )->hub_list();
445 } else {
446 $quarantined_files = array();
447 }
448
449 $antibot_service = wd_di()->get( Antibot_Global_Firewall::class );
450
451 $ret = array(
452 'summary' => array(
453 'count' => $total,
454 'next_scan' => $scan_report->get_next_run_for_hub(),
455 ),
456 'report' => array(
457 'malware_scan' => $scan_report->get_next_run_as_string( true ),
458 'firewall' => wd_di()->get( Firewall_Report::class )->get_next_run_as_string( true ),
459 'audit_logging' => wd_di()->get( Audit_Report::class )->get_next_run_as_string( true ),
460 'tweak_reminder' => wd_di()->get( Tweak_Reminder::class )->get_next_run_as_string( true ),
461 ),
462 'security_tweaks' => array(
463 'issues' => $tweak_arr['count_issues'],
464 'fixed' => $tweak_arr['count_fixed'],
465 'notification' => wd_di()->get( Tweak_Reminder::class )->status === $status_active,
466 'wp_version' => $wp_version,
467 'php_version' => PHP_VERSION,
468 ),
469 'malware_scan' => array(
470 'count' => $scan_total_issues,
471 'notification' => wd_di()->get( Malware_Notification::class )->status === $status_active,
472 ),
473 'firewall' => array(
474 'last_lockout' => Lockout_Log::get_last_lockout_date( true ),
475 '24_hours' => array(
476 'login_lockout' => Lockout_Log::count(
477 strtotime( '-24 hours' ),
478 time(),
479 array( Lockout_Log::AUTH_LOCK )
480 ),
481 '404_lockout' => Lockout_Log::count(
482 strtotime( '-24 hours' ),
483 time(),
484 array( Lockout_Log::LOCKOUT_404 )
485 ),
486 'user_agent_lockout' => Lockout_Log::count(
487 strtotime( '-24 hours' ),
488 time(),
489 array( Lockout_Log::LOCKOUT_UA )
490 ),
491 ),
492 '7_days' => array(
493 'login_lockout' => Lockout_Log::count_login_lockout_last_7_days(),
494 '404_lockout' => Lockout_Log::count_404_lockout_last_7_days(),
495 'user_agent_lockout' => Lockout_Log::count_ua_lockout_last_7_days(),
496 ),
497 '30_days' => array(
498 'login_lockout' => Lockout_Log::count(
499 strtotime( '-30 days' ),
500 time(),
501 array( Lockout_Log::AUTH_LOCK )
502 ),
503 '404_lockout' => Lockout_Log::count(
504 strtotime( '-30 days' ),
505 time(),
506 array( Lockout_Log::LOCKOUT_404 )
507 ),
508 'user_agent_lockout' => Lockout_Log::count(
509 strtotime( '-30 days' ),
510 time(),
511 array( Lockout_Log::LOCKOUT_UA )
512 ),
513 ),
514 'notification_status' => array(
515 'login_lockout' => $login_lockout,
516 '404_lockout' => $nf_lockout,
517 'ua_lockout' => $ua_lockout,
518 ),
519 'login_lockout_enabled' => wd_di()->get( Login_Lockout::class )->enabled,
520 'lockout_404_enabled' => wd_di()->get( Notfound_Lockout::class )->enabled,
521 'user_agent_lockout_enabled' => wd_di()->get( User_Agent_Lockout::class )->enabled,
522 'global_ip_list_enabled' => wd_di()->get( Global_Ip_Lockout::class )->enabled,
523 'antibot_enabled' => $antibot_service->frontend_is_enabled(),
524 'antibot_mode' => $antibot_service->frontend_mode(),
525 ),
526 'audit' => array(
527 'last_event' => $audit['lastEvent'] ?? 'n/a',
528 '24_hours' => $audit['dayCount'] ?? 0,
529 '7_days' => $audit['weekCount'] ?? 0,
530 '30_days' => $audit['monthCount'] ?? 0,
531 'enabled' => $audit_log->model->is_active(),
532 ),
533 'advanced_tools' => array(
534 'security_headers' => array(
535 'sh_xframe' => $model_sec_headers->sh_xframe,
536 'sh_xss_protection' => $model_sec_headers->sh_xss_protection,
537 'sh_content_type_options' => $model_sec_headers->sh_content_type_options,
538 'sh_strict_transport' => $model_sec_headers->sh_strict_transport,
539 'sh_referrer_policy' => $model_sec_headers->sh_referrer_policy,
540 'sh_feature_policy' => $model_sec_headers->sh_feature_policy,
541 ),
542 'mask_login' => wd_di()->get( \WP_Defender\Model\Setting\Mask_Login::class )->is_active(),
543 // We'll change 'google_recaptcha'-key to 'captcha' in the future.
544 'google_recaptcha' => array(
545 'status' => wd_di()->get( \WP_Defender\Model\Setting\Captcha::class )->is_active(),
546 ),
547 'password_protection' => array(
548 'status' => wd_di()->get( \WP_Defender\Model\Setting\Password_Protection::class )->is_active(),
549 ),
550 ),
551 'two_fa' => array(
552 'status' => $two_fa->enabled,
553 'lost_phone' => $two_fa->lost_phone,
554 ),
555 'quarantined_files' => $quarantined_files,
556 );
557
558 wp_send_json_success(
559 array( 'stats' => $ret )
560 );
561 }
562
563 /**
564 * Synchronizes the data with the hub by making a POST request to the WPMUDEV API.
565 *
566 * @return void
567 */
568 public function hub_sync() {
569 $data = $this->build_stats_to_hub();
570 $this->make_wpmu_request(
571 WPMUDEV::API_HUB_SYNC,
572 $data,
573 array( 'method' => 'POST' )
574 );
575 }
576
577 /**
578 * Removes settings for all submodules.
579 */
580 public function remove_settings() {
581 }
582
583 /**
584 * Delete all the data & the cache.
585 */
586 public function remove_data() {
587 }
588
589 /**
590 * Placeholder for frontend data.
591 *
592 * @return array
593 */
594 public function data_frontend() {
595 return array();
596 }
597
598 /**
599 * Converts the current object state to an array.
600 *
601 * @return array The array representation of the object.
602 */
603 public function to_array(): array {
604 return array();
605 }
606
607 /**
608 * Placeholder for importing data.
609 *
610 * @param array $data Data to import.
611 */
612 public function import_data( array $data ) {
613 }
614
615 /**
616 * Exports strings.
617 *
618 * @return array An array of strings.
619 */
620 public function export_strings(): array {
621 return array();
622 }
623
624 /**
625 * Display Onboard if the bool value 'true' and vice versa.
626 *
627 * @param bool $is_show Settings to display.
628 */
629 public function set_onboarding_status( $is_show ) {
630 $this->view_onboard = $is_show;
631 }
632
633 /**
634 * Retrieve the Onboard status.
635 *
636 * @return bool
637 */
638 public function get_onboarding_status(): bool {
639 return $this->view_onboard;
640 }
641
642 /**
643 * Activate/deactivate Captcha from HUB.
644 */
645 public function manage_recaptcha() {
646 $response = null;
647 if ( class_exists( \WP_Defender\Model\Setting\Captcha::class ) ) {
648 $settings = new \WP_Defender\Model\Setting\Captcha();
649 $response = array();
650 if ( true === $settings->enabled ) {
651 $settings->enabled = false;
652 $response['enabled'] = false;
653 } else {
654 $settings->enabled = true;
655 $response['enabled'] = true;
656 }
657 $settings->save();
658 // Track.
659 if ( $this->is_tracking_active() ) {
660 $this->track_feature_from_hub( ! $settings->enabled, 'Google reCAPTCHA' );
661 }
662 }
663 wp_send_json_success( $response );
664 }
665
666 /**
667 * Activate/deactivate 2FA from HUB.
668 *
669 * @param array $params Request parameters.
670 */
671 public function manage_2fa( array $params ) {
672 $response = null;
673 if ( class_exists( Two_Fa::class ) ) {
674 $settings = wd_di()->get( Two_Fa::class );
675 $response = array();
676 if ( true === $settings->enabled ) {
677 $settings->enabled = false;
678 $response['enabled'] = false;
679 } else {
680 $settings->enabled = true;
681 $response['enabled'] = true;
682 }
683 $settings->save();
684 // Track.
685 if ( $this->is_tracking_active() ) {
686 // Only deactivation from the Hub.
687 $this->track_feature_from_hub( false, 'Two-Factor Authentication' );
688 }
689 }
690
691 wp_send_json_success( $response );
692 }
693
694 /**
695 * Activate/deactivate Global IP list from HUB.
696 *
697 * @param object $params Request parameters.
698 *
699 * @return void
700 * @since 3.4.0
701 */
702 public function manage_global_ip_list( object $params ): void {
703 if ( ! isset( $params->enable ) ) {
704 wp_send_json_error(
705 array( 'message' => esc_html__( 'Missing parameter(s)', 'defender-security' ) )
706 );
707 }
708
709 $response = null;
710 if ( class_exists( Global_Ip_Lockout::class ) ) {
711 $settings = wd_di()->get( Global_Ip_Lockout::class );
712
713 $response = array();
714 if ( true === $params->enable ) {
715 $settings->enabled = true;
716 $response['enabled'] = true;
717 } else {
718 $settings->enabled = false;
719 $response['enabled'] = false;
720 }
721 $settings->save();
722 }
723 wp_send_json_success( $response );
724 }
725
726 /**
727 * Set Global IP list.
728 *
729 * @param object $params Request parameters.
730 *
731 * @return void
732 * @since 3.4.0
733 */
734 public function set_global_ips( object $params ): void {
735 $global_ip_component = wd_di()->get( Global_IP::class );
736 $result = $global_ip_component->set_global_ip_list( (array) $params );
737
738 if ( is_wp_error( $result ) ) {
739 wp_send_json_error(
740 array(
741 'message' => implode( ' ', $result->get_error_messages() ),
742 )
743 );
744 }
745
746 wp_send_json_success(
747 array( 'enabled' => $global_ip_component->is_global_ip_enabled() )
748 );
749 }
750
751 /**
752 * Handle plugin deactivation.
753 *
754 * @param string $plugin Path to the plugin file relative to the plugins directory.
755 *
756 * @return void
757 */
758 public function intercept_deactivate( $plugin ) {
759 if ( ! $this->is_tracking_active() ) {
760 return;
761 }
762
763 // Only if Defender.
764 if ( DEFENDER_PLUGIN_BASENAME !== $plugin ) {
765 return;
766 }
767
768 $action = defender_get_data_from_request( 'action', 'r' );
769 // Todo: this is a default value. Need to update it in the future.
770 $triggered_from = 'Unknown';
771 // Deactivated from WPMUDEV Dashboard.
772 if ( 'wdp-project-deactivate' === $action ) {
773 $triggered_from = 'Plugin deactivation - dashboard';
774 } elseif ( 'deactivate' === $action ) {
775 // Deactivated from WP plugins page.
776 $triggered_from = 'Plugin deactivation - wpadmin';
777 } elseif ( $this->is_hub_request() ) {
778 $triggered_from = 'Plugin deactivation - hub';
779 }
780
781 // Send plugin deactivation event.
782 $this->track_opt_toggle( false, $triggered_from );
783 }
784
785 /**
786 * Enable/Disable Antibot Functionality. Only for third party site.
787 *
788 * @param object $params Request parameters.
789 *
790 * @return void
791 * @since 4.11.0
792 */
793 public function set_antibot_status( object $params ): void {
794 if ( ! isset( $params->enable ) && ! isset( $params->mode ) ) {
795 wp_send_json_error(
796 array( 'message' => esc_html__( 'Missing parameter(s)', 'defender-security' ) )
797 );
798 }
799
800 if ( ! class_exists( Antibot_Global_Firewall_Setting::class ) ) {
801 wp_send_json_error(
802 array( 'message' => esc_html__( 'Missing class', 'defender-security' ) )
803 );
804 }
805
806 $is_updated = false;
807 $antibot_settings = wd_di()->get( Antibot_Global_Firewall_Setting::class );
808
809 if ( isset( $params->mode ) ) {
810 if ( ! in_array( $params->mode, Antibot_Global_Firewall_Setting::get_valid_modes(), true ) ) {
811 wp_send_json_error(
812 array( 'message' => esc_html__( 'Invalid mode', 'defender-security' ) )
813 );
814 }
815
816 $old_mode = $antibot_settings->mode;
817 $new_mode = $params->mode;
818 if ( $old_mode !== $new_mode ) {
819 $is_updated = true;
820 $antibot_settings->mode = $new_mode;
821 }
822 }
823
824 if ( isset( $params->enable ) ) {
825 $old_enabled = $antibot_settings->enabled;
826 $new_enabled = (bool) $params->enable;
827 if ( $old_enabled !== $new_enabled ) {
828 $is_updated = true;
829 $antibot_settings->enabled = $new_enabled;
830
831 // Track.
832 if ( $this->is_tracking_active() ) {
833 wd_di()->get( \WP_Defender\Helper\Analytics\Antibot::class )
834 ->track_antibot( $old_enabled, 'Hub' );
835 }
836 }
837 }
838
839 if ( $is_updated ) {
840 $antibot_settings->save();
841
842 /**
843 * Download and store the blocklist.
844 *
845 * @var Antibot_Global_Firewall $antibot_service
846 */
847 $antibot_service = wd_di()->get( Antibot_Global_Firewall::class );
848 if ( 'plugin' === $antibot_service->get_managed_by() && $antibot_service->is_enabled() ) {
849 $antibot_service->download_and_store_blocklist();
850 }
851 }
852
853 wp_send_json_success(
854 array(
855 'enabled' => $antibot_settings->enabled,
856 'mode' => $antibot_settings->mode,
857 )
858 );
859 }
860 }
861