Line 0
Link Here
|
0 |
- |
1 |
/* |
|
|
2 |
* Licensed to the Apache Software Foundation (ASF) under one or more |
3 |
* contributor license agreements. See the NOTICE file distributed with |
4 |
* this work for additional information regarding copyright ownership. |
5 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
6 |
* (the "License"); you may not use this file except in compliance with |
7 |
* the License. You may obtain a copy of the License at |
8 |
* |
9 |
* http://www.apache.org/licenses/LICENSE-2.0 |
10 |
* |
11 |
* Unless required by applicable law or agreed to in writing, software |
12 |
* distributed under the License is distributed on an "AS IS" BASIS, |
13 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 |
* See the License for the specific language governing permissions and |
15 |
* limitations under the License. |
16 |
*/ |
17 |
|
18 |
|
19 |
package org.apache.catalina.valves; |
20 |
|
21 |
|
22 |
import org.apache.catalina.connector.Request; |
23 |
import org.apache.catalina.connector.Response; |
24 |
import org.apache.catalina.util.NetMask; |
25 |
|
26 |
import javax.servlet.ServletException; |
27 |
import javax.servlet.http.HttpServletResponse; |
28 |
import java.io.IOException; |
29 |
import java.math.BigInteger; |
30 |
import java.net.InetAddress; |
31 |
import java.net.UnknownHostException; |
32 |
import java.util.ArrayList; |
33 |
import java.util.Arrays; |
34 |
import java.util.Collections; |
35 |
import java.util.List; |
36 |
|
37 |
/** |
38 |
* Implementation of a Valve that performs IP filtering of a remote host |
39 |
* based on the remote's IP address. This valve replicates (some of) Apache's |
40 |
* "Order", "Allow from" and "Deny" directives with a few limitations: |
41 |
* <ul> |
42 |
* <li>"Order" will always be "deny, allow";</li> |
43 |
* <li>the netmasks in the "allow" and "deny" properties must be fully |
44 |
* qualified CIDR netmasks, and the CIDR <b>must</b> be an integer |
45 |
* (expressions like "10.", "13.0.0.0/255.255.192.0" or ".foo.bar" will |
46 |
* not work);</li> |
47 |
* <li>as a side effect of using @{link java.net.InetAddress}, |
48 |
* expressions like "my.host.com/27" <b>will</b> work, |
49 |
* however their use is discouraged.</li> |
50 |
* </ul> |
51 |
* <p>Note that IPv6 is supported. Also note that invalid netmasks will be |
52 |
* ignored.</p> |
53 |
* <p> |
54 |
* This Valve may be attached to any Container, depending on the granularity |
55 |
* of the filtering you wish to perform.</p> |
56 |
* |
57 |
* @author Francis Galiegue |
58 |
*/ |
59 |
|
60 |
public abstract class RequestNetmaskValve |
61 |
extends ValveBase { |
62 |
|
63 |
//------------------------------------------------------ Constructor |
64 |
public RequestNetmaskValve() { |
65 |
super(true); |
66 |
} |
67 |
|
68 |
// ----------------------------------------------------- Class Variables |
69 |
|
70 |
|
71 |
/** |
72 |
* The descriptive information related to this implementation. |
73 |
*/ |
74 |
private static final String info = |
75 |
"org.apache.catalina.valves.RequestNetmaskValve/1.0"; |
76 |
|
77 |
// ----------------------------------------------------- Instance Variables |
78 |
|
79 |
/** |
80 |
* List of allowed netmasks, if any |
81 |
*/ |
82 |
|
83 |
protected final List<NetMask> allow = new ArrayList<NetMask>(); |
84 |
|
85 |
/** |
86 |
* List of denied netmasks, if any |
87 |
*/ |
88 |
|
89 |
protected final List<NetMask> deny = new ArrayList<NetMask>(); |
90 |
|
91 |
// ------------------------------------------------------------- Properties |
92 |
|
93 |
|
94 |
/** |
95 |
* Return the allowed netmask list as a string. |
96 |
*/ |
97 |
public String getAllow() { |
98 |
return allow.toString(); |
99 |
} |
100 |
|
101 |
|
102 |
/** |
103 |
* Fills the allowed Netmask list. |
104 |
* |
105 |
* @param input The input expression |
106 |
*/ |
107 |
public void setAllow(final String input) { |
108 |
if (input == null || input.length() == 0) |
109 |
return; |
110 |
|
111 |
NetMask nm; |
112 |
|
113 |
for (final String s: input.split("\\s*,\\s*")) |
114 |
try { |
115 |
nm = new NetMask(s); |
116 |
this.allow.add(nm); |
117 |
} catch (IllegalArgumentException e) { |
118 |
// FIXME: log |
119 |
} |
120 |
} |
121 |
|
122 |
|
123 |
/** |
124 |
* Return the denied netmask list as a string. |
125 |
*/ |
126 |
public String getDeny() { |
127 |
return deny.toString(); |
128 |
} |
129 |
|
130 |
|
131 |
/** |
132 |
* Set the regular expression used to test for denied requests for this |
133 |
* Valve, if any. |
134 |
* |
135 |
* @param input The new input expression |
136 |
*/ |
137 |
public void setDeny(final String input) { |
138 |
if (input == null || input.length() == 0) |
139 |
return; |
140 |
|
141 |
NetMask nm; |
142 |
|
143 |
for (final String s: input.split("\\s*,\\s*")) |
144 |
try { |
145 |
nm = new NetMask(s); |
146 |
this.deny.add(nm); |
147 |
} catch (IllegalArgumentException e) { |
148 |
// FIXME: log |
149 |
} |
150 |
} |
151 |
|
152 |
|
153 |
/** |
154 |
* Return descriptive information about this Valve implementation. |
155 |
*/ |
156 |
@Override |
157 |
public String getInfo() { |
158 |
return (info); |
159 |
} |
160 |
|
161 |
|
162 |
// --------------------------------------------------------- Public Methods |
163 |
|
164 |
|
165 |
/** |
166 |
* Extract the desired request property, and pass it (along with the |
167 |
* specified request and response objects) to the protected |
168 |
* <code>process()</code> method to perform the actual filtering. |
169 |
* This method must be implemented by a concrete subclass. |
170 |
* |
171 |
* @param request The servlet request to be processed |
172 |
* @param response The servlet response to be created |
173 |
* |
174 |
* @exception java.io.IOException if an input/output error occurs |
175 |
* @exception javax.servlet.ServletException if a servlet error occurs |
176 |
*/ |
177 |
@Override |
178 |
public abstract void invoke(Request request, Response response) |
179 |
throws IOException, ServletException; |
180 |
|
181 |
|
182 |
// ------------------------------------------------------ Protected Methods |
183 |
|
184 |
|
185 |
/** |
186 |
* Perform the filtering that has been configured for this Valve, matching |
187 |
* against the specified request property. |
188 |
* |
189 |
* @param property The request property on which to filter |
190 |
* @param request The servlet request to be processed |
191 |
* @param response The servlet response to be processed |
192 |
* |
193 |
* @exception java.io.IOException if an input/output error occurs |
194 |
* @exception javax.servlet.ServletException if a servlet error occurs |
195 |
*/ |
196 |
protected void process(String property, Request request, Response response) |
197 |
throws IOException, ServletException { |
198 |
|
199 |
final InetAddress addr = InetAddress.getByName(property); |
200 |
|
201 |
for (final NetMask nm: deny) |
202 |
if (nm.matches(addr)) { |
203 |
response.sendError(HttpServletResponse.SC_FORBIDDEN); |
204 |
return; |
205 |
} |
206 |
|
207 |
if (allow.isEmpty()) { |
208 |
getNext().invoke(request, response); |
209 |
return; |
210 |
} |
211 |
|
212 |
for (final NetMask nm: allow) |
213 |
if (nm.matches(addr)) { |
214 |
getNext().invoke(request, response); |
215 |
return; |
216 |
} |
217 |
|
218 |
response.sendError(HttpServletResponse.SC_FORBIDDEN); |
219 |
} |
220 |
} |