PluginProbe
Loginizer / 2.1.0
Loginizer v2.1.0
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 1.3.4 All 74 releases
loginizer / init.php

init.php in Loginizer 2.1.0, at init.php

1,010 lines 30.9 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.0');
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 // Set the array
241 if(empty($loginizer)){
242 $loginizer = array();
243 }
244
245 $loginizer['prefix'] = !defined('SITEPAD') ? 'Loginizer ' : 'SitePad ';
246 $loginizer['app'] = !defined('SITEPAD') ? 'WordPress' : 'SitePad';
247 $loginizer['login_basename'] = !defined('SITEPAD') ? 'wp-login.php' : 'login.php';
248 $loginizer['wp-includes'] = !defined('SITEPAD') ? 'wp-includes' : 'site-inc';
249
250 // The IP Method to use
251 $loginizer['ip_method'] = get_option('loginizer_ip_method');
252 if($loginizer['ip_method'] == 3){
253 $loginizer['custom_ip_method'] = get_option('loginizer_custom_ip_method');
254 }
255
256 // Load settings
257 $options = get_option('loginizer_options');
258 $loginizer['max_retries'] = empty($options['max_retries']) ? 3 : $options['max_retries'];
259 $loginizer['lockout_time'] = empty($options['lockout_time']) ? 900 : $options['lockout_time']; // 15 minutes
260 $loginizer['max_lockouts'] = empty($options['max_lockouts']) ? 5 : $options['max_lockouts'];
261 $loginizer['lockouts_extend'] = empty($options['lockouts_extend']) ? 86400 : $options['lockouts_extend']; // 24 hours
262 $loginizer['reset_retries'] = empty($options['reset_retries']) ? 86400 : $options['reset_retries']; // 24 hours
263 $loginizer['notify_email'] = empty($options['notify_email']) ? 0 : $options['notify_email'];
264 $loginizer['notify_email_address'] = lz_is_multisite() ? get_site_option('admin_email') : get_option('admin_email');
265 $loginizer['trusted_ips'] = empty($options['trusted_ips']) ? false : true;
266 $loginizer['blocked_screen'] = empty($options['blocked_screen']) ? false : true;
267 $loginizer['social_settings'] = get_option('loginizer_social_settings', []);
268
269 if(!empty($options['notify_email_address'])){
270 $loginizer['notify_email_address'] = $options['notify_email_address'];
271 $loginizer['custom_notify_email'] = 1;
272 }
273
274 // Login Success Email Notification.
275 $loginizer['login_mail'] = get_option('loginizer_login_mail', []);
276 add_action('init', 'loginizer_load_translation_vars', 0);
277
278 $loginizer['login_mail_subject'] = empty($loginizer['login_mail']['subject']) ? '' : $loginizer['login_mail']['subject'];
279 $loginizer['login_mail_body'] = empty($loginizer['login_mail']['body']) ? '' : $loginizer['login_mail']['body'];
280
281 // Load the blacklist and whitelist
282 $loginizer['blacklist'] = get_option('loginizer_blacklist', []);
283 $loginizer['whitelist'] = get_option('loginizer_whitelist', []);
284 $loginizer['2fa_whitelist'] = get_option('loginizer_2fa_whitelist');
285
286 // It should not be false
287 if(empty($loginizer['2fa_whitelist'])){
288 $loginizer['2fa_whitelist'] = array();
289 }
290
291 // When was the database cleared last time
292 $loginizer['last_reset'] = get_option('loginizer_last_reset');
293
294 if(!isset($loginizer['ultimate-member-active'])){
295 $um_is_active = in_array('ultimate-member/ultimate-member.php', apply_filters('active_plugins', get_option('active_plugins', [])));
296
297 $loginizer['ultimate-member-active'] = !empty($um_is_active) ? true : false;
298 }
299
300 //print_r($loginizer);
301
302 // Clear retries
303 if((time() - $loginizer['last_reset']) >= $loginizer['reset_retries']){
304 loginizer_reset_retries();
305 }
306
307 $ins_time = get_option('loginizer_ins_time');
308 if(empty($ins_time)){
309 $ins_time = time();
310 update_option('loginizer_ins_time', $ins_time);
311 }
312 $loginizer['ins_time'] = $ins_time;
313
314 // Set the current IP
315 $loginizer['current_ip'] = lz_getip();
316
317 // Is Brute Force Disabled ?
318 $loginizer['disable_brute'] = get_option('loginizer_disable_brute');
319
320 // Filters and actions
321 if(empty($loginizer['disable_brute'])){
322
323 // Use this to verify before WP tries to login
324 // Is always called and is the first function to be called
325 //add_action('wp_authenticate', 'loginizer_wp_authenticate', 10, 2);// Not called by XML-RPC
326 add_filter('authenticate', 'loginizer_wp_authenticate', 10001, 3);// This one is called by xmlrpc as well as GUI
327
328 // Is called when a login attempt fails
329 // Hence Update our records that the login failed
330 add_action('wp_login_failed', 'loginizer_login_failed');
331
332 // Is called before displaying the error message so that we dont show that the username is wrong or the password
333 // Update Error message
334 add_action('wp_login_errors', 'loginizer_error_handler', 10001, 2);
335 add_action('woocommerce_login_failed', 'loginizer_woocommerce_error_handler', 10001);
336 add_action('wp_login', 'loginizer_login_success', 11, 2);
337 add_action('rsssl_two_factor_user_authenticated', 'loginizer_rsssl_2fa_success');
338
339 if(!empty($loginizer['ultimate-member-active'])){
340 add_action('wp_login_failed', 'loginizer_ultimatemember_error_handler', 10001);
341 }
342
343 if(!empty($_COOKIE['lz_social_error']) && !empty($loginizer['social_settings'])){
344 add_filter('wp_login_errors', 'loginizer_social_login_error_handler', 10000, 2);
345 }
346 }
347
348 // Social Login Form Actions
349 if(!empty($loginizer['social_settings'])){
350 if(!empty($loginizer['social_settings']['login']['login_form'])){
351 add_action('login_form', 'loginizer_social_btn_login');
352 }
353 }
354
355 if((function_exists('wp_doing_ajax') && wp_doing_ajax()) || (defined( 'DOING_AJAX' ) && DOING_AJAX)){
356 include_once LOGINIZER_DIR . '/main/ajax.php';
357 }
358
359 if(is_admin()){
360 include_once LOGINIZER_DIR . '/main/admin.php';
361 }
362
363 // ----------------
364 // PRO INIT END
365 // ----------------
366
367 // Secuity checks for social login.
368 if(!empty($_GET['lz_social_provider']) && loginizer_can_login() && empty($_GET['lz_api'])){
369 add_action('init', 'loginizer_social_login_load');
370 return;
371 }
372 }
373
374 // Should return NULL if everything is fine
375 function loginizer_wp_authenticate($user, $username, $password){
376
377 global $loginizer, $lz_error, $lz_cannot_login, $lz_user_pass;
378
379 if(!empty($username) && !empty($password)){
380 $lz_user_pass = 1;
381 }
382
383 // Are you whitelisted ?
384 if(loginizer_is_whitelisted()){
385 $loginizer['ip_is_whitelisted'] = 1;
386 return $user;
387
388 } else if (!empty($loginizer['trusted_ips'])){
389 $lz_cannot_login = 1;
390
391 // This is used by WP Activity Log
392 apply_filters( 'wp_login_blocked', $username );
393
394 // Shows a blocked screen
395 if(!empty($loginizer['blocked_screen'])){
396 $lz_error['trusted_ip'] = __('You are restricted from logging in as your IP is not whitelisted.', 'loginizer');
397 loginizer_blocked_page($lz_error);
398 }
399
400 return new WP_Error('ip_blacklisted', __('You are restricted from logging in as your IP is not whitelisted.', 'loginizer'));
401 }
402
403 // Are you blacklisted ?
404 if(loginizer_is_blacklisted()){
405 $lz_cannot_login = 1;
406
407 // This is used by WP Activity Log
408 apply_filters( 'wp_login_blocked', $username );
409
410 // Shows a blocked screen
411 if(!empty($loginizer['blocked_screen'])){
412 loginizer_blocked_page($lz_error);
413 }
414
415 return new WP_Error('ip_blacklisted', implode('', $lz_error), 'loginizer');
416 }
417
418 // Is the username blacklisted ?
419 if(function_exists('loginizer_user_blacklisted')){
420 if(loginizer_user_blacklisted($username)){
421 $lz_cannot_login = 1;
422
423 // This is used by WP Activity Log
424 apply_filters( 'wp_login_blocked', $username );
425
426 return new WP_Error('user_blacklisted', implode('', $lz_error), 'loginizer');
427 }
428 }
429
430 if(loginizer_can_login()){
431 return $user;
432 }
433
434 $lz_cannot_login = 1;
435
436 // This is used by WP Activity Log
437 apply_filters( 'wp_login_blocked', $username );
438
439 // Shows a blocked screen
440 if(!empty($loginizer['blocked_screen'])){
441 loginizer_blocked_page($lz_error);
442 }
443
444 return new WP_Error('ip_blocked', implode('', $lz_error), 'loginizer');
445
446 }
447
448 function loginizer_can_login(){
449
450 global $wpdb, $loginizer, $lz_error;
451
452 // Get the logs
453 $sel_query = $wpdb->prepare("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = %s", $loginizer['current_ip']);
454 $result = lz_selectquery($sel_query);
455
456 if(!empty($result['count']) && ($result['count'] % $loginizer['max_retries']) == 0){
457
458 // Has he reached max lockouts ?
459 if($result['lockout'] >= $loginizer['max_lockouts']){
460 $loginizer['lockout_time'] = $loginizer['lockouts_extend'];
461 }
462
463 // Is he in the lockout time ?
464 if($result['time'] >= (time() - $loginizer['lockout_time'])){
465 $banlift = ceil((($result['time'] + $loginizer['lockout_time']) - time()) / 60);
466
467 //echo 'Current Time '.date('d/M/Y H:i:s P', time()).'<br />';
468 //echo 'Last attempt '.date('d/M/Y H:i:s P', $result['time']).'<br />';
469 //echo 'Unlock Time '.date('d/M/Y H:i:s P', $result['time'] + $loginizer['lockout_time']).'<br />';
470
471 $_time = $banlift.' '.$loginizer['msg']['minutes_err'];
472
473 if($banlift > 60){
474 $banlift = ceil($banlift / 60);
475 $_time = $banlift.' '.$loginizer['msg']['hours_err'];
476 }
477
478 $lz_error['ip_blocked'] = $loginizer['msg']['lockout_err'].' '.$_time;
479
480 if(!empty($loginizer['ultimate-member-active']) && class_exists('UM')){
481 \UM()->form()->add_error('blocked_msg', $lz_error['ip_blocked']);
482 }
483 return false;
484 }
485 }
486
487 return true;
488 }
489
490 function loginizer_is_blacklisted(){
491
492 global $wpdb, $loginizer, $lz_error;
493
494 $blacklist = isset($loginizer['blacklist']) ? $loginizer['blacklist'] : [];
495
496 if(empty($blacklist)){
497 return false;
498 }
499
500 $current_ip_inet = inet_ptoi($loginizer['current_ip']);
501
502 foreach($blacklist as $k => $v){
503
504 $start_inet = inet_ptoi($v['start']);
505 $end_inet = inet_ptoi($v['end']);
506
507 // Is the IP in the blacklist ?
508 if($start_inet <= $current_ip_inet && $current_ip_inet <= $end_inet){
509 $result = 1;
510 break;
511 }
512
513 // Is it in a wider range ?
514 if($start_inet >= 0 && $end_inet < 0){
515
516 // Since the end of the RANGE (i.e. current IP range) is beyond the +ve value of inet_ptoi,
517 // if the current IP is <= than the start of the range, it is within the range
518 // OR
519 // if the current IP is <= than the end of the range, it is within the range
520 if($start_inet <= $current_ip_inet
521 || $current_ip_inet <= $end_inet){
522 $result = 1;
523 break;
524 }
525
526 }
527
528 }
529
530 // You are blacklisted
531 if(!empty($result)){
532 $lz_error['ip_blacklisted'] = $loginizer['msg']['ip_blacklisted'];
533 return true;
534 }
535
536 return false;
537
538 }
539
540 // When the login fails, then this is called
541 // We need to update the database
542 function loginizer_login_failed($username, $is_2fa = ''){
543
544 global $wpdb, $loginizer, $lz_cannot_login;
545
546 // 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
547 if(empty($username) || is_null($username)){
548 $username = '';
549 }
550
551 $fail_type = 'Login';
552
553 if(!empty($is_2fa)){
554 $fail_type = '2FA';
555 }
556
557 if(empty($lz_cannot_login) && empty($loginizer['ip_is_whitelisted']) && empty($loginizer['no_loginizer_logs'])){
558
559 // The params which comes when social login returns an error, have some characters, which WordPress could not save.
560 // REQUEST_URI / HTTP_HOST are not always set (WP-CLI, some CGI and XML-RPC setups)
561 $server_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
562 $http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
563
564 if(!empty($server_uri) && strpos($server_uri, 'lz_social_provider') !== FALSE){
565 $request_uri = explode('=', $server_uri);
566 $server_uri = $request_uri[0];
567 }
568
569 // No addslashes() here, $wpdb->prepare() below does the escaping
570 $url = esc_url((!empty($_SERVER['HTTPS']) ? 'https://' : 'http://').$http_host.$server_uri);
571
572 // Must never be 0, we divide by it below
573 $max_retries = (int) $loginizer['max_retries'] < 1 ? 1 : (int) $loginizer['max_retries'];
574
575 // This way is atomic now, the earlier one were causing race condition.
576 // NOTE : In the UPDATE part `count` is already the new value, as MySQL / MariaDB
577 // evaluate the assignments from left to right, so lockout must NOT add 1 again
578 $upsert = $wpdb->prepare(
579 "INSERT INTO `".$wpdb->prefix."loginizer_logs`
580 (username, time, count, ip, lockout, url)
581 VALUES
582 (%s, %d, 1, %s, FLOOR(1 / %d), %s)
583 ON DUPLICATE KEY UPDATE
584 username = VALUES(username),
585 time = VALUES(time),
586 count = count + 1,
587 lockout = FLOOR(count / %d),
588 url = VALUES(url)",
589 $username,
590 time(),
591 $loginizer['current_ip'],
592 $max_retries,
593 $url,
594 $max_retries
595 );
596 $wpdb->query($upsert);
597
598 // Re-read the persisted row so email/retries-left reflect the actual count
599 $sel_query = $wpdb->prepare("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = %s", $loginizer['current_ip']);
600 $result = lz_selectquery($sel_query);
601
602 if(empty($result)){
603 $result = array('count' => 0);
604 }
605
606 $count = (int) $result['count'];
607 $lockout = !empty($result['lockout']) ? (int) $result['lockout'] : 0;
608
609 // The lockout goes up only on every max_retries'th failure, which is the
610 // attempt that actually locks the IP out. On the failures in between there
611 // is nothing new to report, so we must not email on each one of them
612 $is_new_lockout = !empty($count) && ($count % $max_retries) == 0;
613
614 // Do we need to email admin ?
615 if(!empty($loginizer['notify_email']) && !empty($is_new_lockout) && $lockout >= $loginizer['notify_email']){
616
617 $lockout_time = $loginizer['lockout_time'];
618
619 if($lockout >= $loginizer['max_lockouts']){
620 $lockout_time = $loginizer['lockouts_extend'];
621 }
622
623 $sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
624 $mail = array();
625 $mail['to'] = $loginizer['notify_email_address'];
626 $mail['subject'] = 'Failed '.$fail_type.' Attempts from IP '.$loginizer['current_ip'].' ('.$sitename.')';
627 $mail['message'] = 'Hi,
628
629 '.(int) $result['count'].' failed '.strtolower($fail_type).' attempts and '.$lockout.' lockout(s) from IP '.$loginizer['current_ip'].' on your site :
630 '.home_url().'
631
632 Last '.$fail_type.' Attempt : '.date('d/M/Y H:i:s P', time()).'
633 Last User Attempt : '.$username.'
634 IP has been blocked until : '.date('d/M/Y H:i:s P', time() + $lockout_time).'
635
636 Regards,
637 Loginizer';
638
639 @wp_mail($mail['to'], $mail['subject'], $mail['message']);
640 }
641
642 loginizer_update_attempt_stats(0);
643 $loginizer['retries_left'] = $max_retries - ($count % $max_retries);
644 $loginizer['retries_left'] = $loginizer['retries_left'] == $max_retries ? 0 : $loginizer['retries_left'];
645
646 }
647 }
648
649 function loginizer_rsssl_2fa_success($user){
650 loginizer_login_success('', $user);
651 }
652
653 function loginizer_login_success($user_login, $user) {
654 global $wp_version, $loginizer;
655
656 loginizer_update_attempt_stats(1);
657
658 if(empty($loginizer['login_mail'])){
659 return;
660 }
661
662 if(empty($loginizer['login_mail']['enable'])){
663 return;
664 }
665
666 if(!empty($loginizer['login_mail']['disable_whitelist'])){
667 // Check its whitelist ip
668 if(loginizer_is_whitelisted()){
669 return;
670 }
671 }
672
673 if(empty($user_login) && empty($user)){
674 error_log('Loginizer: No user information to send email');
675 return;
676 }
677
678 if(empty($user)){
679 $user = get_user_by('login', $user_login);
680 }
681
682 if(empty($user)){
683 error_log('Loginizer: Unable to get the user');
684 return;
685 }
686
687 if(empty($loginizer['login_mail']['roles']) || !is_array($loginizer['login_mail']['roles'])){
688 return;
689 }
690
691 // Check if the user role is enabled for email notification.
692 if(!array_intersect($user->roles, $loginizer['login_mail']['roles'])){
693 return;
694 }
695
696 // current_datetime & wp_timezone_string were introduced in WordPress 5.3
697 if(!empty($wp_version) && version_compare($wp_version, '5.3', '>') && function_exists('current_datetime')){
698 $time_zone = wp_timezone_string();
699
700 if(!empty($time_zone) && isset($time_zone[1]) && is_numeric($time_zone[1])){
701 $time_zone = 'UTC'.$time_zone;
702 }
703
704 // Setting up data variables.
705 $date = current_datetime()->format('Y-m-d H:i:s') .' '. $time_zone;
706 } else {
707 $date = date("Y-m-d H:i:s", time()) . ' ' . date_default_timezone_get();
708 }
709
710 $sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
711 $email = $user->data->user_email;
712
713 $vars = array(
714 'date' => $date,
715 'ip' => esc_html($loginizer['current_ip']),
716 'sitename' => $sitename,
717 'user_login' => $user_login
718 );
719
720 $message = lz_lang_vars_name($loginizer['login_mail_body'], $vars);
721 $subject = lz_lang_vars_name($loginizer['login_mail_subject'], $vars);
722
723 $headers = [];
724
725 // Do we need to send the email as HTML ?
726 if(!empty($loginizer['login_mail']['html_mail'])){
727 $headers[] = 'Content-Type: text/html; charset=UTF-8';
728
729 if(!empty($loginizer['login_mail']['body'])){
730 $message = html_entity_decode($message);
731 }else{
732 $message = preg_replace("/\<br\s*\/\>/i", "<br/>", $message);
733 $message = preg_replace('/(?<!<br\/>)\n/i', "<br/>\n", $message);
734 }
735 }
736
737 // Sending notification
738 if(empty(wp_mail($email, $subject, $message, $headers))){
739 error_log(__('There was a problem sending your email.', 'loginizer'));
740 return;
741 }
742 }
743
744 function loginizer_update_attempt_stats($type){
745
746 $stats = get_option('loginizer_login_attempt_stats', []);
747 $time = strtotime(date('Y-m-d H:00:00'));
748
749 if(empty($stats[$time][$type])){
750 $stats[$time][$type] = 0;
751 }
752
753 $stats[$time][$type] += 1;
754
755 update_option('loginizer_login_attempt_stats', $stats, false);
756 }
757
758 // Handles the error of the password not being there
759 function loginizer_error_handler($errors, $redirect_to){
760
761 global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
762
763 //echo 'loginizer_error_handler :';print_r($errors->errors);echo '<br>';
764 if(is_null($errors) || empty($errors)){
765 return true;
766 }
767
768 // Remove the empty password error
769 if(is_wp_error($errors)){
770
771 $codes = $errors->get_error_codes();
772
773 foreach($codes as $k => $v){
774 if($v == 'invalid_username' || $v == 'incorrect_password'){
775 $show_error = 1;
776 }
777 }
778
779 $errors->remove('invalid_username');
780 $errors->remove('incorrect_password');
781
782 // Add the error
783 if(!empty($lz_user_pass) && !empty($show_error) && empty($lz_cannot_login)){
784 $errors->add('invalid_userpass', '<b>ERROR:</b> ' . $loginizer['msg']['inv_userpass']);
785 }
786
787 // Add the number of retires left as well
788 if(count($errors->get_error_codes()) > 0 && isset($loginizer['retries_left'])){
789 $errors->add('retries_left', loginizer_retries_left());
790 }
791
792 }
793
794 return $errors;
795
796 }
797
798 // Handles the error of the password not being there
799 function loginizer_woocommerce_error_handler(){
800
801 global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
802
803 if(function_exists('wc_add_notice')){
804 wc_add_notice( loginizer_retries_left(), 'error' );
805 }
806 }
807
808 function loginizer_ultimatemember_error_handler(){
809
810 if(class_exists('UM')){
811 \UM()->form()->add_error('remaining_tries', loginizer_retries_left());
812 }
813 }
814
815 // Handles social login URL
816 function loginizer_social_login_error_handler($errors = '', $redirect_to = ''){
817 global $loginizer;
818
819 if(loginizer_is_blacklisted()){
820 return $errors;
821 }
822
823 loginizer_get_social_error();
824
825 if(empty($loginizer['social_errors'])){
826 return $errors;
827 }
828
829 if(is_null($errors) || empty($errors) || !is_wp_error($errors)){
830 $errors = new WP_Error();
831 }
832
833 foreach($loginizer['social_errors'] as $key => $text){
834 $errors->add($key, $text);
835 }
836
837 return $errors;
838 }
839
840 // Returns a string with the number of retries left
841 function loginizer_retries_left(){
842
843 global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
844
845 // If we are to show the number of retries left
846 if(isset($loginizer['retries_left'])){
847 $retries_left = apply_filters('loginizer_retries_left_num', $loginizer['retries_left']);
848
849 return '<b>'.esc_html($retries_left).'</b> '.$loginizer['msg']['attempts_left'];
850 }
851
852 }
853
854 function loginizer_reset_retries(){
855
856 global $wpdb, $loginizer;
857
858 $deltime = time() - $loginizer['reset_retries'];
859
860 $del_query = $wpdb->prepare("DELETE FROM `".$wpdb->prefix."loginizer_logs` WHERE `time` <= %d", $deltime);
861 $result = $wpdb->query($del_query);
862
863 update_option('loginizer_last_reset', time());
864
865 }
866
867 function loginizer_load_translation_vars(){
868 global $loginizer;
869
870 $loginizer['login_mail_default_sub'] = __('Login Successful at $sitename', 'loginizer');
871 $loginizer['login_mail_default_msg'] = __('Hello $user_login,
872
873 Your account was recently logged in from the IP : $ip
874 Time : $date
875 If it was not you who logged in then please report this to us immediately.
876
877 Regards,
878 $sitename','loginizer');
879
880 if(empty($loginizer['login_mail_subject'])){
881 $loginizer['login_mail_subject'] = $loginizer['login_mail_default_sub'];
882 }
883
884 if(empty($loginizer['login_mail_body'])){
885 $loginizer['login_mail_body'] = $loginizer['login_mail_default_msg'];
886 }
887
888 // Default messages
889 $loginizer['d_msg']['inv_userpass'] = __('Incorrect Username or Password', 'loginizer');
890 $loginizer['d_msg']['ip_blacklisted'] = __('Your IP has been blacklisted', 'loginizer');
891 $loginizer['d_msg']['attempts_left'] = __('attempt(s) left', 'loginizer');
892 $loginizer['d_msg']['lockout_err'] = __('You have exceeded maximum login retries<br /> Please try after', 'loginizer');
893 $loginizer['d_msg']['minutes_err'] = __('minute(s)', 'loginizer');
894 $loginizer['d_msg']['hours_err'] = __('hour(s)', 'loginizer');
895
896 // Message Strings
897 $loginizer['msg'] = get_option('loginizer_msg', []);
898
899 foreach($loginizer['d_msg'] as $lk => $lv){
900 if(empty($loginizer['msg'][$lk])){
901 $loginizer['msg'][$lk] = $loginizer['d_msg'][$lk];
902 }
903 }
904
905 $loginizer['2fa_d_msg']['otp_app'] = __('Please enter the OTP as seen in your App', 'loginizer');
906 $loginizer['2fa_d_msg']['otp_email'] = __('Please enter the OTP emailed to you', 'loginizer');
907 $loginizer['2fa_d_msg']['otp_field'] = __('One Time Password', 'loginizer');
908 $loginizer['2fa_d_msg']['otp_question'] = __('Please answer your security question', 'loginizer');
909 $loginizer['2fa_d_msg']['otp_answer'] = __('Your Answer', 'loginizer');
910
911 // Message Strings
912 $loginizer['2fa_msg'] = get_option('loginizer_2fa_msg', []);
913
914 foreach($loginizer['2fa_d_msg'] as $lk => $lv){
915 if(empty($loginizer['2fa_msg'][$lk])){
916 $loginizer['2fa_msg'][$lk] = $loginizer['2fa_d_msg'][$lk];
917 }
918 }
919
920 }
921
922 function loginizer_social_login_load(){
923 include_once LOGINIZER_DIR . '/main/social-login.php';
924 }
925
926 // Checks if softaculous is installed on the server.
927 function loginizer_check_softaculous(){
928
929 // Checking if we have Softaculous installed?
930 if(!preg_match('/^\/home(?:\d+)?\/.*\//U', ABSPATH, $matches)){
931 return false;
932 }
933
934 if(empty($matches) || empty($matches[0])){
935 return false;
936 }
937
938 $softaculous_path = $matches[0] . '.softaculous/installations.php';
939 if(!file_exists($softaculous_path)){
940 return false;
941 }
942
943 // Checking if users has changed the branding of Softaculous.
944 $universal_file = '';
945 // Plesk, ISPManager, ISPConfig, InterWorx, H-Sphere, CentOS Web Panel, Softaculous Remote and Softaculous Enterprise
946 if(file_exists('/usr/local/softaculous/enduser/universal.php')){
947 $universal_file = '/usr/local/softaculous/enduser/universal.php';
948 }else if(file_exists('/usr/local/cpanel/whostmgr/docroot/cgi/softaculous/enduser/universal.php')){
949 $universal_file = '/usr/local/cpanel/whostmgr/docroot/cgi/softaculous/enduser/universal.php';
950 }else if(file_exists('/usr/local/directadmin/plugins/softaculous/enduser/universal.php')){
951 $universal_file = '/usr/local/directadmin/plugins/softaculous/enduser/universal.php';
952 }else if(file_exists('/usr/local/vesta/softaculous/enduser/universal.php')){
953 $universal_file = '/usr/local/vesta/softaculous/enduser/universal.php';
954 }
955
956 if(empty($universal_file)){
957 return false;
958 }
959
960 $universal = file_get_contents($universal_file);
961
962 if(empty($universal)){
963 return false;
964 }
965
966 // Checking if Softaculous is being whitelabeled
967 if(preg_match('/\$globals\[["\']sn["\']\]\s.?=\s.?["\']Softaculous["\']/', $universal)){
968 update_option('loginizer_softwp_upgrade', time());
969 }
970
971 return false;
972 }
973
974 // Sorry to see you going
975 register_uninstall_hook(LOGINIZER_FILE, 'loginizer_deactivation');
976
977 function loginizer_deactivation(){
978
979 global $wpdb;
980
981 $sql = array();
982 $sql[] = "DROP TABLE ".$wpdb->prefix."loginizer_logs;";
983
984 foreach($sql as $sk => $sv){
985 $wpdb->query($sv);
986 }
987
988 delete_option('loginizer_version');
989 delete_option('loginizer_options');
990 delete_option('loginizer_last_reset');
991 delete_option('loginizer_whitelist');
992 delete_option('loginizer_blacklist');
993 delete_option('loginizer_msg');
994 delete_option('loginizer_2fa_msg');
995 delete_option('loginizer_2fa_email_template');
996 delete_option('loginizer_security');
997 delete_option('loginizer_wp_admin');
998 delete_option('loginizer_csrf_promo_time');
999 delete_option('loginizer_backuply_promo_time');
1000 delete_option('loginizer_promo_time');
1001 delete_option('loginizer_ins_time');
1002 delete_option('loginizer_2fa_whitelist');
1003 delete_option('loginizer_checksums_last_run');
1004 delete_option('loginizer_checksums_diff');
1005 delete_option('loginizer_ip_method');
1006 delete_option('loginizer_2fa_custom_redirect');
1007 delete_option('external_updates-loginizer-security');
1008 delete_option('loginizer_login_attempt_stats');
1009
1010 }