@@ -, +, @@ --- .../apache/catalina/valves/RemoteNetmaskValve.java | 86 ++++++++ .../catalina/valves/RequestNetmaskValve.java | 220 ++++++++++++++++++++ 2 files changed, 306 insertions(+), 0 deletions(-) create mode 100644 java/org/apache/catalina/valves/RemoteNetmaskValve.java create mode 100644 java/org/apache/catalina/valves/RequestNetmaskValve.java --- a/java/org/apache/catalina/valves/RemoteNetmaskValve.java +++ a/java/org/apache/catalina/valves/RemoteNetmaskValve.java @@ -0,0 +1,86 @@ +/* + * 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.valves; + + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import javax.servlet.ServletException; +import java.io.IOException; + + +/** + * Concrete implementation of RequestFilterValve that filters + * based on the string representation of the remote client's IP address. + * + * @author Craig R. McClanahan + * @version $Id$ + */ + +public final class RemoteNetmaskValve + extends RequestNetmaskValve +{ + + + // ----------------------------------------------------- Instance Variables + + + /** + * The descriptive information related to this implementation. + */ + private static final String info = + "org.apache.catalina.valves.RemoteNetmaskValve/1.0"; + + + // ------------------------------------------------------------- Properties + + + /** + * Return descriptive information about this Valve implementation. + */ + @Override + public String getInfo() { + return (info); + } + + + // --------------------------------------------------------- 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 + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + @Override + public void invoke(Request request, Response response) + throws IOException, ServletException { + process(request.getRequest().getRemoteAddr(), request, response); + } + + +} --- a/java/org/apache/catalina/valves/RequestNetmaskValve.java +++ a/java/org/apache/catalina/valves/RequestNetmaskValve.java @@ -0,0 +1,220 @@ +/* + * 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.valves; + + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.util.NetMask; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Implementation of a Valve that performs IP filtering of a remote host + * based on the remote's IP address. This valve replicates (some of) Apache's + * "Order", "Allow from" and "Deny" directives with a few limitations: + * + *

Note that IPv6 is supported. Also note that invalid netmasks will be + * ignored.

+ *

+ * This Valve may be attached to any Container, depending on the granularity + * of the filtering you wish to perform.

+ * + * @author Francis Galiegue + */ + +public abstract class RequestNetmaskValve + extends ValveBase { + + //------------------------------------------------------ Constructor + public RequestNetmaskValve() { + super(true); + } + + // ----------------------------------------------------- Class Variables + + + /** + * The descriptive information related to this implementation. + */ + private static final String info = + "org.apache.catalina.valves.RequestNetmaskValve/1.0"; + + // ----------------------------------------------------- Instance Variables + + /** + * List of allowed netmasks, if any + */ + + protected final List allow = new ArrayList(); + + /** + * List of denied netmasks, if any + */ + + protected final List deny = new ArrayList(); + + // ------------------------------------------------------------- Properties + + + /** + * Return the allowed netmask list as a string. + */ + public String getAllow() { + return allow.toString(); + } + + + /** + * Fills the allowed Netmask list. + * + * @param input The input expression + */ + 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); + this.allow.add(nm); + } catch (IllegalArgumentException e) { + // FIXME: log + } + } + + + /** + * Return the denied netmask list as a string. + */ + public String getDeny() { + return deny.toString(); + } + + + /** + * Set the regular expression used to test for denied requests for this + * Valve, if any. + * + * @param input The new input expression + */ + public void setDeny(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); + this.deny.add(nm); + } catch (IllegalArgumentException e) { + // FIXME: log + } + } + + + /** + * Return descriptive information about this Valve implementation. + */ + @Override + public String getInfo() { + return (info); + } + + + // --------------------------------------------------------- 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 + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + @Override + public abstract void invoke(Request request, Response response) + throws IOException, ServletException; + + + // ------------------------------------------------------ Protected Methods + + + /** + * Perform the filtering that has been configured for this Valve, 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 + * + * @exception java.io.IOException if an input/output error occurs + * @exception javax.servlet.ServletException if a servlet error occurs + */ + protected void process(String property, Request request, Response response) + throws IOException, ServletException { + + final InetAddress addr = InetAddress.getByName(property); + + for (final NetMask nm: deny) + if (nm.matches(addr)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + if (allow.isEmpty()) { + getNext().invoke(request, response); + return; + } + + for (final NetMask nm: allow) + if (nm.matches(addr)) { + getNext().invoke(request, response); + return; + } + + response.sendError(HttpServletResponse.SC_FORBIDDEN); + } +} --