/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.web.tomcat.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jboss.logging.Logger;
/**
* Accept or deny a request based on the IP address of the client who made the
* request. JDK 1.4 or higher is required.
* <p/>
* This filter is configured by setting the "allow" and/or "deny" properties to
* a comma-delimited list of regular expressions (in the syntax supported by the
* java.util.regex package) to which the client IP address will be compared.
* <p/>
* <filter>
* <filter-name>RemoteHostFilter</filter-name>
* <filter-class>org.jboss.remotehostfilter.RemoteHostFilter</filter-class>
* <init-param>
* <param-name>deny</param-name>
* <param-value>128.0.*,192.4.5.7</param-value>
* </init-param>
* <init-param>
* <param-name>allow</param-name>
* <param-value>192.4.5.6,127.0.0.*</param-value>
* </init-param>
* </filter>
* <p/>
* Evaluation proceeds as follows:
* <p/>
* If there are any deny expressions configured, the IP will be compared to each
* expression. If a match is found, this request will be rejected with a
* "Forbidden" HTTP response.
* If there are any allow expressions configured, the IP will be compared to
* each such expression. If a match is NOT found, this request will be rejected
* with a "Forbidden" HTTP response.
* Otherwise, the request will be rejected with a "Forbidden" HTTP response.
*
* @author Stan Silvert
* @version $Revision: 81037 $
*/
public class RemoteHostFilter implements Filter
{
private static final Logger log = Logger.getLogger(RemoteHostFilter.class);
/** The list of hosts explicitly allowed */
private String[] allow;
/** The list of hosts explicitly denied */
private String[] deny;
/** The trace level log falg */
private boolean trace;
private FilterConfig filterConfig = null;
public RemoteHostFilter()
{
trace = log.isTraceEnabled();
}
/**
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @param chain The filter chain we are processing
* @throws IOException if an input/output error occurs
* @throws ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
String clientAddr = request.getRemoteAddr();
if( trace )
log.trace("Client addres is: " + clientAddr);
if (hasMatch(clientAddr, deny))
{
handleInvalidAccess(request, response, clientAddr);
return;
}
if ((allow.length > 0) && !hasMatch(clientAddr, allow))
{
handleInvalidAccess(request, response, clientAddr);
return;
}
chain.doFilter(request, response);
}
private void handleInvalidAccess(ServletRequest request,
ServletResponse response,
String clientAddr) throws IOException
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String url = httpRequest.getRequestURL().toString();
if( trace )
log.trace("Invalid access attempt to " + url + " from " + clientAddr);
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
}
private boolean hasMatch(String clientAddr, String[] regExps)
{
for (int i = 0; i < regExps.length; i++)
{
if (clientAddr.matches(regExps[i]))
return true;
}
return false;
}
/**
* Destroy method for this filter
*/
public void destroy()
{
this.filterConfig = null;
this.allow = null;
this.deny = null;
}
/**
* Init method for this filter
*/
public void init(FilterConfig filterConfig)
{
this.filterConfig = filterConfig;
this.allow = extractRegExps(filterConfig.getInitParameter("allow"));
this.deny = extractRegExps(filterConfig.getInitParameter("deny"));
}
private String[] extractRegExps(String initParam)
{
if (initParam == null)
{
return new String[0];
}
else
{
return initParam.split(",");
}
}
/**
* Return a String representation of this object.
*/
public String toString()
{
if (filterConfig == null) return ("ClientAddrFilter()");
StringBuffer sb = new StringBuffer("ClientAddrFilter(");
sb.append(filterConfig);
sb.append(")");
return sb.toString();
}
}