/** * 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 * * @return bool Either returns true, fires $this->kill_login, or includes a math fallback and returns false */ function check_login_ability($preauth = false) { $headers = $this->get_headers(); $header_hash = md5(json_encode($headers)); $transient_name = 'jpp_li_' . $header_hash; $transient_value = $this->get_transient($transient_name); $ip = jetpack_protect_get_ip(); if (jetpack_protect_ip_is_private($ip)) { return true; } if ($this->ip_is_whitelisted($ip)) { return true; } // Check out our transients if (isset($transient_value) && 'ok' == $transient_value['status']) { return true; } if (isset($transient_value) && 'blocked' == $transient_value['status']) { $this->block_with_math(); } if (isset($transient_value) && 'blocked-hard' == $transient_value['status']) { $this->kill_login(); } // 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'); if (isset($response['math']) && !function_exists('brute_math_authenticate')) { include_once dirname(__FILE__) . '/protect/math-fallback.php'; new Jetpack_Protect_Math_Authenticate(); return false; } if ('blocked' == $response['status']) { $this->block_with_math(); } if ('blocked-hard' == $response['status']) { $this->kill_login(); } return true; }
function jetpack_protect_get_ip() { $trusted_header = get_site_option('trusted_ip_header'); if (isset($trusted_header) && isset($_SERVER[$trusted_header])) { $ip = $_SERVER[$trusted_header]; } else { $ip = $_SERVER['REMOTE_ADDR']; } $ips = array_reverse(explode(', ', $ip)); $ip_list_has_nonprivate_ip = false; foreach ($ips as $ip) { $ip = jetpack_clean_ip($ip); // If the IP is in a private or reserved range, keep looking if ($ip == '127.0.0.1' || $ip == '::1' || jetpack_protect_ip_is_private($ip)) { continue; } else { return $ip; } } return jetpack_clean_ip($_SERVER['REMOTE_ADDR']); }
/** * 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 * * @return bool Either returns true, fires $this->kill_login, or includes a math fallback and returns false */ function check_login_ability($preauth = false) { $ip = jetpack_protect_get_ip(); /** * Short-circuit check_login_ability. * * If there is an alternate way to validate the current IP such as * a hard-coded list of IP addresses, we can short-circuit the rest * of the login ability checks and return true here. * * @module protect * * @since 4.4.0 * * @param bool false Should we allow all logins for the current ip? Default: false */ if (apply_filters('jpp_allow_login', false, $ip)) { return true; } $headers = $this->get_headers(); $header_hash = md5(json_encode($headers)); $transient_name = 'jpp_li_' . $header_hash; $transient_value = $this->get_transient($transient_name); if (jetpack_protect_ip_is_private($ip)) { return true; } if ($this->ip_is_whitelisted($ip)) { return true; } // Check out our transients if (isset($transient_value) && 'ok' == $transient_value['status']) { return true; } if (isset($transient_value) && 'blocked' == $transient_value['status']) { $this->block_with_math(); } if (isset($transient_value) && 'blocked-hard' == $transient_value['status']) { $this->kill_login(); } // 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'); if (isset($response['math']) && !function_exists('brute_math_authenticate')) { include_once dirname(__FILE__) . '/protect/math-fallback.php'; new Jetpack_Protect_Math_Authenticate(); return false; } if ('blocked' == $response['status']) { $this->block_with_math(); } if ('blocked-hard' == $response['status']) { $this->kill_login(); } return true; }
function jetpack_protect_get_ip() { $server_headers = array('HTTP_CLIENT_IP', 'HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'); foreach ($server_headers as $key) { if (!array_key_exists($key, $_SERVER)) { continue; } foreach (explode(',', $_SERVER[$key]) as $ip) { $ip = trim($ip); // just to be safe // Check for IPv4 IP cast as IPv6 if (preg_match('/^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/', $ip, $matches)) { $ip = $matches[1]; } // If the IP is in a private or reserved range, return REMOTE_ADDR to help prevent spoofing if ($ip == '127.0.0.1' || $ip == '::1' || jetpack_protect_ip_is_private($ip)) { return $_SERVER['REMOTE_ADDR']; } return $ip; } } }