| 1 |
<?php defined('ABSPATH') or die("Protected By WT!"); |
| 2 |
|
| 3 |
|
| 4 |
class WTSEC_LIBRARY_App |
| 5 |
{ |
| 6 |
|
| 7 |
public function __construct() |
| 8 |
{ |
| 9 |
$this->auth(); |
| 10 |
} |
| 11 |
|
| 12 |
public function auth(){ |
| 13 |
if(self::getOption('authorized') === false){ |
| 14 |
wp_safe_redirect(wtsec_getUrl('login')); |
| 15 |
exit; |
| 16 |
} |
| 17 |
} |
| 18 |
|
| 19 |
public static function authorized(){ |
| 20 |
return (boolean) self::getOption('authorized'); |
| 21 |
} |
| 22 |
|
| 23 |
public static function login($token){ |
| 24 |
self::_set('authorized', true); |
| 25 |
self::_set('authToken', $token); |
| 26 |
} |
| 27 |
|
| 28 |
public static function logout(){ |
| 29 |
self::_delete(['authToken','authorized','api_key']); |
| 30 |
//self::_set('am_installed', false); |
| 31 |
} |
| 32 |
|
| 33 |
public function getLocalDomains(){ |
| 34 |
return []; |
| 35 |
} |
| 36 |
|
| 37 |
public static function _set($name,$value){ |
| 38 |
return update_option(WTSEC_PLUGIN_PREFIX.$name,$value); |
| 39 |
} |
| 40 |
|
| 41 |
public static function _get($name){ |
| 42 |
return get_option(WTSEC_PLUGIN_PREFIX.$name); |
| 43 |
} |
| 44 |
|
| 45 |
public static function _delete($options){ |
| 46 |
if(is_array($options)){ |
| 47 |
foreach ($options as $option) { |
| 48 |
if ( ! delete_option(WTSEC_PLUGIN_PREFIX.$option)) |
| 49 |
return FALSE; |
| 50 |
} |
| 51 |
} else{ |
| 52 |
delete_option(WTSEC_PLUGIN_PREFIX.$options); |
| 53 |
} |
| 54 |
} |
| 55 |
|
| 56 |
public function set($name,$value){ |
| 57 |
return update_option(WTSEC_PLUGIN_PREFIX.$name,$value); |
| 58 |
} |
| 59 |
|
| 60 |
public function get($name){ |
| 61 |
return get_option(WTSEC_PLUGIN_PREFIX.$name); |
| 62 |
} |
| 63 |
|
| 64 |
public static function getOption($name){ |
| 65 |
return get_option(WTSEC_PLUGIN_PREFIX.$name); |
| 66 |
} |
| 67 |
|
| 68 |
public static function deleteOption($name){ |
| 69 |
return delete_option(WTSEC_PLUGIN_PREFIX.$name); |
| 70 |
} |
| 71 |
|
| 72 |
public static function getToken(){ |
| 73 |
return self::getOption('authToken'); |
| 74 |
} |
| 75 |
|
| 76 |
public static function getName(){ |
| 77 |
return self::getOption('username'); |
| 78 |
} |
| 79 |
|
| 80 |
// Limit login attempt |
| 81 |
public function wtsec_login_check(){ |
| 82 |
|
| 83 |
if( ! $this->wtsec_is_need_check() ) |
| 84 |
return; |
| 85 |
|
| 86 |
$massage = wtsec_locale('login_attempt_message'); |
| 87 |
|
| 88 |
$options = (object) [ |
| 89 |
// время снятия блокировки в секуда� |
| 90 |
|
| 91 |
'lock_time' => 1800, // 1800 |
| 92 |
// Количество попыток авторизоваться |
| 93 |
'lock_num' => 5, |
| 94 |
// Сообщение о блокировке |
| 95 |
'massage' => $massage, |
| 96 |
// время полной очистки файла - 4 дня |
| 97 |
'expire_time' => 3600 * 24 * 4, |
| 98 |
// добавить в названия файлов запрос REQUEST_URI - может пригодится для дебага |
| 99 |
'add_uri' => false, |
| 100 |
// использовать ли мякгий метод получения IP? |
| 101 |
'soft_get_ip' => false, |
| 102 |
]; |
| 103 |
|
| 104 |
// чтобы установить имя файла |
| 105 |
$action = @ $_GET['action']; |
| 106 |
if( ! in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login' ), true ) ) |
| 107 |
$action = 'login'; |
| 108 |
|
| 109 |
// создаем директорию кэша если надо |
| 110 |
$cache_dir = plugin_dir_path(__FILE__) . 'cache'; |
| 111 |
if( ! file_exists($cache_dir) ) |
| 112 |
mkdir( $cache_dir, 0777 ); |
| 113 |
|
| 114 |
// оперделим название файла |
| 115 |
$REQUEST_URI = $options->add_uri ? ( '___'. preg_replace('/[^a-zA-Z0-9:=?_-]/', '-', $_SERVER['REQUEST_URI'] ) /*все на -*/ ) : ''; |
| 116 |
$domen = str_replace('www.', '', $_SERVER['HTTP_HOST'] ); |
| 117 |
$file_path = $cache_dir . "/{$domen}___{$action}{$REQUEST_URI}.ini"; |
| 118 |
|
| 119 |
// оперделим ip |
| 120 |
if( ! $ip = $this->wtsec_get_ip( $options->soft_get_ip ) ) |
| 121 |
die( 'No IP...' ); |
| 122 |
|
| 123 |
// парсим данные |
| 124 |
$data = @ parse_ini_file( $file_path ); |
| 125 |
$data = (!$data) ? [] : $data; |
| 126 |
$attempts = array_key_exists($ip,$data) ? count($data[$ip]) + 1 : 1; |
| 127 |
$last_access_time = array_key_exists($ip,$data) ? max( $data[$ip] ) : 0; |
| 128 |
$blocked_time = $last_access_time + ($options->lock_time * floor( $attempts / $options->lock_num) ); |
| 129 |
|
| 130 |
if ( $data['status'][$ip] == 'blocked' && $blocked_time > time() ){ |
| 131 |
$blocked_time = ($blocked_time - time()) / 60; |
| 132 |
//return new WP_Error('incorrect_password', $options->massage); |
| 133 |
die( sprintf($options->massage, $options->lock_num, $blocked_time) ); // блокируем |
| 134 |
} else{ |
| 135 |
file_put_contents( $file_path, sprintf("{$ip}[] = %d\n", time()), FILE_APPEND ); // добавляем ip и время |
| 136 |
|
| 137 |
if ($data['status'][$ip] == 'blocked'){ |
| 138 |
$new_content = preg_replace("~status\[" . $ip . "\] = [a-z]+\n~", '', file_get_contents($file_path) ); |
| 139 |
file_put_contents( $file_path, $new_content ); // снимает блокировку |
| 140 |
} |
| 141 |
|
| 142 |
if($attempts >= $options->lock_num && ( $attempts % $options->lock_num ) == 0) |
| 143 |
file_put_contents( $file_path, "status[{$ip}] = blocked\n", FILE_APPEND); // добавляем блокировку |
| 144 |
} |
| 145 |
|
| 146 |
// полная очистка файла |
| 147 |
if( empty($data['expire']) ){ |
| 148 |
file_put_contents( $file_path, 'expire = ' . time() . "\n", FILE_APPEND ); |
| 149 |
} |
| 150 |
elseif( $data['expire'] + $options->expire_time < time() ){ |
| 151 |
$content = 'expire = '. time() . "\n"; |
| 152 |
file_put_contents( $file_path, $content ); // очищаем файл полностью |
| 153 |
} |
| 154 |
} |
| 155 |
|
| 156 |
|
| 157 |
protected function wtsec_is_need_check(){ |
| 158 |
|
| 159 |
// работает только для POST запросов. |
| 160 |
if( empty($_POST) ) |
| 161 |
return false; |
| 162 |
|
| 163 |
$need_check = false; |
| 164 |
$settings_value = self::_get('check_login_attempt'); |
| 165 |
|
| 166 |
// для страницы '/wp-login.php' |
| 167 |
if( false !== strpos($_SERVER['REQUEST_URI'], '/wp-login.php') && $settings_value ) |
| 168 |
$need_check = true; |
| 169 |
|
| 170 |
|
| 171 |
return $need_check; |
| 172 |
} |
| 173 |
|
| 174 |
protected function wtsec_get_ip( $soft = false ){ |
| 175 |
|
| 176 |
if( $soft ){ |
| 177 |
$ip = isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : ''; // cloudflare IP support |
| 178 |
if( ! filter_var($ip, FILTER_VALIDATE_IP) ) $ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : ''; |
| 179 |
if( ! filter_var($ip, FILTER_VALIDATE_IP) ) $ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; |
| 180 |
if( ! filter_var($ip, FILTER_VALIDATE_IP) ) $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; |
| 181 |
} |
| 182 |
else { |
| 183 |
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; |
| 184 |
} |
| 185 |
|
| 186 |
return $ip; |
| 187 |
} |
| 188 |
|
| 189 |
|
| 190 |
|
| 191 |
} |