prefix."loginizer_logs` (
`username` varchar(255) NOT NULL DEFAULT '',
`time` int(10) NOT NULL DEFAULT '0',
`count` int(10) NOT NULL DEFAULT '0',
`lockout` int(10) NOT NULL DEFAULT '0',
`ip` varchar(255) NOT NULL DEFAULT '',
UNIQUE KEY `ip` (`ip`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
foreach($sql as $sk => $sv){
$wpdb->query($sv);
}
add_option('loginizer_version', LOGINIZER_VERSION);
add_option('loginizer_options', array());
add_option('loginizer_last_reset', 0);
add_option('loginizer_whitelist', array());
add_option('loginizer_blacklist', array());
}
// Checks if we are to update ?
function loginizer_update_check(){
global $wpdb;
$sql = array();
$current_version = get_option('loginizer_version');
// It must be the 1.0 pre stuff
if(empty($current_version)){
$current_version = get_option('lz_version');
}
$version = (int) str_replace('.', '', $current_version);
// No update required
if($current_version == LOGINIZER_VERSION){
return true;
}
// Is it first run ?
if(empty($current_version)){
// Reinstall
loginizer_activation();
// Trick the following if conditions to not run
$version = (int) str_replace('.', '', LOGINIZER_VERSION);
}
// Is it less than 1.0.1 ?
if($version < 101){
// TODO : GET the existing settings
// Get the existing settings
$lz_failed_logs = lz_selectquery("SELECT * FROM `".$wpdb->prefix."lz_failed_logs`;", 1);
$lz_options = lz_selectquery("SELECT * FROM `".$wpdb->prefix."lz_options`;", 1);
$lz_iprange = lz_selectquery("SELECT * FROM `".$wpdb->prefix."lz_iprange`;", 1);
// Delete the three tables
$sql = array();
$sql[] = "DROP TABLE IF EXISTS ".$wpdb->prefix."lz_failed_logs;";
$sql[] = "DROP TABLE IF EXISTS ".$wpdb->prefix."lz_options;";
$sql[] = "DROP TABLE IF EXISTS ".$wpdb->prefix."lz_iprange;";
foreach($sql as $sk => $sv){
$wpdb->query($sv);
}
// Delete option
delete_option('lz_version');
// Reinstall
loginizer_activation();
// TODO : Save the existing settings
// Update the existing failed logs to new table
if(is_array($lz_failed_logs)){
foreach($lz_failed_logs as $fk => $fv){
$wpdb->query("INSERT INTO ".$wpdb->prefix."loginizer_logs SET `username` = '".$fv['username']."', `time` = '".$fv['time']."', `count` = '".$fv['count']."', `lockout` = '".$fv['lockout']."', `ip` = '".$fv['ip']."';");
}
}
// Update the existing options to new structure
if(is_array($lz_options)){
foreach($lz_options as $ok => $ov){
if($ov['option_name'] == 'lz_last_reset'){
update_option('loginizer_last_reset', $ov['option_value']);
continue;
}
$old_option[str_replace('lz_', '', $ov['option_name'])] = $ov['option_value'];
}
// Save the options
update_option('loginizer_options', $old_option);
}
// Update the existing iprange to new structure
if(is_array($lz_iprange)){
$old_blacklist = array();
$old_whitelist = array();
$bid = 1;
$wid = 1;
foreach($lz_iprange as $ik => $iv){
if(!empty($iv['blacklist'])){
$old_blacklist[$bid] = array();
$old_blacklist[$bid]['start'] = long2ip($iv['start']);
$old_blacklist[$bid]['end'] = long2ip($iv['end']);
$old_blacklist[$bid]['time'] = strtotime($iv['date']);
$bid = $bid + 1;
}
if(!empty($iv['whitelist'])){
$old_whitelist[$wid] = array();
$old_whitelist[$wid]['start'] = long2ip($iv['start']);
$old_whitelist[$wid]['end'] = long2ip($iv['end']);
$old_whitelist[$wid]['time'] = strtotime($iv['date']);
$wid = $wid + 1;
}
}
if(!empty($old_blacklist)) update_option('loginizer_blacklist', $old_blacklist);
if(!empty($old_whitelist)) update_option('loginizer_whitelist', $old_whitelist);
}
}
// Save the new Version
update_option('loginizer_version', LOGINIZER_VERSION);
}
// Add the action to load the plugin
add_action('plugins_loaded', 'loginizer_load_plugin');
// The function that will be called when the plugin is loaded
function loginizer_load_plugin(){
global $loginizer;
// Check if the installed version is outdated
loginizer_update_check();
$options = get_option('loginizer_options');
$loginizer = array();
$loginizer['max_retries'] = empty($options['max_retries']) ? 3 : $options['max_retries'];
$loginizer['lockout_time'] = empty($options['lockout_time']) ? 900 : $options['lockout_time']; // 15 minutes
$loginizer['max_lockouts'] = empty($options['max_lockouts']) ? 5 : $options['max_lockouts'];
$loginizer['lockouts_extend'] = empty($options['lockouts_extend']) ? 86400 : $options['lockouts_extend']; // 24 hours
$loginizer['reset_retries'] = empty($options['reset_retries']) ? 86400 : $options['reset_retries']; // 24 hours
$loginizer['notify_email'] = empty($options['notify_email']) ? 0 : $options['notify_email'];
// Load the blacklist and whitelist
$loginizer['blacklist'] = get_option('loginizer_blacklist');
$loginizer['whitelist'] = get_option('loginizer_whitelist');
// When was the database cleared last time
$loginizer['last_reset'] = get_option('loginizer_last_reset');
//print_r($loginizer);
// Clear retries
if((time() - $loginizer['last_reset']) >= $loginizer['reset_retries']){
loginizer_reset_retries();
}
$ins_time = get_option('loginizer_ins_time');
if(empty($ins_time)){
$ins_time = time();
update_option('loginizer_ins_time', $ins_time);
}
$loginizer['ins_time'] = $ins_time;
// Set the current IP
$loginizer['current_ip'] = lz_getip();
/* Filters and actions */
// Use this to verify before WP tries to login
// Is always called and is the first function to be called
//add_action('wp_authenticate', 'loginizer_wp_authenticate', 10, 2);// Not called by XML-RPC
add_filter('authenticate', 'loginizer_wp_authenticate', 10001, 3);// This one is called by xmlrpc as well as GUI
// Is called when a login attempt fails
// Hence Update our records that the login failed
add_action('wp_login_failed', 'loginizer_login_failed');
// Is called before displaying the error message so that we dont show that the username is wrong or the password
// Update Error message
add_action('wp_login_errors', 'loginizer_error_handler', 10001, 2);
// Is the premium features there ?
if(file_exists(LOGINIZER_DIR.'/premium.php')){
// Include the file
include_once(LOGINIZER_DIR.'/premium.php');
loginizer_security_init();
}
}
// Should return NULL if everything is fine
function loginizer_wp_authenticate($user, $username, $password){
global $loginizer, $lz_error, $lz_cannot_login, $lz_user_pass;
if(!empty($username) && !empty($password)){
$lz_user_pass = 1;
}
// Are you whitelisted ?
if(loginizer_is_whitelisted()){
$loginizer['ip_is_whitelisted'] = 1;
return $user;
}
// Are you blacklisted ?
if(loginizer_is_blacklisted()){
$lz_cannot_login = 1;
return new WP_Error('ip_blacklisted', implode('', $lz_error), 'loginizer');
}
if(loginizer_can_login()){
return $user;
}
$lz_cannot_login = 1;
return new WP_Error('ip_blocked', implode('', $lz_error), 'loginizer');
}
function loginizer_can_login(){
global $wpdb, $loginizer, $lz_error;
// Get the logs
$result = lz_selectquery("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = '".$loginizer['current_ip']."';");
if(!empty($result['count']) && ($result['count'] % $loginizer['max_retries']) == 0){
// Has he reached max lockouts ?
if($result['lockout'] >= $loginizer['max_lockouts']){
$loginizer['lockout_time'] = $loginizer['lockouts_extend'];
}
// Is he in the lockout time ?
if($result['time'] >= (time() - $loginizer['lockout_time'])){
$banlift = ceil((($result['time'] + $loginizer['lockout_time']) - time()) / 60);
//echo 'Current Time '.date('m/d/Y H:i:s', time()).'
';
//echo 'Last attempt '.date('m/d/Y H:i:s', $result['time']).'
';
//echo 'Unlock Time '.date('m/d/Y H:i:s', $result['time'] + $loginizer['lockout_time']).'
';
$_time = $banlift.' minute(s)';
if($banlift > 60){
$banlift = ceil($banlift / 60);
$_time = $banlift.' hour(s)';
}
$lz_error['ip_blocked'] = 'You have exceeded maximum login retries
Please try after '.$_time;
return false;
}
}
return true;
}
function loginizer_is_blacklisted(){
global $wpdb, $loginizer, $lz_error;
$blacklist = $loginizer['blacklist'];
foreach($blacklist as $k => $v){
// Is the IP in the blacklist ?
if(ip2long($v['start']) <= ip2long($loginizer['current_ip']) && ip2long($loginizer['current_ip']) <= ip2long($v['end'])){
$result = 1;
break;
}
// Is it in a wider range ?
if(ip2long($v['start']) >= 0 && ip2long($v['end']) < 0){
// Since the end of the RANGE (i.e. current IP range) is beyond the +ve value of ip2long,
// if the current IP is <= than the start of the range, it is within the range
// OR
// if the current IP is <= than the end of the range, it is within the range
if(ip2long($v['start']) <= ip2long($loginizer['current_ip'])
|| ip2long($loginizer['current_ip']) <= ip2long($v['end'])){
$result = 1;
break;
}
}
}
// You are blacklisted
if(!empty($result)){
$lz_error['ip_blacklisted'] = 'Your IP has been blacklisted';
return true;
}
return false;
}
function loginizer_is_whitelisted(){
global $wpdb, $loginizer, $lz_error;
$whitelist = $loginizer['whitelist'];
foreach($whitelist as $k => $v){
// Is the IP in the blacklist ?
if(ip2long($v['start']) <= ip2long($loginizer['current_ip']) && ip2long($loginizer['current_ip']) <= ip2long($v['end'])){
$result = 1;
break;
}
// Is it in a wider range ?
if(ip2long($v['start']) >= 0 && ip2long($v['end']) < 0){
// Since the end of the RANGE (i.e. current IP range) is beyond the +ve value of ip2long,
// if the current IP is <= than the start of the range, it is within the range
// OR
// if the current IP is <= than the end of the range, it is within the range
if(ip2long($v['start']) <= ip2long($loginizer['current_ip'])
|| ip2long($loginizer['current_ip']) <= ip2long($v['end'])){
$result = 1;
break;
}
}
}
// You are whitelisted
if(!empty($result)){
return true;
}
return false;
}
// When the login fails, then this is called
// We need to update the database
function loginizer_login_failed($username){
global $wpdb, $loginizer, $lz_cannot_login;
if(empty($lz_cannot_login) && empty($loginizer['ip_is_whitelisted']) && empty($loginizer['no_loginizer_logs'])){
$result = lz_selectquery("SELECT * FROM `".$wpdb->prefix."loginizer_logs` WHERE `ip` = '".$loginizer['current_ip']."';");
if(!empty($result)){
$lockout = floor((($result['count']+1) / $loginizer['max_retries']));
$sresult = $wpdb->query("UPDATE `".$wpdb->prefix."loginizer_logs` SET `username` = '".$username."', `time` = '".time()."', `count` = `count`+1, `lockout` = '".$lockout."' WHERE `ip` = '".$loginizer['current_ip']."';");
// Do we need to email admin ?
if(!empty($loginizer['notify_email']) && $lockout >= $loginizer['notify_email']){
$sitename = lz_is_multisite() ? get_site_option('site_name') : get_option('blogname');
$mail = array();
$mail['to'] = lz_is_multisite() ? get_site_option('admin_email') : get_option('admin_email');
$mail['subject'] = 'Failed Login Attempts from IP '.$loginizer['current_ip'].' ('.$sitename.')';
$mail['message'] = 'Hi,
'.($result['count']+1).' failed login attempts and '.$lockout.' lockout(s) from IP '.$loginizer['current_ip'].'
Last Login Attempt : '.date('d/m/Y H:i:s', time()).'
Last User Attempt : '.$username.'
IP has been blocked until : '.date('d/m/Y H:i:s', time() + $loginizer['lockout_time']).'
Regards,
Loginizer';
@wp_mail($mail['to'], $mail['subject'], $mail['message']);
}
}else{
$insert = $wpdb->query("INSERT INTO `".$wpdb->prefix."loginizer_logs` SET `username` = '".$username."', `time` = '".time()."', `count` = '1', `ip` = '".$loginizer['current_ip']."', `lockout` = '0';");
}
// We need to add one as this is a failed attempt as well
$result['count'] = $result['count'] + 1;
$loginizer['retries_left'] = ($loginizer['max_retries'] - ($result['count'] % $loginizer['max_retries']));
$loginizer['retries_left'] = $loginizer['retries_left'] == $loginizer['max_retries'] ? 0 : $loginizer['retries_left'];
}
}
// Handles the error of the password not being there
function loginizer_error_handler($errors, $redirect_to){
global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
//echo 'loginizer_error_handler :';print_r($errors->errors);echo '
';
// Remove the empty password error
if(is_wp_error($errors)){
$codes = $errors->get_error_codes();
foreach($codes as $k => $v){
if($v == 'invalid_username' || $v == 'incorrect_password'){
$show_error = 1;
}
}
$errors->remove('invalid_username');
$errors->remove('incorrect_password');
}
// Add the error
if(!empty($lz_user_pass) && !empty($show_error) && empty($lz_cannot_login)){
$errors->add('invalid_userpass', 'ERROR: Incorrect Username or Password');
}
// Add the number of retires left as well
if(count($errors->get_error_codes()) > 0 && isset($loginizer['retries_left'])){
$errors->add('retries_left', loginizer_retries_left());
}
return $errors;
}
// Returns a string with the number of retries left
function loginizer_retries_left(){
global $wpdb, $loginizer, $lz_user_pass, $lz_cannot_login;
// If we are to show the number of retries left
if(isset($loginizer['retries_left'])){
return ''.$loginizer['retries_left'].' attempt(s) left';
}
}
function loginizer_reset_retries(){
global $wpdb, $loginizer;
$deltime = time() - $loginizer['reset_retries'];
$result = $wpdb->query("DELETE FROM `".$wpdb->prefix."loginizer_logs` WHERE `time` <= '".$deltime."';");
update_option('loginizer_last_reset', time());
}
add_filter("plugin_action_links_$plugin_loginizer", 'loginizer_plugin_action_links');
// Add settings link on plugin page
function loginizer_plugin_action_links($links) {
if(!defined('LOGINIZER_PREMIUM')){
$links[] = ''._x('Upgrade', 'Plugin action link label.', 'loginizer').'';
}
$settings_link = 'Settings';
array_unshift($links, $settings_link);
return $links;
}
add_action('admin_menu', 'loginizer_admin_menu');
// Shows the admin menu of Loginizer
function loginizer_admin_menu() {
global $wp_version, $loginizer;
// Add the menu page
add_menu_page(__('Loginizer Dashboard'), __('Loginizer Security'), 'activate_plugins', 'loginizer', 'loginizer_page_dashboard');
// Dashboard
add_submenu_page('loginizer', __('Loginizer Dashboard'), __('Dashboard'), 'activate_plugins', 'loginizer', 'loginizer_page_dashboard');
// Brute Force
add_submenu_page('loginizer', __('Loginizer Brute Force Settings'), __('Brute Force'), 'activate_plugins', 'loginizer_brute_force', 'loginizer_page_brute_force');
if(defined('LOGINIZER_PREMIUM')){
// PasswordLess
add_submenu_page('loginizer', __('Loginizer PasswordLess Settings'), __('PasswordLess'), 'activate_plugins', 'loginizer_passwordless', 'loginizer_page_passwordless');
// Two Factor Auth
add_submenu_page('loginizer', __('Loginizer Two Factor Authentication'), __('Two Factor Auth'), 'activate_plugins', 'loginizer_2fa', 'loginizer_page_2fa');
// reCaptcha
add_submenu_page('loginizer', __('Loginizer reCAPTCHA Settings'), __('reCAPTCHA'), 'activate_plugins', 'loginizer_recaptcha', 'loginizer_page_recaptcha');
// Security Settings
add_submenu_page('loginizer', __('Loginizer Security Settings'), __('Security Settings'), 'activate_plugins', 'loginizer_security', 'loginizer_page_security');
}elseif(!defined('LOGINIZER_PREMIUM') && !empty($loginizer['ins_time']) && $loginizer['ins_time'] < (time() - (30*24*3600))){
// Go Pro link
add_submenu_page('loginizer', __('Loginizer Go Pro'), __('Go Pro'), 'activate_plugins', LOGINIZER_PRO_URL);
}
}
// The Loginizer Admin Options Page
function loginizer_page_header($title = 'Loginizer'){
/*wp_enqueue_script('common');
wp_enqueue_script('wp-lists');
wp_enqueue_script('postbox');
wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
echo '
';*/
?>
'. __('The settings were saved successfully', 'loginizer'). '
' . __('The settings were saved successfully', 'loginizer') . '
' . __('The Blacklist IP range has been deleted successfully', 'loginizer') . '
' . __('The Whitelist IP range has been deleted successfully', 'loginizer') . '
' . __('Blacklist IP range added successfully', 'loginizer') . '
' . __('Whitelist IP range added successfully', 'loginizer') . '
| No Logs. You will see logs about failed login attempts here. | '; }else{ foreach($result as $ik => $iv){ $status_button = (!empty($iv['status']) ? 'disable' : 'enable'); echo '|||
| '.$iv['ip'].' | '.date('d/m/Y H:i:s', $iv['time']).' | '.$iv['count'].' | '.$iv['lockout'].' |
| No Blacklist IPs. You will see blacklisted IP ranges here. | '; }else{ foreach($loginizer['blacklist'] as $ik => $iv){ echo '|||
| '.$iv['start'].' | '.$iv['end'].' | '.date('d/m/Y', $iv['time']).' | Delete |
| No Whitelist IPs. You will see whitelisted IP ranges here. | '; }else{ foreach($loginizer['whitelist'] as $ik => $iv){ echo '|||
| '.$iv['start'].' | '.$iv['end'].' | '.date('d/m/Y', $iv['time']).' | Delete |