Ticket #41083: 41083.3.diff
File 41083.3.diff, 5.6 KB (added by , 7 years ago) |
---|
-
src/wp-admin/includes/class-wp-community-events.php
diff --git src/wp-admin/includes/class-wp-community-events.php src/wp-admin/includes/class-wp-community-events.php index 053d92db1a..7f6d331190 100644
class WP_Community_Events { 224 224 * or false on failure. 225 225 */ 226 226 public static function get_unsafe_client_ip() { 227 $client_ip = false;227 $client_ip = $netmask = false; 228 228 229 229 // In order of preference, with the best ones for this purpose first. 230 230 $address_headers = array( … … class WP_Community_Events { 251 251 } 252 252 } 253 253 254 // These functions are not available on Windows until PHP 5.3. 255 if ( function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) { 256 if ( 4 === strlen( inet_pton( $client_ip ) ) ) { 257 $netmask = '255.255.255.0'; // ipv4. 258 } else { 259 $netmask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; // ipv6. 260 } 254 $address_format = self::detect_ip_address_format( (string) $client_ip ); 255 if ( ! $address_format ) { 256 $client_ip = false; 257 } 261 258 259 if ( $client_ip ) { 260 $client_ip = self::strip_port_from_ip_address( $client_ip, $address_format ); 261 $netmask = 4 === $address_format ? '255.255.255.0' : 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; 262 } 263 264 // Partially anonymize the IP by reducing it to the corresponding network ID 265 // These functions are not available on Windows until PHP 5.3. 266 if ( $client_ip && $netmask && function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) { 262 267 $client_ip = inet_ntop( inet_pton( $client_ip ) & inet_pton( $netmask ) ); 263 268 } 264 269 … … class WP_Community_Events { 266 271 } 267 272 268 273 /** 274 * Detect the format of an IP address. 275 * 276 * `filter_var()` is avoided because it can be disabled in PHP builds, and 277 * `WP_Http::is_ip_address()` is avoided because it will return false if the address 278 * contains a port number. 279 * 280 * A valid IPv6 address must have at least two colons (because 281 * addresses like `0:0:0:0:0:0:0:0` can be reduced to `::`). It can contain a valid 282 * IPv4 address incompatibility mode (e.g., ::ffff:10.10.1.1). 283 * A valid IPv4 address must have exactly 3 periods and at most 1 colon. 284 * 285 * @param string $address 286 * 287 * @return false|int todo document false if couldn't determine (probably not valid ip), 4, 6 288 */ 289 protected static function detect_ip_address_format( $address ) { 290 $format = false; 291 292 if ( substr_count( $address, ':' ) > 1 ) { 293 $format = 6; 294 } elseif ( 3 === substr_count( $address, '.' ) ) { 295 $format = 4; 296 } 297 298 return $format; 299 } 300 301 302 // todo document 303 protected static function strip_port_from_ip_address( $ip_address, $address_format ) { 304 if ( 4 === $address_format ) { 305 $port_delimiter = strpos( $ip_address, ':' ); 306 307 if ( false !== $port_delimiter ) { 308 $ip_address = substr( $ip_address, 0, $port_delimiter ); 309 } 310 } elseif ( 6 === $address_format ) { 311 $port_delimiter = strpos( $ip_address, ']' ); 312 313 if ( false !== $port_delimiter ) { 314 $ip_address = substr( $ip_address, 1, $port_delimiter - 1 ); 315 // todo verify it always has the brackets when there's a port 316 } 317 } 318 319 return $ip_address; 320 } 321 322 323 /** 269 324 * Test if two pairs of latitude/longitude coordinates match each other. 270 325 * 271 326 * @since 4.8.0 -
tests/phpunit/tests/admin/includesCommunityEvents.php
diff --git tests/phpunit/tests/admin/includesCommunityEvents.php tests/phpunit/tests/admin/includesCommunityEvents.php index ed5cc2caee..fefd4a4822 100644
class Test_WP_Community_Events extends WP_UnitTestCase { 255 255 'filename' => '', 256 256 ); 257 257 } 258 259 /** 260 * Test that get_unsafe_client_ip() properly anonymizes all possible address formats 261 * 262 * @ticket 41083 263 * @since 4.8.1 264 */ 265 public function test_get_unsafe_client_ip_anonymization() { 266 // todo cases that are commented out are failing and need to be fixed 267 268 $test_cases = array( 269 '' => false, // Invalid IP. 270 'unknown' => false, // Invalid IP. Sometimes proxies add things like this, or other arbitrary strings. 271 '10.20.30.45' => '10.20.30.0', // IPv4, no port 272 '10.20.30.45:20000' => '10.20.30.0', // IPv4, port 273 '2a03:2880:2110:df07:face:b00c::1' => '2a03:2880:2110:df07::', // IPv6, no port 274 '[2a03:2880:2110:df07:face:b00c::1]:20000' => '2a03:2880:2110:df07::', // IPv6, port 275 '0000:0000:0000:0000:0000:0000:0000:0001' => '::', // IPv6, no port, reducible representation 276 '::' => '::', // IPv6, no port, reduced representation 277 '::1' => '::', // IPv6, no port, reduced representation 278 '[::]:20000' => '::', // IPv6, port, reduced representation 279 '[::1]' => '::', // IPv6, address brackets without port delimiter and number, reduced representation 280 //'::127.0.0.1' => '::127.0.0.0', // IPv6, no port, compatibility mode 281 //'[::ffff:10.10.1.1]:30000' => '::ffff:10.10.1.0', // IPv6, port, compatibility mode 282 ); 283 284 foreach ( $test_cases as $raw_ip => $expected_result ) { 285 $_SERVER['REMOTE_ADDR'] = $raw_ip; 286 $actual_result = WP_Community_Events::get_unsafe_client_ip(); 287 288 $this->assertEquals( $expected_result, $actual_result ); 289 } 290 } 258 291 }