diff options
author | stilez <stilez@users.noreply.github.com> | 2015-12-22 22:54:14 +0000 |
---|---|---|
committer | Stephen Beaver <sbeaver@netgate.com> | 2015-12-23 10:34:24 -0500 |
commit | 4557e3fba627c91c37afba04681cdabf71eccf57 (patch) | |
tree | 624678065cede034d9ce7f404762f1efe970ade9 | |
parent | 4ee63405fde1a1f095cca3e16760accdc7a163c7 (diff) | |
download | pfsense-4557e3fba627c91c37afba04681cdabf71eccf57.zip pfsense-4557e3fba627c91c37afba04681cdabf71eccf57.tar.gz |
data sanitising: ip2long32, ip2ulong, long2ip32 (FIXED RESUBMIT of #2152)
Self explanatory. If these functions find themselves trying to convert non-int data (or an x64 int with non-zeros in any bits >32) to dotted IPv4, or non-dotted IPv4 to integer IPv4 values, something's wrong and they shouldn't return a value that looks like they succeeded.
The original PR caused issues with VPN. This was because, to check the presence of any bits beyond #32 were zero (if INT was 64 bits or larger), the operator >>32 was used. Unfortunately this was undefined on x32 platforms. (See https://forum.pfsense.org/index.php?topic=104175 ).
The fix below was tested on x32, on the same thread.
TEST PR'ed IN #2152 (FAILS ON x32):
return ((is_int($ip) && ($ip >> 32) == 0) ? long2ip($ip & 0xFFFFFFFF) : '');
TEST NOW USED (SEEMS RELIABLE ON ALL SYSTEM INT SIZES):
return ((is_int($ip) && ($ip & ~0xFFFFFFFF) == 0) ? long2ip($ip & 0xFFFFFFFF) : '');
Other than this line and a comment, this code is identical to PR #2152
-rw-r--r-- | src/etc/inc/util.inc | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/src/etc/inc/util.inc b/src/etc/inc/util.inc index b542566..bd761d6 100644 --- a/src/etc/inc/util.inc +++ b/src/etc/inc/util.inc @@ -422,21 +422,28 @@ function gen_subnet_mask($bits) { } /* Convert long int to IPv4 address - Returns '' if not valid IPv4 (including if any bits >32 are non-zero) */ + Returns '' if not valid IPv4 (including if any bits >32 are non-zero) + NOTE: The test needs care, as several methods to test whether any high bits >= 33 are set, fails on x32 platforms. + The test uses ~0xFFFFFFFF which set all high bits >= 33 (if any) whatever the system INT size + Alternative test if ever needed that's known to work, is: (PHP_INT_SIZE <= 4 || ($ip >> 32) == 0)) + since if INT <4 bytes it's always ok and if not >>32 should be reliable. +*/ function long2ip32($ip) { - return long2ip($ip & 0xFFFFFFFF); -} + return ((is_int($ip) && ($ip & ~0xFFFFFFFF) == 0) ? long2ip($ip & 0xFFFFFFFF) : ''); + } /* Convert IPv4 address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. Returns '' if not valid IPv4. */ function ip2long32($ip) { - return (ip2long($ip) & 0xFFFFFFFF); + $a = ip2long($ip); + return ($a === False ? '' : $a & 0xFFFFFFFF); } /* Convert IPv4 address to unsigned long int. Returns '' if not valid IPv4. */ function ip2ulong($ip) { - return sprintf("%u", ip2long32($ip)); + $a = ip2long($ip); + return ($a === False ? '' : sprintf("%u", $a & 0xFFFFFFFF)); } /* Find out how many IPs are contained within a given IP range |