/** * Verifies the received SSL certificate against its Common Names and subjectAltName fields. * * PHP's SSL verifications only verify that it's a valid Certificate, it doesn't verify if * the certificate is valid for the hostname which was requested. * This function verifies the requested hostname against certificate's subjectAltName field, * if that is empty, or contains no DNS entries, a fallback to the Common Name field is used. * * IP Address support is included if the request is being made to an IP address. * * @since 3.7.0 * @static * * @param stream $stream The PHP Stream which the SSL request is being made over * @param string $host The hostname being requested * @return bool If the cerficiate presented in $stream is valid for $host */ public static function verify_ssl_certificate($stream, $host) { $context_options = stream_context_get_options($stream); if (empty($context_options['ssl']['peer_certificate'])) { return false; } $cert = openssl_x509_parse($context_options['ssl']['peer_certificate']); if (!$cert) { return false; } /* * If the request is being made to an IP address, we'll validate against IP fields * in the cert (if they exist) */ $host_type = WP_Http::is_ip_address($host) ? 'ip' : 'dns'; $certificate_hostnames = array(); if (!empty($cert['extensions']['subjectAltName'])) { $match_against = preg_split('/,\\s*/', $cert['extensions']['subjectAltName']); foreach ($match_against as $match) { list($match_type, $match_host) = explode(':', $match); if ($host_type == strtolower(trim($match_type))) { // IP: or DNS: $certificate_hostnames[] = strtolower(trim($match_host)); } } } elseif (!empty($cert['subject']['CN'])) { // Only use the CN when the certificate includes no subjectAltName extension. $certificate_hostnames[] = strtolower($cert['subject']['CN']); } // Exact hostname/IP matches. if (in_array(strtolower($host), $certificate_hostnames)) { return true; } // IP's can't be wildcards, Stop processing. if ('ip' == $host_type) { return false; } // Test to see if the domain is at least 2 deep for wildcard support. if (substr_count($host, '.') < 2) { return false; } // Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com. $wildcard_host = preg_replace('/^[^.]+\\./', '*.', $host); return in_array(strtolower($wildcard_host), $certificate_hostnames); }
public static function is_ip_address($var) { return false !== WP_Http::is_ip_address($var); }
static function getrules_enable_login_whitelist() { global $aio_wp_security; $rules = ''; if ($aio_wp_security->configs->get_value('aiowps_enable_whitelisting') == '1') { $site_url = AIOWPSEC_WP_URL; $parse_url = parse_url($site_url); $hostname = $parse_url['host']; $host_ip = gethostbyname($hostname); $special_case = false; $rules .= AIOWPSecurity_Utility_Htaccess::$enable_login_whitelist_marker_start . PHP_EOL; //Add feature marker start //If the rename login page feature is active, we will need to adjust the directives if ($aio_wp_security->configs->get_value('aiowps_enable_rename_login_page') == '1') { $secret_slug = $aio_wp_security->configs->get_value('aiowps_login_page_slug'); if (!get_option('permalink_structure')) { //standard url structure is being used - ie, non permalinks $special_case = true; $rules .= '<IfModule mod_rewrite.c>' . PHP_EOL; $rules .= 'RewriteEngine on' . PHP_EOL; $rules .= 'RewriteCond %{QUERY_STRING} ^' . $secret_slug . '$' . PHP_EOL; $rules .= 'RewriteCond %{REMOTE_ADDR} !^' . preg_quote($host_ip) . '[OR]' . PHP_EOL; } else { $slug = preg_quote($secret_slug); //escape any applicable chars $rules .= '<FilesMatch "^(' . $slug . ')">' . PHP_EOL; } } else { $rules .= '<FilesMatch "^(wp-login\\.php)">' . PHP_EOL; } if (!$special_case) { $rules .= 'Order Allow,Deny' . PHP_EOL; $rules .= 'Allow from ' . $hostname . PHP_EOL; $rules .= 'Allow from ' . $host_ip . PHP_EOL; } //Let's get list of whitelisted IPs $hosts = explode(PHP_EOL, $aio_wp_security->configs->get_value('aiowps_allowed_ip_addresses')); if (!empty($hosts) && !(sizeof($hosts) == 1 && trim($hosts[0]) == '')) { $phosts = array(); $num_hosts = count($hosts); $i = 0; foreach ($hosts as $host) { $host = trim($host); $or_string = $i == $num_hosts - 1 ? '' : '[OR]'; //Add an [OR] clause for all except the last condition if (!in_array($host, $phosts)) { if (strstr($host, '*')) { $parts = array_reverse(explode('.', $host)); $netmask = 32; foreach ($parts as $part) { if (strstr(trim($part), '*')) { $netmask = $netmask - 8; } } //*****Bug Fix ****** //Seems that netmask does not work when using the following type of directive, ie, //RewriteCond %{REMOTE_ADDR} !^203\.87\.121\.0/24 //The following works: //RewriteCond %{REMOTE_ADDR} !^203\.87\.121\. //$dhost = trim( str_replace('*', '0', implode( '.', array_reverse( $parts ) ) ) . '/' . $netmask ); $dhost = trim(str_replace('*', '', implode('.', array_reverse($parts)))); if (strlen($dhost) > 4) { if ($special_case) { $dhost = preg_quote($dhost); //escape any applicable chars $trule = 'RewriteCond %{REMOTE_ADDR} !^' . $dhost . $or_string . PHP_EOL; if (trim($trule) != 'RewriteCond %{REMOTE_ADDR}!=') { $rules .= $trule; } } else { $trule = 'Allow from ' . $dhost . PHP_EOL; if (trim($trule) != 'Allow from') { $rules .= $trule; } } } } else { $dhost = trim($host); //ipv6 - for now we will support only whole ipv6 addresses, NOT ranges if (strpos($dhost, ':') !== false) { //possible ipv6 addr $res = WP_Http::is_ip_address($dhost); if (FALSE === $res) { continue; } } if (strlen($dhost) > 4 || $res == '6') { if ($special_case) { $dhost = preg_quote($dhost); //escape any applicable chars $rules .= 'RewriteCond %{REMOTE_ADDR} !^' . $dhost . $or_string . PHP_EOL; } else { $rules .= 'Allow from ' . $dhost . PHP_EOL; } } } } $phosts[] = $host; $i++; } } if ($special_case) { $rules .= 'RewriteRule .* http://127.0.0.1 [L]' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; } else { $rules .= '</FilesMatch>' . PHP_EOL; } $rules .= AIOWPSecurity_Utility_Htaccess::$enable_login_whitelist_marker_end . PHP_EOL; //Add feature marker end } return $rules; }
static function validate_ip_list($ip_list_array, $list_type = '') { @ini_set('auto_detect_line_endings', true); $errors = ''; //validate list $submitted_ips = $ip_list_array; $list = array(); if (!empty($submitted_ips)) { foreach ($submitted_ips as $item) { $item = filter_var($item, FILTER_SANITIZE_STRING); if (strlen($item) > 0) { //ipv6 - for now we will support only whole ipv6 addresses, NOT ranges if (strpos($item, ':') !== false) { //possible ipv6 addr $res = WP_Http::is_ip_address($item); if (FALSE === $res) { $errors .= '<p>' . $item . __(' is not a valid ip address format.', 'all-in-one-wp-security-and-firewall') . '</p>'; } else { if ($res == '6') { $list[] = trim($item); } } continue; } $ipParts = explode('.', $item); $isIP = 0; $partcount = 1; $goodip = true; $foundwild = false; if (count($ipParts) < 2) { $errors .= '<p>' . $item . __(' is not a valid ip address format.', 'all-in-one-wp-security-and-firewall') . '</p>'; continue; } foreach ($ipParts as $part) { if ($goodip == true) { if (is_numeric(trim($part)) && trim($part) <= 255 && trim($part) >= 0 || trim($part) == '*') { $isIP++; } switch ($partcount) { case 1: if (trim($part) == '*') { $goodip = false; $errors .= '<p>' . $item . __(' is not a valid ip address format.', 'all-in-one-wp-security-and-firewall') . '</p>'; } break; case 2: if (trim($part) == '*') { $foundwild = true; } break; default: if (trim($part) != '*') { if ($foundwild == true) { $goodip = false; $errors .= '<p>' . $item . __(' is not a valid ip address format.', 'all-in-one-wp-security-and-firewall') . '</p>'; } } else { $foundwild = true; } break; } $partcount++; } } if (ip2long(trim(str_replace('*', '0', $item))) == false) { //invalid ip $errors .= '<p>' . $item . __(' is not a valid ip address format.', 'all-in-one-wp-security-and-firewall') . '</p>'; } elseif (strlen($item) > 4 && !in_array($item, $list)) { $current_user_ip = AIOWPSecurity_Utility_IP::get_user_ip_address(); if ($current_user_ip == $item && $list_type == 'blacklist') { //You can't ban your own IP $errors .= '<p>' . __('You cannot ban your own IP address: ', 'all-in-one-wp-security-and-firewall') . $item . '</p>'; } else { $list[] = trim($item); } } } } } else { //This function was called with an empty IP address array list } if (strlen($errors) > 0) { $return_payload = array(-1, array($errors)); return $return_payload; } if (sizeof($list) >= 1) { sort($list); $list = array_unique($list, SORT_STRING); $return_payload = array(1, $list); return $return_payload; } $return_payload = array(1, array()); return $return_payload; }
private function get_remote_ip_addr() { if (isset($_SERVER['REMOTE_ADDR']) && WP_Http::is_ip_address($_SERVER['REMOTE_ADDR'])) { return $_SERVER['REMOTE_ADDR']; } return ''; }
/** * Will check the current visitor IP against the blocked table * If IP present will block the visitor from viewing the site */ static function check_visitor_ip_and_perform_blocking() { global $aio_wp_security, $wpdb; $visitor_ip = AIOWPSecurity_Utility_IP::get_user_ip_address(); $ip_type = WP_Http::is_ip_address($visitor_ip); if (empty($ip_type)) { $aio_wp_security->debug_logger->log_debug("do_general_ip_blocking_tasks: " . $visitor_ip . " is not a valid IP!", 4); return; } //Check if this IP address is in the block list $blocked = AIOWPSecurity_Blocking::is_ip_blocked($visitor_ip); //TODO - future feature: add blocking whitelist and check if (empty($blocked)) { return; //Visitor IP is not blocked - allow page to load } else { //block this visitor!! AIOWPSecurity_Utility::redirect_to_url('http://127.0.0.1'); } return; }