PATH:
home
/
letacommog
/
gdiags.fr
/
wp-content
/
plugins
/
wordfence
/
modules
/
login-security
/
classes
/
controller
<?php namespace WordfenceLS; use WordfenceLS\Settings\Model_DB; use WordfenceLS\Settings\Model_WPOptions; class Controller_Settings { //Configurable const OPTION_XMLRPC_ENABLED = 'xmlrpc-enabled'; const OPTION_2FA_WHITELISTED = 'whitelisted'; const OPTION_IP_SOURCE = 'ip-source'; const OPTION_IP_TRUSTED_PROXIES = 'ip-trusted-proxies'; const OPTION_REQUIRE_2FA_ADMIN = 'require-2fa.administrator'; const OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED = 'require-2fa-grace-period-enabled'; const OPTION_REQUIRE_2FA_GRACE_PERIOD = 'require-2fa-grace-period'; const OPTION_REMEMBER_DEVICE_ENABLED = 'remember-device'; const OPTION_REMEMBER_DEVICE_DURATION = 'remember-device-duration'; const OPTION_ALLOW_XML_RPC = 'allow-xml-rpc'; const OPTION_ENABLE_AUTH_CAPTCHA = 'enable-auth-captcha'; const OPTION_CAPTCHA_TEST_MODE = 'recaptcha-test-mode'; const OPTION_RECAPTCHA_SITE_KEY = 'recaptcha-site-key'; const OPTION_RECAPTCHA_SECRET = 'recaptcha-secret'; const OPTION_RECAPTCHA_THRESHOLD = 'recaptcha-threshold'; const OPTION_DELETE_ON_DEACTIVATION = 'delete-deactivation'; //Internal const OPTION_GLOBAL_NOTICES = 'global-notices'; const OPTION_LAST_SECRET_REFRESH = 'last-secret-refresh'; const OPTION_USE_NTP = 'use-ntp'; const OPTION_NTP_OFFSET = 'ntp-offset'; const OPTION_SHARED_HASH_SECRET_KEY = 'shared-hash-secret'; const OPTION_SHARED_SYMMETRIC_SECRET_KEY = 'shared-symmetric-secret'; const OPTION_DISMISSED_FRESH_INSTALL_MODAL = 'dismissed-fresh-install-modal'; const OPTION_CAPTCHA_STATS = 'captcha-stats'; protected $_settingsStorage; /** * Returns the singleton Controller_Settings. * * @return Controller_Settings */ public static function shared() { static $_shared = null; if ($_shared === null) { $_shared = new Controller_Settings(); } return $_shared; } public function __construct($settingsStorage = false) { if (!$settingsStorage) { $settingsStorage = new Model_DB(); } $this->_settingsStorage = $settingsStorage; } public function set_defaults() { $this->_settingsStorage->set_multiple(array( self::OPTION_XMLRPC_ENABLED => array('value' => true, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_2FA_WHITELISTED => array('value' => '', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_IP_SOURCE => array('value' => Model_Request::IP_SOURCE_AUTOMATIC, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_IP_TRUSTED_PROXIES => array('value' => '', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_REQUIRE_2FA_ADMIN => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_GLOBAL_NOTICES => array('value' => '[]', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_REMEMBER_DEVICE_ENABLED => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_REMEMBER_DEVICE_DURATION => array('value' => (30 * 86400), 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_ALLOW_XML_RPC => array('value' => true, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_ENABLE_AUTH_CAPTCHA => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_CAPTCHA_STATS => array('value' => '{"counts":[0,0,0,0,0,0,0,0,0,0,0],"avg":0}', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_RECAPTCHA_THRESHOLD => array('value' => 0.5, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_LAST_SECRET_REFRESH => array('value' => 0, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), self::OPTION_DELETE_ON_DEACTIVATION => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false), )); } public function set($key, $value, $already_validated = false) { return $this->set_multiple(array($key => $value), $already_validated); } public function set_array($key, $value, $already_validated = false) { return $this->set_multiple(array($key => json_encode($value)), $already_validated); } public function set_multiple($changes, $already_validated = false) { if (!$already_validated && $this->validate_multiple($changes) !== true) { return false; } $changes = $this->clean_multiple($changes); $changes = $this->preprocess_multiple($changes); $this->_settingsStorage->set_multiple($changes); return true; } public function get($key, $default = false) { return $this->_settingsStorage->get($key, $default); } public function get_bool($key, $default = false) { return $this->_truthy_to_bool($this->get($key, $default)); } public function get_int($key, $default = 0) { return intval($this->get($key, $default)); } public function get_float($key, $default = 0.0) { return (float) $this->get($key, $default); } public function get_array($key, $default = array()) { return (array) @json_decode($this->get($key, $default), true); } public function remove($key) { $this->_settingsStorage->remove($key); } /** * Validates whether a user-entered setting value is acceptable. Returns true if valid or an error message if not. * * @param string $key * @param mixed $value * @return bool|string */ public function validate($key, $value) { switch ($key) { //Boolean case self::OPTION_XMLRPC_ENABLED: case self::OPTION_REQUIRE_2FA_ADMIN: case self::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED: case self::OPTION_REMEMBER_DEVICE_ENABLED: case self::OPTION_ALLOW_XML_RPC: case self::OPTION_ENABLE_AUTH_CAPTCHA: case self::OPTION_CAPTCHA_TEST_MODE: case self::OPTION_DISMISSED_FRESH_INSTALL_MODAL: case self::OPTION_DELETE_ON_DEACTIVATION: return true; //Int case self::OPTION_LAST_SECRET_REFRESH: return is_numeric($value); //Array case self::OPTION_GLOBAL_NOTICES: case self::OPTION_CAPTCHA_STATS: return preg_match('/^\[.*\]$/', $value) || preg_match('/^\{.*\}$/', $value); //Only a rough JSON validation //Special case self::OPTION_IP_TRUSTED_PROXIES: case self::OPTION_2FA_WHITELISTED: $parsed = array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $value))); foreach ($parsed as $entry) { if (!Controller_Whitelist::shared()->is_valid_range($entry)) { return sprintf(__('The IP/range %s is invalid.', 'wordfence-2fa'), esc_html($entry)); } } return true; case self::OPTION_IP_SOURCE: if (!in_array($value, array(Model_Request::IP_SOURCE_AUTOMATIC, Model_Request::IP_SOURCE_REMOTE_ADDR, Model_Request::IP_SOURCE_X_FORWARDED_FOR, Model_Request::IP_SOURCE_X_REAL_IP))) { return __('An invalid IP source was provided.', 'wordfence-2fa'); } return true; case self::OPTION_REQUIRE_2FA_GRACE_PERIOD: $gracePeriodEnd = strtotime($value); if ($gracePeriodEnd <= \WordfenceLS\Controller_Time::time()) { return __('The grace period end time must be in the future.', 'wordfence-2fa'); } return true; case self::OPTION_REMEMBER_DEVICE_DURATION: return is_numeric($value) && $value > 0; case self::OPTION_RECAPTCHA_THRESHOLD: return is_numeric($value) && $value >= 0 && $value <= 1; case self::OPTION_RECAPTCHA_SITE_KEY: if (empty($value)) { return true; } $response = wp_remote_get('https://www.google.com/recaptcha/api.js?render=' . urlencode($value)); if (!is_wp_error($response)) { $status = wp_remote_retrieve_response_code($response); if ($status == 200) { return true; } $data = wp_remote_retrieve_body($response); if (strpos($data, 'grecaptcha') === false) { return __('Unable to validate the reCAPTCHA site key. Please check the key and try again.', 'wordfence-2fa'); } return true; } return sprintf(__('An error was encountered while validating the reCAPTCHA site key: %s', 'wordfence-2fa'), $response->get_error_message()); } return true; } public function validate_multiple($values) { $errors = array(); foreach ($values as $key => $value) { $status = $this->validate($key, $value); if ($status !== true) { $errors[$key] = $status; } } if (!empty($errors)) { return $errors; } return true; } /** * Cleans and normalizes a setting value for use in saving. * * @param string $key * @param mixed $value * @return mixed */ public function clean($key, $value) { switch ($key) { //Boolean case self::OPTION_XMLRPC_ENABLED: case self::OPTION_REQUIRE_2FA_ADMIN: case self::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED: case self::OPTION_REMEMBER_DEVICE_ENABLED: case self::OPTION_ALLOW_XML_RPC: case self::OPTION_ENABLE_AUTH_CAPTCHA: case self::OPTION_CAPTCHA_TEST_MODE: case self::OPTION_DISMISSED_FRESH_INSTALL_MODAL: case self::OPTION_DELETE_ON_DEACTIVATION: return $this->_truthy_to_bool($value); //Int case self::OPTION_REMEMBER_DEVICE_DURATION: case self::OPTION_LAST_SECRET_REFRESH: return (int) $value; //Float case self::OPTION_RECAPTCHA_THRESHOLD: return (float) $value; //Special case self::OPTION_IP_TRUSTED_PROXIES: case self::OPTION_2FA_WHITELISTED: $parsed = array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $value))); $cleaned = array(); foreach ($parsed as $item) { $cleaned[] = $this->_sanitize_ip_range($item); } return implode("\n", $cleaned); case self::OPTION_REQUIRE_2FA_GRACE_PERIOD: $dt = $this->_parse_local_time($value); return $dt->format('U'); case self::OPTION_RECAPTCHA_SITE_KEY: case self::OPTION_RECAPTCHA_SECRET: return trim($value); } return $value; } public function clean_multiple($changes) { $cleaned = array(); foreach ($changes as $key => $value) { $cleaned[$key] = $this->clean($key, $value); } return $cleaned; } /** * Preprocesses the value, returning true if it was saved here (e.g., saved 2fa enabled by assigning a role * capability) or false if it is to be saved by the backing storage. * * @param string $key * @param mixed $value * @return bool */ public function preprocess($key, $value) { if (preg_match('/^enabled-roles\.(.+)$/', $key, $matches)) { //Enabled roles are stored as capabilities rather than in the settings storage $role = $matches[1]; if ($this->_truthy_to_bool($value)) { Controller_Permissions::shared()->allow_2fa_self($role); } else { Controller_Permissions::shared()->disallow_2fa_self($role); } return true; } return false; } public function preprocess_multiple($changes) { $remaining = array(); foreach ($changes as $key => $value) { if (!$this->preprocess($key, $value)) { $remaining[$key] = $value; } } return $remaining; } /** * Convenience */ /** * Returns a cleaned array containing the whitelist entries. * * @return array */ public function whitelisted_ips() { return array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $this->get(self::OPTION_2FA_WHITELISTED, '')))); } /** * Returns a cleaned array containing the trusted proxy entries. * * @return array */ public function trusted_proxies() { return array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $this->get(self::OPTION_IP_TRUSTED_PROXIES, '')))); } /** * Utility */ /** * Translates a value to a boolean, correctly interpreting various textual representations. * * @param $value * @return bool */ protected function _truthy_to_bool($value) { if ($value === true || $value === false) { return $value; } if (is_numeric($value)) { return !!$value; } if (preg_match('/^(?:f(?:alse)?|no?|off)$/i', $value)) { return false; } else if (preg_match('/^(?:t(?:rue)?|y(?:es)?|on)$/i', $value)) { return true; } return !empty($value); } /** * Parses the given time string and returns its DateTime with the server's configured time zone. * * @param string $timestring * @return \DateTime */ protected function _parse_local_time($timestring) { $utc = new \DateTimeZone('UTC'); $tz = get_option('timezone_string'); if (!empty($tz)) { $tz = new \DateTimeZone($tz); return new \DateTime($timestring, $tz); } else { $gmt = get_option('gmt_offset'); if (!empty($gmt)) { if (PHP_VERSION_ID < 50510) { $timestamp = strtotime($timestring); $dtStr = gmdate("c", (int) ($timestamp + $gmt * 3600)); //Have to do it this way because of < PHP 5.5.10 return new \DateTime($dtStr, $utc); } else { $direction = ($gmt > 0 ? '+' : '-'); $gmt = abs($gmt); $h = (int) $gmt; $m = ($gmt - $h) * 60; $tz = new \DateTimeZone($direction . str_pad($h, 2, '0', STR_PAD_LEFT) . str_pad($m, 2, '0', STR_PAD_LEFT)); return new \DateTime($timestring, $tz); } } } return new \DateTime($timestring); } /** * Cleans a user-entered IP range of unnecessary characters and normalizes some glyphs. * * @param string $range * @return string */ protected function _sanitize_ip_range($range) { $range = preg_replace('/\s/', '', $range); //Strip whitespace $range = preg_replace('/[\\x{2013}-\\x{2015}]/u', '-', $range); //Non-hyphen dashes to hyphen $range = strtolower($range); if (preg_match('/^\d+-\d+$/', $range)) { //v5 32 bit int style format list($start, $end) = explode('-', $range); $start = long2ip($start); $end = long2ip($end); $range = "{$start}-{$end}"; } return $range; } }
[+]
..
[-] cron.php
[edit]
[-] time.php
[edit]
[-] ajax.php
[edit]
[-] wordfencels.php
[edit]
[-] captcha.php
[edit]
[-] users.php
[edit]
[-] support.php
[edit]
[-] permissions.php
[edit]
[-] notices.php
[edit]
[-] settings.php
[edit]
[-] whitelist.php
[edit]
[-] totp.php
[edit]
[-] db.php
[edit]