103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.server.handler;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collections;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
2503928aee4356845252ac6b662d5c72c29903813eJake Slack
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponse;
2903928aee4356845252ac6b662d5c72c29903813eJake Slack
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpStatus;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.PathMap;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EndPoint;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractHttpConnection;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Request;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.IPAddressMap;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
3803928aee4356845252ac6b662d5c72c29903813eJake Slack
3903928aee4356845252ac6b662d5c72c29903813eJake Slack
4003928aee4356845252ac6b662d5c72c29903813eJake Slack/**
4103928aee4356845252ac6b662d5c72c29903813eJake Slack * IP Access Handler
4203928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
4303928aee4356845252ac6b662d5c72c29903813eJake Slack * Controls access to the wrapped handler by the real remote IP. Control is provided
4403928aee4356845252ac6b662d5c72c29903813eJake Slack * by white/black lists that include both internet addresses and URIs. This handler
4503928aee4356845252ac6b662d5c72c29903813eJake Slack * uses the real internet address of the connection, not one reported in the forwarded
4603928aee4356845252ac6b662d5c72c29903813eJake Slack * for headers, as this cannot be as easily forged.
4703928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
4803928aee4356845252ac6b662d5c72c29903813eJake Slack * Typically, the black/white lists will be used in one of three modes:
4903928aee4356845252ac6b662d5c72c29903813eJake Slack * <ul>
5003928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>Blocking a few specific IPs/URLs by specifying several black list entries.
5103928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>Allowing only some specific IPs/URLs by specifying several white lists entries.
5203928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>Allowing a general range of IPs/URLs by specifying several general white list
5303928aee4356845252ac6b662d5c72c29903813eJake Slack * entries, that are then further refined by several specific black list exceptions
5403928aee4356845252ac6b662d5c72c29903813eJake Slack * </ul>
5503928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
5603928aee4356845252ac6b662d5c72c29903813eJake Slack * An empty white list is treated as match all. If there is at least one entry in
5703928aee4356845252ac6b662d5c72c29903813eJake Slack * the white list, then a request must match a white list entry. Black list entries
5803928aee4356845252ac6b662d5c72c29903813eJake Slack * are always applied, so that even if an entry matches the white list, a black list
5903928aee4356845252ac6b662d5c72c29903813eJake Slack * entry will override it.
6003928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
6103928aee4356845252ac6b662d5c72c29903813eJake Slack * Internet addresses may be specified as absolute address or as a combination of
6203928aee4356845252ac6b662d5c72c29903813eJake Slack * four octet wildcard specifications (a.b.c.d) that are defined as follows.
6303928aee4356845252ac6b662d5c72c29903813eJake Slack * </p>
6403928aee4356845252ac6b662d5c72c29903813eJake Slack * <pre>
6503928aee4356845252ac6b662d5c72c29903813eJake Slack * nnn - an absolute value (0-255)
6603928aee4356845252ac6b662d5c72c29903813eJake Slack * mmm-nnn - an inclusive range of absolute values,
6703928aee4356845252ac6b662d5c72c29903813eJake Slack *           with following shorthand notations:
6803928aee4356845252ac6b662d5c72c29903813eJake Slack *           nnn- => nnn-255
6903928aee4356845252ac6b662d5c72c29903813eJake Slack *           -nnn => 0-nnn
7003928aee4356845252ac6b662d5c72c29903813eJake Slack *           -    => 0-255
7103928aee4356845252ac6b662d5c72c29903813eJake Slack * a,b,... - a list of wildcard specifications
7203928aee4356845252ac6b662d5c72c29903813eJake Slack * </pre>
7303928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
7403928aee4356845252ac6b662d5c72c29903813eJake Slack * Internet address specification is separated from the URI pattern using the "|" (pipe)
7503928aee4356845252ac6b662d5c72c29903813eJake Slack * character. URI patterns follow the servlet specification for simple * prefix and
7603928aee4356845252ac6b662d5c72c29903813eJake Slack * suffix wild cards (e.g. /, /foo, /foo/bar, /foo/bar/*, *.baz).
7703928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
7803928aee4356845252ac6b662d5c72c29903813eJake Slack * Earlier versions of the handler used internet address prefix wildcard specification
7903928aee4356845252ac6b662d5c72c29903813eJake Slack * to define a range of the internet addresses (e.g. 127., 10.10., 172.16.1.).
8003928aee4356845252ac6b662d5c72c29903813eJake Slack * They also used the first "/" character of the URI pattern to separate it from the
8103928aee4356845252ac6b662d5c72c29903813eJake Slack * internet address. Both of these features have been deprecated in the current version.
8203928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
8303928aee4356845252ac6b662d5c72c29903813eJake Slack * Examples of the entry specifications are:
8403928aee4356845252ac6b662d5c72c29903813eJake Slack * <ul>
8503928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.1.2 - all requests from IP 10.10.1.2
8603928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.1.2|/foo/bar - all requests from IP 10.10.1.2 to URI /foo/bar
8703928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.1.2|/foo/* - all requests from IP 10.10.1.2 to URIs starting with /foo/
8803928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.1.2|*.html - all requests from IP 10.10.1.2 to URIs ending with .html
8903928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.0-255.0-255 - all requests from IPs within 10.10.0.0/16 subnet
9003928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.0-.-255|/foo/bar - all requests from IPs within 10.10.0.0/16 subnet to URI /foo/bar
9103928aee4356845252ac6b662d5c72c29903813eJake Slack * <li>10.10.0-3,1,3,7,15|/foo/* - all requests from IPs addresses with last octet equal
9203928aee4356845252ac6b662d5c72c29903813eJake Slack *                                  to 1,3,7,15 in subnet 10.10.0.0/22 to URIs starting with /foo/
9303928aee4356845252ac6b662d5c72c29903813eJake Slack * </ul>
9403928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
9503928aee4356845252ac6b662d5c72c29903813eJake Slack * Earlier versions of the handler used internet address prefix wildcard specification
9603928aee4356845252ac6b662d5c72c29903813eJake Slack * to define a range of the internet addresses (e.g. 127., 10.10., 172.16.1.).
9703928aee4356845252ac6b662d5c72c29903813eJake Slack * They also used the first "/" character of the URI pattern to separate it from the
9803928aee4356845252ac6b662d5c72c29903813eJake Slack * internet address. Both of these features have been deprecated in the current version.
9903928aee4356845252ac6b662d5c72c29903813eJake Slack */
10003928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class IPAccessHandler extends HandlerWrapper
10103928aee4356845252ac6b662d5c72c29903813eJake Slack{
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(IPAccessHandler.class);
10303928aee4356845252ac6b662d5c72c29903813eJake Slack
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    IPAddressMap<PathMap> _white = new IPAddressMap<PathMap>();
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    IPAddressMap<PathMap> _black = new IPAddressMap<PathMap>();
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
10903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Creates new handler object
11003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    public IPAccessHandler()
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11303928aee4356845252ac6b662d5c72c29903813eJake Slack        super();
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11503928aee4356845252ac6b662d5c72c29903813eJake Slack
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
11803928aee4356845252ac6b662d5c72c29903813eJake Slack     * Creates new handler object and initializes white- and black-list
11903928aee4356845252ac6b662d5c72c29903813eJake Slack     *
12003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param white array of whitelist entries
12103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param black array of blacklist entries
12203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12303928aee4356845252ac6b662d5c72c29903813eJake Slack    public IPAccessHandler(String[] white, String []black)
12403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12503928aee4356845252ac6b662d5c72c29903813eJake Slack        super();
12603928aee4356845252ac6b662d5c72c29903813eJake Slack
12703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (white != null && white.length > 0)
12803928aee4356845252ac6b662d5c72c29903813eJake Slack            setWhite(white);
12903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (black != null && black.length > 0)
13003928aee4356845252ac6b662d5c72c29903813eJake Slack            setBlack(black);
13103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13203928aee4356845252ac6b662d5c72c29903813eJake Slack
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
13503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Add a whitelist entry to an existing handler configuration
13603928aee4356845252ac6b662d5c72c29903813eJake Slack     *
13703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param entry new whitelist entry
13803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
13903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addWhite(String entry)
14003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14103928aee4356845252ac6b662d5c72c29903813eJake Slack        add(entry, _white);
14203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14303928aee4356845252ac6b662d5c72c29903813eJake Slack
14403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
14603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Add a blacklist entry to an existing handler configuration
14703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
14803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param entry new blacklist entry
14903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
15003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addBlack(String entry)
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15203928aee4356845252ac6b662d5c72c29903813eJake Slack        add(entry, _black);
15303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15403928aee4356845252ac6b662d5c72c29903813eJake Slack
15503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
15703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Re-initialize the whitelist of existing handler object
15803928aee4356845252ac6b662d5c72c29903813eJake Slack     *
15903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param entries array of whitelist entries
16003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
16103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setWhite(String[] entries)
16203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack        set(entries, _white);
16403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16503928aee4356845252ac6b662d5c72c29903813eJake Slack
16603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
16803928aee4356845252ac6b662d5c72c29903813eJake Slack     * Re-initialize the blacklist of existing handler object
16903928aee4356845252ac6b662d5c72c29903813eJake Slack     *
17003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param entries array of blacklist entries
17103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setBlack(String[] entries)
17303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17403928aee4356845252ac6b662d5c72c29903813eJake Slack        set(entries, _black);
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17603928aee4356845252ac6b662d5c72c29903813eJake Slack
17703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
17903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Checks the incoming request against the whitelist and blacklist
18003928aee4356845252ac6b662d5c72c29903813eJake Slack     *
18103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
18203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
18403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
18503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18603928aee4356845252ac6b662d5c72c29903813eJake Slack        // Get the real remote IP (not the one set by the forwarded headers (which may be forged))
18703928aee4356845252ac6b662d5c72c29903813eJake Slack        AbstractHttpConnection connection = baseRequest.getConnection();
18803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (connection!=null)
18903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19003928aee4356845252ac6b662d5c72c29903813eJake Slack            EndPoint endp=connection.getEndPoint();
19103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (endp!=null)
19203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
19303928aee4356845252ac6b662d5c72c29903813eJake Slack                String addr = endp.getRemoteAddr();
19403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (addr!=null && !isAddrUriAllowed(addr,baseRequest.getPathInfo()))
19503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
19603928aee4356845252ac6b662d5c72c29903813eJake Slack                    response.sendError(HttpStatus.FORBIDDEN_403);
19703928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setHandled(true);
19803928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
19903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
20003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
20103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20203928aee4356845252ac6b662d5c72c29903813eJake Slack
20303928aee4356845252ac6b662d5c72c29903813eJake Slack        getHandler().handle(target,baseRequest, request, response);
20403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20503928aee4356845252ac6b662d5c72c29903813eJake Slack
20603928aee4356845252ac6b662d5c72c29903813eJake Slack
20703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
20903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Helper method to parse the new entry and add it to
21003928aee4356845252ac6b662d5c72c29903813eJake Slack     * the specified address pattern map.
21103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
21203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param entry new entry
21303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param patternMap target address pattern map
21403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
21503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void add(String entry, IPAddressMap<PathMap> patternMap)
21603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (entry != null && entry.length() > 0)
21803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21903928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean deprecated = false;
22003928aee4356845252ac6b662d5c72c29903813eJake Slack            int idx;
22103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (entry.indexOf('|') > 0 )
22203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
22303928aee4356845252ac6b662d5c72c29903813eJake Slack                idx = entry.indexOf('|');
22403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22503928aee4356845252ac6b662d5c72c29903813eJake Slack            else
22603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
22703928aee4356845252ac6b662d5c72c29903813eJake Slack                idx = entry.indexOf('/');
22803928aee4356845252ac6b662d5c72c29903813eJake Slack                deprecated = (idx >= 0);
22903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
23003928aee4356845252ac6b662d5c72c29903813eJake Slack
23103928aee4356845252ac6b662d5c72c29903813eJake Slack            String addr = idx > 0 ? entry.substring(0,idx) : entry;
23203928aee4356845252ac6b662d5c72c29903813eJake Slack            String path = idx > 0 ? entry.substring(idx) : "/*";
23303928aee4356845252ac6b662d5c72c29903813eJake Slack
23403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (addr.endsWith("."))
23503928aee4356845252ac6b662d5c72c29903813eJake Slack                deprecated = true;
23603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (path!=null && (path.startsWith("|") || path.startsWith("/*.")))
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                path=path.substring(1);
23803928aee4356845252ac6b662d5c72c29903813eJake Slack
23903928aee4356845252ac6b662d5c72c29903813eJake Slack            PathMap pathMap = patternMap.get(addr);
24003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (pathMap == null)
24103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                pathMap = new PathMap(true);
24303928aee4356845252ac6b662d5c72c29903813eJake Slack                patternMap.put(addr,pathMap);
24403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
24503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (path != null && !"".equals(path))
24603928aee4356845252ac6b662d5c72c29903813eJake Slack                pathMap.put(path,path);
24703928aee4356845252ac6b662d5c72c29903813eJake Slack
24803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (deprecated)
24903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(toString() +" - deprecated specification syntax: "+entry);
25003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
25103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
25203928aee4356845252ac6b662d5c72c29903813eJake Slack
25303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
25403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
25503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Helper method to process a list of new entries and replace
25603928aee4356845252ac6b662d5c72c29903813eJake Slack     * the content of the specified address pattern map
25703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
25803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param entries new entries
25903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param patternMap target address pattern map
26003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
26103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void set(String[] entries,  IPAddressMap<PathMap> patternMap)
26203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
26303928aee4356845252ac6b662d5c72c29903813eJake Slack        patternMap.clear();
26403928aee4356845252ac6b662d5c72c29903813eJake Slack
26503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (entries != null && entries.length > 0)
26603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
26703928aee4356845252ac6b662d5c72c29903813eJake Slack            for (String addrPath:entries)
26803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
26903928aee4356845252ac6b662d5c72c29903813eJake Slack                add(addrPath, patternMap);
27003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
27103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
27203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27303928aee4356845252ac6b662d5c72c29903813eJake Slack
27403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
27603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Check if specified request is allowed by current IPAccess rules.
27703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
27803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param addr internet address
27903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param path context path
28003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return true if request is allowed
28103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
28203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean isAddrUriAllowed(String addr, String path)
28403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
28503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_white.size()>0)
28603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28703928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean match = false;
28803928aee4356845252ac6b662d5c72c29903813eJake Slack
28903928aee4356845252ac6b662d5c72c29903813eJake Slack            Object whiteObj = _white.getLazyMatches(addr);
29003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (whiteObj != null)
29103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
29203928aee4356845252ac6b662d5c72c29903813eJake Slack                List whiteList = (whiteObj instanceof List) ? (List)whiteObj : Collections.singletonList(whiteObj);
29303928aee4356845252ac6b662d5c72c29903813eJake Slack
29403928aee4356845252ac6b662d5c72c29903813eJake Slack                for (Object entry: whiteList)
29503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
29603928aee4356845252ac6b662d5c72c29903813eJake Slack                    PathMap pathMap = ((Map.Entry<String,PathMap>)entry).getValue();
29703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (match = (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null)))
29803928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
29903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
30003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
30103928aee4356845252ac6b662d5c72c29903813eJake Slack
30203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!match)
30303928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
30403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
30503928aee4356845252ac6b662d5c72c29903813eJake Slack
30603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_black.size() > 0)
30703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
30803928aee4356845252ac6b662d5c72c29903813eJake Slack            Object blackObj = _black.getLazyMatches(addr);
30903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (blackObj != null)
31003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31103928aee4356845252ac6b662d5c72c29903813eJake Slack                List blackList = (blackObj instanceof List) ? (List)blackObj : Collections.singletonList(blackObj);
31203928aee4356845252ac6b662d5c72c29903813eJake Slack
31303928aee4356845252ac6b662d5c72c29903813eJake Slack                for (Object entry: blackList)
31403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
31503928aee4356845252ac6b662d5c72c29903813eJake Slack                    PathMap pathMap = ((Map.Entry<String,PathMap>)entry).getValue();
31603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null))
31703928aee4356845252ac6b662d5c72c29903813eJake Slack                        return false;
31803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
31903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
32003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
32103928aee4356845252ac6b662d5c72c29903813eJake Slack
32203928aee4356845252ac6b662d5c72c29903813eJake Slack        return true;
32303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32403928aee4356845252ac6b662d5c72c29903813eJake Slack
32503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
32703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Dump the white- and black-list configurations when started
32803928aee4356845252ac6b662d5c72c29903813eJake Slack     *
32903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.handler.HandlerWrapper#doStart()
33003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
33103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
33203928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStart()
33303928aee4356845252ac6b662d5c72c29903813eJake Slack        throws Exception
33403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
33503928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
33603928aee4356845252ac6b662d5c72c29903813eJake Slack
33703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (LOG.isDebugEnabled())
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
33903928aee4356845252ac6b662d5c72c29903813eJake Slack            System.err.println(dump());
34003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34203928aee4356845252ac6b662d5c72c29903813eJake Slack
34303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
34403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
34503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Dump the handler configuration
34603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
34703928aee4356845252ac6b662d5c72c29903813eJake Slack    public String dump()
34803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
34903928aee4356845252ac6b662d5c72c29903813eJake Slack        StringBuilder buf = new StringBuilder();
35003928aee4356845252ac6b662d5c72c29903813eJake Slack
35103928aee4356845252ac6b662d5c72c29903813eJake Slack        buf.append(toString());
35203928aee4356845252ac6b662d5c72c29903813eJake Slack        buf.append(" WHITELIST:\n");
35303928aee4356845252ac6b662d5c72c29903813eJake Slack        dump(buf, _white);
35403928aee4356845252ac6b662d5c72c29903813eJake Slack        buf.append(toString());
35503928aee4356845252ac6b662d5c72c29903813eJake Slack        buf.append(" BLACKLIST:\n");
35603928aee4356845252ac6b662d5c72c29903813eJake Slack        dump(buf, _black);
35703928aee4356845252ac6b662d5c72c29903813eJake Slack
35803928aee4356845252ac6b662d5c72c29903813eJake Slack        return buf.toString();
35903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36003928aee4356845252ac6b662d5c72c29903813eJake Slack
36103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
36303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Dump a pattern map into a StringBuilder buffer
36403928aee4356845252ac6b662d5c72c29903813eJake Slack     *
36503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param buf buffer
36603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param patternMap pattern map to dump
36703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
36803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void dump(StringBuilder buf, IPAddressMap<PathMap> patternMap)
36903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37003928aee4356845252ac6b662d5c72c29903813eJake Slack        for (String addr: patternMap.keySet())
37103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
37203928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Object path: ((PathMap)patternMap.get(addr)).values())
37303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
37403928aee4356845252ac6b662d5c72c29903813eJake Slack                buf.append("# ");
37503928aee4356845252ac6b662d5c72c29903813eJake Slack                buf.append(addr);
37603928aee4356845252ac6b662d5c72c29903813eJake Slack                buf.append("|");
37703928aee4356845252ac6b662d5c72c29903813eJake Slack                buf.append(path);
37803928aee4356845252ac6b662d5c72c29903813eJake Slack                buf.append("\n");
37903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
38003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
38103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
38203928aee4356845252ac6b662d5c72c29903813eJake Slack }
383