Skip to content

Commit

Permalink
rfe #3542567 Accept IPv6 ranges and IPv6 CIDR notations in $cfg['Serv…
Browse files Browse the repository at this point in the history
…ers'][$i]['AllowDeny']['rules']
  • Loading branch information
mynetx committed Dec 27, 2012
1 parent 584f49f commit 84f4f1a
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 9 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Expand Up @@ -79,6 +79,7 @@ VerboseMultiSubmit, ReplaceHelpImg
+ Patch #3597529 [status] Add raw value as title on server status page + Patch #3597529 [status] Add raw value as title on server status page
+ Support MySQL 5.6 partitioning + Support MySQL 5.6 partitioning
+ Removed the AjaxEnable directive + Removed the AjaxEnable directive
+ rfe #3542567 Accept IPv6 ranges and IPv6 CIDR notations in $cfg['Servers'][$i]['AllowDeny']['rules']


3.5.6.0 (not yet released) 3.5.6.0 (not yet released)
- bug #3593604 [status] Erroneous advisor rule - bug #3593604 [status] Erroneous advisor rule
Expand Down
16 changes: 12 additions & 4 deletions doc/config.rst
Expand Up @@ -862,18 +862,26 @@ Server connection settings
from all'`` if your rule order is set to ``'allow,deny'`` or from all'`` if your rule order is set to ``'allow,deny'`` or
``'explicit'``. ``'explicit'``.


For the :term:`IP` matching For the :term:`IP address` matching
system, the following work: system, the following work:


* ``xxx.xxx.xxx.xxx`` (an exact :term:`IP` address) * ``xxx.xxx.xxx.xxx`` (an exact :term:`IP address`)
* ``xxx.xxx.xxx.[yyy-zzz]`` (an :term:`IP` address range) * ``xxx.xxx.xxx.[yyy-zzz]`` (an :term:`IP address` range)
* ``xxx.xxx.xxx.xxx/nn`` (CIDR, Classless Inter-Domain Routing type :term:`IP` addresses) * ``xxx.xxx.xxx.xxx/nn`` (CIDR, Classless Inter-Domain Routing type :term:`IP` addresses)


But the following does not work: But the following does not work:


* ``xxx.xxx.xxx.xx[yyy-zzz]`` (partial :term:`IP` address range) * ``xxx.xxx.xxx.xx[yyy-zzz]`` (partial :term:`IP` address range)


Also IPv6 addresses are not supported. For :term:`IPv6` addresses, the following work:

* ``xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx`` (an exact :term:`IPv6` address)
* ``xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:[yyyy-zzzz]`` (an :term:`IPv6` address range)
* ``xxxx:xxxx:xxxx:xxxx/nn`` (CIDR, Classless Inter-Domain Routing type :term:`IPv6` addresses)

But the following does not work:

* ``xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx[yyy-zzz]`` (partial :term:`IPv6` address range)


.. config:option:: $cfg['Servers'][$i]['DisableIS'] .. config:option:: $cfg['Servers'][$i]['DisableIS']
Expand Down
7 changes: 7 additions & 0 deletions doc/glossary.rst
Expand Up @@ -161,6 +161,13 @@ From Wikipedia, the free encyclopedia


.. seealso:: <http://www.wikipedia.org/wiki/IP_Address> .. seealso:: <http://www.wikipedia.org/wiki/IP_Address>


IPv6
IPv6 (Internet Protocol version 6) is the latest revision of the
Internet Protocol (:term:`IP`), designed to deal with the
long-anticipated problem of its precedessor IPv4 running out of addresses.

.. seealso:: <http://www.wikipedia.org/wiki/IPv6>

ISAPI ISAPI
Internet Server Application Programming Interface is the API of Internet Information Services (IIS). Internet Server Application Programming Interface is the API of Internet Information Services (IIS).


