Rev Author Line No. Line
250 kaklik 1 <?php
2 /* $Id: ip_allow_deny.lib.php,v 2.7.2.1 2006/04/11 16:33:33 cybot_tm Exp $ */
3 // vim: expandtab sw=4 ts=4 sts=4:
4  
5 /**
6 * This library is used with the server IP allow/deny host authentication
7 * feature
8 */
9  
10  
11 /**
12 * Gets the "true" IP address of the current user
13 *
14 * @return string the ip of the user
15 *
16 * @access private
17 */
18 function PMA_getIp()
19 {
20 global $REMOTE_ADDR;
21 global $HTTP_X_FORWARDED_FOR, $HTTP_X_FORWARDED, $HTTP_FORWARDED_FOR, $HTTP_FORWARDED;
22 global $HTTP_VIA, $HTTP_X_COMING_FROM, $HTTP_COMING_FROM;
23  
24 // Get some server/environment variables values
25 if (empty($REMOTE_ADDR) && PMA_getenv('REMOTE_ADDR')) {
26 $REMOTE_ADDR = PMA_getenv('REMOTE_ADDR');
27 }
28 if (empty($HTTP_X_FORWARDED_FOR) && PMA_getenv('HTTP_X_FORWARDED_FOR')) {
29 $HTTP_X_FORWARDED_FOR = PMA_getenv('HTTP_X_FORWARDED_FOR');
30 }
31 if (empty($HTTP_X_FORWARDED) && PMA_getenv('HTTP_X_FORWARDED')) {
32 $HTTP_X_FORWARDED = PMA_getenv('HTTP_X_FORWARDED');
33 }
34 if (empty($HTTP_FORWARDED_FOR) && PMA_getenv('HTTP_FORWARDED_FOR')) {
35 $HTTP_FORWARDED_FOR = PMA_getenv('HTTP_FORWARDED_FOR');
36 }
37 if (empty($HTTP_FORWARDED) && PMA_getenv('HTTP_FORWARDED')) {
38 $HTTP_FORWARDED = PMA_getenv('HTTP_FORWARDED');
39 }
40 if (empty($HTTP_VIA) && PMA_getenv('HTTP_VIA')) {
41 $HTTP_VIA = PMA_getenv('HTTP_VIA');
42 }
43 if (empty($HTTP_X_COMING_FROM) && PMA_getenv('HTTP_X_COMING_FROM')) {
44 $HTTP_X_COMING_FROM = PMA_getenv('HTTP_X_COMING_FROM');
45 }
46 if (empty($HTTP_COMING_FROM) && PMA_getenv('HTTP_COMING_FROM')) {
47 $HTTP_COMING_FROM = PMA_getenv('HTTP_COMING_FROM');
48 }
49  
50 // Gets the default ip sent by the user
51 if (!empty($REMOTE_ADDR)) {
52 $direct_ip = $REMOTE_ADDR;
53 }
54  
55 // Gets the proxy ip sent by the user
56 $proxy_ip = '';
57 if (!empty($HTTP_X_FORWARDED_FOR)) {
58 $proxy_ip = $HTTP_X_FORWARDED_FOR;
59 } elseif (!empty($HTTP_X_FORWARDED)) {
60 $proxy_ip = $HTTP_X_FORWARDED;
61 } elseif (!empty($HTTP_FORWARDED_FOR)) {
62 $proxy_ip = $HTTP_FORWARDED_FOR;
63 } elseif (!empty($HTTP_FORWARDED)) {
64 $proxy_ip = $HTTP_FORWARDED;
65 } elseif (!empty($HTTP_VIA)) {
66 $proxy_ip = $HTTP_VIA;
67 } elseif (!empty($HTTP_X_COMING_FROM)) {
68 $proxy_ip = $HTTP_X_COMING_FROM;
69 } elseif (!empty($HTTP_COMING_FROM)) {
70 $proxy_ip = $HTTP_COMING_FROM;
71 } // end if... elseif...
72  
73 // Returns the true IP if it has been found, else FALSE
74 if (empty($proxy_ip)) {
75 // True IP without proxy
76 return $direct_ip;
77 } else {
78 $is_ip = preg_match('|^([0-9]{1,3}\.){3,3}[0-9]{1,3}|', $proxy_ip, $regs);
79 if ($is_ip && (count($regs) > 0)) {
80 // True IP behind a proxy
81 return $regs[0];
82 } else {
83 // Can't define IP: there is a proxy but we don't have
84 // information about the true IP
85 return FALSE;
86 }
87 } // end if... else...
88 } // end of the 'PMA_getIp()' function
89  
90  
91 /**
92 * Based on IP Pattern Matcher
93 * Originally by J.Adams <jna@retina.net>
94 * Found on <http://www.php.net/manual/en/function.ip2long.php>
95 * Modified by Robbat2 <robbat2@users.sourceforge.net>
96 *
97 * Matches:
98 * xxx.xxx.xxx.xxx (exact)
99 * xxx.xxx.xxx.[yyy-zzz] (range)
100 * xxx.xxx.xxx.xxx/nn (CIDR)
101 *
102 * Does not match:
103 * xxx.xxx.xxx.xx[yyy-zzz] (range, partial octets not supported)
104 *
105 * @param string string of IP range to match
106 * @param string string of IP to test against range
107 *
108 * @return boolean always true
109 *
110 * @access public
111 */
112 function PMA_ipMaskTest($testRange, $ipToTest)
113 {
114 $result = TRUE;
115  
116 if (preg_match('|([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/([0-9]+)|', $testRange, $regs)) {
117 // performs a mask match
118 $ipl = ip2long($ipToTest);
119 $rangel = ip2long($regs[1] . '.' . $regs[2] . '.' . $regs[3] . '.' . $regs[4]);
120  
121 $maskl = 0;
122  
123 for ($i = 0; $i < 31; $i++) {
124 if ($i < $regs[5] - 1) {
125 $maskl = $maskl + pow(2, (30 - $i));
126 } // end if
127 } // end for
128  
129 if (($maskl & $rangel) == ($maskl & $ipl)) {
130 return TRUE;
131 } else {
132 return FALSE;
133 }
134 } else {
135 // range based
136 $maskocts = explode('.', $testRange);
137 $ipocts = explode('.', $ipToTest);
138  
139 // perform a range match
140 for ($i = 0; $i < 4; $i++) {
141 if (preg_match('|\[([0-9]+)\-([0-9]+)\]|', $maskocts[$i], $regs)) {
142 if (($ipocts[$i] > $regs[2])
143 || ($ipocts[$i] < $regs[1])) {
144 $result = FALSE;
145 } // end if
146 } else {
147 if ($maskocts[$i] <> $ipocts[$i]) {
148 $result = FALSE;
149 } // end if
150 } // end if/else
151 } //end for
152 } //end if/else
153  
154 return $result;
155 } // end of the "PMA_IPMaskTest()" function
156  
157  
158 /**
159 * Runs through IP Allow/Deny rules the use of it below for more information
160 *
161 * @param string 'allow' | 'deny' type of rule to match
162 *
163 * @return bool Matched a rule ?
164 *
165 * @access public
166 *
167 * @see PMA_getIp()
168 */
169 function PMA_allowDeny($type)
170 {
171 global $cfg;
172  
173 // Grabs true IP of the user and returns if it can't be found
174 $remote_ip = PMA_getIp();
175 if (empty($remote_ip)) {
176 return FALSE;
177 }
178  
179 // copy username
180 $username = $cfg['Server']['user'];
181  
182 // copy rule database
183 $rules = $cfg['Server']['AllowDeny']['rules'];
184  
185 // lookup table for some name shortcuts
186 $shortcuts = array(
187 'all' => '0.0.0.0/0',
188 'localhost' => '127.0.0.1/8'
189 );
190  
191 // Provide some useful shortcuts if server gives us address:
192 if (PMA_getenv('SERVER_ADDR')) {
193 $shortcuts['localnetA'] = PMA_getenv('SERVER_ADDR') . '/8';
194 $shortcuts['localnetB'] = PMA_getenv('SERVER_ADDR') . '/16';
195 $shortcuts['localnetC'] = PMA_getenv('SERVER_ADDR') . '/24';
196 }
197  
198 foreach ($rules AS $rule) {
199 // extract rule data
200 $rule_data = explode(' ', $rule);
201  
202 // check for rule type
203 if ($rule_data[0] != $type) {
204 continue;
205 }
206  
207 // check for username
208 if (($rule_data[1] != '%') //wildcarded first
209 && ($rule_data[1] != $username)) {
210 continue;
211 }
212  
213 // check if the config file has the full string with an extra
214 // 'from' in it and if it does, just discard it
215 if ($rule_data[2] == 'from') {
216 $rule_data[2] = $rule_data[3];
217 }
218  
219 // Handle shortcuts with above array
220 // DON'T use "array_key_exists" as it's only PHP 4.1 and newer.
221 if (isset($shortcuts[$rule_data[2]])) {
222 $rule_data[2] = $shortcuts[$rule_data[2]];
223 }
224  
225 // Add code for host lookups here
226 // Excluded for the moment
227  
228 // Do the actual matching now
229 if (PMA_ipMaskTest($rule_data[2], $remote_ip)) {
230 return TRUE;
231 }
232 } // end while
233  
234 return FALSE;
235 } // end of the "PMA_AllowDeny()" function
236  
237 ?>