From 60d58a3fd464cbfc101bfe7a02f00f52d3c44fd9 Mon Sep 17 00:00:00 2001 From: Francis Galiegue Date: Tue, 4 Oct 2011 19:58:09 +0200 Subject: [PATCH 2/3] Netmask filtering: netmask Filter --- .../catalina/filters/RemoteNetmaskFilter.java | 97 +++++++ .../catalina/filters/RequestNetmaskFilter.java | 269 ++++++++++++++++++++ 2 files changed, 366 insertions(+), 0 deletions(-) create mode 100644 java/org/apache/catalina/filters/RemoteNetmaskFilter.java create mode 100644 java/org/apache/catalina/filters/RequestNetmaskFilter.java diff --git a/java/org/apache/catalina/filters/RemoteNetmaskFilter.java b/java/org/apache/catalina/filters/RemoteNetmaskFilter.java new file mode 100644 index 0000000..b6e40a4 --- /dev/null +++ b/java/org/apache/catalina/filters/RemoteNetmaskFilter.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.catalina.filters; + + +import org.apache.catalina.comet.CometEvent; +import org.apache.catalina.comet.CometFilterChain; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.IOException; + + +/** + * Concrete implementation of RequestNetmaskFilter that filters + * based on the string representation of the remote client's IP address. + * + */ + +public final class RemoteNetmaskFilter + extends RequestFilter { + + // ----------------------------------------------------- Instance Variables + private static final Log log = LogFactory.getLog(RemoteNetmaskFilter.class); + + + // ------------------------------------------------------------- Properties + + + + // --------------------------------------------------------- Public Methods + + + /** + * Extract the desired request property, and pass it (along with the + * specified request and response objects and associated filter chain) to + * the protected process() method to perform the actual + * filtering. + * + * @param request The servlet request to be processed + * @param response The servlet response to be created + * @param chain The filter chain for this request + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + process(request.getRemoteAddr(), request, response, chain); + + } + + /** + * Extract the desired request property, and pass it (along with the comet + * event and filter chain) to the protected process() method + * to perform the actual filtering. + * + * @param event The comet event to be processed + * @param chain The filter chain for this event + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + @Override + public void doFilterEvent(CometEvent event, CometFilterChain chain) + throws IOException, ServletException { + processCometEvent(event.getHttpServletRequest().getRemoteHost(), + event, chain); + } + + @Override + protected Log getLogger() { + return log; + } +} diff --git a/java/org/apache/catalina/filters/RequestNetmaskFilter.java b/java/org/apache/catalina/filters/RequestNetmaskFilter.java new file mode 100644 index 0000000..25088dd --- /dev/null +++ b/java/org/apache/catalina/filters/RequestNetmaskFilter.java @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.catalina.filters; + + +import org.apache.catalina.comet.CometEvent; +import org.apache.catalina.comet.CometFilter; +import org.apache.catalina.comet.CometFilterChain; +import org.apache.catalina.util.NetMask; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of a Filter that performs filtering based on comparing the + * appropriate request property (selected based on which subclass you choose + * to configure into your Container's pipeline) against the regular expressions + * configured for this Filter. + *

+ * This filter is configured by setting the allow and/or + * deny properties to a regular expressions (in the syntax + * supported by {@link java.util.regex.Pattern}) to which the appropriate request property will + * be compared. Evaluation proceeds as follows: + *

+ */ + +public abstract class RequestNetmaskFilter + extends FilterBase implements CometFilter { + + + // ----------------------------------------------------- Instance Variables + + /** + * The regular expression used to test for allowed requests. + */ + protected final List allow = new ArrayList(); + + /** + * The regular expression used to test for denied requests. + */ + protected final List deny = new ArrayList(); + + /** + * mime type -- "text/plain" + */ + private static final String PLAIN_TEXT_MIME_TYPE = "text/plain"; + + + // ------------------------------------------------------------- Properties + + + /** + * Return a string representation of the NetMask list in allow. + */ + public String getAllow() { + return allow.toString(); + } + + + /** + * Fill the allow list with the list of netmasks provided as an argument, + * if any. + * + * @param input The list of netmasks, as a comma separated string + */ + public void setAllow(final String input) { + if (input == null || input.length() == 0) + return; + + NetMask nm; + + for (final String s: input.split("\\s*,\\s*")) + try { + nm = new NetMask(s); + allow.add(nm); + } catch (IllegalArgumentException e) { + // FIXME: log + } + } + + + /** + * Return a string representation of the NetMask list in deny. + */ + public String getDeny() { + if (deny == null) { + return null; + } + return deny.toString(); + } + + + /** + * Fill the deny list with the list of netmasks provided as an argument, + * if any. + * + * @param input The list of netmasks, as a comma separated string + */ + public void setDeny(String input) { + if (input == null || input.length() == 0) + return; + + NetMask nm; + + for (final String s: input.split("\\s*,\\s*")) + try { + nm = new NetMask(s); + deny.add(nm); + } catch (IllegalArgumentException e) { + // FIXME: log + } + } + + + // --------------------------------------------------------- Public Methods + + + /** + * Extract the desired request property, and pass it (along with the + * specified request and response objects) to the protected + * process() method to perform the actual filtering. + * This method must be implemented by a concrete subclass. + * + * @param request The servlet request to be processed + * @param response The servlet response to be created + * @param chain The filter chain + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + @Override + public abstract void doFilter(ServletRequest request, + ServletResponse response, FilterChain chain) throws IOException, + ServletException; + + + // ------------------------------------------------------ Protected Methods + + + /** + * Perform the filtering that has been configured for this Filter, matching + * against the specified request property. + * + * @param property The request property on which to filter + * @param request The servlet request to be processed + * @param response The servlet response to be processed + * @param chain The filter chain + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + protected void process(String property, ServletRequest request, + ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + if (isAllowed(property)) { + chain.doFilter(request, response); + return; + } + + if (!(response instanceof HttpServletResponse)) { + sendErrorWhenNotHttp(response); + return; + } + + ((HttpServletResponse) response) + .sendError(HttpServletResponse.SC_FORBIDDEN); + } + + /** + * Perform the filtering that has been configured for this Filter, matching + * against the specified request property. + * + * @param property The property to check against the allow/deny rules + * @param event The comet event to be filtered + * @param chain The comet filter chain + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + protected void processCometEvent(String property, CometEvent event, + CometFilterChain chain) throws IOException, ServletException { + HttpServletResponse response = event.getHttpServletResponse(); + + if (isAllowed(property)) { + chain.doFilterEvent(event); + return; + } + + response.sendError(HttpServletResponse.SC_FORBIDDEN); + event.close(); + } + + /** + * Process the allow and deny rules for the provided property. + * + * @param property The property to test against the allow and deny lists + * @return true if this request should be allowed, + * false otherwise + */ + private boolean isAllowed(String property) { + final InetAddress addr; + + try { + addr = InetAddress.getByName(property); + } catch (UnknownHostException e) { + //Eh? + return false; + } + + for (final NetMask nm: deny) + if (nm.matches(addr)) + return false; + + for (final NetMask nm: allow) + if (nm.matches(addr)) + return true; + + // Allow if denies specified but not allows + if (!deny.isEmpty() && allow.isEmpty()) + return true; + + // Deny this request + return false; + } + + private void sendErrorWhenNotHttp(ServletResponse response) + throws IOException { + response.setContentType(PLAIN_TEXT_MIME_TYPE); + response.getWriter().write(sm.getString("http.403")); + response.getWriter().flush(); + } +} -- 1.7.6