Mercurial Hosting > luan
comparison src/org/eclipse/jetty/server/handler/IPAccessHandler.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
16 // ======================================================================== | |
17 // | |
18 | |
19 package org.eclipse.jetty.server.handler; | |
20 | |
21 import java.io.IOException; | |
22 import java.util.Collections; | |
23 import java.util.List; | |
24 import java.util.Map; | |
25 | |
26 import javax.servlet.ServletException; | |
27 import javax.servlet.http.HttpServletRequest; | |
28 import javax.servlet.http.HttpServletResponse; | |
29 | |
30 import org.eclipse.jetty.http.HttpStatus; | |
31 import org.eclipse.jetty.http.PathMap; | |
32 import org.eclipse.jetty.io.EndPoint; | |
33 import org.eclipse.jetty.server.AbstractHttpConnection; | |
34 import org.eclipse.jetty.server.Request; | |
35 import org.eclipse.jetty.util.IPAddressMap; | |
36 import org.eclipse.jetty.util.log.Log; | |
37 import org.eclipse.jetty.util.log.Logger; | |
38 | |
39 | |
40 /** | |
41 * IP Access Handler | |
42 * <p> | |
43 * Controls access to the wrapped handler by the real remote IP. Control is provided | |
44 * by white/black lists that include both internet addresses and URIs. This handler | |
45 * uses the real internet address of the connection, not one reported in the forwarded | |
46 * for headers, as this cannot be as easily forged. | |
47 * <p> | |
48 * Typically, the black/white lists will be used in one of three modes: | |
49 * <ul> | |
50 * <li>Blocking a few specific IPs/URLs by specifying several black list entries. | |
51 * <li>Allowing only some specific IPs/URLs by specifying several white lists entries. | |
52 * <li>Allowing a general range of IPs/URLs by specifying several general white list | |
53 * entries, that are then further refined by several specific black list exceptions | |
54 * </ul> | |
55 * <p> | |
56 * An empty white list is treated as match all. If there is at least one entry in | |
57 * the white list, then a request must match a white list entry. Black list entries | |
58 * are always applied, so that even if an entry matches the white list, a black list | |
59 * entry will override it. | |
60 * <p> | |
61 * Internet addresses may be specified as absolute address or as a combination of | |
62 * four octet wildcard specifications (a.b.c.d) that are defined as follows. | |
63 * </p> | |
64 * <pre> | |
65 * nnn - an absolute value (0-255) | |
66 * mmm-nnn - an inclusive range of absolute values, | |
67 * with following shorthand notations: | |
68 * nnn- => nnn-255 | |
69 * -nnn => 0-nnn | |
70 * - => 0-255 | |
71 * a,b,... - a list of wildcard specifications | |
72 * </pre> | |
73 * <p> | |
74 * Internet address specification is separated from the URI pattern using the "|" (pipe) | |
75 * character. URI patterns follow the servlet specification for simple * prefix and | |
76 * suffix wild cards (e.g. /, /foo, /foo/bar, /foo/bar/*, *.baz). | |
77 * <p> | |
78 * Earlier versions of the handler used internet address prefix wildcard specification | |
79 * to define a range of the internet addresses (e.g. 127., 10.10., 172.16.1.). | |
80 * They also used the first "/" character of the URI pattern to separate it from the | |
81 * internet address. Both of these features have been deprecated in the current version. | |
82 * <p> | |
83 * Examples of the entry specifications are: | |
84 * <ul> | |
85 * <li>10.10.1.2 - all requests from IP 10.10.1.2 | |
86 * <li>10.10.1.2|/foo/bar - all requests from IP 10.10.1.2 to URI /foo/bar | |
87 * <li>10.10.1.2|/foo/* - all requests from IP 10.10.1.2 to URIs starting with /foo/ | |
88 * <li>10.10.1.2|*.html - all requests from IP 10.10.1.2 to URIs ending with .html | |
89 * <li>10.10.0-255.0-255 - all requests from IPs within 10.10.0.0/16 subnet | |
90 * <li>10.10.0-.-255|/foo/bar - all requests from IPs within 10.10.0.0/16 subnet to URI /foo/bar | |
91 * <li>10.10.0-3,1,3,7,15|/foo/* - all requests from IPs addresses with last octet equal | |
92 * to 1,3,7,15 in subnet 10.10.0.0/22 to URIs starting with /foo/ | |
93 * </ul> | |
94 * <p> | |
95 * Earlier versions of the handler used internet address prefix wildcard specification | |
96 * to define a range of the internet addresses (e.g. 127., 10.10., 172.16.1.). | |
97 * They also used the first "/" character of the URI pattern to separate it from the | |
98 * internet address. Both of these features have been deprecated in the current version. | |
99 */ | |
100 public class IPAccessHandler extends HandlerWrapper | |
101 { | |
102 private static final Logger LOG = Log.getLogger(IPAccessHandler.class); | |
103 | |
104 IPAddressMap<PathMap> _white = new IPAddressMap<PathMap>(); | |
105 IPAddressMap<PathMap> _black = new IPAddressMap<PathMap>(); | |
106 | |
107 /* ------------------------------------------------------------ */ | |
108 /** | |
109 * Creates new handler object | |
110 */ | |
111 public IPAccessHandler() | |
112 { | |
113 super(); | |
114 } | |
115 | |
116 /* ------------------------------------------------------------ */ | |
117 /** | |
118 * Creates new handler object and initializes white- and black-list | |
119 * | |
120 * @param white array of whitelist entries | |
121 * @param black array of blacklist entries | |
122 */ | |
123 public IPAccessHandler(String[] white, String []black) | |
124 { | |
125 super(); | |
126 | |
127 if (white != null && white.length > 0) | |
128 setWhite(white); | |
129 if (black != null && black.length > 0) | |
130 setBlack(black); | |
131 } | |
132 | |
133 /* ------------------------------------------------------------ */ | |
134 /** | |
135 * Add a whitelist entry to an existing handler configuration | |
136 * | |
137 * @param entry new whitelist entry | |
138 */ | |
139 public void addWhite(String entry) | |
140 { | |
141 add(entry, _white); | |
142 } | |
143 | |
144 /* ------------------------------------------------------------ */ | |
145 /** | |
146 * Add a blacklist entry to an existing handler configuration | |
147 * | |
148 * @param entry new blacklist entry | |
149 */ | |
150 public void addBlack(String entry) | |
151 { | |
152 add(entry, _black); | |
153 } | |
154 | |
155 /* ------------------------------------------------------------ */ | |
156 /** | |
157 * Re-initialize the whitelist of existing handler object | |
158 * | |
159 * @param entries array of whitelist entries | |
160 */ | |
161 public void setWhite(String[] entries) | |
162 { | |
163 set(entries, _white); | |
164 } | |
165 | |
166 /* ------------------------------------------------------------ */ | |
167 /** | |
168 * Re-initialize the blacklist of existing handler object | |
169 * | |
170 * @param entries array of blacklist entries | |
171 */ | |
172 public void setBlack(String[] entries) | |
173 { | |
174 set(entries, _black); | |
175 } | |
176 | |
177 /* ------------------------------------------------------------ */ | |
178 /** | |
179 * Checks the incoming request against the whitelist and blacklist | |
180 * | |
181 * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) | |
182 */ | |
183 @Override | |
184 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException | |
185 { | |
186 // Get the real remote IP (not the one set by the forwarded headers (which may be forged)) | |
187 AbstractHttpConnection connection = baseRequest.getConnection(); | |
188 if (connection!=null) | |
189 { | |
190 EndPoint endp=connection.getEndPoint(); | |
191 if (endp!=null) | |
192 { | |
193 String addr = endp.getRemoteAddr(); | |
194 if (addr!=null && !isAddrUriAllowed(addr,baseRequest.getPathInfo())) | |
195 { | |
196 response.sendError(HttpStatus.FORBIDDEN_403); | |
197 baseRequest.setHandled(true); | |
198 return; | |
199 } | |
200 } | |
201 } | |
202 | |
203 getHandler().handle(target,baseRequest, request, response); | |
204 } | |
205 | |
206 | |
207 /* ------------------------------------------------------------ */ | |
208 /** | |
209 * Helper method to parse the new entry and add it to | |
210 * the specified address pattern map. | |
211 * | |
212 * @param entry new entry | |
213 * @param patternMap target address pattern map | |
214 */ | |
215 protected void add(String entry, IPAddressMap<PathMap> patternMap) | |
216 { | |
217 if (entry != null && entry.length() > 0) | |
218 { | |
219 boolean deprecated = false; | |
220 int idx; | |
221 if (entry.indexOf('|') > 0 ) | |
222 { | |
223 idx = entry.indexOf('|'); | |
224 } | |
225 else | |
226 { | |
227 idx = entry.indexOf('/'); | |
228 deprecated = (idx >= 0); | |
229 } | |
230 | |
231 String addr = idx > 0 ? entry.substring(0,idx) : entry; | |
232 String path = idx > 0 ? entry.substring(idx) : "/*"; | |
233 | |
234 if (addr.endsWith(".")) | |
235 deprecated = true; | |
236 if (path!=null && (path.startsWith("|") || path.startsWith("/*."))) | |
237 path=path.substring(1); | |
238 | |
239 PathMap pathMap = patternMap.get(addr); | |
240 if (pathMap == null) | |
241 { | |
242 pathMap = new PathMap(true); | |
243 patternMap.put(addr,pathMap); | |
244 } | |
245 if (path != null && !"".equals(path)) | |
246 pathMap.put(path,path); | |
247 | |
248 if (deprecated) | |
249 LOG.debug(toString() +" - deprecated specification syntax: "+entry); | |
250 } | |
251 } | |
252 | |
253 /* ------------------------------------------------------------ */ | |
254 /** | |
255 * Helper method to process a list of new entries and replace | |
256 * the content of the specified address pattern map | |
257 * | |
258 * @param entries new entries | |
259 * @param patternMap target address pattern map | |
260 */ | |
261 protected void set(String[] entries, IPAddressMap<PathMap> patternMap) | |
262 { | |
263 patternMap.clear(); | |
264 | |
265 if (entries != null && entries.length > 0) | |
266 { | |
267 for (String addrPath:entries) | |
268 { | |
269 add(addrPath, patternMap); | |
270 } | |
271 } | |
272 } | |
273 | |
274 /* ------------------------------------------------------------ */ | |
275 /** | |
276 * Check if specified request is allowed by current IPAccess rules. | |
277 * | |
278 * @param addr internet address | |
279 * @param path context path | |
280 * @return true if request is allowed | |
281 * | |
282 */ | |
283 protected boolean isAddrUriAllowed(String addr, String path) | |
284 { | |
285 if (_white.size()>0) | |
286 { | |
287 boolean match = false; | |
288 | |
289 Object whiteObj = _white.getLazyMatches(addr); | |
290 if (whiteObj != null) | |
291 { | |
292 List whiteList = (whiteObj instanceof List) ? (List)whiteObj : Collections.singletonList(whiteObj); | |
293 | |
294 for (Object entry: whiteList) | |
295 { | |
296 PathMap pathMap = ((Map.Entry<String,PathMap>)entry).getValue(); | |
297 if (match = (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null))) | |
298 break; | |
299 } | |
300 } | |
301 | |
302 if (!match) | |
303 return false; | |
304 } | |
305 | |
306 if (_black.size() > 0) | |
307 { | |
308 Object blackObj = _black.getLazyMatches(addr); | |
309 if (blackObj != null) | |
310 { | |
311 List blackList = (blackObj instanceof List) ? (List)blackObj : Collections.singletonList(blackObj); | |
312 | |
313 for (Object entry: blackList) | |
314 { | |
315 PathMap pathMap = ((Map.Entry<String,PathMap>)entry).getValue(); | |
316 if (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null)) | |
317 return false; | |
318 } | |
319 } | |
320 } | |
321 | |
322 return true; | |
323 } | |
324 | |
325 /* ------------------------------------------------------------ */ | |
326 /** | |
327 * Dump the white- and black-list configurations when started | |
328 * | |
329 * @see org.eclipse.jetty.server.handler.HandlerWrapper#doStart() | |
330 */ | |
331 @Override | |
332 protected void doStart() | |
333 throws Exception | |
334 { | |
335 super.doStart(); | |
336 | |
337 if (LOG.isDebugEnabled()) | |
338 { | |
339 System.err.println(dump()); | |
340 } | |
341 } | |
342 | |
343 /* ------------------------------------------------------------ */ | |
344 /** | |
345 * Dump the handler configuration | |
346 */ | |
347 public String dump() | |
348 { | |
349 StringBuilder buf = new StringBuilder(); | |
350 | |
351 buf.append(toString()); | |
352 buf.append(" WHITELIST:\n"); | |
353 dump(buf, _white); | |
354 buf.append(toString()); | |
355 buf.append(" BLACKLIST:\n"); | |
356 dump(buf, _black); | |
357 | |
358 return buf.toString(); | |
359 } | |
360 | |
361 /* ------------------------------------------------------------ */ | |
362 /** | |
363 * Dump a pattern map into a StringBuilder buffer | |
364 * | |
365 * @param buf buffer | |
366 * @param patternMap pattern map to dump | |
367 */ | |
368 protected void dump(StringBuilder buf, IPAddressMap<PathMap> patternMap) | |
369 { | |
370 for (String addr: patternMap.keySet()) | |
371 { | |
372 for (Object path: ((PathMap)patternMap.get(addr)).values()) | |
373 { | |
374 buf.append("# "); | |
375 buf.append(addr); | |
376 buf.append("|"); | |
377 buf.append(path); | |
378 buf.append("\n"); | |
379 } | |
380 } | |
381 } | |
382 } |