diff options
Diffstat (limited to 'plugins/jetpack/modules/protect.php')
-rw-r--r-- | plugins/jetpack/modules/protect.php | 399 |
1 files changed, 256 insertions, 143 deletions
diff --git a/plugins/jetpack/modules/protect.php b/plugins/jetpack/modules/protect.php index bcbaf94c..e0073001 100644 --- a/plugins/jetpack/modules/protect.php +++ b/plugins/jetpack/modules/protect.php @@ -1,6 +1,6 @@ -<?php +<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName /** - * Module Name: Protect + * Module Name: Brute force protection * Module Description: Enabling brute force protection will prevent bots and hackers from attempting to log in to your website with common username and password combinations. * Sort Order: 1 * Recommendation Order: 4 @@ -15,20 +15,93 @@ use Automattic\Jetpack\Constants; -include_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php'; +require_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php'; +/** + * Jetpack project module class. + */ class Jetpack_Protect_Module { - private static $__instance = null; + /** + * Instance of the class. + * + * @var Jetpack_Protect_Module() + */ + private static $instance = null; + + /** + * API Key. + * + * @var string + */ public $api_key; + + /** + * API Key error. + * + * @var string + */ public $api_key_error; + + /** + * Whitelisted ips + * + * @var array + */ public $whitelist; + + /** + * Whitelist error. + * + * @var string + */ public $whitelist_error; + + /** + * Whitelist saved + * + * @todo find out if this is even used. + * + * @var array + */ public $whitelist_saved; + + /** + * The URI. + * + * @var string + */ private $local_host; + + /** + * Last request. + * + * @todo find out if this is even used. + * + * @var string + */ public $last_request; + + /** + * Response fetched from wp_remote_post() + * + * @var array + */ public $last_response_raw; + + /** + * Last response. + * + * @todo find out if this is used. + * @var array + */ public $last_response; + + /** + * Block login with math, default is 1. + * + * @var int + */ private $block_login_with_math; /** @@ -37,53 +110,53 @@ class Jetpack_Protect_Module { * @return object */ public static function instance() { - if ( ! is_a( self::$__instance, 'Jetpack_Protect_Module' ) ) { - self::$__instance = new Jetpack_Protect_Module(); + if ( ! is_a( self::$instance, 'Jetpack_Protect_Module' ) ) { + self::$instance = new Jetpack_Protect_Module(); } - return self::$__instance; + return self::$instance; } /** * Registers actions */ private function __construct() { - add_action( 'jetpack_activate_module_protect', array ( $this, 'on_activation' ) ); - add_action( 'jetpack_deactivate_module_protect', array ( $this, 'on_deactivation' ) ); - add_action( 'jetpack_modules_loaded', array ( $this, 'modules_loaded' ) ); - add_action( 'login_form', array ( $this, 'check_use_math' ), 0 ); - add_filter( 'authenticate', array ( $this, 'check_preauth' ), 10, 3 ); - add_action( 'wp_login', array ( $this, 'log_successful_login' ), 10, 2 ); - add_action( 'wp_login_failed', array ( $this, 'log_failed_attempt' ) ); - add_action( 'admin_init', array ( $this, 'maybe_update_headers' ) ); - add_action( 'admin_init', array ( $this, 'maybe_display_security_warning' ) ); + add_action( 'jetpack_activate_module_protect', array( $this, 'on_activation' ) ); + add_action( 'jetpack_deactivate_module_protect', array( $this, 'on_deactivation' ) ); + add_action( 'jetpack_modules_loaded', array( $this, 'modules_loaded' ) ); + add_action( 'login_form', array( $this, 'check_use_math' ), 0 ); + add_filter( 'authenticate', array( $this, 'check_preauth' ), 10, 3 ); + add_action( 'wp_login', array( $this, 'log_successful_login' ), 10, 2 ); + add_action( 'wp_login_failed', array( $this, 'log_failed_attempt' ) ); + add_action( 'admin_init', array( $this, 'maybe_update_headers' ) ); + add_action( 'admin_init', array( $this, 'maybe_display_security_warning' ) ); - // This is a backup in case $pagenow fails for some reason - add_action( 'login_form', array ( $this, 'check_login_ability' ), 1 ); + // This is a backup in case $pagenow fails for some reason. + add_action( 'login_form', array( $this, 'check_login_ability' ), 1 ); - // Load math fallback after math page form submission - if ( isset( $_POST[ 'jetpack_protect_process_math_form' ] ) ) { - include_once dirname( __FILE__ ) . '/protect/math-fallback.php'; - new Jetpack_Protect_Math_Authenticate; + // Load math fallback after math page form submission. + if ( isset( $_POST['jetpack_protect_process_math_form'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- POST request just determines if we need to use Math for Authentication. + include_once __DIR__ . '/protect/math-fallback.php'; + new Jetpack_Protect_Math_Authenticate(); } // Runs a script every day to clean up expired transients so they don't - // clog up our users' databases - require_once( JETPACK__PLUGIN_DIR . '/modules/protect/transient-cleanup.php' ); + // clog up our users' databases. + require_once JETPACK__PLUGIN_DIR . '/modules/protect/transient-cleanup.php'; } /** * On module activation, try to get an api key */ public function on_activation() { - if ( is_multisite() && is_main_site() && get_site_option( 'jetpack_protect_active', 0 ) == 0 ) { + if ( is_multisite() && is_main_site() && get_site_option( 'jetpack_protect_active', 0 ) == 0 ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual update_site_option( 'jetpack_protect_active', 1 ); } update_site_option( 'jetpack_protect_activating', 'activating' ); - // Get BruteProtect's counter number - Jetpack_Protect_Module::protect_call( 'check_key' ); + // Get BruteProtect's counter number. + self::protect_call( 'check_key' ); } /** @@ -95,6 +168,9 @@ class Jetpack_Protect_Module { } } + /** + * Get the protect key, + */ public function maybe_get_protect_key() { if ( get_site_option( 'jetpack_protect_activating', false ) && ! get_site_option( 'jetpack_protect_key', false ) ) { $key = $this->get_protect_key(); @@ -109,23 +185,25 @@ class Jetpack_Protect_Module { * Sends a "check_key" API call once a day. This call allows us to track IP-related * headers for this server via the Protect API, in order to better identify the source * IP for login attempts + * + * @param bool $force - if we're forcing the request. */ public function maybe_update_headers( $force = false ) { $updated_recently = $this->get_transient( 'jpp_headers_updated_recently' ); if ( ! $force ) { - if ( isset( $_GET['protect_update_headers'] ) ) { + if ( isset( $_GET['protect_update_headers'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- this doesn't change anything, just forces the once-a-day check to run via force if set. $force = true; } } // check that current user is admin so we prevent a lower level user from adding - // a trusted header, allowing them to brute force an admin account + // a trusted header, allowing them to brute force an admin account. if ( ( $updated_recently && ! $force ) || ! current_user_can( 'update_plugins' ) ) { return; } - $response = Jetpack_Protect_Module::protect_call( 'check_key' ); + $response = self::protect_call( 'check_key' ); $this->set_transient( 'jpp_headers_updated_recently', 1, DAY_IN_SECONDS ); if ( isset( $response['msg'] ) && $response['msg'] ) { @@ -134,10 +212,13 @@ class Jetpack_Protect_Module { } + /** + * Handle discplaying a security warning. + */ public function maybe_display_security_warning() { if ( is_multisite() && current_user_can( 'manage_network' ) ) { if ( ! function_exists( 'is_plugin_active_for_network' ) ) { - require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); + require_once ABSPATH . '/wp-admin/includes/plugin.php'; } if ( ! is_plugin_active_for_network( plugin_basename( JETPACK__PLUGIN_FILE ) ) ) { @@ -147,15 +228,21 @@ class Jetpack_Protect_Module { } } + /** + * Handles preparing the multisite notice. + */ public function prepare_jetpack_protect_multisite_notice() { $dismissed = get_site_option( 'jetpack_dismissed_protect_multisite_banner' ); if ( $dismissed ) { return; } - add_action( 'admin_notices', array ( $this, 'admin_jetpack_manage_notice' ) ); + add_action( 'admin_notices', array( $this, 'admin_jetpack_manage_notice' ) ); } + /** + * Handle dismissing the multisite banner. + */ public function ajax_dismiss_handler() { check_ajax_referer( 'jetpack_protect_multisite_banner_opt_out' ); @@ -184,7 +271,7 @@ class Jetpack_Protect_Module { <?php esc_html_e( 'View Network Admin', 'jetpack' ); ?> </a> <a class="button" href="<?php echo esc_url( __( 'https://jetpack.com/support/multisite-protect', 'jetpack' ) ); ?>" target="_blank"> - <?php esc_html_e( 'Learn More' ); ?> + <?php esc_html_e( 'Learn More', 'jetpack' ); ?> </a> </p> </div> @@ -198,9 +285,11 @@ class Jetpack_Protect_Module { { _wpnonce: $( event.delegateTarget ).data( 'dismiss-nonce' ), } - ).fail( function( error ) { <?php + ).fail( function( error ) { + <?php // A failure here is really strange, and there's not really anything a site owner can do to fix one. - // Just log the error for now to help debugging. ?> + // Just log the error for now to help debugging. + ?> if ( 'function' === typeof error.done && '-1' === error.responseText ) { console.error( 'Notice dismissal failed: check_ajax_referer' ); @@ -221,23 +310,23 @@ class Jetpack_Protect_Module { */ public function get_protect_key() { - $protect_blog_id = Jetpack_Protect_Module::get_main_blog_jetpack_id(); + $protect_blog_id = self::get_main_blog_jetpack_id(); // If we can't find the the blog id, that means we are on multisite, and the main site never connected - // the protect api key is linked to the main blog id - instruct the user to connect their main blog + // the protect api key is linked to the main blog id - instruct the user to connect their main blog. if ( ! $protect_blog_id ) { $this->api_key_error = __( 'Your main blog is not connected to WordPress.com. Please connect to get an API key.', 'jetpack' ); return false; } - $request = array ( + $request = array( 'jetpack_blog_id' => $protect_blog_id, 'bruteprotect_api_key' => get_site_option( 'bruteprotect_api_key' ), 'multisite' => '0', ); - // Send the number of blogs on the network if we are on multisite + // Send the number of blogs on the network if we are on multisite. if ( is_multisite() ) { $request['multisite'] = get_blog_count(); if ( ! $request['multisite'] ) { @@ -246,14 +335,15 @@ class Jetpack_Protect_Module { } } - // Request the key + // Request the key. $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.protect.requestKey', $request ); - // Hmm, can't talk to wordpress.com + // Hmm, can't talk to wordpress.com. if ( $xml->isError() ) { - $code = $xml->getErrorCode(); - $message = $xml->getErrorMessage(); + $code = $xml->getErrorCode(); + $message = $xml->getErrorMessage(); + // Translators: The xml error code, and the xml error message. $this->api_key_error = sprintf( __( 'Error connecting to WordPress.com. Code: %1$s, %2$s', 'jetpack' ), $code, $message ); return false; @@ -261,14 +351,14 @@ class Jetpack_Protect_Module { $response = $xml->getResponse(); - // Hmm. Can't talk to the protect servers ( api.bruteprotect.com ) + // Hmm, can't talk to the protect servers ( api.bruteprotect.com ). if ( ! isset( $response['data'] ) ) { $this->api_key_error = __( 'No reply from Jetpack servers', 'jetpack' ); return false; } - // There was an issue generating the key + // There was an issue generating the key. if ( empty( $response['success'] ) ) { $this->api_key_error = $response['data']; @@ -278,8 +368,8 @@ class Jetpack_Protect_Module { // Key generation successful! $active_plugins = Jetpack::get_active_plugins(); - // We only want to deactivate BruteProtect if we successfully get a key - if ( in_array( 'bruteprotect/bruteprotect.php', $active_plugins ) ) { + // We only want to deactivate BruteProtect if we successfully get a key. + if ( in_array( 'bruteprotect/bruteprotect.php', $active_plugins, true ) ) { Jetpack_Client_Server::deactivate_plugin( 'bruteprotect/bruteprotect.php', 'BruteProtect' ); } @@ -294,9 +384,10 @@ class Jetpack_Protect_Module { * * Fires custom, plugable action jpp_log_failed_attempt with the IP * + * @param string $login_user - the user attempting to log in. * @return void */ - function log_failed_attempt( $login_user = null ) { + public function log_failed_attempt( $login_user = null ) { /** * Fires before every failed login attempt. @@ -314,16 +405,15 @@ class Jetpack_Protect_Module { if ( isset( $_COOKIE['jpp_math_pass'] ) ) { - $transient = $this->get_transient( 'jpp_math_pass_' . $_COOKIE['jpp_math_pass'] ); + $transient = $this->get_transient( 'jpp_math_pass_' . sanitize_key( $_COOKIE['jpp_math_pass'] ) ); $transient--; if ( ! $transient || $transient < 1 ) { - $this->delete_transient( 'jpp_math_pass_' . $_COOKIE['jpp_math_pass'] ); - setcookie( 'jpp_math_pass', 0, time() - DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, false ); + $this->delete_transient( 'jpp_math_pass_' . sanitize_key( $_COOKIE['jpp_math_pass'] ) ); + setcookie( 'jpp_math_pass', 0, time() - DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, false, true ); } else { - $this->set_transient( 'jpp_math_pass_' . $_COOKIE['jpp_math_pass'], $transient, DAY_IN_SECONDS ); + $this->set_transient( 'jpp_math_pass_' . sanitize_key( $_COOKIE['jpp_math_pass'] ), $transient, DAY_IN_SECONDS ); } - } $this->protect_call( 'failed_attempt' ); } @@ -339,28 +429,30 @@ class Jetpack_Protect_Module { * Logs a successful login back to our servers, this allows us to make sure we're not blocking * a busy IP that has a lot of good logins along with some forgotten passwords. Also saves current user's ip * to the ip address whitelist + * + * @param string $user_login - the user loggign in. + * @param string $user - the user. */ public function log_successful_login( $user_login, $user = null ) { if ( ! $user ) { // For do_action( 'wp_login' ) calls that lacked passing the 2nd arg. $user = get_user_by( 'login', $user_login ); } - $this->protect_call( 'successful_login', array ( 'roles' => $user->roles ) ); + $this->protect_call( 'successful_login', array( 'roles' => $user->roles ) ); } - /** * Checks for loginability BEFORE authentication so that bots don't get to go around the log in form. * * If we are using our math fallback, authenticate via math-fallback.php * - * @param string $user - * @param string $username - * @param string $password + * @param string $user - the user. + * @param string $username - the username. + * @param string $password - the password. * * @return string $user */ - function check_preauth( $user = 'Not Used By Protect', $username = 'Not Used By Protect', $password = 'Not Used By Protect' ) { + public function check_preauth( $user = 'Not Used By Protect', $username = 'Not Used By Protect', $password = 'Not Used By Protect' ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable $allow_login = $this->check_login_ability( true ); $use_math = $this->get_transient( 'brute_use_math' ); @@ -368,8 +460,8 @@ class Jetpack_Protect_Module { $this->block_with_math(); } - if ( ( 1 == $use_math || 1 == $this->block_login_with_math ) && isset( $_POST['log'] ) ) { - include_once dirname( __FILE__ ) . '/protect/math-fallback.php'; + if ( ( 1 == $use_math || 1 == $this->block_login_with_math ) && isset( $_POST['log'] ) ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual, WordPress.Security.NonceVerification.Missing -- POST request just determines if we use math authentication. + include_once __DIR__ . '/protect/math-fallback.php'; Jetpack_Protect_Math_Authenticate::math_authenticate(); } @@ -381,9 +473,9 @@ class Jetpack_Protect_Module { * * @return array */ - function get_headers() { + public function get_headers() { $output = array(); - $ip_related_headers = array ( + $ip_related_headers = array( 'GD_PHP_HANDLER', 'HTTP_AKAMAI_ORIGIN_HOP', 'HTTP_CF_CONNECTING_IP', @@ -400,41 +492,41 @@ class Jetpack_Protect_Module { 'HTTP_X_IP_TRAIL', 'HTTP_X_REAL_IP', 'HTTP_X_VARNISH', - 'REMOTE_ADDR' + 'REMOTE_ADDR', ); foreach ( $ip_related_headers as $header ) { if ( ! empty( $_SERVER[ $header ] ) ) { - $output[ $header ] = $_SERVER[ $header ]; + $output[ $header ] = wp_unslash( $_SERVER[ $header ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized } } return $output; } - /* + /** * Checks if the IP address has been whitelisted * - * @param string $ip + * @param string $ip - the IP address. * * @return bool */ - function ip_is_whitelisted( $ip ) { - // If we found an exact match in wp-config - if ( defined( 'JETPACK_IP_ADDRESS_OK' ) && JETPACK_IP_ADDRESS_OK == $ip ) { + public function ip_is_whitelisted( $ip ) { + // If we found an exact match in wp-config. + if ( defined( 'JETPACK_IP_ADDRESS_OK' ) && JETPACK_IP_ADDRESS_OK === $ip ) { return true; } $whitelist = jetpack_protect_get_local_whitelist(); if ( is_multisite() ) { - $whitelist = array_merge( $whitelist, get_site_option( 'jetpack_protect_global_whitelist', array () ) ); + $whitelist = array_merge( $whitelist, get_site_option( 'jetpack_protect_global_whitelist', array() ) ); } if ( ! empty( $whitelist ) ) : foreach ( $whitelist as $item ) : - // If the IPs are an exact match - if ( ! $item->range && isset( $item->ip_address ) && $item->ip_address == $ip ) { + // If the IPs are an exact match. + if ( ! $item->range && isset( $item->ip_address ) && $item->ip_address === $ip ) { return true; } @@ -452,11 +544,11 @@ class Jetpack_Protect_Module { /** * Checks the status for a given IP. API results are cached as transients * - * @param bool $preauth Whether or not we are checking prior to authorization + * @param bool $preauth - Whether or not we are checking prior to authorization. * * @return bool Either returns true, fires $this->kill_login, or includes a math fallback and returns false */ - function check_login_ability( $preauth = false ) { + public function check_login_ability( $preauth = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable /** * JETPACK_ALWAYS_PROTECT_LOGIN will always disable the login page, and use a page provided by Jetpack. @@ -466,19 +558,19 @@ class Jetpack_Protect_Module { } if ( $this->is_current_ip_whitelisted() ) { - return true; - } + return true; + } $status = $this->get_cached_status(); if ( empty( $status ) ) { // If we've reached this point, this means that the IP isn't cached. - // Now we check with the Protect API to see if we should allow login - $response = $this->protect_call( $action = 'check_ip' ); + // Now we check with the Protect API to see if we should allow login. + $response = $this->protect_call( $action = 'check_ip' ); // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found if ( isset( $response['math'] ) && ! function_exists( 'brute_math_authenticate' ) ) { - include_once dirname( __FILE__ ) . '/protect/math-fallback.php'; - new Jetpack_Protect_Math_Authenticate; + include_once __DIR__ . '/protect/math-fallback.php'; + new Jetpack_Protect_Math_Authenticate(); return false; } @@ -486,21 +578,24 @@ class Jetpack_Protect_Module { $status = $response['status']; } - if ( 'blocked' == $status ) { + if ( 'blocked' === $status ) { $this->block_with_math(); } - if ( 'blocked-hard' == $status ) { + if ( 'blocked-hard' === $status ) { $this->kill_login(); } return true; } - function is_current_ip_whitelisted() { + /** + * Check if IP is whitelisted. + */ + public function is_current_ip_whitelisted() { $ip = jetpack_protect_get_ip(); - // Server is misconfigured and we can't get an IP + // Server is misconfigured and we can't get an IP. if ( ! $ip && class_exists( 'Jetpack' ) ) { Jetpack::deactivate_module( 'protect' ); ob_start(); @@ -533,29 +628,38 @@ class Jetpack_Protect_Module { if ( $this->ip_is_whitelisted( $ip ) ) { return true; } - } - - function has_login_ability() { - if ( $this->is_current_ip_whitelisted() ) { - return true; - } - $status = $this->get_cached_status(); - if ( empty( $status ) || $status === 'ok' ) { - return true; - } - return false; - } - - function get_cached_status() { - $transient_name = $this->get_transient_name(); - $value = $this->get_transient( $transient_name ); + } + + /** + * Check if someone is able to login based on IP. + */ + public function has_login_ability() { + if ( $this->is_current_ip_whitelisted() ) { + return true; + } + $status = $this->get_cached_status(); + if ( empty( $status ) || 'ok' === $status ) { + return true; + } + return false; + } + + /** + * Check the status of the cached transient. + */ + public function get_cached_status() { + $transient_name = $this->get_transient_name(); + $value = $this->get_transient( $transient_name ); if ( isset( $value['status'] ) ) { - return $value['status']; - } - return ''; + return $value['status']; + } + return ''; } - function block_with_math() { + /** + * Check if we need to block with a math question to continue logging in. + */ + public function block_with_math() { /** * By default, Protect will allow a user who has been blocked for too * many failed logins to start answering math questions to continue logging in @@ -580,27 +684,27 @@ class Jetpack_Protect_Module { * @param bool true Should we fallback to the Math questions when an IP is blocked. Default to true. */ $allow_math_fallback_on_fail = apply_filters( 'jpp_use_captcha_when_blocked', true ); - if ( ! $allow_math_fallback_on_fail ) { + if ( ! $allow_math_fallback_on_fail ) { $this->kill_login(); } - include_once dirname( __FILE__ ) . '/protect/math-fallback.php'; - new Jetpack_Protect_Math_Authenticate; + include_once __DIR__ . '/protect/math-fallback.php'; + new Jetpack_Protect_Math_Authenticate(); return false; } - /* + /** * Kill a login attempt */ - function kill_login() { + public function kill_login() { if ( isset( $_GET['action'], $_GET['_wpnonce'] ) && 'logout' === $_GET['action'] && - wp_verify_nonce( $_GET['_wpnonce'], 'log-out' ) && + wp_verify_nonce( $_GET['_wpnonce'], 'log-out' ) && // phpcs:ignore WordPress.Security.ValidatedSanitizedInput wp_get_current_user() ) { - // Allow users to logout + // Allow users to logout. return; } @@ -616,16 +720,17 @@ class Jetpack_Protect_Module { */ do_action( 'jpp_kill_login', $ip ); - if( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { + if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { + // translators: variable is the IP address that was flagged. $die_string = sprintf( __( 'Your IP (%1$s) has been flagged for potential security violations.', 'jetpack' ), str_replace( 'http://', '', esc_url( 'http://' . $ip ) ) ); wp_die( - $die_string, - __( 'Login Blocked by Jetpack', 'jetpack' ), - array ( 'response' => 403 ) + $die_string, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- esc_url used when forming string. + esc_html__( 'Login Blocked by Jetpack', 'jetpack' ), + array( 'response' => 403 ) ); } - require_once dirname( __FILE__ ) . '/protect/blocked-login-page.php'; + require_once __DIR__ . '/protect/blocked-login-page.php'; $blocked_login_page = Jetpack_Protect_Blocked_Login_Page::instance( $ip ); if ( $blocked_login_page->is_blocked_user_valid() ) { @@ -635,14 +740,14 @@ class Jetpack_Protect_Module { $blocked_login_page->render_and_die(); } - /* + /** * Checks if the protect API call has failed, and if so initiates the math captcha fallback. */ public function check_use_math() { $use_math = $this->get_transient( 'brute_use_math' ); if ( $use_math ) { - include_once dirname( __FILE__ ) . '/protect/math-fallback.php'; - new Jetpack_Protect_Math_Authenticate; + include_once __DIR__ . '/protect/math-fallback.php'; + new Jetpack_Protect_Math_Authenticate(); } } @@ -679,6 +784,9 @@ class Jetpack_Protect_Module { return $id; } + /** + * Checks the API key. + */ public function check_api_key() { $response = $this->protect_call( 'check_key' ); @@ -688,11 +796,11 @@ class Jetpack_Protect_Module { if ( isset( $response['error'] ) ) { - if ( $response['error'] == 'Invalid API Key' ) { + if ( 'Invalid API Key' === $response['error'] ) { $this->api_key_error = __( 'Your API key is invalid', 'jetpack' ); } - if ( $response['error'] == 'API Key Required' ) { + if ( 'API Key Required' === $response['error'] ) { $this->api_key_error = __( 'No API key', 'jetpack' ); } } @@ -705,12 +813,12 @@ class Jetpack_Protect_Module { /** * Calls over to the api using wp_remote_post * - * @param string $action 'check_ip', 'check_key', or 'failed_attempt' - * @param array $request Any custom data to post to the api + * @param string $action - 'check_ip', 'check_key', or 'failed_attempt'. + * @param array $request - Any custom data to post to the api. * * @return array */ - function protect_call( $action = 'check_ip', $request = array () ) { + public function protect_call( $action = 'check_ip', $request = array() ) { global $wp_version; $api_key = $this->maybe_get_protect_key(); @@ -720,17 +828,16 @@ class Jetpack_Protect_Module { $request['action'] = $action; $request['ip'] = jetpack_protect_get_ip(); $request['host'] = $this->get_local_host(); - $request['headers'] = json_encode( $this->get_headers() ); + $request['headers'] = wp_json_encode( $this->get_headers() ); $request['jetpack_version'] = constant( 'JETPACK__VERSION' ); - $request['wordpress_version'] = (string) $wp_version ; + $request['wordpress_version'] = (string) $wp_version; $request['api_key'] = $api_key; - $request['multisite'] = "0"; + $request['multisite'] = '0'; if ( is_multisite() ) { $request['multisite'] = get_blog_count(); } - /** * Filter controls maximum timeout in waiting for reponse from Protect servers. * @@ -742,11 +849,11 @@ class Jetpack_Protect_Module { */ $timeout = apply_filters( 'jetpack_protect_connect_timeout', 30 ); - $args = array ( + $args = array( 'body' => $request, 'user-agent' => $user_agent, 'httpversion' => '1.0', - 'timeout' => absint( $timeout ) + 'timeout' => absint( $timeout ), ); $response_json = wp_remote_post( JETPACK_PROTECT__API_HOST, $args ); @@ -767,7 +874,7 @@ class Jetpack_Protect_Module { $response['expire'] = time() + $response['seconds_remaining']; $this->set_transient( $transient_name, $response, $response['seconds_remaining'] ); $this->delete_transient( 'brute_use_math' ); - } else { // Fallback to Math Captcha if no response from API host + } else { // Fallback to Math Captcha if no response from API host. $this->set_transient( 'brute_use_math', 1, 600 ); $response['status'] = 'ok'; $response['math'] = true; @@ -782,9 +889,12 @@ class Jetpack_Protect_Module { return $response; } - function get_transient_name() { + /** + * Gets the transient name. + */ + public function get_transient_name() { $headers = $this->get_headers(); - $header_hash = md5( json_encode( $headers ) ); + $header_hash = md5( wp_json_encode( $headers ) ); return 'jpp_li_' . $header_hash; } @@ -799,13 +909,13 @@ class Jetpack_Protect_Module { * * @param string $transient Transient name. Expected to not be SQL-escaped. Must be * 45 characters or fewer in length. - * @param mixed $value Transient value. Must be serializable if non-scalar. - * Expected to not be SQL-escaped. - * @param int $expiration Optional. Time until expiration in seconds. Default 0. + * @param mixed $value Transient value. Must be serializable if non-scalar. + * Expected to not be SQL-escaped. + * @param int $expiration Optional. Time until expiration in seconds. Default 0. * * @return bool False if value was not set and true if value was set. */ - function set_transient( $transient, $value, $expiration ) { + public function set_transient( $transient, $value, $expiration ) { if ( is_multisite() && ! is_main_site() ) { switch_to_blog( $this->get_main_blog_id() ); $return = set_transient( $transient, $value, $expiration ); @@ -825,7 +935,7 @@ class Jetpack_Protect_Module { * * @return bool true if successful, false otherwise */ - function delete_transient( $transient ) { + public function delete_transient( $transient ) { if ( is_multisite() && ! is_main_site() ) { switch_to_blog( $this->get_main_blog_id() ); $return = delete_transient( $transient ); @@ -845,7 +955,7 @@ class Jetpack_Protect_Module { * * @return mixed Value of transient. */ - function get_transient( $transient ) { + public function get_transient( $transient ) { if ( is_multisite() && ! is_main_site() ) { switch_to_blog( $this->get_main_blog_id() ); $return = get_transient( $transient ); @@ -857,12 +967,15 @@ class Jetpack_Protect_Module { return get_transient( $transient ); } - function get_local_host() { + /** + * Returns the local host. + */ + public function get_local_host() { if ( isset( $this->local_host ) ) { return $this->local_host; } - $uri = 'http://' . strtolower( $_SERVER['HTTP_HOST'] ); + $uri = 'http://' . strtolower( isset( $_SERVER['HTTP_HOST'] ) ? filter_var( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '' ); if ( is_multisite() ) { $uri = network_home_url(); @@ -872,7 +985,7 @@ class Jetpack_Protect_Module { $domain = $uridata['host']; - // If we still don't have the site_url, get it + // If we still don't have the site_url, get it. if ( ! $domain ) { $uri = get_site_url( 1 ); $uridata = wp_parse_url( $uri ); |