Expand Down
132 changes: 127 additions & 5 deletions libraries/ip_allow_deny.lib.php
Expand Up @@ -4,8 +4,6 @@
* This library is used with the server IP allow/deny host authentication * This library is used with the server IP allow/deny host authentication
* feature * feature
* *
* @todo Broken for IPv6
*
* @package PhpMyAdmin * @package PhpMyAdmin
*/ */
if (! defined('PHPMYADMIN')) { if (! defined('PHPMYADMIN')) {
Expand Down Expand Up @@ -51,6 +49,31 @@ function PMA_getIp()
} // end of the 'PMA_getIp()' function } // end of the 'PMA_getIp()' function




/**
* Matches for IPv4 or IPv6 addresses
*
* @param string $testRange string of IP range to match
* @param string $ipToTest string of IP to test against range
*
* @return boolean whether the IP mask matches
*
* @access public
*/
function PMA_ipMaskTest($testRange, $ipToTest)
{
$result = true;

if (strpos($testRange, ':') > -1 || strpos($ipToTest, ':') > -1) {
// assume IPv6
$result = PMA_ipv6MaskTest($testRange, $ipToTest);
} else {
$result = PMA_ipv4MaskTest($testRange, $ipToTest);
}

return $result;
} // end of the "PMA_ipMaskTest()" function


/** /**
* Based on IP Pattern Matcher * Based on IP Pattern Matcher
* Originally by J.Adams <jna@retina.net> * Originally by J.Adams <jna@retina.net>
Expand All @@ -68,11 +91,11 @@ function PMA_getIp()
* @param string $testRange string of IP range to match * @param string $testRange string of IP range to match
* @param string $ipToTest string of IP to test against range * @param string $ipToTest string of IP to test against range
* *
* @return boolean always true * @return boolean whether the IP mask matches
* *
* @access public * @access public
*/ */
function PMA_ipMaskTest($testRange, $ipToTest) function PMA_ipv4MaskTest($testRange, $ipToTest)
{ {
$result = true; $result = true;
$match = preg_match( $match = preg_match(
Expand Down Expand Up @@ -120,7 +143,106 @@ function PMA_ipMaskTest($testRange, $ipToTest)
} //end if/else } //end if/else


return $result; return $result;
} // end of the "PMA_IPMaskTest()" function } // end of the "PMA_ipv4MaskTest()" function


/**
* IPv6 matcher
* CIDR section taken from http://stackoverflow.com/a/10086404
* Modified for phpMyAdmin
*
* Matches:
* xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx (exact)
* xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:[yyyy-zzzz] (range, only at end of IP - no subnets)
* xxxx:xxxx:xxxx:xxxx/nn (CIDR)
*
* Does not match:
* xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx[yyy-zzz] (range, partial octets not supported)
*
* @param string $test_range string of IP range to match
* @param string $ip_to_test string of IP to test against range
*
* @return boolean whether the IP mask matches
*
* @access public
*/
function PMA_ipv6MaskTest($test_range, $ip_to_test)
{
$result = true;

// convert to lowercase for easier comparison
$test_range = strtolower($test_range);
$ip_to_test = strtolower($ip_to_test);

$is_cidr = strpos($test_range, '/') > -1;
$is_range = strpos($test_range, '[') > -1;
$is_single = ! $is_cidr && ! $is_range;

$ip_hex = bin2hex(inet_pton($ip_to_test));

if ($is_single) {
$range_hex = bin2hex(inet_pton($test_range));
$result = $ip_hex === $range_hex;
} elseif ($is_range) {
// what range do we operate on?
$range_match = array();
if (preg_match('/\[([0-9a-f]+)\-([0-9a-f]+)\]/', $test_range, $range_match)) {
$range_start = $range_match[1];
$range_end = $range_match[2];

// get the first and last allowed IPs
$first_ip = str_replace($range_match[0], $range_start, $test_range);
$first_hex = bin2hex(inet_pton($first_ip));
$last_ip = str_replace($range_match[0], $range_end, $test_range);
$last_hex = bin2hex(inet_pton($last_ip));

// check if the IP to test is within the range
$result = ($ip_hex >= $first_hex && $ip_hex <= $last_hex);
}
} elseif ($is_cidr) {
// Split in address and prefix length
list($first_ip, $subnet) = explode('/', $test_range);

// Parse the address into a binary string
$first_bin = inet_pton($first_ip);
$first_hex = bin2hex($first_bin);

// Overwriting first address string to make sure notation is optimal
$first_ip = inet_ntop($first_bin);

$flexbits = 128 - $subnet;

// Build the hexadecimal string of the last address
$last_hex = $first_hex;

$pos = 31;
while ($flexbits > 0) {
// Get the character at this position
$orig = substr($last_hex, $pos, 1);

// Convert it to an integer
$origval = hexdec($orig);

// OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
$newval = $origval | (pow(2, min(4, $flexbits)) - 1);

// Convert it back to a hexadecimal character
$new = dechex($newval);

// And put that character back in the string
$last_hex = substr_replace($last_hex, $new, $pos, 1);

// We processed one nibble, move to previous position
$flexbits -= 4;
$pos -= 1;
}

// check if the IP to test is within the range
$result = ($ip_hex >= $first_hex && $ip_hex <= $last_hex);
}

return $result;
} // end of the "PMA_ipv6MaskTest()" function




/** /**
Expand Down

0 comments on commit 84f4f1a

Please sign in to comment.