| @@ -1,271 +1,319 @@ | ||
| 1 | -<?php | |
| 1 | +<?php | |
| 2 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 3 | + exit; | |
| 4 | +} | |
| 2 | 5 | |
| 6 | + | |
| 7 | +require_once (dirname(__FILE__).'/easy-basic-authentication-log-class.php'); | |
| 8 | +require_once (dirname(__FILE__).'/easy-basic-authentication-emailalert-class.php'); | |
| 9 | +require_once (dirname(__FILE__).'/easy-basic-authentication-form-class.php'); | |
| 10 | +require_once (dirname(__FILE__).'/easy-basic-authentication-notice-class.php'); | |
| 11 | +require_once (dirname(__FILE__).'/easy-basic-authentication-compatcheck-class.php'); | |
| 12 | + | |
| 3 | 13 | class easy_basic_authentication_class { |
| 4 | 14 | |
| 15 | + private $log; | |
| 16 | + private $email; | |
| 17 | + private $form; | |
| 18 | + private $compatcheck; | |
| 5 | 19 | |
| 6 | 20 | public function __construct() |
| 7 | 21 | { |
| 8 | - if(get_option( 'basic_auth_plugin_admin_enable' )) { | |
| 9 | - if (in_array($GLOBALS['pagenow'], array('wp-login.php', 'wp-register.php'))) { | |
| 10 | - add_action( 'init', array($this,'basic_auth_admin') ); | |
| 22 | + $this->log = new easy_basic_authentication_log_class(); | |
| 23 | + $this->email = new easy_basic_authentication_emailalert_class(); | |
| 24 | + $this->form = new easy_basic_authentication_form_class(); | |
| 25 | + $notice = new easy_basic_authentication_notice_class(); | |
| 26 | + $this->compatcheck = new easy_basic_authentication_compatcheck_class(); | |
| 27 | + $this->compatcheck->register_hooks(); | |
| 28 | + | |
| 29 | + // Fuori da una richiesta HTTP la sfida 401 non ha alcun senso: da riga di comando | |
| 30 | + // diventa un exit() silenzioso che blocca WP-CLI, il cron di sistema e qualunque | |
| 31 | + // script che faccia require di wp-load.php. | |
| 32 | + if ( ! self::is_cli() ) { | |
| 33 | + $pagenow = isset( $GLOBALS['pagenow'] ) ? $GLOBALS['pagenow'] : ''; | |
| 34 | + | |
| 35 | + if(get_option( 'basic_auth_plugin_admin_enable' )) { | |
| 36 | + if (in_array($pagenow, array('wp-login.php', 'wp-register.php'))) { | |
| 37 | + add_action( 'init', array($this,'basic_auth_root') ); | |
| 38 | + } | |
| 11 | 39 | } |
| 12 | - } | |
| 13 | 40 | |
| 14 | - if(get_option( 'basic_auth_plugin_enable' ) && get_option( 'basic_auth_plugin_admin_enable' )){ | |
| 15 | - add_action( 'init', array($this,'basic_auth_root') ); | |
| 41 | + if(get_option( 'basic_auth_plugin_enable' ) && get_option( 'basic_auth_plugin_admin_enable' )){ | |
| 42 | + add_action( 'init', array($this,'basic_auth_root') ); | |
| 43 | + } | |
| 16 | 44 | } |
| 17 | 45 | |
| 46 | + add_action( 'init', array($this, 'maybe_upgrade'), 1 ); | |
| 47 | + | |
| 18 | 48 | add_action( 'admin_menu', array($this,'basic_auth_plugin_menu' )); |
| 19 | - add_action( 'admin_init', array($this,'basic_auth_plugin_settings_init' )); | |
| 49 | + add_action( 'admin_init', array($this->form,'basic_auth_plugin_settings_init' )); | |
| 20 | 50 | |
| 21 | - add_action( 'admin_init', array($this,'basic_auth_plugin_save_settings') ); | |
| 51 | + add_action('admin_init', function () { | |
| 52 | + if ( ! current_user_can( 'manage_options' ) ) { | |
| 53 | + return; | |
| 54 | + } | |
| 55 | + | |
| 56 | + // Il nonce e verificato dentro basic_auth_plugin_save_settings(), che riceve | |
| 57 | + // i dati grezzi perche deve distinguere un campo assente da uno vuoto (le | |
| 58 | + // checkbox non spuntate non vengono inviate). | |
| 59 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 60 | + $post_data = $_POST; | |
| 61 | + $this->form->basic_auth_plugin_save_settings($post_data); | |
| 62 | + }); | |
| 22 | 63 | |
| 23 | 64 | } |
| 24 | 65 | |
| 25 | - public function basic_auth_root() { | |
| 26 | - $user = get_option( 'basic_auth_plugin_username' ); | |
| 27 | - $pass = get_option( 'basic_auth_plugin_password' ); | |
| 28 | - | |
| 29 | - if ( !isset( $_SERVER['PHP_AUTH_USER'] ) || !isset( $_SERVER['PHP_AUTH_PW'] ) || | |
| 30 | - $_SERVER['PHP_AUTH_USER'] != $user || !wp_check_password( $_SERVER['PHP_AUTH_PW'], $pass ) ) { | |
| 31 | - | |
| 32 | - $this->basic_auth_log_failed_access(); | |
| 66 | + /** | |
| 67 | + * Se stiamo girando fuori da una richiesta HTTP (WP-CLI, cron di sistema, script). | |
| 68 | + * | |
| 69 | + * @return bool | |
| 70 | + */ | |
| 71 | + public static function is_cli() { | |
| 72 | + if ( defined( 'WP_CLI' ) && WP_CLI ) { | |
| 73 | + return true; | |
| 74 | + } | |
| 33 | 75 | |
| 34 | - do_action('basic_auth_before_401'); | |
| 35 | - | |
| 36 | - header( 'WWW-Authenticate: Basic realm="My Website"' ); | |
| 37 | - header( 'HTTP/1.0 401 Unauthorized' ); | |
| 38 | - echo 'Autenticazione richiesta'; | |
| 39 | - exit; | |
| 40 | - } | |
| 76 | + return 'cli' === PHP_SAPI || 'phpdbg' === PHP_SAPI; | |
| 41 | 77 | } |
| 42 | - | |
| 43 | - public function basic_auth_admin() { | |
| 44 | - $user = get_option( 'basic_auth_plugin_username' ); | |
| 45 | - $pass = get_option( 'basic_auth_plugin_password' ); | |
| 46 | - | |
| 47 | - if ( !isset( $_SERVER['PHP_AUTH_USER'] ) || !isset( $_SERVER['PHP_AUTH_PW'] ) || | |
| 48 | - $_SERVER['PHP_AUTH_USER'] != $user || !wp_check_password( $_SERVER['PHP_AUTH_PW'], $pass ) ) { | |
| 49 | - | |
| 50 | - $this->basic_auth_log_failed_access(); | |
| 51 | - | |
| 52 | - do_action('basic_auth_before_401'); | |
| 53 | 78 | |
| 54 | - header( 'HTTP/1.1 401 Unauthorized' ); | |
| 55 | - header( 'WWW-Authenticate: Basic realm="Admin Area"' ); | |
| 56 | - exit; | |
| 57 | - } | |
| 58 | - } | |
| 59 | - | |
| 60 | - | |
| 61 | - public function basic_auth_plugin_menu() { | |
| 62 | - $access_count = $this->basic_auth_count_not_viewed_log_failed_access(); | |
| 63 | - add_menu_page( | |
| 64 | - __('Configurations for Easy Basic Authentication', 'easy-basic-authentication'), | |
| 65 | - __('Easy Basic A.', 'easy-basic-authentication'), | |
| 66 | - 'manage_options', | |
| 67 | - 'basic-auth-plugin', | |
| 68 | - array($this, 'basic_auth_plugin_settings_page'), | |
| 69 | - 'dashicons-lock' | |
| 70 | - ); | |
| 71 | - if($this->log_is_enabled()) { | |
| 72 | - $access_count = $this->basic_auth_count_not_viewed_log_failed_access(); | |
| 73 | - add_submenu_page( | |
| 74 | - 'basic-auth-plugin', | |
| 75 | - __('Log Page', 'easy-basic-authentication'), | |
| 76 | - __('Log Page', 'easy-basic-authentication'). '<span class="update-plugins count-' . $access_count . '"><span class="plugin-count">' . $access_count . '</span></span>', | |
| 77 | - 'manage_options', | |
| 78 | - 'basic-auth-login', | |
| 79 | - array($this, 'basic_auth_login_page') | |
| 80 | - ); | |
| 79 | + public function basic_auth_root() | |
| 80 | + { | |
| 81 | + if ( self::is_cli() ) { | |
| 82 | + return; | |
| 81 | 83 | } |
| 84 | + | |
| 85 | + $user = get_option('basic_auth_plugin_username'); | |
| 86 | + $pass = get_option('basic_auth_plugin_password'); | |
| 82 | 87 | |
| 88 | + if ($this->whiteListChecker()) { | |
| 89 | + return; | |
| 90 | + } | |
| 91 | + | |
| 92 | + if ($this->urlWhiteListChecker()) { | |
| 93 | + return; | |
| 94 | + } | |
| 95 | + | |
| 96 | + // Alcuni server (nginx + FastCGI su tutti) non popolano PHP_AUTH_USER da soli: | |
| 97 | + // le credenziali arrivano solo nell'header Authorization e vanno estratte a mano. | |
| 98 | + if (!isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['HTTP_AUTHORIZATION'])) { | |
| 99 | + $authorization = sanitize_text_field( wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ) ); | |
| 100 | + | |
| 101 | + if ( preg_match( '#^Basic\s+([A-Za-z0-9+/=]+)$#i', $authorization, $matches ) ) { | |
| 102 | + $decoded = base64_decode( $matches[1], true ); | |
| 103 | + | |
| 104 | + // Senza i due punti non ci sono due campi: la list() originale | |
| 105 | + // generava un warning "Undefined array key 1" su PHP 8. | |
| 106 | + if ( false !== $decoded && false !== strpos( $decoded, ':' ) ) { | |
| 107 | + list( $sent_user, $sent_pass ) = explode( ':', $decoded, 2 ); | |
| 108 | + $_SERVER['PHP_AUTH_USER'] = $sent_user; | |
| 109 | + $_SERVER['PHP_AUTH_PW'] = $sent_pass; | |
| 110 | + } | |
| 111 | + } | |
| 112 | + } | |
| 113 | + | |
| 114 | + // Basic Auth prevede sempre un primo giro senza credenziali: il browser chiede, | |
| 115 | + // riceve 401, e solo allora rimanda con utente e password. Quel 401 non e un | |
| 116 | + // tentativo fallito, e registrarlo significherebbe una voce di log (e una mail) | |
| 117 | + // per ogni visitatore e ogni bot che passa. | |
| 118 | + $credentials_sent = isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']); | |
| 119 | + | |
| 120 | + if (!$credentials_sent) { | |
| 121 | + $this->do_exit(true, false); | |
| 122 | + return; | |
| 123 | + } | |
| 124 | + | |
| 125 | + // L'utente e salvato passando per sanitize_text_field(), quindi quello in arrivo | |
| 126 | + // va normalizzato allo stesso modo perche il confronto sia sensato. | |
| 127 | + $sent_user = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) ); | |
| 128 | + | |
| 129 | + // La password invece NON va sanitizzata: alterarla farebbe fallire l'accesso a | |
| 130 | + // chiunque ne usi una con caratteri speciali. Non viene mai stampata, solo | |
| 131 | + // confrontata con l'hash. | |
| 132 | + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | |
| 133 | + $sent_pass = wp_unslash( $_SERVER['PHP_AUTH_PW'] ); | |
| 134 | + | |
| 135 | + $credentials_valid = hash_equals( (string) $user, $sent_user ) | |
| 136 | + && wp_check_password( $sent_pass, $pass ); | |
| 137 | + | |
| 138 | + if (!$credentials_valid) { | |
| 139 | + // Credenziali inviate e sbagliate: questo si che va segnalato. | |
| 140 | + $this->do_exit(true, true); | |
| 141 | + } | |
| 83 | 142 | } |
| 84 | - | |
| 85 | - public function basic_auth_login_page() { | |
| 86 | - if(array_key_exists('clear_mode',$_POST)) { | |
| 87 | - update_option('basic_auth_failure_logs', array()); | |
| 143 | + | |
| 144 | + public function urlWhiteListChecker() { | |
| 145 | + if (empty($_SERVER['HTTP_HOST']) || empty($_SERVER['REQUEST_URI'])) { | |
| 146 | + return false; | |
| 88 | 147 | } |
| 89 | - $user_log_data = array_reverse($this->basic_auth_get_log_failed_access()); | |
| 90 | - include plugin_dir_path( __FILE__ ) . '../template/log_page.php'; | |
| 91 | - $this->update_view(); | |
| 148 | + | |
| 149 | + $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; | |
| 150 | + | |
| 151 | + $host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ); | |
| 152 | + | |
| 153 | + // L'URI serve solo al confronto con la whitelist, non viene mai stampato. | |
| 154 | + // sanitize_text_field() qui sarebbe dannoso: rimuove le sequenze %xx e | |
| 155 | + // cambierebbe il confronto su qualsiasi percorso con caratteri codificati. | |
| 156 | + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | |
| 157 | + $request_uri = wp_unslash( $_SERVER['REQUEST_URI'] ); | |
| 158 | + | |
| 159 | + $currentUrl = $scheme . '://' . $host . $request_uri; | |
| 160 | + | |
| 161 | + $whitelist = $this->getUrlWhiteList(); | |
| 162 | + | |
| 163 | + foreach ($whitelist as $entry) { | |
| 164 | + if ($this->isUrlAllowed($currentUrl, $entry)) { | |
| 165 | + return true; | |
| 166 | + } | |
| 167 | + } | |
| 168 | + | |
| 169 | + return false; | |
| 92 | 170 | } |
| 93 | - | |
| 94 | 171 | |
| 95 | - public function basic_auth_plugin_settings_page() { | |
| 96 | - include plugin_dir_path( __FILE__ ) . '../template/settings_page.php'; | |
| 172 | + private function isUrlAllowed($currentUrl, $entry) { | |
| 173 | + $currentUrl = rtrim($currentUrl, '/'); | |
| 174 | + $entry = rtrim($entry, '/'); | |
| 175 | + | |
| 176 | + if (strpos($entry, '/') === 0) { | |
| 177 | + $path = wp_parse_url($currentUrl, PHP_URL_PATH); | |
| 178 | + return stripos($path, $entry) === 0; | |
| 179 | + } | |
| 180 | + | |
| 181 | + if (!preg_match('#^https?://#i', $entry)) { | |
| 182 | + $scheme = wp_parse_url($currentUrl, PHP_URL_SCHEME) ?: 'https'; | |
| 183 | + $entry = $scheme . '://' . $entry; | |
| 184 | + } | |
| 185 | + | |
| 186 | + return stripos($currentUrl, $entry) === 0; | |
| 97 | 187 | } |
| 188 | + | |
| 189 | + public function whiteListChecker() { | |
| 190 | + if (!isset($_SERVER['REMOTE_ADDR'])) { | |
| 191 | + return false; | |
| 192 | + } | |
| 98 | 193 | |
| 99 | - public function basic_auth_plugin_settings_init() { | |
| 100 | - register_setting( 'basic-auth-plugin-settings', 'basic_auth_plugin_admin_enable' ); | |
| 101 | - register_setting( 'basic-auth-plugin-settings', 'basic_auth_plugin_enable' ); | |
| 102 | - register_setting( 'basic-auth-plugin-settings', 'basic_auth_plugin_username' ); | |
| 103 | - register_setting( 'basic-auth-plugin-settings', 'basic_auth_plugin_admin_log_enable' ); | |
| 104 | - | |
| 105 | - add_settings_section( | |
| 106 | - 'basic-auth-plugin-section', | |
| 107 | - __('Configurations for Easy Basic Authentication', 'easy-basic-authentication'), | |
| 108 | - array($this,'basic_auth_plugin_section_cb'), | |
| 109 | - 'basic-auth-plugin-settings' | |
| 110 | - ); | |
| 111 | - | |
| 112 | - add_settings_field( | |
| 113 | - 'basic-auth-plugin-admin-enable', | |
| 114 | - __('Enable for wp-admin', 'easy-basic-authentication'), | |
| 115 | - array($this,'basic_auth_plugin_admin_enable_cb'), | |
| 116 | - 'basic-auth-plugin-settings', | |
| 117 | - 'basic-auth-plugin-section' | |
| 118 | - ); | |
| 119 | - | |
| 120 | - add_settings_field( | |
| 121 | - 'basic-auth-plugin-enable', | |
| 122 | - __('Enable for the entire site (only if wp-admin is enabled)', 'easy-basic-authentication'), | |
| 123 | - array($this,'basic_auth_plugin_enable_cb'), | |
| 124 | - 'basic-auth-plugin-settings', | |
| 125 | - 'basic-auth-plugin-section' | |
| 126 | - ); | |
| 127 | - | |
| 128 | - add_settings_field( | |
| 129 | - 'basic-auth-plugin-username', | |
| 130 | - __('Username', 'easy-basic-authentication'), | |
| 131 | - array($this,'basic_auth_plugin_username_cb'), | |
| 132 | - 'basic-auth-plugin-settings', | |
| 133 | - 'basic-auth-plugin-section' | |
| 134 | - ); | |
| 135 | - | |
| 136 | - add_settings_field( | |
| 137 | - 'basic-auth-plugin-password', | |
| 138 | - __('Password', 'easy-basic-authentication'), | |
| 139 | - array($this,'basic_auth_plugin_password_cb'), | |
| 140 | - 'basic-auth-plugin-settings', | |
| 141 | - 'basic-auth-plugin-section' | |
| 142 | - ); | |
| 143 | - | |
| 144 | - add_settings_field( | |
| 145 | - 'basic-auth-plugin-admin-log-enable', | |
| 146 | - __('Enable access logs', 'easy-basic-authentication'), | |
| 147 | - array($this,'basic_auth_plugin_admin_log_enable_cb'), | |
| 148 | - 'basic-auth-plugin-settings', | |
| 149 | - 'basic-auth-plugin-section' | |
| 150 | - ); | |
| 151 | - | |
| 194 | + // Un REMOTE_ADDR malformato non deve arrivare ai confronti della whitelist: | |
| 195 | + // ip2long() restituirebbe false e il risultato sarebbe imprevedibile. | |
| 196 | + $ip = filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ); | |
| 197 | + | |
| 198 | + if ( false === $ip ) { | |
| 199 | + return false; | |
| 200 | + } | |
| 201 | + | |
| 202 | + $whitelist = $this->getWhiteList(); | |
| 203 | + | |
| 204 | + foreach ($whitelist as $entry) { | |
| 205 | + if ($this->isIpAllowed($ip, $entry)) { | |
| 206 | + return true; | |
| 207 | + } | |
| 208 | + } | |
| 209 | + return false; | |
| 152 | 210 | } |
| 153 | 211 | |
| 154 | - public function basic_auth_plugin_section_cb() { | |
| 155 | - echo __('Configure basic authentication', 'easy-basic-authentication'); | |
| 212 | + private function isIpAllowed($ip, $entry) { | |
| 213 | + if (filter_var($entry, FILTER_VALIDATE_IP)) { | |
| 214 | + return $ip === $entry; | |
| 215 | + } elseif (strpos($entry, '/') !== false) { | |
| 216 | + return $this->isIpInCidr($ip, $entry); | |
| 217 | + } elseif (strpos($entry, '-') !== false) { | |
| 218 | + return $this->isIpInRange($ip, $entry); | |
| 219 | + } | |
| 220 | + return false; | |
| 156 | 221 | } |
| 157 | 222 | |
| 158 | - public function basic_auth_plugin_enable_cb() { | |
| 159 | - $admin_enable = get_option( 'basic_auth_plugin_admin_enable' ); | |
| 160 | - $enable = get_option( 'basic_auth_plugin_enable' ); | |
| 161 | - ?> | |
| 162 | - <input type="checkbox" name="basic_auth_plugin_enable" value="1" <?php checked( $enable, 1 ); ?><?php disabled( !$admin_enable ); ?>> | |
| 163 | - <?php | |
| 223 | + private function isIpInCidr($ip, $cidr) { | |
| 224 | + list($subnet, $mask) = explode('/', $cidr); | |
| 225 | + $ipLong = ip2long($ip); | |
| 226 | + $subnetLong = ip2long($subnet); | |
| 227 | + $maskLong = -1 << (32 - $mask); | |
| 228 | + return ($ipLong & $maskLong) === ($subnetLong & $maskLong); | |
| 164 | 229 | } |
| 165 | 230 | |
| 166 | - public function basic_auth_plugin_admin_enable_cb() { | |
| 167 | - $enable = get_option( 'basic_auth_plugin_admin_enable' ); | |
| 168 | - ?> | |
| 169 | - <input type="checkbox" name="basic_auth_plugin_admin_enable" value="1" <?php checked( $enable, 1 ); ?>> | |
| 170 | - <?php | |
| 231 | + private function isIpInRange($ip, $range) { | |
| 232 | + list($start, $end) = array_map('trim', explode('-', $range)); | |
| 233 | + $ipLong = ip2long($ip); | |
| 234 | + $startLong = ip2long($start); | |
| 235 | + $endLong = ip2long($end); | |
| 236 | + return ($ipLong >= $startLong && $ipLong <= $endLong); | |
| 171 | 237 | } |
| 172 | - | |
| 173 | - public function basic_auth_plugin_username_cb() { | |
| 174 | - $username = get_option( 'basic_auth_plugin_username' ); | |
| 175 | - ?> | |
| 176 | - <input type="text" name="basic_auth_plugin_username" value="<?php echo esc_attr( $username ); ?>"> | |
| 177 | - <?php | |
| 178 | - } | |
| 179 | - | |
| 180 | - public function basic_auth_plugin_password_cb() { | |
| 181 | - $password = get_option( 'basic_auth_plugin_password' ) | |
| 182 | - ? __('Password entered', 'easy-basic-authentication') | |
| 183 | - : __('Enter the password', 'easy-basic-authentication'); | |
| 184 | - ?> | |
| 185 | - <input type="password" name="basic_auth_plugin_password" value="" placeholder="<?php echo $password; ?>"> | |
| 186 | - <?php | |
| 187 | - } | |
| 188 | - | |
| 189 | - public function basic_auth_plugin_admin_log_enable_cb() { | |
| 190 | - $enable = get_option( 'basic_auth_plugin_admin_log_enable' ); | |
| 191 | - ?> | |
| 192 | - <input type="checkbox" name="basic_auth_plugin_admin_log_enable" value="1" <?php checked( $enable, 1 ); ?>> | |
| 193 | - <?php | |
| 194 | - } | |
| 195 | - | |
| 196 | - | |
| 197 | - public function basic_auth_plugin_save_settings() { | |
| 198 | - if ( isset( $_POST['eba_submit'] ) ) { | |
| 199 | - $admin_enable = isset( $_POST['basic_auth_plugin_admin_enable'] ) ? 1 : 0; | |
| 200 | - $enable = isset( $_POST['basic_auth_plugin_enable'] ) ? 1 : 0; | |
| 201 | - $username = sanitize_text_field( $_POST['basic_auth_plugin_username'] ); | |
| 202 | - $password = sanitize_text_field( $_POST['basic_auth_plugin_password'] ); | |
| 203 | - $log_enable = isset( $_POST['basic_auth_plugin_admin_log_enable'] ) ? 1 : 0; | |
| 204 | - | |
| 205 | - update_option( 'basic_auth_plugin_admin_enable', $admin_enable ); | |
| 206 | - update_option( 'basic_auth_plugin_enable', $enable ); | |
| 207 | - update_option( 'basic_auth_plugin_username', $username ); | |
| 208 | - update_option( 'basic_auth_plugin_admin_log_enable', $log_enable ); | |
| 209 | - | |
| 210 | - if ( ! empty( $password ) ) { | |
| 211 | - $hashed_password = wp_hash_password( $password ); | |
| 212 | - update_option( 'basic_auth_plugin_password', $hashed_password ); | |
| 213 | - } | |
| 214 | - } | |
| 215 | - } | |
| 216 | 238 | |
| 217 | - public function basic_auth_log_failed_access() { | |
| 218 | - if($this->log_is_enabled()) { | |
| 219 | - $logs = get_option('basic_auth_failure_logs', array()); | |
| 239 | + /** | |
| 240 | + * Manda la sfida 401. | |
| 241 | + * | |
| 242 | + * @param bool $admin_area Se la richiesta riguarda l'area di amministrazione. | |
| 243 | + * @param bool $log_attempt Se registrare l'accesso fra i tentativi falliti. | |
| 244 | + * False per il 401 iniziale, che fa parte del protocollo. | |
| 245 | + */ | |
| 246 | + public function do_exit($admin_area = false, $log_attempt = true) { | |
| 220 | 247 | |
| 221 | - $log_entry = array( | |
| 222 | - 'id' => uniqid(), | |
| 223 | - 'ip' => esc_attr($_SERVER['REMOTE_ADDR']), | |
| 224 | - 'data' => current_time('mysql'), | |
| 225 | - 'browser' => esc_attr($_SERVER['HTTP_USER_AGENT']), | |
| 226 | - 'request_uri' => esc_attr($_SERVER["REQUEST_URI"]), | |
| 227 | - 'viewed' => 0 | |
| 228 | - ); | |
| 248 | + if ($log_attempt) { | |
| 249 | + $this->basic_auth_action_failed_access(); | |
| 250 | + } | |
| 229 | 251 | |
| 230 | - $log_entry = apply_filters('basic_auth_single_log_entry', $log_entry); | |
| 252 | + do_action('basic_auth_before_401'); | |
| 231 | 253 | |
| 232 | - $logs[] = $log_entry; | |
| 254 | + if ($admin_area) { | |
| 255 | + do_action('basic_auth_before_401_admin_area'); | |
| 256 | + } | |
| 233 | 257 | |
| 234 | - $logs = apply_filters('basic_auth_logs_entry', $logs); | |
| 258 | + // I browser memorizzano le credenziali per realm: cambiare questa stringa fa | |
| 259 | + // ricomparire la richiesta di accesso a chi era gia autenticato. Il valore | |
| 260 | + // predefinito resta quello storico; chi vuole cambiarlo usa il filtro. | |
| 261 | + $realm = apply_filters('basic_auth_realm', 'My Website', $admin_area); | |
| 262 | + $realm = str_replace(array('"', "\r", "\n"), '', (string) $realm); | |
| 235 | 263 | |
| 236 | - update_option('basic_auth_failure_logs', $logs); | |
| 237 | - } | |
| 264 | + header('WWW-Authenticate: Basic realm="' . $realm . '"'); | |
| 265 | + status_header(401); | |
| 266 | + exit; | |
| 238 | 267 | } |
| 239 | 268 | |
| 240 | - public function basic_auth_get_log_failed_access() { | |
| 241 | - return get_option('basic_auth_failure_logs', array()); | |
| 269 | + public function getWhiteList() { | |
| 270 | + return get_option( 'basic_auth_plugin_whitelist' )?explode(',',get_option( 'basic_auth_plugin_whitelist' )):[]; | |
| 242 | 271 | } |
| 243 | 272 | |
| 244 | - public function basic_auth_count_log_failed_access() { | |
| 245 | - return count($this->basic_auth_get_log_failed_access()); | |
| 273 | + public function getUrlWhiteList() { | |
| 274 | + return get_option( 'basic_auth_plugin_urlwhitelist' )?explode(',',get_option( 'basic_auth_plugin_urlwhitelist' )):[]; | |
| 246 | 275 | } |
| 247 | 276 | |
| 248 | - public function basic_auth_not_viewed_log_failed_access() { | |
| 249 | - $return_not_viewed = array_filter($this->basic_auth_get_log_failed_access(), function ($entry) { | |
| 250 | - return isset($entry['viewed']) && $entry['viewed'] === 0; | |
| 251 | - }); | |
| 252 | - return $return_not_viewed; | |
| 253 | - } | |
| 277 | + public function basic_auth_plugin_menu() { | |
| 278 | + add_menu_page( | |
| 279 | + __('Configurations for Easy Basic Authentication', 'easy-basic-authentication'), | |
| 280 | + __('Easy Basic A.', 'easy-basic-authentication'), | |
| 281 | + 'manage_options', | |
| 282 | + 'basic-auth-plugin', | |
| 283 | + array($this->form, 'basic_auth_plugin_settings_page'), | |
| 284 | + 'dashicons-lock' | |
| 285 | + ); | |
| 286 | + if($this->log->is_enabled()) { | |
| 287 | + $this->log->getMenu(); | |
| 288 | + } | |
| 289 | + } | |
| 290 | + | |
| 291 | + /** | |
| 292 | + * Migrazioni una tantum, eseguite quando cambia la versione del plugin. | |
| 293 | + * | |
| 294 | + * Fino alla 4.0.0 il log degli accessi stava in un'opzione in autoload: fino a | |
| 295 | + * 500 voci, circa 144 KB, deserializzate a ogni richiesta del sito. | |
| 296 | + */ | |
| 297 | + public function maybe_upgrade() { | |
| 298 | + if ( get_option( 'basic_auth_plugin_db_version' ) === EASY_BASIC_AUTHENTICATION_VERSION ) { | |
| 299 | + return; | |
| 300 | + } | |
| 254 | 301 | |
| 255 | - public function basic_auth_count_not_viewed_log_failed_access() { | |
| 256 | - return count($this->basic_auth_not_viewed_log_failed_access()); | |
| 302 | + $logs = get_option( 'basic_auth_failure_logs', null ); | |
| 303 | + if ( null !== $logs ) { | |
| 304 | + update_option( 'basic_auth_failure_logs', $logs, false ); | |
| 305 | + } | |
| 306 | + | |
| 307 | + update_option( 'basic_auth_plugin_db_version', EASY_BASIC_AUTHENTICATION_VERSION, false ); | |
| 257 | 308 | } |
| 258 | 309 | |
| 259 | - public function update_view() { | |
| 260 | - $logs = get_option('basic_auth_failure_logs', array()); | |
| 261 | - foreach ($logs as &$entry) { | |
| 262 | - $entry['viewed'] = 1; | |
| 310 | + public function basic_auth_action_failed_access() { | |
| 311 | + if($this->log->is_enabled()) { | |
| 312 | + $this->log->update_status($_SERVER); | |
| 263 | 313 | } |
| 264 | - update_option('basic_auth_failure_logs', $logs); | |
| 265 | - } | |
| 266 | - | |
| 267 | - public function log_is_enabled() { | |
| 268 | - return get_option( 'basic_auth_plugin_admin_log_enable' ); | |
| 314 | + if($this->email->is_enabled()) { | |
| 315 | + $this->email->sendAlert($_SERVER); | |
| 316 | + } | |
| 269 | 317 | } |
| 270 | 318 | |
| 271 | 319 | } |