PluginProbe
Loginizer / 2.1.1
Loginizer v2.1.1
2.1.1 2.1.0 2.0.9 2.0.8 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 All 75 releases
loginizer / init.php

init.php in Loginizer 2.1.1, at init.php

1,020 lines 31.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if(!function_exists('add_action')){
4 echo 'You are not allowed to access this page directly.';
5 exit;
6 }
7
8 define('LOGINIZER_VERSION', '2.1.1');
9 define('LOGINIZER_DIR', dirname(LOGINIZER_FILE));
10 define('LOGINIZER_URL', plugins_url('', LOGINIZER_FILE));
11 define('LOGINIZER_PRO_URL', 'https://loginizer.com/features#compare');
12 define('LOGINIZER_PRICING_URL', 'https://loginizer.com/pricing');
13 define('LOGINIZER_DOCS', 'https://loginizer.com/docs/');
14
15 include_once(LOGINIZER_DIR.'/functions.php');
16
17 // Ok so we are now ready to go
18 register_activation_hook(LOGINIZER_FILE, 'loginizer_activation');
19
20 // Is called when the ADMIN enables the plugin
21 function loginizer_activation(){
22
23 global $wpdb;
24
25 $sql = array();
26
27 $sql[] = "DROP TABLE IF EXISTS `".$wpdb->prefix."loginizer_logs`";
28
29 $sql[] = "CREATE TABLE `".$wpdb->prefix."loginizer_logs` (
30 `username` varchar(255) NOT NULL DEFAULT '',
31 `time` int(10) NOT NULL DEFAULT '0',
32 `count` int(10) NOT NULL DEFAULT '0',
33 `lockout` int(10) NOT NULL DEFAULT '0',
34 `ip` varchar(255) NOT NULL DEFAULT '',
35 `url` varchar(255) NOT NULL DEFAULT '',
36 UNIQUE KEY `ip` (`ip`)
37 ) DEFAULT CHARSET=utf8;";
38
39 foreach($sql as $sk => $sv){
40 $wpdb->query($sv);
41 }
42
43 add_option('loginizer_version', LOGINIZER_VERSION);
44 add_option('loginizer_options', array());
45 add_option('loginizer_last_reset', 0);
46 add_option('loginizer_whitelist', array());
47 add_option('loginizer_blacklist', array());
48 add_option('loginizer_2fa_whitelist', array());
49
50 // TODO:: REMOVE THIS AFTER MARCH 2025
51 $softwp_upgrade = get_option('loginizer_softwp_upgrade', 0);
52 if(!defined('SITEPAD') && empty($softwp_upgrade)){
53 loginizer_check_softaculous();
54 }
55 }
56
57 /**
58 * Updates the database structure for Loginizer
59 *
60 * If the plugin files are updated but database structure is not updated
61 * this function will update the database structure as per the plugin version
62 * NOTE: This does not update plugin files it just updates the database structure
63 */
64 function loginizer_update_check(){
65
66 global $wpdb;
67
68 $sql = array();
69 $current_version = get_option('loginizer_version');
70
71 // It must be the 1.0 pre stuff
72 if(empty($current_version)){
73 $current_version = get_option('lz_version');
74 }
75
76 $version = (int) str_replace('.', '', $current_version);
77
78 // No update required
79 if($current_version == LOGINIZER_VERSION){
80 return true;
81 }
82
83 // Is it first run ?
84 if(empty($current_version)){
85
86 // Reinstall
87 loginizer_activation();
88
89 // Trick the following if conditions to not run
90 $version = (int) str_replace('.', '', LOGINIZER_VERSION);
91
92 }
93
94 // Is it less than 1.0.1 ?
95 if($version < 101){
96
97 // TODO : GET the existing settings
98
99 // Get the existing settings
100 $lz_failed_logs = lz_selectquery("SELECT * FROM `".$wpdb->prefix."lz_failed_logs`;", 1);
101 $lz_options = lz_selectquery("SELECT * FROM `".$wpdb->prefix."lz_options`;", 1);
102 $lz_iprange = lz_selectquery("SELECT * FROM `".$wpdb->prefix."lz_iprange`;", 1);
103
104 // Delete the three tables
105 $sql = array();
106 $sql[] = "DROP TABLE IF EXISTS ".$wpdb->prefix."lz_failed_logs;";
107 $sql[] = "DROP TABLE IF EXISTS ".$wpdb->prefix."lz_options;";
108 $sql[] = "DROP TABLE IF EXISTS ".$wpdb->prefix."lz_iprange;";
109
110 foreach($sql as $sk => $sv){
111 $wpdb->query($sv);
112 }
113
114 // Delete option
115 delete_option('lz_version');
116
117 // Reinstall
118 loginizer_activation();
119
120 // TODO : Save the existing settings
121
122 // Update the existing failed logs to new table
123 if(is_array($lz_failed_logs)){
124 foreach($lz_failed_logs as $fk => $fv){
125 $insert_data = array('username' => $fv['username'],
126 'time' => $fv['time'],
127 'count' => $fv['count'],
128 'lockout' => $fv['lockout'],
129 'ip' => $fv['ip']);
130
131 $format = array('%s','%d','%d','%d','%s');
132
133 $wpdb->insert($wpdb->prefix.'loginizer_logs', $insert_data, $format);
134 }
135 }
136
137 // Update the existing options to new structure
138 if(is_array($lz_options)){
139 foreach($lz_options as $ok => $ov){
140
141 if($ov['option_name'] == 'lz_last_reset'){
142 update_option('loginizer_last_reset', $ov['option_value']);
143 continue;
144 }
145
146 $old_option[str_replace('lz_', '', $ov['option_name'])] = $ov['option_value'];
147 }
148 // Save the options
149 update_option('loginizer_options', $old_option);
150 }
151
152 // Update the existing iprange to new structure
153 if(is_array($lz_iprange)){
154
155 $old_blacklist = array();
156 $old_whitelist = array();
157 $bid = 1;
158 $wid = 1;
159 foreach($lz_iprange as $ik => $iv){
160
161 if(!empty($iv['blacklist'])){
162 $old_blacklist[$bid] = array();
163 $old_blacklist[$bid]['start'] = long2ip($iv['start']);
164 $old_blacklist[$bid]['end'] = long2ip($iv['end']);
165 $old_blacklist[$bid]['time'] = strtotime($iv['date']);
166 $bid = $bid + 1;
167 }
168
169 if(!empty($iv['whitelist'])){
170 $old_whitelist[$wid] = array();
171 $old_whitelist[$wid]['start'] = long2ip($iv['start']);
172 $old_whitelist[$wid]['end'] = long2ip($iv['end']);
173 $old_whitelist[$wid]['time'] = strtotime($iv['date']);
174 $wid = $wid + 1;
175 }
176 }
177
178 if(!empty($old_blacklist)) update_option('loginizer_blacklist', $old_blacklist);
179 if(!empty($old_whitelist)) update_option('loginizer_whitelist', $old_whitelist);
180 }
181
182 }
183
184 // Is it less than 1.3.9 ?
185 if($version < 139){
186
187 $wpdb->query("ALTER TABLE ".$wpdb->prefix."loginizer_logs ADD `url` VARCHAR(255) NOT NULL DEFAULT '' AFTER `ip`;");
188
189 }
190
191 // Setting alignment to left in social login ?
192 if($version < 201){
193 $social_settings = get_option('loginizer_social_settings', []);
194
195 if(!empty($social_settings)){
196 if(!empty($social_settings['login']) && (!empty($social_settings['login']['login_form']) || !empty($social_settings['login']['registration_form']))){
197 $social_settings['login']['button_alignment'] = 'left';
198 }
199
200 if(!empty($social_settings['woocommerce']) && (!empty($social_settings['woocommmerce']['login_form']) || !empty($social_settings['woocommerce']['registration_form']))){
201 $social_settings['woocommerce']['button_alignment'] = 'left';
202 }
203
204 if(!empty($social_settings['comment']) && !empty($social_settings['comment']['enable_buttons'])){
205 $social_settings['comment']['button_alignment'] = 'left';
206 }
207
208 update_option('loginizer_social_settings', $social_settings);
209 }
210 }
211
212 // Save the new Version
213 update_option('loginizer_version', LOGINIZER_VERSION);
214
215 // TODO:: REMOVE THIS AFTER MARCH 2025
216 $softwp_upgrade = get_option('loginizer_softwp_upgrade', 0);
217 if(!defined('SITEPAD') && empty($softwp_upgrade)){
218 loginizer_check_softaculous();
219 }
220
221 // In Sitepad Math Captcha is enabled by default
222 if(defined('SITEPAD') && get_option('loginizer_captcha') === false){
223 $option['captcha_no_google'] = 1;
224 add_option('loginizer_captcha', $option);
225 }
226
227 }
228
229 // Add the action to load the plugin
230 add_action('plugins_loaded', 'loginizer_load_plugin');
231
232 // The function that will be called when the plugin is loaded
233 function loginizer_load_plugin(){
234
235 global $loginizer;
236
237 // Check if the installed version is outdated
238 loginizer_update_check();
239
240 // There was an issue were for some users update was stuck, and free was able to get updated through auto updater option
241 // removing these filters fixes that issue, and our Pro update blocker was improved in 2.1.1
242 // This check can be removed 1 year from 28.09.2026
243 if(defined('LOGINIZER_PRO_VERSION') && version_compare(LOGINIZER_PRO_VERSION, '2.1.1', '<')){
244 foreach(['site_transient_update_plugins', 'pre_site_transient_update_plugins'] as $hook){
245 remove_filter($hook, 'loginizer_pro_disable_manual_update_for_plugin'); // Older Pro used the default priority
246 remove_filter($hook, 'loginizer_pro_disable_manual_update_for_plugin', 99);
247 }
248 }
249
250 // Set the array
251 if(empty($loginizer)){
252 $loginizer = array();
253 }
254
255 $loginizer['prefix'] = !defined('SITEPAD') ? 'Loginizer ' : 'SitePad ';
256 $loginizer['app'] = !defined('SITEPAD') ? 'WordPress' : 'SitePad';
257 $loginizer['login_basename'] = !defined('SITEPAD') ? 'wp-login.php' : 'login.php';
258 $loginizer['wp-includes'] = !defined('SITEPAD') ? 'wp-includes' : 'site-inc';
259
260 // The IP Method to use
261 $loginizer['ip_method'] = get_option('loginizer_ip_method');
262 if($loginizer['ip_method'] == 3){
263 $loginizer['custom_ip_method'] = get_option('loginizer_custom_ip_method');
264 }
265
266 // Load settings
267 $options = get_option('loginizer_options');
268 $loginizer['max_retries'] = empty($options['max_retries']) ? 3 : $options['max_retries'];
269 $loginizer['lockout_time'] = empty($options['lockout_time']) ? 900 : $options['lockout_time']; // 15 minutes
270 $loginizer['max_lockouts'] = empty($options['max_lockouts']) ? 5 : $options['max_lockouts'];
271 $loginizer['lockouts_extend'] = empty($options['lockouts_extend']) ? 86400 : $options['lockouts_extend']; // 24 hours
272 $loginizer['reset_retries'] = empty($options['reset_retries']) ? 86400 : $options['reset_retries']; // 24 hours
273 $loginizer['notify_email'] = empty($options['notify_email']) ? 0 : $options['notify_email'];
274 $loginizer['notify_email_address'] = lz_is_multisite() ? get_site_option('admin_email') : get_option('admin_email');
275 $loginizer['trusted_ips'] = empty($options['trusted_ips']) ? false : true;
276 $loginizer['blocked_screen'] = empty($options['blocked_screen']) ? false : true;
277 $loginizer['social_settings'] = get_option('loginizer_social_settings', []);
278
279 if(!empty($options['notify_email_address'])){
280 $loginizer['notify_email_address'] = $options['notify_email_address'];
281 $loginizer['custom_notify_email'] = 1;
282 }
283
284 // Login Success Email Notification.
285 $loginizer['login_mail'] = get_option('loginizer_login_mail', []);
286 add_action('init', 'loginizer_load_translation_vars', 0);
287
288 $loginizer['login_mail_subject'] = empty($loginizer['login_mail']['subject']) ? '' : $loginizer['login_mail']['subject'];
289 $loginizer['login_mail_body'] = empty($loginizer['login_mail']['body']) ? '' : $loginizer['login_mail']['body'];
290
291 // Load the blacklist and whitelist
292 $loginizer['blacklist'] = get_option('loginizer_blacklist', []);
293 $loginizer['whitelist'] = get_option('loginizer_whitelist', []);
294 $loginizer['2fa_whitelist'] = get_option('loginizer_2fa_whitelist');
295
296 // It should not be false
297 if(empty($loginizer['2fa_whitelist'])){
298 $loginizer['2fa_whitelist'] = array();
299 }
300
301 // When was the database cleared last time
302 $loginizer['last_reset'] = get_option('loginizer_last_reset');
303
304 if(!isset($loginizer['ultimate-member-active'])){
305 $um_is_active = in_array('ultimate-member/ultimate-member.php', apply_filters('active_plugins', get_option('active_plugins', [])));
306
307 $loginizer['ultimate-member-active'] = !empty($um_is_active) ? true : false;
308 }
309
310 //print_r($loginizer);
311
312 // Clear retries
313 if((time() - $loginizer['last_reset']) >= $loginizer['reset_retries']){
314 loginizer_reset_retries();
315 }
316
317 $ins_time = get_option('loginizer_ins_time');
318 if(empty($ins_time)){
319 $ins_time = time();
320 update_option('loginizer_ins_time', $ins_time);
321 }
322 $loginizer['ins_time'] = $ins_time;
323
324 // Set the current IP
325 $loginizer['current_ip'] = lz_getip();
326
327 // Is Brute Force Disabled ?
328 $loginizer['disable_brute'] = get_option('loginizer_disable_brute');
329
330 // Filters and actions
331 if(empty($loginizer['disable_brute'])){
332
333 // Use this to verify before WP tries to login
334 // Is always called and is the first function to be called
335 //add_action('wp_authenticate', 'loginizer_wp_authenticate', 10, 2);// Not called by XML-RPC
336 add_filter('authenticate', 'loginizer_wp_authenticate', 10001, 3);// This one is called by xmlrpc as well as GUI
337
338 // Is called when a login attempt fails
339 // Hence Update our records that the login failed
340 add_action('wp_login_failed', 'loginizer_login_failed');
341
342 // Is called before displaying the error message so that we dont show that the username is wrong or the password
343 // Update Error message
344 add_action('wp_login_errors', 'loginizer_error_handler', 10001, 2);
345 add_action('woocommerce_login_failed', 'loginizer_woocommerce_error_handler', 10001);
346 add_action('wp_login', 'loginizer_login_success', 11, 2);
347 add_action('rsssl_two_factor_user_authenticated', 'loginizer_rsssl_2fa_success');
348
349 if(!empty($loginizer['ultimate-member-active'])){
350 add_action('wp_login_failed', 'loginizer_ultimatemember_error_handler', 10001);
351 }
352
353 if(!empty($_COOKIE['lz_social_error']) && !empty($loginizer['social_settings'])){
354 add_filter('wp_login_errors', 'loginizer_social_login_error_handler', 10000, 2);
355 }
356 }
357
358 // Social Login Form Actions
359 if(!empty($loginizer['social_settings'])){
360 if(!empty($loginizer['social_settings']['login']['login_form'])){
361 add_action('login_form', 'loginizer_social_btn_login');
362 }
363 }
364
365 if((function_exists('wp_doing_ajax') && wp_doing_ajax()) || (defined( 'DOING_AJAX' ) && DOING_AJAX)){
366 include_once LOGINIZER_DIR . '/main/ajax.php';
367 }
368
369 if(is_admin()){
370 include_once LOGINIZER_DIR . '/main/admin.php';
371 }
372
373 // ----------------
374 // PRO INIT END
375 // ----------------
376
377 // Secuity checks for social login.
378 if(!empty($_GET['lz_social_provider']) && loginizer_can_login() && empty($_GET['lz_api'])){
379 add_action('init', 'loginizer_social_login_load');
380 return;
381 }
382 }
383
384 // Should return NULL if everything is fine
385 function loginizer_wp_authenticate($user, $username, $password){
386
387 global $loginizer, $lz_error, $lz_cannot_login, $lz_user_pass;
388
389 if(!empty($username) && !empty($password)){
390 $lz_user_pass = 1;
391 }
392
393 // Are you whitelisted ?
394 if(loginizer_is_whitelisted()){
395 $loginizer['ip_is_whitelisted'] = 1;
396 return $user;
397
398 } else if (!empty($loginizer['trusted_ips'])){
399 $lz_cannot_login = 1;
400
401 // This is used by WP Activity Log
402 apply_filters( 'wp_login_blocked', $username );
403
404 // Shows a blocked screen
405 if(!empty($loginizer['blocked_screen'])){
406 $lz_error['trusted_ip'] = __('You are restricted from logging in as your IP is not whitelisted.', 'loginizer');
407 loginizer_blocked_page($lz_error);
408 }
409
410 return new WP_Error('ip_blacklisted', __('You are restricted from logging in as your IP is not whitelisted.', 'loginizer'));
411 }
412
413 // Are you blacklisted ?
414 if(loginizer_is_blacklisted()){
415 $lz_cannot_login = 1;
416
417 // This is used by WP Activity Log
418 apply_filters( 'wp_login_blocked', $username );
419
420 // Shows a blocked screen
421 if(!empty($loginizer['blocked_screen'])){
422 loginizer_blocked_page($lz_error);
423 }
424
425 return new WP_Error('ip_blacklisted', implode('', $lz_error), 'loginizer');
426 }
427
428 // Is the username blacklisted ?
429 if(function_exists('loginizer_user_blacklisted')){
430 if(loginizer_user_blacklisted($username)){
431 $lz_cannot_login = 1;
432
433 // This is used by WP Activity Log
434 apply_filters( 'wp_login_blocked', $username );
435
436 return new WP_Error('user_blacklisted', implode('', $lz_error), 'loginizer');
437 }
438 }
439
440 if(loginizer_can_login()){
441 return $user;
442 }
443
444 $lz_cannot_login = 1;
445
446 // This is used by WP Activity Log
447 apply_filters( 'wp_login_blocked', $username );
448
449 // Shows a blocked screen
450 if(!empty($loginizer['blocked_screen'])){
451 loginizer_blocked_page($lz_error);
452 }
453
454 return new WP_Error('ip_blocked', implode('', $lz_error), 'loginizer');
455
456 }
457
458 function loginizer_can_login(){
459
460 global $wpdb, $loginizer, $lz_error;
461
462 // Get the logs
463 $sel_query = $wpdb->prepare("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = %s", $loginizer['current_ip']);
464 $result = lz_selectquery($sel_query);
465
466 if(!empty($result['count']) && ($result['count'] % $loginizer['max_retries']) == 0){
467
468 // Has he reached max lockouts ?
469 if($result['lockout'] >= $loginizer['max_lockouts']){
470 $loginizer['lockout_time'] = $loginizer['lockouts_extend'];
471 }
472
473 // Is he in the lockout time ?
474 if($result['time'] >= (time() - $loginizer['lockout_time'])){
475 $banlift = ceil((($result['time'] + $loginizer['lockout_time']) - time()) / 60);
476
477 //echo 'Current Time '.date('d/M/Y H:i:s P', time()).'<br />';
478 //echo 'Last attempt '.date('d/M/Y H:i:s P', $result['time']).'<br />';
479 //echo 'Unlock Time '.date('d/M/Y H:i:s P', $result['time'] + $loginizer['lockout_time']).'<br />';
480
481 $_time = $banlift.' '.$loginizer['msg']['minutes_err'];
482
483 if($banlift > 60){
484 $banlift = ceil($banlift / 60);
485 $_time = $banlift.' '.$loginizer['msg']['hours_err'];
486 }
487
488 $lz_error['ip_blocked'] = $loginizer['msg']['lockout_err'].' '.$_time;
489
490 if(!empty($loginizer['ultimate-member-active']) && class_exists('UM')){
491 \UM()->form()->add_error('blocked_msg', $lz_error['ip_blocked']);
492 }
493 return false;
494 }
495 }
496
497 return true;
498 }
499
500 function loginizer_is_blacklisted(){
501
502 global $wpdb, $loginizer, $lz_error;
503
504 $blacklist = isset($loginizer['blacklist']) ? $loginizer['blacklist'] : [];
505
506 if(empty($blacklist)){
507 return false;
508 }
509
510 $current_ip_inet = inet_ptoi($loginizer['current_ip']);
511
512 foreach($blacklist as $k => $v){
513
514 $start_inet = inet_ptoi($v['start']);
515 $end_inet = inet_ptoi($v['end']);
516
517 // Is the IP in the blacklist ?
518 if($start_inet <= $current_ip_inet && $current_ip_inet <= $end_inet){
519 $result = 1;
520 break;
521 }
522
523 // Is it in a wider range ?
524 if($start_inet >= 0 && $end_inet < 0){
525
526 // Since the end of the RANGE (i.e. current IP range) is beyond the +ve value of inet_ptoi,
527 // if the current IP is <= than the start of the range, it is within the range
528 // OR
529 // if the current IP is <= than the end of the range, it is within the range
530 if($start_inet <= $current_ip_inet
531 || $current_ip_inet <= $end_inet){
532 $result = 1;
533 break;
534 }
535
536 }
537
538 }
539
540 // You are blacklisted
541 if(!empty($result)){
542 $lz_error['ip_blacklisted'] = $loginizer['msg']['ip_blacklisted'];
543 return true;
544 }
545
546 return false;
547
548 }
549
550 // When the login fails, then this is called
551 // We need to update the database
552 function loginizer_login_failed($username, $is_2fa = ''){
553
554 global $wpdb, $loginizer, $lz_cannot_login;
555
556 // Some plugins are changing the value for username as null so we need to handle it before using it for the INSERT OR UPDATE query
557 if(empty($username) || is_null($username)){
558 $username = '';
559 }
560
561 $fail_type = 'Login';
562
563 if(!empty($is_2fa)){
564 $fail_type = '2FA';
565 }
566
567 if(empty($lz_cannot_login) && empty($loginizer['ip_is_whitelisted']) && empty($loginizer['no_loginizer_logs'])){
568
569 // The params which comes when social login returns an error, have some characters, which WordPress could not save.
570 // REQUEST_URI / HTTP_HOST are not always set (WP-CLI, some CGI and XML-RPC setups)
571 $server_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
572 $http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
573
574 if(!empty($server_uri) && strpos($server_uri, 'lz_social_provider') !== FALSE){
575 $request_uri = explode('=', $server_uri);
576 $server_uri = $request_uri[0];
577 }
578
579 // No addslashes() here, $wpdb->prepare() below does the escaping
580 $url = esc_url((!empty($_SERVER['HTTPS']) ? 'https://' : 'http://').$http_host.$server_uri);
581
582 // Must never be 0, we divide by it below
583 $max_retries = (int) $loginizer['max_retries'] < 1 ? 1 : (int) $loginizer['max_retries'];
584
585 // This way is atomic now, the earlier one were causing race condition.
586 // NOTE : In the UPDATE part `count` is already the new value, as MySQL / MariaDB
587 // evaluate the assignments from left to right, so lockout must NOT add 1 again
588 $upsert = $wpdb->prepare(
589 "INSERT INTO `".$wpdb->prefix."loginizer_logs`
590 (username, time, count, ip, lockout, url)
591 VALUES
592 (%s, %d, 1, %s, FLOOR(1 / %d), %s)
593 ON DUPLICATE KEY UPDATE
594 username = VALUES(username),
595 time = VALUES(time),
596 count = count + 1,
597 lockout = FLOOR(count / %d),
598 url = VALUES(url)",
599 $username,
600 time(),
601 $loginizer['current_ip'],
602 $max_retries,
603 $url,
604 $max_retries
605 );
606 $wpdb->query($upsert);
607
608 // Re-read the persisted row so email/retries-left reflect the actual count
609 $sel_query = $wpdb->prepare("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = %s", $loginizer['current_ip']);
610 $result = lz_selectquery($sel_query);
611
612 if(empty($result)){
613 $result = array('count' => 0);
614 }
615
616 $count = (int) $result['count'];
617 $lockout = !empty($result['lockout']) ? (int) $result['lockout'] : 0;
618
619 // The lockout goes up only on every max_retries'th failure, which is the
620 // attempt that actually locks the IP out. On the failures in between there
621 // is nothing new to report, so we must not email on each one of them
622 $is_new_lockout = !empty($count) && ($count % $max_retries) == 0;
623
624 // Do we need to email admin ?
625 if(!empty($loginizer['notify_email']) && !empty($is_new_lockout) && $lockout >= $loginizer['notify_email']){
626
627 $lockout_time = $loginizer['lockout_time'];
628
629 if($lockout >= $loginizer['max_lockouts']){
630 $lockout_time = $loginizer['lockouts_extend'];
631 }
632
633 $sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
634 $mail = array();
635 $mail['to'] = $loginizer['notify_email_address'];
636 $mail['subject'] = 'Failed '.$fail_type.' Attempts from IP '.$loginizer['current_ip'].' ('.$sitename.')';
637 $mail['message'] = 'Hi,
638
639 '.(int) $result['count'].' failed '.strtolower($fail_type).' attempts and '.$lockout.' lockout(s) from IP '.$loginizer['current_ip'].' on your site :
640 '.home_url().'
641
642 Last '.$fail_type.' Attempt : '.date('d/M/Y H:i:s P', time()).'
643 Last User Attempt : '.$username.'
644 IP has been blocked until : '.date('d/M/Y H:i:s P', time() + $lockout_time).'
645
646 Regards,
647 Loginizer';
648
649 @wp_mail($mail['to'], $mail['subject'], $mail['message']);
650 }
651
652 loginizer_update_attempt_stats(0);
653 $loginizer['retries_left'] = $max_retries - ($count % $max_retries);
654 $loginizer['retries_left'] = $loginizer['retries_left'] == $max_retries ? 0 : $loginizer['retries_left'];
655
656 }
657 }
658
659 function loginizer_rsssl_2fa_success($user){
660 loginizer_login_success('', $user);
661 }
662
663 function loginizer_login_success($user_login, $user) {
664 global $wp_version, $loginizer;
665
666 loginizer_update_attempt_stats(1);
667
668 if(empty($loginizer['login_mail'])){
669 return;
670 }
671
672 if(empty($loginizer['login_mail']['enable'])){
673 return;
674 }
675
676 if(!empty($loginizer['login_mail']['disable_whitelist'])){
677 // Check its whitelist ip
678 if(loginizer_is_whitelisted()){
679 return;
680 }
681 }
682
683 if(empty($user_login) && empty($user)){
684 error_log('Loginizer: No user information to send email');
685 return;
686 }
687
688 if(empty($user)){
689 $user = get_user_by('login', $user_login);
690 }
691
692 if(empty($user)){
693 error_log('Loginizer: Unable to get the user');
694 return;
695 }
696
697 if(empty($loginizer['login_mail']['roles']) || !is_array($loginizer['login_mail']['roles'])){
698 return;
699 }
700
701 // Check if the user role is enabled for email notification.
702 if(!array_intersect($user->roles, $loginizer['login_mail']['roles'])){
703 return;
704 }
705
706 // current_datetime & wp_timezone_string were introduced in WordPress 5.3
707 if(!empty($wp_version) && version_compare($wp_version, '5.3', '>') && function_exists('current_datetime')){
708 $time_zone = wp_timezone_string();
709
710 if(!empty($time_zone) && isset($time_zone[1]) && is_numeric($time_zone[1])){
711 $time_zone = 'UTC'.$time_zone;
712 }
713
714 // Setting up data variables.
715 $date = current_datetime()->format('Y-m-d H:i:s') .' '. $time_zone;
716 } else {
717 $date = date("Y-m-d H:i:s", time()) . ' ' . date_default_timezone_get();
718 }
719
720 $sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
721 $email = $user->data->user_email;
722
723 $vars = array(
724 'date' => $date,
725 'ip' => esc_html($loginizer['current_ip']),
726 'sitename' => $sitename,
727 'user_login' => $user_login
728 );
729
730 $message = lz_lang_vars_name($loginizer['login_mail_body'], $vars);
731 $subject = lz_lang_vars_name($loginizer['login_mail_subject'], $vars);
732
733 $headers = [];
734
735 // Do we need to send the email as HTML ?
736 if(!empty($loginizer['login_mail']['html_mail'])){
737 $headers[] = 'Content-Type: text/html; charset=UTF-8';
738
739 if(!empty($loginizer['login_mail']['body'])){
740 $message = html_entity_decode($message);
741 }else{
742 $message = preg_replace("/\<br\s*\/\>/i", "<br/>", $message);
743 $message = preg_replace('/(?<!<br\/>)\n/i', "<br/>\n", $message);
744 }
745 }
746
747 // Sending notification
748 if(empty(wp_mail($email, $subject, $message, $headers))){
749 error_log(__('There was a problem sending your email.', 'loginizer'));
750 return;
751 }
752 }
753
754 function loginizer_update_attempt_stats($type){
755
756 $stats = get_option('loginizer_login_attempt_stats', []);
757 $time = strtotime(date('Y-m-d H:00:00'));
758
759 if(empty($stats[$time][$type])){
760 $stats[$time][$type] = 0;
761 }
762
763 $stats[$time][$type] += 1;
764
765 update_option('loginizer_login_attempt_stats', $stats, false);
766 }
767
768 // Handles the error of the password not being there
769 function loginizer_error_handler($errors, $redirect_to){
770
771 global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
772
773 //echo 'loginizer_error_handler :';print_r($errors->errors);echo '<br>';
774 if(is_null($errors) || empty($errors)){
775 return true;
776 }
777
778 // Remove the empty password error
779 if(is_wp_error($errors)){
780
781 $codes = $errors->get_error_codes();
782
783 foreach($codes as $k => $v){
784 if($v == 'invalid_username' || $v == 'incorrect_password'){
785 $show_error = 1;
786 }
787 }
788
789 $errors->remove('invalid_username');
790 $errors->remove('incorrect_password');
791
792 // Add the error
793 if(!empty($lz_user_pass) && !empty($show_error) && empty($lz_cannot_login)){
794 $errors->add('invalid_userpass', '<b>ERROR:</b> ' . $loginizer['msg']['inv_userpass']);
795 }
796
797 // Add the number of retires left as well
798 if(count($errors->get_error_codes()) > 0 && isset($loginizer['retries_left'])){
799 $errors->add('retries_left', loginizer_retries_left());
800 }
801
802 }
803
804 return $errors;
805
806 }
807
808 // Handles the error of the password not being there
809 function loginizer_woocommerce_error_handler(){
810
811 global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
812
813 if(function_exists('wc_add_notice')){
814 wc_add_notice( loginizer_retries_left(), 'error' );
815 }
816 }
817
818 function loginizer_ultimatemember_error_handler(){
819
820 if(class_exists('UM')){
821 \UM()->form()->add_error('remaining_tries', loginizer_retries_left());
822 }
823 }
824
825 // Handles social login URL
826 function loginizer_social_login_error_handler($errors = '', $redirect_to = ''){
827 global $loginizer;
828
829 if(loginizer_is_blacklisted()){
830 return $errors;
831 }
832
833 loginizer_get_social_error();
834
835 if(empty($loginizer['social_errors'])){
836 return $errors;
837 }
838
839 if(is_null($errors) || empty($errors) || !is_wp_error($errors)){
840 $errors = new WP_Error();
841 }
842
843 foreach($loginizer['social_errors'] as $key => $text){
844 $errors->add($key, $text);
845 }
846
847 return $errors;
848 }
849
850 // Returns a string with the number of retries left
851 function loginizer_retries_left(){
852
853 global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
854
855 // If we are to show the number of retries left
856 if(isset($loginizer['retries_left'])){
857 $retries_left = apply_filters('loginizer_retries_left_num', $loginizer['retries_left']);
858
859 return '<b>'.esc_html($retries_left).'</b> '.$loginizer['msg']['attempts_left'];
860 }
861
862 }
863
864 function loginizer_reset_retries(){
865
866 global $wpdb, $loginizer;
867
868 $deltime = time() - $loginizer['reset_retries'];
869
870 $del_query = $wpdb->prepare("DELETE FROM `".$wpdb->prefix."loginizer_logs` WHERE `time` <= %d", $deltime);
871 $result = $wpdb->query($del_query);
872
873 update_option('loginizer_last_reset', time());
874
875 }
876
877 function loginizer_load_translation_vars(){
878 global $loginizer;
879
880 $loginizer['login_mail_default_sub'] = __('Login Successful at $sitename', 'loginizer');
881 $loginizer['login_mail_default_msg'] = __('Hello $user_login,
882
883 Your account was recently logged in from the IP : $ip
884 Time : $date
885 If it was not you who logged in then please report this to us immediately.
886
887 Regards,
888 $sitename','loginizer');
889
890 if(empty($loginizer['login_mail_subject'])){
891 $loginizer['login_mail_subject'] = $loginizer['login_mail_default_sub'];
892 }
893
894 if(empty($loginizer['login_mail_body'])){
895 $loginizer['login_mail_body'] = $loginizer['login_mail_default_msg'];
896 }
897
898 // Default messages
899 $loginizer['d_msg']['inv_userpass'] = __('Incorrect Username or Password', 'loginizer');
900 $loginizer['d_msg']['ip_blacklisted'] = __('Your IP has been blacklisted', 'loginizer');
901 $loginizer['d_msg']['attempts_left'] = __('attempt(s) left', 'loginizer');
902 $loginizer['d_msg']['lockout_err'] = __('You have exceeded maximum login retries<br /> Please try after', 'loginizer');
903 $loginizer['d_msg']['minutes_err'] = __('minute(s)', 'loginizer');
904 $loginizer['d_msg']['hours_err'] = __('hour(s)', 'loginizer');
905
906 // Message Strings
907 $loginizer['msg'] = get_option('loginizer_msg', []);
908
909 foreach($loginizer['d_msg'] as $lk => $lv){
910 if(empty($loginizer['msg'][$lk])){
911 $loginizer['msg'][$lk] = $loginizer['d_msg'][$lk];
912 }
913 }
914
915 $loginizer['2fa_d_msg']['otp_app'] = __('Please enter the OTP as seen in your App', 'loginizer');
916 $loginizer['2fa_d_msg']['otp_email'] = __('Please enter the OTP emailed to you', 'loginizer');
917 $loginizer['2fa_d_msg']['otp_field'] = __('One Time Password', 'loginizer');
918 $loginizer['2fa_d_msg']['otp_question'] = __('Please answer your security question', 'loginizer');
919 $loginizer['2fa_d_msg']['otp_answer'] = __('Your Answer', 'loginizer');
920
921 // Message Strings
922 $loginizer['2fa_msg'] = get_option('loginizer_2fa_msg', []);
923
924 foreach($loginizer['2fa_d_msg'] as $lk => $lv){
925 if(empty($loginizer['2fa_msg'][$lk])){
926 $loginizer['2fa_msg'][$lk] = $loginizer['2fa_d_msg'][$lk];
927 }
928 }
929
930 }
931
932 function loginizer_social_login_load(){
933 include_once LOGINIZER_DIR . '/main/social-login.php';
934 }
935
936 // Checks if softaculous is installed on the server.
937 function loginizer_check_softaculous(){
938
939 // Checking if we have Softaculous installed?
940 if(!preg_match('/^\/home(?:\d+)?\/.*\//U', ABSPATH, $matches)){
941 return false;
942 }
943
944 if(empty($matches) || empty($matches[0])){
945 return false;
946 }
947
948 $softaculous_path = $matches[0] . '.softaculous/installations.php';
949 if(!file_exists($softaculous_path)){
950 return false;
951 }
952
953 // Checking if users has changed the branding of Softaculous.
954 $universal_file = '';
955 // Plesk, ISPManager, ISPConfig, InterWorx, H-Sphere, CentOS Web Panel, Softaculous Remote and Softaculous Enterprise
956 if(file_exists('/usr/local/softaculous/enduser/universal.php')){
957 $universal_file = '/usr/local/softaculous/enduser/universal.php';
958 }else if(file_exists('/usr/local/cpanel/whostmgr/docroot/cgi/softaculous/enduser/universal.php')){
959 $universal_file = '/usr/local/cpanel/whostmgr/docroot/cgi/softaculous/enduser/universal.php';
960 }else if(file_exists('/usr/local/directadmin/plugins/softaculous/enduser/universal.php')){
961 $universal_file = '/usr/local/directadmin/plugins/softaculous/enduser/universal.php';
962 }else if(file_exists('/usr/local/vesta/softaculous/enduser/universal.php')){
963 $universal_file = '/usr/local/vesta/softaculous/enduser/universal.php';
964 }
965
966 if(empty($universal_file)){
967 return false;
968 }
969
970 $universal = file_get_contents($universal_file);
971
972 if(empty($universal)){
973 return false;
974 }
975
976 // Checking if Softaculous is being whitelabeled
977 if(preg_match('/\$globals\[["\']sn["\']\]\s.?=\s.?["\']Softaculous["\']/', $universal)){
978 update_option('loginizer_softwp_upgrade', time());
979 }
980
981 return false;
982 }
983
984 // Sorry to see you going
985 register_uninstall_hook(LOGINIZER_FILE, 'loginizer_deactivation');
986
987 function loginizer_deactivation(){
988
989 global $wpdb;
990
991 $sql = array();
992 $sql[] = "DROP TABLE ".$wpdb->prefix."loginizer_logs;";
993
994 foreach($sql as $sk => $sv){
995 $wpdb->query($sv);
996 }
997
998 delete_option('loginizer_version');
999 delete_option('loginizer_options');
1000 delete_option('loginizer_last_reset');
1001 delete_option('loginizer_whitelist');
1002 delete_option('loginizer_blacklist');
1003 delete_option('loginizer_msg');
1004 delete_option('loginizer_2fa_msg');
1005 delete_option('loginizer_2fa_email_template');
1006 delete_option('loginizer_security');
1007 delete_option('loginizer_wp_admin');
1008 delete_option('loginizer_csrf_promo_time');
1009 delete_option('loginizer_backuply_promo_time');
1010 delete_option('loginizer_promo_time');
1011 delete_option('loginizer_ins_time');
1012 delete_option('loginizer_2fa_whitelist');
1013 delete_option('loginizer_checksums_last_run');
1014 delete_option('loginizer_checksums_diff');
1015 delete_option('loginizer_ip_method');
1016 delete_option('loginizer_2fa_custom_redirect');
1017 delete_option('external_updates-loginizer-security');
1018 delete_option('loginizer_login_attempt_stats');
1019
1020 }