Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

rfe #3542567 Accept IPv6 ranges and IPv6 CIDR notations in $cfg['Serv…

…ers'][$i]['AllowDeny']['rules']
  • Loading branch information...
commit 84f4f1a246cf107d74e7e62d25af6f884b712ba4 1 parent 584f49f
J.M authored
1  ChangeLog
@@ -79,6 +79,7 @@ VerboseMultiSubmit, ReplaceHelpImg
79 79 + Patch #3597529 [status] Add raw value as title on server status page
80 80 + Support MySQL 5.6 partitioning
81 81 + Removed the AjaxEnable directive
  82 ++ rfe #3542567 Accept IPv6 ranges and IPv6 CIDR notations in $cfg['Servers'][$i]['AllowDeny']['rules']
82 83
83 84 3.5.6.0 (not yet released)
84 85 - bug #3593604 [status] Erroneous advisor rule
16 doc/config.rst
Source Rendered
@@ -862,18 +862,26 @@ Server connection settings
862 862 from all'`` if your rule order is set to ``'allow,deny'`` or
863 863 ``'explicit'``.
864 864
865   - For the :term:`IP` matching
  865 + For the :term:`IP address` matching
866 866 system, the following work:
867 867
868   - * ``xxx.xxx.xxx.xxx`` (an exact :term:`IP` address)
869   - * ``xxx.xxx.xxx.[yyy-zzz]`` (an :term:`IP` address range)
  868 + * ``xxx.xxx.xxx.xxx`` (an exact :term:`IP address`)
  869 + * ``xxx.xxx.xxx.[yyy-zzz]`` (an :term:`IP address` range)
870 870 * ``xxx.xxx.xxx.xxx/nn`` (CIDR, Classless Inter-Domain Routing type :term:`IP` addresses)
871 871
872 872 But the following does not work:
873 873
874 874 * ``xxx.xxx.xxx.xx[yyy-zzz]`` (partial :term:`IP` address range)
875 875
876   - Also IPv6 addresses are not supported.
  876 + For :term:`IPv6` addresses, the following work:
  877 +
  878 + * ``xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx`` (an exact :term:`IPv6` address)
  879 + * ``xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:[yyyy-zzzz]`` (an :term:`IPv6` address range)
  880 + * ``xxxx:xxxx:xxxx:xxxx/nn`` (CIDR, Classless Inter-Domain Routing type :term:`IPv6` addresses)
  881 +
  882 + But the following does not work:
  883 +
  884 + * ``xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx[yyy-zzz]`` (partial :term:`IPv6` address range)
877 885
878 886 .. config:option:: $cfg['Servers'][$i]['DisableIS']
879 887
7 doc/glossary.rst
Source Rendered
@@ -161,6 +161,13 @@ From Wikipedia, the free encyclopedia
161 161
162 162 .. seealso:: <http://www.wikipedia.org/wiki/IP_Address>
163 163
  164 + IPv6
  165 + IPv6 (Internet Protocol version 6) is the latest revision of the
  166 + Internet Protocol (:term:`IP`), designed to deal with the
  167 + long-anticipated problem of its precedessor IPv4 running out of addresses.
  168 +
  169 + .. seealso:: <http://www.wikipedia.org/wiki/IPv6>
  170 +
