Ticket #41083: 41083.2.diff
File 41083.2.diff, 5.0 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..edea9492cb 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 { 237 237 'REMOTE_ADDR', 238 238 ); 239 239 240 // Determine the best address to use 240 241 foreach ( $address_headers as $header ) { 241 242 if ( array_key_exists( $header, $_SERVER ) ) { 242 243 /* … … class WP_Community_Events { 251 252 } 252 253 } 253 254 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 } 255 $address_format = self::detect_ip_address_format( (string) $client_ip ); 256 257 if ( ! $address_format ) { 258 $client_ip = false; 259 } 261 260 261 if ( $client_ip ) { 262 $client_ip = self::strip_ip_address_port( $client_ip, $address_format ); 263 $netmask = 4 === $address_format ? '255.255.255.0' : 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; 264 } 265 266 // Partially anonymize the IP by reducing it to the corresponding network ID 267 // These functions are not available on Windows until PHP 5.3. 268 if ( $client_ip && $netmask && function_exists( 'inet_pton' ) && function_exists( 'inet_ntop' ) ) { 262 269 $client_ip = inet_ntop( inet_pton( $client_ip ) & inet_pton( $netmask ) ); 263 270 } 264 271 … … class WP_Community_Events { 266 273 } 267 274 268 275 /** 276 * Detect the format of an IP address. 277 * 278 * `filter_var()` is avoided because it can be disabled in PHP builds, and 279 * `WP_Http::is_ip_address()` is avoided because it will return false if the address 280 * contains a port number. 281 * 282 * A valid IPv4 address must have exactly 3 periods and at most 1 colon. 283 * A valid IPv6 address cannot have periods, and must have at least two colons (because 284 * addresses like `0:0:0:0:0:0:0:0` can be reduced to `::`). 285 * 286 * @param string $address 287 * 288 * @return false|int todo document false, 4, 6 289 */ 290 protected static function detect_ip_address_format( $address ) { 291 $format = false; 292 293 if ( 3 === substr_count( $address, '.' ) ) { 294 $format = 4; 295 } elseif ( substr_count( $address, ':' ) >= 2 ) { 296 $format = 6; 297 } 298 299 return $format; 300 } 301 302 // todo document 303 protected static function strip_ip_address_port( $ip_address, $address_format ) { 304 if ( 4 === $address_format ) { 305 $port_delimiter = strpos( $ip_address, ':' ); 306 307 if ( $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 ( $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..32864f5a0f 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 $test_cases = array( 267 false => false, // Invalid IP 268 'unknown' => false, // Invalid IP 269 '10.20.30.45' => '10.20.30.0', // IPv4, no port 270 '10.20.30.45:20000' => '10.20.30.0', // IPv4, port 271 '2a03:2880:2110:df07:face:b00c::1' => '2a03:2880:2110:df07::', // IPv6, no port 272 '[2a03:2880:2110:df07:face:b00c::1]:20000' => '2a03:2880:2110:df07::', // IPv6, port 273 '::' => '::', // IPv6, no port, reduced representation 274 '[::]:20000' => '::', // IPv6, port, reduced representation 275 ); 276 277 foreach ( $test_cases as $raw_ip => $expected_result ) { 278 $_SERVER['REMOTE_ADDR'] = $raw_ip; 279 $actual_result = WP_Community_Events::get_unsafe_client_ip(); 280 281 $this->assertEquals( $expected_result, $actual_result ); 282 } 283 } 258 284 }