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 } |
