PluginProbe
WebTotem Security / 3.0.2
WebTotem Security v3.0.2
3.0.2 3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 All 110 releases
wt-security / lib / Ajax.php

Ajax.php in WebTotem Security 3.0.2, at lib/Ajax.php

1,960 lines 59.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
3 if (!headers_sent()) {
4 header('HTTP/1.1 403 Forbidden');
5 }
6 die('Protected By WebTotem!');
7 }
8
9 class WebTotemAjax
10 {
11
12 /**
13 * Activation plugin.
14 *
15 * @return void
16 */
17 public static function activation()
18 {
19
20 if (WebTotemRequest::post('ajax_action') !== 'activation') {
21 return;
22 }
23
24 if ($api_key = WebTotemRequest::post('api_key')) {
25
26 $result = WebTotemAPI::auth($api_key);
27
28 if ($result == 'success') {
29 // if (WebTotem::isMultiSite()) {
30 // $link = WebTotem::adminURL('admin.php?page=wtotem_all_sites');
31 // } else {
32 // $link = WebTotem::adminURL('admin.php?page=wtotem');
33 // }
34 $link = WebTotem::adminURL('admin.php?page=wtotem');
35 // $email = WebTotemAPI::getEmail();
36 // WebTotemOption::setOptions(['user_email' => $email]);
37 wp_send_json([
38 'link' => $link,
39 'success' => true,
40 // 'user' => $email,
41 ], 200);
42 } else {
43
44 wp_send_json([
45 'notifications' => self::notifications(),
46 'success' => false,
47 ], 200);
48 }
49 }
50
51 }
52
53 /**
54 * The process of installing agents (WAF, AV) on the main page.
55 *
56 * @return void
57 */
58 public static function agentsInstallation()
59 {
60
61 if (WebTotemRequest::post('ajax_action') !== 'agents_installation') {
62 return;
63 }
64
65 $av_installed = WebTotemOption::getOption('av_installed');
66 $waf_installed = WebTotemOption::getOption('waf_installed');
67
68 // Check if the agents are installed.
69 if ($av_installed and $waf_installed) {
70 $agents_statuses = [
71 'process_statuses' => [
72 'av' => 'available',
73 'waf' => 'available',
74 ],
75 ];
76 } else {
77 // If not installed, then request statuses from the WebTotem API.
78 $data = WebTotemAPI::getAgentsStatusesFromAPI();
79
80 $agents_statuses = [
81 'av' => $data['av'],
82 'waf' => $data['waf'],
83 ];
84
85 $agents_statuses = WebTotem::getAgentsStatuses($agents_statuses);
86 }
87
88 $build[] = [
89 'variables' => [
90 'process_status' => $agents_statuses['process_statuses'],
91 ],
92 'template' => 'agents_installation',
93 ];
94
95 $status = [
96 'av' => $agents_statuses['process_statuses']['av'] == 'available',
97 'waf' => $agents_statuses['process_statuses']['waf'] == 'available',
98 ];
99
100 WebTotemOption::setOptions([
101 'av_installed' => $status['av'],
102 'waf_installed' => $status['waf'],
103 ]);
104
105 $template = new WebTotemTemplate();
106 $agents = $template->arrayRender($build);
107
108 wp_send_json([
109 'success' => true,
110 'notifications' => self::notifications(),
111 'agents' => $agents,
112 'agents_statuses' => $status['av'] && $status['waf'],
113 ]);
114 }
115
116 /**
117 * Reinstall agents.
118 *
119 * @return void
120 */
121 public static function reinstallAgents()
122 {
123
124 if (WebTotemRequest::post('ajax_action') !== 'reinstall_agents') {
125 return;
126 }
127
128 WebTotemAgentManager::amInstall();
129
130 $response['success'] = true;
131 $response['redirect_link'] = WebTotem::adminURL('admin.php?page=wtotem');
132 wp_send_json($response);
133
134 }
135
136 /**
137 * Deleting plugin activation data and redirecting to the activation page.
138 *
139 * @return void
140 */
141 public static function logout()
142 {
143
144 if (WebTotemRequest::post('ajax_action') !== 'logout') {
145 return;
146 }
147
148 WebTotemOption::logout();
149
150 $response['success'] = true;
151 $response['redirect_link'] = WebTotem::adminURL('admin.php?page=wtotem_activation');
152 wp_send_json($response);
153
154 }
155
156 /**
157 * Creating a modal window.
158 *
159 * @return void
160 */
161 public static function popup()
162 {
163
164 if (WebTotemRequest::post('ajax_action') !== 'popup') {
165 return;
166 }
167
168 $action = WebTotemRequest::post('popup_action');
169 $template = new WebTotemTemplate();
170
171 if ($action) {
172 switch ($action) {
173 case 'reinstall_agents':
174 $build[] = [
175 'variables' => [
176 'message' => sprintf(__('Some scanning data for %s may be deleted.', 'wtotem'), WEBTOTEM_SITE_DOMAIN),
177 'action' => 'reinstall_agents',
178 'page_nonce' => wp_create_nonce('wtotem_page_nonce'),
179 ],
180 'template' => 'popup',
181 ];
182 break;
183
184 case 'logout':
185 $build[] = [
186 'variables' => [
187 'message' => __('Are you sure you want to change the API key?', 'wtotem'),
188 'action' => 'logout',
189 'page_nonce' => wp_create_nonce('wtotem_page_nonce'),
190 ],
191 'template' => 'popup',
192 ];
193 break;
194
195
196 case 'update_plugin':
197 $build[] = [
198 'variables' => [
199 'message' => __('Do you really want to update the plugin?', 'wtotem'),
200 'action' => 'update_plugin',
201 'slug' => WebTotemRequest::post('slug'),
202 'page_nonce' => wp_create_nonce('wtotem_page_nonce'),
203 ],
204 'template' => 'popup',
205 ];
206 break;
207
208 }
209
210 wp_send_json([
211 'success' => true,
212 'content' => $template->arrayRender($build),
213 ]);
214 }
215
216 wp_send_json([
217 'success' => false,
218 ]);
219
220 }
221
222 /**
223 * Request to update charts with parameters.
224 *
225 * @return void
226 */
227 public static function chart()
228 {
229
230 if (WebTotemRequest::post('ajax_action') !== 'chart') {
231 return;
232 }
233
234 $template = new WebTotemTemplate();
235
236 $days = (integer)WebTotemRequest::post('days');
237 $service = WebTotemRequest::post('service');
238
239
240 switch ($service) {
241 case 'waf':
242
243 WebTotemOption::setSessionOptions(['firewall_period' => $days]);
244
245 // Firewall chart.
246 $data = WebTotemAPI::getFirewallStatistics($days);
247 $chart = WebTotem::generateWafChart($data['signatures_statistic'] ?? []);
248
249 $_chart[] = [
250 'variables' => [
251 'days' => $days,
252 'chart' => $chart['chart'],
253 ],
254 'template' => 'firewall_chart',
255 ];
256
257 $response = [
258 'chart' => $template->arrayRender($_chart),
259 'service' => 'waf',
260 ];
261
262 break;
263
264 case 'map':
265
266 $data = WebTotemAPI::getFirewallStatistics($days);
267 $chart = WebTotem::generateAttacksMapChart($data['countries_statistics'] ?? []);
268 $world_map_json = WEBTOTEM_URL . '/includes/js/world_map.json';
269
270 $_chart[] = [
271 'variables' => [
272 'attacks_map' => $chart,
273 'world_map_json' => $world_map_json,
274 ],
275 'template' => 'map_chart',
276 ];
277
278 $response = [
279 'chart' => $template->arrayRender($_chart),
280 'service' => 'map',
281 ];
282
283 break;
284
285 }
286
287 if ($service) {
288 $response['success'] = true;
289 $response['notifications'] = self::notifications();
290 wp_send_json($response);
291 }
292
293 }
294
295
296 /**
297 * Pagination.
298 * @return void
299 */
300 public static function pagination()
301 {
302
303 if (WebTotemRequest::post('ajax_action') !== 'pagination') {
304 return;
305 }
306
307 $template = new WebTotemTemplate();
308
309 $service = WebTotemRequest::post('service');
310 $current_page = WebTotemRequest::post('current_page');
311
312
313 switch ($service) {
314
315 case 'firewall':
316 $firewall_data = WebTotemAPI::getFirewall(10, $current_page, 7);
317
318 $build[] = [
319 'variables' => [
320 "logs" => WebTotem::wafLogs($firewall_data['logs'] ?? []),
321 ],
322 'template' => 'firewall_logs',
323 ];
324 $pagination = WebTotem::paginationBuild(10, $firewall_data['total'], $current_page);
325
326 break;
327
328 case 'antivirus':
329 $antivirus_history_data = WebTotemAPI::getAntivirusHistory($current_page);
330 $build[] = [
331 'variables' => [
332 "logs" => WebTotem::getAntivirusLogsData($antivirus_history_data['history']),
333 ],
334 'template' => 'antivirus_history_items',
335 ];
336
337 $pagination = WebTotem::paginationBuild(10, $antivirus_history_data['total'], $current_page);
338
339 break;
340
341 case 'infected_files':
342 $infected_files = WebTotemAPI::getAntivirusCurrentDetails($current_page);
343 $build[] = [
344 'variables' => [
345 "logs" => WebTotem::getInfectedFilesData($infected_files['current_infected_files'] ?? []),
346 "type" => 'infected',
347 ],
348 'template' => 'quarantine_logs',
349 ];
350
351 $pagination = WebTotem::paginationBuild(5, (int)$infected_files['total'], $current_page);
352 break;
353
354 case 'quarantine':
355 $quarantine_files = WebTotemAPI::getQuarantineList($current_page);
356 $build[] = [
357 'variables' => [
358 "logs" => WebTotem::getQuarantineListData($quarantine_files['quarantine_files'] ?? []),
359 "type" => 'quarantine',
360 ],
361 'template' => 'quarantine_logs',
362 ];
363
364 $pagination = WebTotem::paginationBuild(5, (int)$quarantine_files['total'], $current_page);
365 break;
366 }
367
368 if ($service) {
369
370 wp_send_json([
371 'success' => true,
372 'content' => $template->arrayRender($build),
373 'pagination' => $pagination,
374 'notifications' => self::notifications(),
375 ]);
376 }
377 }
378
379
380 /**
381 * Data lazy load.
382 * @return void
383 */
384 public static function logs()
385 {
386 if (WebTotemRequest::post('ajax_action') !== 'logs') {
387 return;
388 }
389
390 $template = new WebTotemTemplate();
391 $logs_action = WebTotemRequest::post('logs_action');
392
393 switch ($logs_action) {
394 case 'audit_logs_pagination':
395 $order = WebTotemRequest::post('order') === 'ascending' ? 'ASC' : 'DESC';
396 $current_page = (int)WebTotemRequest::post('current_page');
397 $event = WebTotemRequest::post('event');
398 $filter = $event === 'All' ? [] : ['LIKE', ['event' => $event . '%']];
399
400 $audit_logs = WebTotemDB::getRows(
401 $filter,
402 'audit_logs',
403 false,
404 ['limit' => 10, 'page' => $current_page],
405 ['order_by' => 'created_at', 'direction' => $order]
406 );
407
408 $build[] = [
409 'variables' => [
410 "audit_logs" => WebTotem::getAuditLogs($audit_logs['data'], $audit_logs['dates_count']),
411 ],
412 'template' => 'scan_audit_logs',
413 ];
414
415 $response = [
416 'success' => true,
417 'content' => $template->arrayRender($build),
418 "pagination" => WebTotem::paginationBuild(10, $audit_logs['count'], $current_page),
419 'notifications' => self::notifications(),
420 ];
421
422 break;
423
424 case 'audit_logs_sort_filter':
425 $order = WebTotemRequest::post('order') === 'ascending' ? 'ASC' : 'DESC';
426 $event = WebTotemRequest::post('event');
427 $filter = $event === 'All' ? [] : ['LIKE', ['event' => $event . '%']];
428 $audit_logs = WebTotemDB::getRows(
429 $filter,
430 'audit_logs',
431 false,
432 ['limit' => 10, 'page' => 1],
433 ['order_by' => 'created_at', 'direction' => $order]
434 );
435
436 $build[] = [
437 'variables' => [
438 "audit_logs" => WebTotem::getAuditLogs($audit_logs['data'], $audit_logs['dates_count']),
439 ],
440 'template' => 'scan_audit_logs',
441 ];
442
443 $response = [
444 'success' => true,
445 'content' => $template->arrayRender($build),
446 "pagination" => WebTotem::paginationBuild(10, $audit_logs['count'], 1),
447 'notifications' => self::notifications(),
448 ];
449
450 break;
451
452 case 'confidential_files':
453 $id = WebTotemRequest::post('id') ?? false;
454 if ($id) {
455 $file = WebTotemDB::getData(['id' => $id], 'confidential_files');
456 if ($file['path']) {
457 $path = urldecode($file['path']);
458 if(file_exists($path)) unlink($path);
459 WebTotemDB::deleteData(['id' => $id], 'confidential_files');
460 WebTotemOption::setNotification('info', sprintf(__('File %s was deleted', 'wtotem'), json_decode($file['name'])));
461 }
462 }
463 $order_by = WebTotemRequest::post('order');
464 $direction = WebTotemRequest::post('direction') === 'ascending' ? 'ASC' : 'DESC';
465 $current_page = (int)WebTotemRequest::post('current_page') ?: 1;
466
467 $confidential_files = WebTotemDB::getRows(
468 [],
469 'confidential_files',
470 false,
471 ['limit' => 10, 'page' => $current_page],
472 $order_by ? ['order_by' => $order_by, 'direction' => $direction] : ['order_by' => 'id', 'direction' => 'DESC']
473 );
474
475 $build[] = [
476 'variables' => [
477 "confidential_files" => WebTotem::getConfidentialFiles($confidential_files['data']),
478 ],
479 'template' => 'scan_confidential_files',
480 ];
481
482 $response = [
483 'success' => true,
484 'content' => $template->arrayRender($build),
485 'count' => $confidential_files['count'],
486 "pagination" => WebTotem::paginationBuild(10, $confidential_files['count'], $current_page),
487 'notifications' => self::notifications(),
488 ];
489
490 break;
491
492 case 'logs_pagination':
493 $current_page = (int)WebTotemRequest::post('current_page');
494 $type = WebTotemRequest::post('type');
495 $direction = WebTotemRequest::post('direction') === 'ascending' ? 'ASC' : 'DESC';
496
497 $scan_logs = WebTotemDB::getRows(
498 ['AND', ['data_type' => $type]],
499 'scan_logs',
500 'content',
501 ['limit' => 10, 'page' => $current_page],
502 !empty($direction) ? ['order_by' => 'is_internal', 'direction' => $direction] : ['order_by' => 'id', 'direction' => 'DESC']
503 );
504
505 $build[] = [
506 'variables' => [
507 "logs" => WebTotem::prepareLinksData($scan_logs['data']),
508 "data_type" => $type
509 ],
510 'template' => 'scan_logs_items',
511 ];
512
513 $response = [
514 'success' => true,
515 'content' => $template->arrayRender($build),
516 "pagination" => WebTotem::paginationBuild(10, $scan_logs['count'], $current_page),
517 'notifications' => self::notifications(),
518 ];
519
520 break;
521
522 case 'rescan':
523 WebTotemOption::setOptions(['scan_init' => 1]);
524 WebTotemScan::initialize();
525 $response = [
526 'success' => true,
527 'notifications' => self::notifications(),
528 ];
529
530 break;
531
532 case 'check_scan':
533
534 if(WebTotemOption::getOption('scan_init')){
535 WebTotemScan::initialize();
536 $response = [
537 'success' => true,
538 'scan_finished' => false,
539 'notifications' => self::notifications(),
540 ];
541 } else {
542 $content = [];
543 $pagination = [];
544 $count = [];
545 $types = ['links', 'scripts', 'iframes'];
546
547 foreach ($types as $type) {
548 $scan_logs = WebTotemDB::getRows(
549 ['AND', ['data_type' => $type]],
550 'scan_logs',
551 'content'
552 );
553
554 $build[$type][] = [
555 'variables' => [
556 "logs" => $scan_logs['data'],
557 "data_type" => $type
558 ],
559 'template' => 'scan_logs_items',
560 ];
561 $content[$type] = $template->arrayRender($build[$type]);
562 $pagination[$type] = WebTotem::paginationBuild(10, $scan_logs['count']);
563 $count[$type] = $scan_logs['count'];
564 }
565
566 $confidential_files = WebTotemDB::getRows([], 'confidential_files');
567 $content['confidential_files'] = $template->arrayRender([
568 'variables' => [
569 "confidential_files" => WebTotem::getConfidentialFiles($confidential_files['data']),
570 ],
571 'template' => 'scan_confidential_files',
572 ]);
573 $pagination['confidential_files'] = WebTotem::paginationBuild(10, $confidential_files['count']);
574 $count['confidential_files'] = $confidential_files['count'];
575
576 // Resetting the task in the cron.
577 wp_clear_scheduled_hook('webtotem_daily_cron');
578 wp_schedule_event(time() + 86395, 'daily', 'webtotem_daily_cron');
579
580 $until_next_scan = wp_next_scheduled('webtotem_daily_cron') - time();
581
582 $hr = floor($until_next_scan / 3600);
583 $min = floor(($until_next_scan % 3600) / 60);
584
585 $response = [
586 'success' => true,
587 'scan_finished' => true,
588 'content' => $content,
589 "pagination" => $pagination,
590 "next_scan" => sprintf(__('%dh %dm', 'wtotem'), $hr, $min),
591 "count" => $count,
592 'notifications' => self::notifications(),
593 ];
594 }
595
596 break;
597 }
598
599 wp_send_json($response ?? []);
600 }
601
602 /**
603 * Add date filter.
604 *
605 * @return void
606 */
607 public static function wafDateFilter()
608 {
609
610 if (WebTotemRequest::post('ajax_action') !== 'waf_date_filter') {
611 return;
612 }
613
614 $template = new WebTotemTemplate();
615
616 $period = [WebTotemRequest::post('date_from'), WebTotemRequest::post('date_to')];
617 WebTotemOption::setSessionOptions(['firewall_period' => $period]);
618
619 $page_size = 10;
620
621 // Firewall logs.
622 $firewall_data = WebTotemAPI::getFirewall($page_size, 1, $period);
623
624 $waf_logs[] = [
625 'variables' => [
626 'logs' => WebTotem::wafLogs($firewall_data['logs'] ?? []),
627 ],
628 'template' => 'firewall_logs',
629 ];
630
631 // Firewall statistics (chart and attack map).
632 $statistics = WebTotemAPI::getFirewallStatistics($period);
633 $chart = WebTotem::generateWafChart($statistics['signatures_statistic'] ?? []);
634
635 $_chart[] = [
636 'variables' => [
637 'days' => $chart['days'],
638 'chart' => $chart['chart'],
639 ],
640 'template' => 'firewall_chart',
641 ];
642
643 // Firewall stats.
644 $waf_stats[] = [
645 'variables' => [
646 'is_waf_training' => WebTotem::isWafTraining(),
647 'all_attacks' => $chart['count_attacks'],
648 'blocking' => $chart['count_blocks'],
649 'not_blocking' => (int)$chart['count_attacks'] - (int)$chart['count_blocks'],
650 'most_attacks' => WebTotem::getMostAttacksData($statistics['countries_statistics'] ?? []),
651 ],
652 'template' => 'firewall_stats',
653 ];
654
655 $total = (int)($firewall_data['total'] ?? 0);
656
657 $response = [
658 'success' => true,
659 'chart' => $template->arrayRender($_chart),
660 'waf_logs' => $template->arrayRender($waf_logs),
661 'waf_stats' => $template->arrayRender($waf_stats),
662 'has_next_page' => $total > $page_size,
663 'pagination' => WebTotem::paginationBuild($page_size, $total),
664 'notifications' => self::notifications(),
665 ];
666
667 wp_send_json($response);
668 }
669
670
671 /**
672 * Request to restart re-scan and receive antivirus data.
673 *
674 * @return void
675 */
676 public static function antivirus()
677 {
678
679 if (WebTotemRequest::post('ajax_action') !== 'antivirus') {
680 return;
681 }
682
683 $action = WebTotemRequest::post('av_action');
684 $host = WebTotemAPI::siteInfo();
685 $template = new WebTotemTemplate();
686
687 switch ($action) {
688
689
690 case 'get_infected_files':
691 $session_id = WebTotemRequest::post('session_id');
692 $page_num = WebTotemRequest::post('page_num') ?? 1;
693
694 $infected_files = WebTotemAPI::getAntivirusHistoryDetails($session_id, $page_num);
695
696 $infected_files_wrap[] = [
697 'variables' => [
698 "logs" => WebTotem::getInfectedFilesData($infected_files['history_details']),
699 "total" => $infected_files['total'],
700 "type" => 'infected_ajax',
701 ],
702 'template' => 'quarantine_logs',
703 ];
704
705 $response['content'] = $template->arrayRender($infected_files_wrap);
706
707 break;
708 }
709
710 $response['success'] = true;
711 $response['notifications'] = self::notifications();
712
713 wp_send_json($response);
714 }
715
716 /**
717 * Request to add a file to quarantine.
718 *
719 * @return void
720 */
721 public static function quarantine()
722 {
723 if (WebTotemRequest::post('ajax_action') !== 'quarantine') {
724 return;
725 }
726
727 $action = WebTotemRequest::post('quarantine_action');
728
729 // The API identifies a file by its id (File.id), not by its path.
730 $file_id = WebTotemRequest::post('file_id');
731 if (!$file_id) {
732 // Older markup posted the id under the "path" key.
733 $file_id = WebTotemRequest::post('path');
734 }
735 $file_id = is_string($file_id) ? trim($file_id) : '';
736
737 $response = [];
738
739 if ($file_id === '') {
740 WebTotemOption::setNotification('error', __('The file could not be identified.', 'wtotem'));
741 wp_send_json([
742 'success' => false,
743 'notifications' => self::notifications(),
744 ]);
745 }
746
747 switch ($action) {
748 case 'add':
749 $api_response = WebTotemAPI::moveToQuarantine($file_id);
750 break;
751
752 case 'remove':
753 $api_response = WebTotemAPI::moveFromQuarantine($file_id);
754 break;
755 }
756
757 $response['success'] = false;
758 if (!isset($api_response['message'])) {
759
760 $infected_files_data = WebTotemAPI::getAntivirusCurrentDetails();
761 $quarantine_files_data = WebTotemAPI::getQuarantineList();
762
763 $quarantine = [
764 'variables' => [
765 "logs" => WebTotem::getQuarantineListData($quarantine_files_data['quarantine_files'] ?? []),
766 "type" => 'quarantine',
767 ],
768 'template' => 'quarantine_logs',
769 ];
770 $pagination_quarantine = WebTotem::paginationBuild(5, (int)$quarantine_files_data['total']);
771
772 $infected_files = [
773 'variables' => [
774 "logs" => WebTotem::getInfectedFilesData($infected_files_data['current_infected_files'] ?? []),
775 "type" => 'infected',
776 ],
777 'template' => 'quarantine_logs',
778 ];
779 $pagination_infected_files = WebTotem::paginationBuild(5, (int)$infected_files_data['total']);
780
781 $template = new WebTotemTemplate();
782 $response = [
783 'infected_files' => $template->arrayRender($infected_files),
784 'quarantine_files' => $template->arrayRender($quarantine),
785 'pagination_infected_files' => $pagination_infected_files,
786 'pagination_quarantine' => $pagination_quarantine,
787 'infected_files_total' => (int)$infected_files_data['total'],
788 'quarantine_files_total' => (int)$quarantine_files_data['total'],
789 ];
790
791 $response['success'] = true;
792 }
793
794 $response['notifications'] = self::notifications();
795
796 wp_send_json($response);
797
798 }
799
800 /**
801 * Request for a report link.
802 *
803 * @return void
804 */
805 public static function settings()
806 {
807
808 if (WebTotemRequest::post('ajax_action') !== 'settings') {
809 return;
810 }
811
812 $av_installed = WebTotemOption::getOption('av_installed');
813 $waf_installed = WebTotemOption::getOption('waf_installed');
814 $action = WebTotemRequest::post('settings_action');
815
816 if (in_array($action, ['module_toggle', 'module_notifications', 'waf_settings', 'add_allow_ip', 'add_deny_ip', 'add_allow_url', 'add_ip_list', 'country_blocking'])) {
817 if (!$av_installed && !$waf_installed) {
818 WebTotemOption::setNotification('warning', __('It is not possible to make changes because the agents are not installed.', 'wtotem'));
819
820 wp_send_json([
821 'success' => false,
822 'notifications' => self::notifications()
823 ]);
824 return;
825 }
826 }
827
828 $host = WebTotemAPI::siteInfo();
829 $template = new WebTotemTemplate();
830
831 switch ($action) {
832
833 case 'waf_settings':
834
835 $response['success'] = true;
836
837 $dos = filter_var( WebTotemRequest::post('dos'), FILTER_VALIDATE_BOOLEAN);
838 $dos_limit = WebTotemRequest::post('dos_limit');
839 $gdn= filter_var( WebTotemRequest::post('gdn'), FILTER_VALIDATE_BOOLEAN);
840 // $login_attempt = filter_var( WebTotemRequest::post('login_attempt'), FILTER_VALIDATE_BOOLEAN);
841 // $login_attempt_limit = WebTotemRequest::post('login_attempt_limit');
842
843 if ($dos) {
844 if (empty($dos_limit)) {
845 $response['errors']['dos_limit'] = __('The field is required.', 'wtotem');
846 } else if ($dos_limit < 500 or $dos_limit > 10000) {
847 $response['success'] = false;
848 $response['errors']['dos_limit'] = sprintf(__('Please specify a value from %s to %s.', 'wtotem'), '500', '10 000');
849 }
850 }
851
852 // if ($login_attempt) {
853 // if (empty($login_attempt_limit)) {
854 // $response['errors']['login_attempt_limit'] = __('The field is required.', 'wtotem');
855 // } else if ($login_attempt_limit < 5 or $login_attempt_limit > 30) {
856 // $response['success'] = false;
857 // $response['errors']['login_attempt_limit'] = sprintf(__('Please specify a value from %s to %s.', 'wtotem'), '5', '30');
858 // }
859 // }
860
861 if (!$response['success']) {
862 break;
863 } else {
864 $response['errors'] = false;
865 }
866
867 $waf_settings = WebTotemAPI::getFirewallSettings();
868
869 $waf_settings['dos_protect'] = $dos;
870 $waf_settings['dos_limit'] = (int) $dos_limit;
871 $waf_settings['global_defense_network'] = $gdn;
872
873 $api_response = WebTotemAPI::setFirewallSettings($waf_settings);
874
875 if (!$api_response['message']) {
876 WebTotemCache::setData(['getFirewallSettings' => $waf_settings], $host['id']);
877 WebTotemOption::setNotification('success', __('Your changes have been applied successfully.', 'wtotem'));
878 }
879
880 break;
881
882 case 'recaptcha_settings':
883
884 $recaptcha_v3_site_key = WebTotemRequest::post('recaptcha_v3_site_key');
885 $recaptcha_v3_secret = WebTotemRequest::post('recaptcha_v3_secret');
886 $recaptcha_token = WebTotemRequest::post('recaptcha_token');
887 $recaptcha = filter_var(WebTotemRequest::post('recaptcha'), FILTER_VALIDATE_BOOLEAN) ?: false;
888
889 if ($recaptcha) {
890 if (empty($recaptcha_v3_site_key) or empty($recaptcha_v3_secret) or strlen($recaptcha_v3_site_key) != 40 or strlen($recaptcha_v3_secret) != 40) {
891 $response['success'] = false;
892
893 $response['errors'] = ['recaptcha_v3_site_key' => '', 'recaptcha_v3_secret' => ''];
894
895 if (empty($recaptcha_v3_site_key)) {
896 $response['errors']['recaptcha_v3_site_key'] = __('The field is required.', 'wtotem');
897 } else if (strlen($recaptcha_v3_site_key) != 40) {
898 $response['errors']['recaptcha_v3_site_key'] = __('Invalid field length.', 'wtotem');
899 }
900 if (empty($recaptcha_v3_secret)) {
901 $response['errors']['recaptcha_v3_secret'] = __('The field is required.', 'wtotem');
902 } else if (strlen($recaptcha_v3_secret) != 40) {
903 $response['errors']['recaptcha_v3_secret'] = __('Invalid field length.', 'wtotem');
904 }
905
906 break;
907 }
908
909 $score = WebTotemCaptcha::score($recaptcha_token, $recaptcha_v3_secret);
910
911 if ($score == 0) {
912 $response['success'] = false;
913 $response['errors']['recaptcha_v3_secret'] = __('Please check your keys and try again.', 'wtotem');
914 $response['errors']['recaptcha_v3_site_key'] = __('Please check your keys and try again.', 'wtotem');
915 break;
916 }
917 }
918
919 if ($recaptcha) {
920 $settings = [
921 'recaptcha_v3_site_key' => $recaptcha_v3_site_key,
922 'recaptcha_v3_secret' => $recaptcha_v3_secret,
923 ];
924 }
925 $settings['recaptcha'] = $recaptcha;
926
927 if ($settings['hide_wp_version']) {
928 WebTotemOption::hideReadme();
929 } else {
930 WebTotemOption::restoreReadme();
931 }
932
933 WebTotemOption::setPluginSettings($settings);
934
935 WebTotemOption::setNotification('success', __('Your changes have been applied successfully.', 'wtotem'));
936 if($recaptcha){
937 WebTotemOption::setNotification('warning', __('Please make sure that no other recaptcha is used on your site. Otherwise, there may be a conflict that will cause problems when logging into the admin panel.', 'wtotem'));
938 }
939
940 $response['success'] = true;
941
942
943 break;
944
945 case 'two_factor_settings':
946 $two_factor = filter_var(WebTotemRequest::post('two_factor'), FILTER_VALIDATE_BOOLEAN) ?: false;
947
948 WebTotemOption::setPluginSettings([
949 'two_factor' => $two_factor,
950 ]);
951
952 WebTotemOption::setNotification('success', __('Your changes have been applied successfully.', 'wtotem'));
953 if ($two_factor) {
954 WebTotemOption::setNotification('warning', __('Please make sure that no other 2FA is used on your site. Otherwise, there may be a conflict that will cause problems when logging into the admin panel.', 'wtotem'));
955 }
956
957 $response['success'] = true;
958
959 break;
960
961
962 case 'other_settings':
963
964 $settings = [
965 'hide_wp_version' => filter_var(WebTotemRequest::post('hide_wp_version'), FILTER_VALIDATE_BOOLEAN) ?: false,
966 'disable_user_enumeration' => filter_var(WebTotemRequest::post('disable_user_enumeration'), FILTER_VALIDATE_BOOLEAN) ?: false,
967 ];
968
969 if ($settings['hide_wp_version']) {
970 WebTotemOption::hideReadme();
971
972 } else {
973 WebTotemOption::restoreReadme();
974 }
975
976 WebTotemOption::setPluginSettings($settings);
977
978 WebTotemOption::setNotification('success', __('Your changes have been applied successfully.', 'wtotem'));
979
980 $response['success'] = true;
981
982 break;
983
984 case 'bruteforce_protection_settings':
985
986 $data = WebTotemRequest::post('data');
987 $response['success'] = true;
988
989 $login_attempts = filter_var($data['login_attempts'], FILTER_VALIDATE_BOOLEAN) ?: false;
990 $password_reset = filter_var($data['password_reset'], FILTER_VALIDATE_BOOLEAN) ?: false;
991
992 if ($login_attempts) {
993 $response['errors'] = ['login_number_of_attempts' => '', 'login_minutes_of_ban' => ''];
994
995 if (empty($data['login_number_of_attempts']) or empty($data['login_minutes_of_ban'])) {
996 $response['success'] = false;
997
998 if (empty($data['login_number_of_attempts'])) {
999 $response['errors']['login_number_of_attempts'] = __('The field is required.', 'wtotem');
1000 }
1001 if (empty($data['login_minutes_of_ban'])) {
1002 $response['errors']['login_minutes_of_ban'] = __('The field is required.', 'wtotem');
1003 }
1004 } else if ($data['login_number_of_attempts'] <= 0 or $data['login_number_of_attempts'] > 1000000) {
1005 $response['success'] = false;
1006 $response['errors']['login_number_of_attempts'] = sprintf(__('Please specify a value from %s to %s.', 'wtotem'), '1', '1000000');
1007 }
1008 }
1009
1010 if ($password_reset) {
1011 if (empty($data['password_reset_number_of_attempts']) or empty($data['password_reset_minutes_of_ban'])) {
1012 $response['success'] = false;
1013
1014 $response['errors']['password_reset_number_of_attempts'] = '';
1015 $response['errors']['password_reset_minutes_of_ban'] = '';
1016
1017 if (empty($data['password_reset_number_of_attempts'])) {
1018 $response['errors']['password_reset_number_of_attempts'] = __('The field is required.', 'wtotem');
1019 }
1020 if (empty($data['password_reset_minutes_of_ban'])) {
1021 $response['errors']['password_reset_minutes_of_ban'] = __('The field is required.', 'wtotem');
1022 }
1023 } else if ($data['password_reset_number_of_attempts'] <= 0 or $data['password_reset_number_of_attempts'] > 1000000) {
1024 $response['success'] = false;
1025 $response['errors']['password_reset_number_of_attempts'] = sprintf(__('Please specify a value from %s to %s.', 'wtotem'), '1', '1000000');
1026 }
1027 }
1028 if (!$response['success']) {
1029 break;
1030 } else {
1031 $response['errors'] = false;
1032 }
1033
1034 $settings = [
1035 'login_attempts' => $login_attempts,
1036 'password_reset' => $password_reset,
1037 ];
1038
1039 if ($login_attempts) {
1040 $settings['login_number_of_attempts'] = $data['login_number_of_attempts'];
1041 $settings['login_minutes_of_ban'] = $data['login_minutes_of_ban'];
1042 }
1043 if ($password_reset) {
1044 $settings['password_reset_number_of_attempts'] = $data['password_reset_number_of_attempts'];
1045 $settings['password_reset_minutes_of_ban'] = $data['password_reset_minutes_of_ban'];
1046 }
1047
1048 WebTotemOption::setPluginSettings($settings);
1049
1050 WebTotemOption::setNotification('success', __('Your changes have been applied successfully.', 'wtotem'));
1051
1052 break;
1053
1054 case 'add_allow_ip':
1055 $ip = WebTotemRequest::post('value');
1056 if(!WebTotem::validateIpOrCidr($ip)){
1057 WebTotemOption::setNotification('warning', __('The IP address is incorrect', 'wtotem'));
1058 $response['success'] = false;
1059 break;
1060 }
1061 if($ip){
1062 $api_response = WebTotemAPI::addIpToList([$ip], 'whitelist');
1063 if ($api_response) {
1064
1065 $data = WebTotemAPI::getIpLists('whitelist');
1066 WebTotemCache::setData(['getIpLists_whitelist' => $data], $host['id']);
1067
1068 $build[] = [
1069 'variables' => [
1070 "list" => WebTotem::getIpList($data, 'ip_allow'),
1071 ],
1072 'template' => 'allow_deny_list',
1073 ];
1074
1075 $response['content'] = $template->arrayRender($build);
1076 }
1077
1078 $response['success'] = true;
1079 } else {
1080 $response['success'] = false;
1081 }
1082
1083 break;
1084
1085 case 'add_deny_ip':
1086 $ip = WebTotemRequest::post('value');
1087 if(!WebTotem::validateIpOrCidr($ip)){
1088 WebTotemOption::setNotification('warning', __('The IP address is incorrect', 'wtotem'));
1089 $response['success'] = false;
1090 break;
1091 }
1092 if($ip){
1093 $api_response = WebTotemAPI::addIpToList([$ip], 'blacklist');
1094 if ($api_response) {
1095 $data = WebTotemAPI::getIpLists();
1096 WebTotemCache::setData(['getIpLists_blacklist' => $data], $host['id']);
1097
1098 $build[] = [
1099 'variables' => [
1100 "list" => WebTotem::getIpList($data, 'ip_deny'),
1101 ],
1102 'template' => 'allow_deny_list',
1103 ];
1104
1105 $response['content'] = $template->arrayRender($build);
1106 }
1107
1108 $response['success'] = true;
1109 } else {
1110 $response['success'] = false;
1111 }
1112 break;
1113
1114 case 'add_allow_url':
1115 $url = WebTotemRequest::post('value');
1116 if($url){
1117 $api_response = WebTotemAPI::addIpToList([$url], 'checklist');
1118 if ($api_response) {
1119 $data = WebTotemAPI::getIpLists('checklist');
1120 WebTotemCache::setData(['getIpLists_checklist' => $data], $host['id']);
1121
1122 $build[] = [
1123 'variables' => [
1124 "list" => WebTotem::getIpList($data, 'allow_url'),
1125 ],
1126 'template' => 'allow_deny_list',
1127 ];
1128
1129 $response['content'] = $template->arrayRender($build);
1130 }
1131
1132 $response['success'] = true;
1133 } else {
1134 $response['success'] = false;
1135 }
1136 break;
1137
1138 case 'add_ip_list':
1139 $ips = WebTotem::convertIpListForApi(WebTotemRequest::post('ips'));
1140 $list_name = WebTotemRequest::post('list');
1141
1142 foreach ($ips as $key => $ip){
1143 if(!WebTotem::validateIpOrCidr($ip)){
1144 WebTotemOption::setNotification('warning', __('The IP address is incorrect', 'wtotem')) . ': ' . $ip;
1145 unset($ips[$key]);
1146 }
1147 }
1148
1149 $api_response = WebTotemAPI::addIpToList($ips, $list_name);
1150
1151 if ($api_response) {
1152 $data = WebTotemAPI::getIpLists($list_name);
1153 WebTotemCache::setData(['getIpLists_' . $list_name => $data], $host['id']);
1154 $ip_list = ($list_name == 'whitelist') ? 'ip_allow' : 'ip_deny';
1155
1156 $build[] = [
1157 'variables' => [
1158 "list" => WebTotem::getIpList($data, $ip_list),
1159 ],
1160 'template' => 'allow_deny_list',
1161 ];
1162
1163 if ($api_response['status'] != 0) {
1164 $response['invalidIPs'] = implode("\n", $api_response['invalidIPs']);
1165 }
1166
1167 $response['wrap'] = ($list_name == 'whitelist') ? '#wtotem_ip_allow_list' : '#wtotem_ip_deny_list';
1168 $response['content'] = $template->arrayRender($build);
1169 }
1170 $response['success'] = true;
1171
1172 break;
1173 }
1174
1175 $response['notifications'] = self::notifications();
1176 wp_send_json($response);
1177 }
1178
1179
1180 /**
1181 * Update cash data.
1182 *
1183 * @return void
1184 */
1185 public static function cashUpdate()
1186 {
1187
1188 if (WebTotemRequest::post('ajax_action') !== 'cash_update') {
1189 return;
1190 }
1191
1192 $page = WebTotemRequest::post('page');
1193
1194 $host = WebTotemAPI::siteInfo();
1195 $template = new WebTotemTemplate();
1196
1197 switch ($page) {
1198 case 'dashboard':
1199
1200 if ($cacheData = WebTotemCache::getdata('getMonitoringData', $host['id'])) {
1201 if ($cacheData['remained'] < 60) {
1202 $data_monitoring = WebTotemAPI::getMonitoringData($host['id']);
1203 WebTotemCache::setData(['getMonitoringData' => $data_monitoring], $host['id']);
1204 }
1205 }
1206 if ($cacheData = WebTotemCache::getdata('getFirewall', $host['id'])) {
1207 if ($cacheData['remained'] < 60) {
1208 $data_firewall = WebTotemAPI::getFirewall(10, 1, 7);
1209 WebTotemCache::setData(['getFirewall' => $data_firewall], $host['id']);
1210 }
1211 }
1212 if ($cacheData = WebTotemCache::getdata('getFirewallStatistics', $host['id'])) {
1213 if ($cacheData['remained'] < 60) {
1214 $data_firewall_statistics = WebTotemAPI::getFirewallStatistics();
1215 WebTotemCache::setData(['getFirewallStatistics' => $data_firewall_statistics], $host['id']);
1216 }
1217 }
1218 if ($cacheData = WebTotemCache::getdata('getAgentsStatusesFromAPI', $host['id'])) {
1219 if ($cacheData['remained'] < 60) {
1220 $data_agents_statuses = WebTotemAPI::getAgentsStatusesFromAPI();
1221 WebTotemCache::setData(['getAgentsStatusesFromAPI' => $data_agents_statuses], $host['id']);
1222 }
1223 }
1224 break;
1225
1226 case 'open_paths':
1227 if($cacheData = WebTotemCache::getdata('getMonitoringData', $host['id'])) {
1228 if ($cacheData['remained'] < 60) {
1229 $data = WebTotemAPI::getMonitoringData($host['id']);
1230 WebTotemCache::setData(['getMonitoringData' => $data], $host['id']);
1231 }
1232 }
1233 break;
1234
1235
1236 case 'firewall':
1237 if ($cacheData = WebTotemCache::getdata('getFirewallStatistics', $host['id'])) {
1238 if ($cacheData['remained'] < 60) {
1239 $data_firewall_statistics = WebTotemAPI::getFirewallStatistics();
1240 WebTotemCache::setData(['getFirewallStatistics' => $data_firewall_statistics], $host['id']);
1241 }
1242 }
1243 if ($cacheData = WebTotemCache::getdata('getFirewall', $host['id'])) {
1244 if ($cacheData['remained'] < 60) {
1245 $data_firewall = WebTotemAPI::getFirewall(10, 1, 7);
1246 WebTotemCache::setData(['getFirewall' => $data_firewall], $host['id']);
1247 }
1248 }
1249 break;
1250
1251 case 'antivirus':
1252 if ($cacheData = WebTotemCache::getdata('getAntivirusHistory', $host['id'])) {
1253 if ($cacheData['remained'] < 60) {
1254
1255 $antivirus_history_data = WebTotemAPI::getAntivirusHistory();
1256 WebTotemCache::setData(['getAntivirusHistory' => $antivirus_history_data], $host['id']);
1257 }
1258 }
1259 if ($cacheData = WebTotemCache::getdata('getAntivirusCurrentDetails', $host['id'])) {
1260 if ($cacheData['remained'] < 60) {
1261 $infected_files = WebTotemAPI::getAntivirusCurrentDetails();
1262 WebTotemCache::setData(['getAntivirusCurrentDetails' => $infected_files], $host['id']);
1263
1264 }
1265 }
1266
1267 if ($cacheData = WebTotemCache::getdata('getQuarantineList', $host['id'])) {
1268 if ($cacheData['remained'] < 60) {
1269 $quarantine_files = WebTotemAPI::getQuarantineList();
1270 WebTotemCache::setData(['getQuarantineList' => $quarantine_files], $host['id']);
1271 }
1272 }
1273 break;
1274
1275 case 'settings':
1276 if ($cacheData = WebTotemCache::getdata('getAgentsStatusesFromAPI', $host['id'])) {
1277 if ($cacheData['remained'] < 60) {
1278 $agents_statuses = WebTotemAPI::getAgentsStatusesFromAPI();
1279 WebTotemCache::setData(['getAgentsStatusesFromAPI' => $agents_statuses], $host['id']);
1280 }
1281 }
1282 if ($cacheData = WebTotemCache::getdata('getFirewallSettings', $host['id'])) {
1283 if ($cacheData['remained'] < 60) {
1284 $waf_settings = WebTotemAPI::getFirewallSettings();
1285 WebTotemCache::setData(['getFirewallSettings' => $waf_settings], $host['id']);
1286 }
1287 }
1288 if ($cacheData = WebTotemCache::getdata('getIpLists_whitelist', $host['id'])) {
1289 if ($cacheData['remained'] < 60) {
1290 $ip_whiteList = WebTotemAPI::getIpLists('whitelist');
1291 WebTotemCache::setData(['getIpLists_whitelist' => $ip_whiteList], $host['id']);
1292 }
1293 }
1294 if ($cacheData = WebTotemCache::getdata('getIpLists_blacklist', $host['id'])) {
1295 if ($cacheData['remained'] < 60) {
1296 $ip_blackList = WebTotemAPI::getIpLists();
1297 WebTotemCache::setData(['getIpLists_blacklist' => $ip_blackList], $host['id']);
1298 }
1299 }
1300 if ($cacheData = WebTotemCache::getdata('getIpLists_checklist', $host['id'])) {
1301 if ($cacheData['remained'] < 60) {
1302 $ip_checklist = WebTotemAPI::getIpLists('checklist');
1303 WebTotemCache::setData(['getIpLists_checklist' => $ip_checklist], $host['id']);
1304 }
1305 }
1306 break;
1307
1308 }
1309
1310 $response['success'] = true;
1311 $response['notifications'] = self::notifications();
1312 wp_send_json($response);
1313 }
1314
1315 /**
1316 * Request to remove from the list of deny/allowed ip or url addresses.
1317 *
1318 * @return void
1319 */
1320 public static function remove()
1321 {
1322
1323 if (WebTotemRequest::post('ajax_action') !== 'remove') {
1324 return;
1325 }
1326
1327 $av_installed = WebTotemOption::getOption('av_installed');
1328 $waf_installed = WebTotemOption::getOption('waf_installed');
1329
1330 if (!$av_installed && !$waf_installed) {
1331 WebTotemOption::setNotification('warning', __('It is not possible to make changes because the agents are not installed.', 'wtotem'));
1332
1333 wp_send_json([
1334 'success' => false,
1335 'notifications' => self::notifications()
1336 ]);
1337 }
1338
1339 $action = WebTotemRequest::post('remove_action');
1340 $host = WebTotemAPI::siteInfo();
1341 $template = new WebTotemTemplate();
1342
1343 switch ($action) {
1344 case 'ip_allow':
1345 $api_response = WebTotemAPI::removeIpFromList(WebTotemRequest::post('ip'), 'whitelist');
1346
1347 if ($api_response) {
1348 $data = WebTotemAPI::getIpLists('whitelist');
1349 WebTotemCache::setData(['getIpLists_whitelist' => $data], $host['id']);
1350
1351 $build[] = [
1352 'variables' => [
1353 "list" => WebTotem::getIpList($data, 'ip_allow'),
1354 ],
1355 'template' => 'allow_deny_list',
1356 ];
1357
1358 $response['content'] = $template->arrayRender($build);
1359 $response['wrap'] = '#wtotem_ip_allow_list';
1360 }
1361 break;
1362
1363 case 'ip_deny':
1364 $api_response = WebTotemAPI::removeIpFromList(WebTotemRequest::post('ip'), 'blacklist');
1365
1366 if ($api_response) {
1367 $data = WebTotemAPI::getIpLists();
1368 WebTotemCache::setData(['getIpLists_blacklist' => $data], $host['id']);
1369
1370 $build[] = [
1371 'variables' => [
1372 "list" => WebTotem::getIpList($data, 'ip_deny'),
1373 ],
1374 'template' => 'allow_deny_list',
1375 ];
1376
1377 $response['content'] = $template->arrayRender($build);
1378 $response['wrap'] = '#wtotem_ip_deny_list';
1379 }
1380 break;
1381
1382 case 'url_allow':
1383 $api_response = WebTotemAPI::removeIpFromList(WebTotemRequest::post('ip'), 'checklist');
1384
1385 if ($api_response) {
1386 $data = WebTotemAPI::getIpLists('checklist');
1387 WebTotemCache::setData(['getIpLists_checklist' => $data], $host['id']);
1388
1389 $build[] = [
1390 'variables' => [
1391 "list" => WebTotem::getIpList($data, 'allow_url'),
1392 ],
1393 'template' => 'allow_deny_list',
1394 ];
1395
1396 $response['content'] = $template->arrayRender($build);
1397 $response['wrap'] = '#wtotem_allow_url';
1398 }
1399 break;
1400 }
1401
1402 $response['success'] = true;
1403 $response['notifications'] = self::notifications();
1404 wp_send_json($response);
1405 }
1406
1407 /**
1408 * Request to remove site from WebTotem.
1409 *
1410 * @return void
1411 */
1412 public static function twoFactorAuth()
1413 {
1414
1415 if (WebTotemRequest::post('ajax_action') !== 'two_factor_auth') {
1416 return;
1417 }
1418
1419 $action = WebTotemRequest::post('case_action');
1420 $template = new WebTotemTemplate();
1421 $current_user = wp_get_current_user();
1422
1423 if ($user_id = (int)WebTotemRequest::post('user_id')) {
1424 if ($current_user->ID !== $user_id and !current_user_can('manage_options')) {
1425
1426 WebTotemOption::setNotification('info', '$current_user->ID: ' . $current_user->ID . ', $user_id: ' . $user_id);
1427 WebTotemOption::setNotification('error', __('You cannot edit this user.', 'wtotem'));
1428 return;
1429 }
1430 $user = get_user_by('id', $user_id);
1431 } else {
1432 $user = $current_user;
1433 }
1434
1435 switch ($action) {
1436 case 'activate':
1437
1438 $g = new WebTotemGoogleAuthenticator();
1439
1440 $secret = WebTotemRequest::post('secret');
1441 $recovery = WebTotemRequest::post('recovery');
1442 $code = WebTotemRequest::post('code');
1443
1444 if ($g->checkCode($secret, $code)) {
1445 WebTotemLogin::saveData($user->ID, $recovery, $secret);
1446 WebTotemOption::setNotification('success', __('Your changes have been applied successfully.', 'wtotem'));
1447 $response['success'] = true;
1448 } else {
1449 WebTotemOption::setNotification('error', __('You have entered an incorrect activation code.', 'wtotem'));
1450 $response['success'] = false;
1451 }
1452
1453 break;
1454
1455 case 'deactivate':
1456
1457 WebTotemLogin::delete($user->ID);
1458
1459 $response['success'] = true;
1460
1461 break;
1462 }
1463
1464 $build[] = [
1465 'variables' => [
1466 'two_factor' => WebTotemLogin::getTwoFactorData($user),
1467 'page_nonce' => wp_create_nonce('wtotem_page_nonce'),
1468 'user_id' => $user->ID,
1469 ],
1470 'template' => 'two_factor_auth'
1471 ];
1472
1473 $response['content'] = $template->arrayRender($build);
1474
1475 $response['notifications'] = self::notifications();
1476 wp_send_json($response);
1477 }
1478
1479 /**
1480 * Changing the theme mode.
1481 *
1482 * @return void
1483 */
1484 public static function changeThemeMode()
1485 {
1486
1487 if (WebTotemRequest::post('ajax_action') !== 'theme_mode') {
1488 return;
1489 }
1490
1491 $theme_mode = WebTotemOption::getSessionOption('theme_mode');
1492
1493 if ($theme_mode == 'dark') {
1494 WebTotemOption::setSessionOptions(['theme_mode' => 'light']);
1495 $response = 'light';
1496 } else {
1497 WebTotemOption::setSessionOptions(['theme_mode' => 'dark']);
1498 $response = 'dark';
1499 }
1500
1501 wp_send_json($response);
1502 }
1503
1504 /**
1505 * Set user time zone offset.
1506 *
1507 * @return void
1508 */
1509 public static function userTimeZone()
1510 {
1511
1512 if (WebTotemRequest::post('ajax_action') !== 'set_time_zone') {
1513 return;
1514 }
1515
1516 // The REST API exposes no user time zone, so the browser offset is the
1517 // source of truth here.
1518 $time_zone_offset = WebTotemRequest::post('offset');
1519 $time_zone_offset = is_numeric($time_zone_offset) ? (float) $time_zone_offset : 0;
1520 $time_zone_offset = max(-14, min(14, $time_zone_offset));
1521
1522 $now = strtotime('now');
1523 $check = WebTotemOption::getOption('time_zone_check') ?: 0;
1524
1525 // Checking whether an hour has elapsed since the previous request.
1526 if ($now >= $check) {
1527 WebTotemOption::setOptions([
1528 'time_zone_check' => $now + 3600,
1529 'time_zone_offset' => $time_zone_offset,
1530 ]);
1531 }
1532
1533 wp_send_json([
1534 'success' => true,
1535 'time_zone_offset' => $time_zone_offset
1536 ]);
1537
1538 }
1539
1540 /**
1541 * Issue a single-use ticket for the browser WebSocket connection.
1542 *
1543 * The browser asks for a fresh ticket before every connect and every
1544 * reconnect: tickets are short-lived and may be used only once, which is why
1545 * the access token no longer has to be printed into the page.
1546 *
1547 * @return void
1548 */
1549 public static function getWsTicket()
1550 {
1551 if (WebTotemRequest::post('ajax_action') !== 'get_ws_ticket') {
1552 return;
1553 }
1554
1555 $origin = self::allowedOrigin(WebTotemRequest::post('origin'));
1556 $ticket = WebTotemAPI::getWSTicket($origin);
1557
1558 if ($ticket !== '') {
1559 wp_send_json([
1560 'success' => true,
1561 'mode' => 'ticket',
1562 'ticket' => $ticket,
1563 'notifications' => self::notifications(),
1564 ]);
1565 }
1566
1567 // Transitional: an API build without the ticket endpoint answers 404.
1568 // Until every environment is updated, fall back to the bearer token, which
1569 // the old socket accepts. The token is handed to an administrator over the
1570 // nonce-checked AJAX call only, never printed into the page, and this
1571 // branch disappears as soon as the endpoint exists everywhere.
1572 if (in_array(WebTotemAPI::getLastStatus(), [404, 405, 501], TRUE)) {
1573 $token = WebTotemOption::getAuthToken();
1574
1575 if ($token) {
1576 wp_send_json([
1577 'success' => true,
1578 'mode' => 'token',
1579 'token' => $token,
1580 'notifications' => self::notifications(),
1581 ]);
1582 }
1583 }
1584
1585 wp_send_json([
1586 'success' => false,
1587 'error' => 'ws_ticket_unavailable',
1588 'notifications' => self::notifications(),
1589 ]);
1590 }
1591
1592 /**
1593 * Normalise the requested WebSocket origin against this site's own origins.
1594 *
1595 * A ticket is bound to the origin it was issued for, so the plugin only ever
1596 * asks for one of its own origins and ignores whatever else was posted.
1597 *
1598 * @param mixed $origin
1599 * Origin posted by the browser.
1600 *
1601 * @return string
1602 * An allowed origin, or an empty string to fall back to the server-side
1603 * allowlist.
1604 */
1605 protected static function allowedOrigin($origin)
1606 {
1607 $origin = is_string($origin) ? trim($origin) : '';
1608 if ($origin === '') {
1609 return '';
1610 }
1611
1612 $known = [];
1613 foreach ([home_url(), site_url(), admin_url()] as $url) {
1614 $parts = wp_parse_url($url);
1615 if (empty($parts['scheme']) || empty($parts['host'])) {
1616 continue;
1617 }
1618 $known[] = strtolower(
1619 $parts['scheme'] . '://' . $parts['host']
1620 . (empty($parts['port']) ? '' : ':' . $parts['port'])
1621 );
1622 }
1623
1624 $parts = wp_parse_url($origin);
1625 if (empty($parts['scheme']) || empty($parts['host'])) {
1626 return '';
1627 }
1628
1629 $normalized = strtolower(
1630 $parts['scheme'] . '://' . $parts['host']
1631 . (empty($parts['port']) ? '' : ':' . $parts['port'])
1632 );
1633
1634 return in_array($normalized, $known, TRUE) ? $normalized : '';
1635 }
1636
1637 /**
1638 * Forced checking of services.
1639 *
1640 * @return void
1641 */
1642 public static function force_check()
1643 {
1644 if (WebTotemRequest::post('ajax_action') !== 'force_check') {
1645 return;
1646 }
1647
1648 $service = WebTotemRequest::post('service');
1649 $host = WebTotemAPI::siteInfo();
1650 $template = new WebTotemTemplate();
1651
1652 $response['success'] = false;
1653
1654 if($service){
1655
1656 $services = [
1657 'ssl' => 'ssl',
1658 'rc' => 'reputation',
1659 // 'dec' => 'location',
1660 'ops' => 'openPath',
1661 'ps' => 'openPort',
1662 'availability' => 'availability',
1663 ];
1664
1665 // force check service
1666 if($service == 'av'){
1667 $_response = WebTotemAPI::forceCheckAV();
1668 } else {
1669 if(isset( $services[$service] )){
1670 $_response = WebTotemAPI::forceCheck($host['id'], $services[$service]);
1671 }
1672 }
1673
1674 if (!isset($_response['message'])) {
1675
1676 switch ($service) {
1677
1678 case 'ssl':
1679 $data = WebTotemAPI::getMonitoringData($host['id']);
1680
1681 $ssl = [
1682 'status' => WebTotem::getStatusData($data['module_ssl']['info']['status']),
1683 'cert_name' => $data['module_ssl']['result']['certificate_name'],
1684 'days_left' => $data['module_ssl']['result']['days_left'],
1685 'issue_date' => WebTotem::dateFormatter($data['module_ssl']['result']['issue_date']),
1686 'expiry_date' => WebTotem::dateFormatter($data['module_ssl']['result']['expiry_date']),
1687 ];
1688
1689 $build[] = [
1690 'variables' => [
1691 'ssl' => $ssl,
1692 ],
1693 'template' => 'monitoring_ssl',
1694 ];
1695
1696 $response['content'] = $template->arrayRender($build);
1697 $response['success'] = true;
1698 break;
1699
1700 case 'availability':
1701 $data = WebTotemAPI::getMonitoringData($host['id']);
1702
1703 $domain = [
1704 'status' => WebTotem::getStatusData($data['module_location']['info']['status']),
1705 "redirect_link" => $data['module_location']['result']['redirect_link'],
1706 "is_created_at" => (bool)$data['module_location']['result']['checked_at'],
1707 "created_at" => WebTotem::dateFormatter($data['module_location']['result']['checked_at']),
1708 "is_taken" => $data['module_location']['result']['is_taken'],
1709 "ips" => $data['module_location']['result']['locations'],
1710 "protection" => $data['module_location']['result']['protection'],
1711 ];
1712
1713 $build[] = [
1714 'variables' => [
1715 'domain' => $domain,
1716 'availability' => [
1717 'chart' => json_encode($data['module_availability']['result']['stats_by_day']),
1718 'status' => WebTotem::getStatusData($data['module_availability']['info']['status'])
1719 ],
1720 ],
1721 'template' => 'monitoring_domain',
1722 ];
1723
1724 $response['content'] = $template->arrayRender($build);
1725 $response['success'] = true;
1726 break;
1727
1728 case 'rc':
1729 $data = WebTotemAPI::getMonitoringData($host['id']);
1730
1731 $reputation = [
1732 "status" => WebTotem::getStatusData($data['module_reputation']['info']['status'] ?? ''),
1733 "info" => WebTotem::getReputationInfo($data['reputation']['result']['status'] ?? ''),
1734 "last_test" => WebTotem::dateFormatter($data['reputation']['result']['checked_at'] ?? ''),
1735 ];
1736
1737 $build[] = [
1738 'variables' => [
1739 'reputation' => $reputation,
1740 ],
1741 'template' => 'monitoring_reputation',
1742 ];
1743
1744 $response['content'] = $template->arrayRender($build);
1745 $response['success'] = true;
1746 break;
1747
1748 case 'ps':
1749 $data = WebTotemAPI::getMonitoringData($host['id']);
1750 $ports = $data['module_port_scanner']['result']['open_ports'];
1751
1752 if($ports['TCPResults']){
1753 $open_ports[] = [
1754 'variables' => [
1755 "ports" => WebTotem::getOpenPortsData($ports['open_ports'] ?? []),
1756 ],
1757 'template' => 'open_ports',
1758 ];
1759
1760 $open_ports_few[] = [
1761 'variables' => [
1762 "ports" => $ports['open_ports'] ? WebTotem::getOpenPortsData(array_slice($ports['open_ports'], 0, 3)) : [],
1763 "more" => true,
1764 ],
1765 'template' => 'open_ports',
1766 ];
1767 }
1768
1769
1770 $response = [
1771 'status' => WebTotem::getStatusData($ports['module_port_scanner']['info']['status']),
1772 'last_test' => WebTotem::dateFormatter($data['module_port_scanner']['result']['checked_at']),
1773 'open_ports' => (isset($open_ports)) ? $template->arrayRender($open_ports) : '',
1774 'open_ports_few' => (isset($open_ports_few)) ? $template->arrayRender($open_ports_few) : '',
1775 ];
1776
1777 $response['success'] = true;
1778
1779 break;
1780
1781 case 'ops':
1782
1783 $data = WebTotemAPI::getMonitoringData($host['id']);
1784 $open_path[] = [
1785 'variables' => [
1786 "paths" => $data['module_open_paths']['result']['open_paths'],
1787 ],
1788 'template' => 'open_paths',
1789 ];
1790
1791 $response = [
1792 'status' => WebTotem::getStatusData($data['module_open_paths']['info']['status'] ),
1793 "last_test" => WebTotem::dateFormatter($data['module_open_paths']['result']['checked_at'] ?? false),
1794 'open_paths' => $template->arrayRender($open_path),
1795 ];
1796
1797 $response['success'] = true;
1798 break;
1799 }
1800
1801 }
1802 }
1803
1804 $response['notifications'] = self::notifications();
1805
1806 wp_send_json($response);
1807 }
1808
1809 /**
1810 * Initialization scanning and checking the current status.
1811 *
1812 * @return void
1813 */
1814 public static function wtotem_scan()
1815 {
1816
1817 if (WebTotemRequest::get('ajax_action') !== 'wtotem_scan') {
1818 return;
1819 }
1820
1821 $logs_action = WebTotemRequest::get('scan_action');
1822
1823 switch ($logs_action) {
1824 case 'init':
1825 if(!WebTotemOption::getOption('scan_init')){
1826 WebTotemOption::setOptions(['scan_init' => 1]);
1827 WebTotemScan::initialize();
1828 $response = [
1829 'success' => true,
1830 'scan_start' => 'success',
1831 ];
1832 } else {
1833 $response = [
1834 'success' => false,
1835 'error' => 'The scan is already running',
1836 ];
1837 }
1838
1839 break;
1840
1841 case 'push':
1842 if(WebTotemOption::getOption('scan_init')) {
1843 WebTotemScan::initialize();
1844 $response = [
1845 'success' => true,
1846 'scan_finished' => false,
1847 'push' => 'success',
1848 ];
1849 } else {
1850 $response = [
1851 'success' => false,
1852 'scan_finished' => true,
1853 'push' => 'fail',
1854 'error' => 'Scan completed',
1855 ];
1856 }
1857
1858 break;
1859 }
1860
1861
1862 wp_send_json($response ?? ['success' => false, 'error' => 'No action found']);
1863 }
1864
1865
1866 public static function authenticate()
1867 {
1868
1869 if (WebTotemRequest::post('ajax_action') !== 'authenticate') {
1870 return;
1871 }
1872
1873 $credentials = array(
1874 'log' => 'pwd',
1875 'username' => 'password'
1876 );
1877 $username = null;
1878 $password = null;
1879 foreach ($credentials as $usernameKey => $passwordKey) {
1880 if (array_key_exists($usernameKey, $_POST) &&
1881 array_key_exists($passwordKey, $_POST) &&
1882 is_string($_POST[$usernameKey]) &&
1883 is_string($_POST[$passwordKey])) {
1884 $username = $_POST[$usernameKey];
1885 $password = $_POST[$passwordKey];
1886 break;
1887 }
1888 }
1889 if (empty($username) || empty($password)) {
1890 $response['error'] = wp_kses(sprintf(__('<strong>ERROR</strong>: A username and password must be provided. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), wp_lostpassword_url()), array('strong' => array(), 'a' => array('href' => array(), 'title' => array())));
1891 }
1892
1893 do_action_ref_array('wp_authenticate', array(&$username, &$password));
1894
1895 $user = wp_authenticate($username, $password);
1896 $user = WebTotemBFProtection::checkBruteForceAttempts($user, $username);
1897
1898 if (is_object($user) && ($user instanceof \WP_User)) {
1899
1900 $response['login'] = true;
1901
1902 if (WebTotemLogin::hasUser2faActivated($user)) {
1903
1904 $template = new WebTotemTemplate();
1905
1906 $response['2fa'] = true;
1907 $response['content'] = $template->getHtml('login_auth_form');
1908
1909 }
1910 } else if (is_wp_error($user)) {
1911 $errors = array();
1912 foreach ($user->get_error_codes() as $code) {
1913 if ($code == 'invalid_username' || $code == 'invalid_email' || $code == 'incorrect_password' || $code == 'authentication_failed') {
1914 $errors[] = wp_kses(sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), wp_lostpassword_url()), array('strong' => array(), 'a' => array('href' => array(), 'title' => array())));
1915 } else {
1916 foreach ($user->get_error_messages($code) as $error_message) {
1917 $errors[] = $error_message;
1918 }
1919 }
1920 }
1921
1922 if (!empty($errors)) {
1923 $errors = implode('<br>', $errors);
1924 $response['error'] = apply_filters('login_errors', $errors);
1925 }
1926
1927 }
1928
1929 wp_send_json($response);
1930 }
1931
1932 /**
1933 * Notification output.
1934 *
1935 * @return string
1936 */
1937 public static function notifications()
1938 {
1939
1940 $notifications = WebTotem::getNotifications();
1941
1942 if ($notifications) {
1943 $build[] = [
1944 'variables' => [
1945 'notifications' => $notifications,
1946 ],
1947
1948 'template' => 'notifications',
1949 ];
1950
1951 $template = new WebTotemTemplate();
1952 return $template->arrayRender($build);
1953 }
1954 return false;
1955
1956 }
1957
1958
1959 }
1960