164 171 ISAPI
165 172 Internet Server Application Programming Interface is the API of Internet Information Services (IIS).
166 173
132 libraries/ip_allow_deny.lib.php
@@ -4,8 +4,6 @@
4 4 * This library is used with the server IP allow/deny host authentication
5 5 * feature
6 6 *
7   - * @todo Broken for IPv6
8   - *
9 7 * @package PhpMyAdmin
10 8 */
11 9 if (! defined('PHPMYADMIN')) {
@@ -52,6 +50,31 @@ function PMA_getIp()
52 50
53 51
54 52 /**
  53 + * Matches for IPv4 or IPv6 addresses
  54 + *
  55 + * @param string $testRange string of IP range to match
  56 + * @param string $ipToTest string of IP to test against range
  57 + *
  58 + * @return boolean whether the IP mask matches
  59 + *
  60 + * @access public
  61 + */
  62 +function PMA_ipMaskTest($testRange, $ipToTest)
  63 +{
  64 + $result = true;
  65 +
  66 + if (strpos($testRange, ':') > -1 || strpos($ipToTest, ':') > -1) {
  67 + // assume IPv6
  68 + $result = PMA_ipv6MaskTest($testRange, $ipToTest);
  69 + } else {
  70 + $result = PMA_ipv4MaskTest($testRange, $ipToTest);
  71 + }
  72 +
  73 + return $result;
  74 +} // end of the "PMA_ipMaskTest()" function
  75 +
  76 +
  77 +/**
55 78 * Based on IP Pattern Matcher
56 79 * Originally by J.Adams <jna@retina.net>
57 80 * Found on <http://www.php.net/manual/en/function.ip2long.php>
@@ -68,11 +91,11 @@ function PMA_getIp()
68 91 * @param string $testRange string of IP range to match
69 92 * @param string $ipToTest string of IP to test against range
70 93 *
71   - * @return boolean always true
  94 + * @return boolean whether the IP mask matches
72 95 *
73 96 * @access public
74 97 */
75   -function PMA_ipMaskTest($testRange, $ipToTest)
  98 +function PMA_ipv4MaskTest($testRange, $ipToTest)
76 99 {
77 100 $result = true;
78 101 $match = preg_match(
@@ -120,7 +143,106 @@ function PMA_ipMaskTest($testRange, $ipToTest)
120 143 } //end if/else
121 144
122 145 return $result;
123   -} // end of the "PMA_IPMaskTest()" function
  146 +} // end of the "PMA_ipv4MaskTest()" function
  147 +
  148 +
  149 +/**
  150 + * IPv6 matcher
  151 + * CIDR section taken from http://stackoverflow.com/a/10086404
  152 + * Modified for phpMyAdmin
  153 + *
  154 + * Matches:
  155 + * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx (exact)
  156 + * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:[yyyy-zzzz] (range, only at end of IP - no subnets)
  157 + * xxxx:xxxx:xxxx:xxxx/nn (CIDR)
  158 + *
  159 + * Does not match:
  160 + * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx[yyy-zzz] (range, partial octets not supported)
  161 + *
  162 + * @param string $test_range string of IP range to match
  163 + * @param string $ip_to_test string of IP to test against range
  164 + *
  165 + * @return boolean whether the IP mask matches
  166 + *
  167 + * @access public
  168 + */
  169 +function PMA_ipv6MaskTest($test_range, $ip_to_test)
  170 +{
  171 + $result = true;
  172 +
  173 + // convert to lowercase for easier comparison
  174 + $test_range = strtolower($test_range);
  175 + $ip_to_test = strtolower($ip_to_test);
  176 +
  177 + $is_cidr = strpos($test_range, '/') > -1;
  178 + $is_range = strpos($test_range, '[') > -1;
  179 + $is_single = ! $is_cidr && ! $is_range;
  180 +
  181 + $ip_hex = bin2hex(inet_pton($ip_to_test));
  182 +
  183 + if ($is_single) {
  184 + $range_hex = bin2hex(inet_pton($test_range));
  185 + $result = $ip_hex === $range_hex;
  186 + } elseif ($is_range) {
  187 + // what range do we operate on?
  188 + $range_match = array();
  189 + if (preg_match('/\[([0-9a-f]+)\-([0-9a-f]+)\]/', $test_range, $range_match)) {
  190 + $range_start = $range_match[1];
  191 + $range_end = $range_match[2];
  192 +
  193 + // get the first and last allowed IPs
  194 + $first_ip = str_replace($range_match[0], $range_start, $test_range);
  195 + $first_hex = bin2hex(inet_pton($first_ip));
  196 + $last_ip = str_replace($range_match[0], $range_end, $test_range);
  197 + $last_hex = bin2hex(inet_pton($last_ip));
  198 +
  199 + // check if the IP to test is within the range
  200 + $result = ($ip_hex >= $first_hex && $ip_hex <= $last_hex);
  201 + }
  202 + } elseif ($is_cidr) {
  203 + // Split in address and prefix length
  204 + list($first_ip, $subnet) = explode('/', $test_range);
  205 +
  206 + // Parse the address into a binary string
  207 + $first_bin = inet_pton($first_ip);
  208 + $first_hex = bin2hex($first_bin);
  209 +
  210 + // Overwriting first address string to make sure notation is optimal
  211 + $first_ip = inet_ntop($first_bin);
  212 +
  213 + $flexbits = 128 - $subnet;
  214 +
  215 + // Build the hexadecimal string of the last address
  216 + $last_hex = $first_hex;
  217 +
  218 + $pos = 31;
  219 + while ($flexbits > 0) {
  220 + // Get the character at this position
  221 + $orig = substr($last_hex, $pos, 1);
  222 +
  223 + // Convert it to an integer
  224 + $origval = hexdec($orig);
  225 +
  226 + // OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
  227 + $newval = $origval | (pow(2, min(4, $flexbits)) - 1);
  228 +
  229 + // Convert it back to a hexadecimal character
  230 + $new = dechex($newval);
  231 +
  232 + // And put that character back in the string
  233 + $last_hex = substr_replace($last_hex, $new, $pos, 1);
  234 +
  235 + // We processed one nibble, move to previous position
  236 + $flexbits -= 4;
  237 + $pos -= 1;
  238 + }
  239 +
  240 + // check if the IP to test is within the range
  241 + $result = ($ip_hex >= $first_hex && $ip_hex <= $last_hex);
  242 + }
  243 +
  244 + return $result;
  245 +} // end of the "PMA_ipv6MaskTest()" function
124 246
125 247
126 248 /**

0 comments on commit 84f4f1a

Please sign in to comment.
Something went wrong with that request. Please try again.