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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.catalina.valves;
20
import java.io.IOException;
21
import java.util.ArrayList;
22
import java.util.Arrays;
23
import java.util.List;
25
import javax.servlet.ServletException;
27
import junit.framework.TestCase;
29
import org.apache.catalina.connector.Request;
30
import org.apache.catalina.connector.Response;
31
import org.apache.catalina.valves.ValveBase;
34
* {@link RemoteIpValve} Tests
36
public class RemoteIpValveTest extends TestCase {
38
static class RemoteAddrAndHostTrackerValve extends ValveBase {
39
private String remoteAddr;
40
private String remoteHost;
42
public String getRemoteAddr() {
46
public String getRemoteHost() {
51
public void invoke(Request request, Response response) throws IOException, ServletException {
52
this.remoteHost = request.getRemoteHost();
53
this.remoteAddr = request.getRemoteAddr();
57
public void testCommaDelimitedListToStringArray() {
58
List<String> elements = Arrays.asList("element1", "element2", "element3");
59
String actual = RemoteIpValve.listToCommaDelimitedString(elements);
60
assertEquals("element1, element2, element3", actual);
63
public void testCommaDelimitedListToStringArrayEmptyList() {
64
List<String> elements = new ArrayList<String>();
65
String actual = RemoteIpValve.listToCommaDelimitedString(elements);
66
assertEquals("", actual);
69
public void testCommaDelimitedListToStringArrayNullList() {
70
String actual = RemoteIpValve.listToCommaDelimitedString(null);
71
assertEquals("", actual);
74
public void testInvokeAllowedRemoteAddrWithNullRemoteIpHeader() throws Exception {
76
RemoteIpValve remoteIpValve = new RemoteIpValve();
77
remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11");
78
remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3");
79
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
80
remoteIpValve.setProxiesHeader("x-forwarded-by");
81
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
82
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
84
Request request = new Request();
85
request.setCoyoteRequest(new org.apache.coyote.Request());
86
request.setRemoteAddr("192.168.0.10");
87
request.setRemoteHost("remote-host-original-value");
90
remoteIpValve.invoke(request, null);
93
String actualXForwardedFor = request.getHeader("x-forwarded-for");
94
assertNull("x-forwarded-for must be null", actualXForwardedFor);
96
String actualXForwardedBy = request.getHeader("x-forwarded-by");
97
assertNull("x-forwarded-by must be null", actualXForwardedBy);
99
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
100
assertEquals("remoteAddr", "192.168.0.10", actualRemoteAddr);
102
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
103
assertEquals("remoteHost", "remote-host-original-value", actualRemoteHost);
105
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
106
assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr);
108
String actualPostInvokeRemoteHost = request.getRemoteHost();
109
assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost);
113
public void testInvokeAllProxiesAreTrusted() throws Exception {
116
RemoteIpValve remoteIpValve = new RemoteIpValve();
117
remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11");
118
remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3");
119
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
120
remoteIpValve.setProxiesHeader("x-forwarded-by");
121
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
122
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
124
Request request = new Request();
125
request.setCoyoteRequest(new org.apache.coyote.Request());
126
request.setRemoteAddr("192.168.0.10");
127
request.setRemoteHost("remote-host-original-value");
128
request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, proxy1, proxy2");
131
remoteIpValve.invoke(request, null);
134
String actualXForwardedFor = request.getHeader("x-forwarded-for");
135
assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor);
137
String actualXForwardedBy = request.getHeader("x-forwarded-by");
138
assertEquals("all proxies are trusted, they must appear in x-forwarded-by", "proxy1, proxy2", actualXForwardedBy);
140
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
141
assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr);
143
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
144
assertEquals("remoteHost", "140.211.11.130", actualRemoteHost);
146
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
147
assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr);
149
String actualPostInvokeRemoteHost = request.getRemoteHost();
150
assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost);
153
public void testInvokeAllProxiesAreTrustedOrInternal() throws Exception {
156
RemoteIpValve remoteIpValve = new RemoteIpValve();
157
remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11");
158
remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3");
159
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
160
remoteIpValve.setProxiesHeader("x-forwarded-by");
161
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
162
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
164
Request request = new Request();
165
request.setCoyoteRequest(new org.apache.coyote.Request());
166
request.setRemoteAddr("192.168.0.10");
167
request.setRemoteHost("remote-host-original-value");
168
request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for")
169
.setString("140.211.11.130, proxy1, proxy2, 192.168.0.10, 192.168.0.11");
172
remoteIpValve.invoke(request, null);
175
String actualXForwardedFor = request.getHeader("x-forwarded-for");
176
assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor);
178
String actualXForwardedBy = request.getHeader("x-forwarded-by");
179
assertEquals("all proxies are trusted, they must appear in x-forwarded-by", "proxy1, proxy2", actualXForwardedBy);
181
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
182
assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr);
184
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
185
assertEquals("remoteHost", "140.211.11.130", actualRemoteHost);
187
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
188
assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr);
190
String actualPostInvokeRemoteHost = request.getRemoteHost();
191
assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost);
194
public void testInvokeAllProxiesAreInternal() throws Exception {
197
RemoteIpValve remoteIpValve = new RemoteIpValve();
198
remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11");
199
remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3");
200
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
201
remoteIpValve.setProxiesHeader("x-forwarded-by");
202
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
203
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
205
Request request = new Request();
206
request.setCoyoteRequest(new org.apache.coyote.Request());
207
request.setRemoteAddr("192.168.0.10");
208
request.setRemoteHost("remote-host-original-value");
209
request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, 192.168.0.10, 192.168.0.11");
212
remoteIpValve.invoke(request, null);
215
String actualXForwardedFor = request.getHeader("x-forwarded-for");
216
assertNull("all proxies are internal, x-forwarded-for must be null", actualXForwardedFor);
218
String actualXForwardedBy = request.getHeader("x-forwarded-by");
219
assertNull("all proxies are internal, x-forwarded-by must be null", actualXForwardedBy);
221
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
222
assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr);
224
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
225
assertEquals("remoteHost", "140.211.11.130", actualRemoteHost);
227
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
228
assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr);
230
String actualPostInvokeRemoteHost = request.getRemoteHost();
231
assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost);
234
public void testInvokeAllProxiesAreTrustedAndRemoteAddrMatchRegexp() throws Exception {
237
RemoteIpValve remoteIpValve = new RemoteIpValve();
238
remoteIpValve.setInternalProxies("127\\.0\\.0\\.1, 192\\.168\\..*, another-internal-proxy");
239
remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3");
240
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
241
remoteIpValve.setProxiesHeader("x-forwarded-by");
242
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
243
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
245
Request request = new Request();
246
request.setCoyoteRequest(new org.apache.coyote.Request());
247
request.setRemoteAddr("192.168.0.10");
248
request.setRemoteHost("remote-host-original-value");
249
request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, proxy1, proxy2");
252
remoteIpValve.invoke(request, null);
255
String actualXForwardedFor = request.getHeader("x-forwarded-for");
256
assertNull("all proxies are trusted, x-forwarded-for must be null", actualXForwardedFor);
258
String actualXForwardedBy = request.getHeader("x-forwarded-by");
259
assertEquals("all proxies are trusted, they must appear in x-forwarded-by", "proxy1, proxy2", actualXForwardedBy);
261
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
262
assertEquals("remoteAddr", "140.211.11.130", actualRemoteAddr);
264
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
265
assertEquals("remoteHost", "140.211.11.130", actualRemoteHost);
267
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
268
assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr);
270
String actualPostInvokeRemoteHost = request.getRemoteHost();
271
assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost);
274
public void testInvokeNotAllowedRemoteAddr() throws Exception {
276
RemoteIpValve remoteIpValve = new RemoteIpValve();
277
remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11");
278
remoteIpValve.setTrustedProxies("proxy1,proxy2,proxy3");
279
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
280
remoteIpValve.setProxiesHeader("x-forwarded-by");
281
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
282
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
284
Request request = new Request();
285
request.setCoyoteRequest(new org.apache.coyote.Request());
286
request.setRemoteAddr("not-allowed-internal-proxy");
287
request.setRemoteHost("not-allowed-internal-proxy-host");
288
request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for").setString("140.211.11.130, proxy1, proxy2");
291
remoteIpValve.invoke(request, null);
294
String actualXForwardedFor = request.getHeader("x-forwarded-for");
295
assertEquals("x-forwarded-for must be unchanged", "140.211.11.130, proxy1, proxy2", actualXForwardedFor);
297
String actualXForwardedBy = request.getHeader("x-forwarded-by");
298
assertNull("x-forwarded-by must be null", actualXForwardedBy);
300
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
301
assertEquals("remoteAddr", "not-allowed-internal-proxy", actualRemoteAddr);
303
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
304
assertEquals("remoteHost", "not-allowed-internal-proxy-host", actualRemoteHost);
306
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
307
assertEquals("postInvoke remoteAddr", "not-allowed-internal-proxy", actualPostInvokeRemoteAddr);
309
String actualPostInvokeRemoteHost = request.getRemoteHost();
310
assertEquals("postInvoke remoteAddr", "not-allowed-internal-proxy-host", actualPostInvokeRemoteHost);
313
public void testInvokeUntrustedProxyInTheChain() throws Exception {
315
RemoteIpValve remoteIpValve = new RemoteIpValve();
316
remoteIpValve.setInternalProxies("192\\.168\\.0\\.10, 192\\.168\\.0\\.11");
317
remoteIpValve.setTrustedProxies("proxy1, proxy2, proxy3");
318
remoteIpValve.setRemoteIpHeader("x-forwarded-for");
319
remoteIpValve.setProxiesHeader("x-forwarded-by");
320
RemoteAddrAndHostTrackerValve remoteAddrAndHostTrackerValve = new RemoteAddrAndHostTrackerValve();
321
remoteIpValve.setNext(remoteAddrAndHostTrackerValve);
323
Request request = new Request();
324
request.setCoyoteRequest(new org.apache.coyote.Request());
325
request.setRemoteAddr("192.168.0.10");
326
request.setRemoteHost("remote-host-original-value");
327
request.getCoyoteRequest().getMimeHeaders().addValue("x-forwarded-for")
328
.setString("140.211.11.130, proxy1, untrusted-proxy, proxy2");
331
remoteIpValve.invoke(request, null);
334
String actualXForwardedFor = request.getHeader("x-forwarded-for");
335
assertEquals("ip/host before untrusted-proxy must appear in x-forwarded-for", "140.211.11.130, proxy1", actualXForwardedFor);
337
String actualXForwardedBy = request.getHeader("x-forwarded-by");
338
assertEquals("ip/host after untrusted-proxy must appear in x-forwarded-by", "proxy2", actualXForwardedBy);
340
String actualRemoteAddr = remoteAddrAndHostTrackerValve.getRemoteAddr();
341
assertEquals("remoteAddr", "untrusted-proxy", actualRemoteAddr);
343
String actualRemoteHost = remoteAddrAndHostTrackerValve.getRemoteHost();
344
assertEquals("remoteHost", "untrusted-proxy", actualRemoteHost);
346
String actualPostInvokeRemoteAddr = request.getRemoteAddr();
347
assertEquals("postInvoke remoteAddr", "192.168.0.10", actualPostInvokeRemoteAddr);
349
String actualPostInvokeRemoteHost = request.getRemoteHost();
350
assertEquals("postInvoke remoteAddr", "remote-host-original-value", actualPostInvokeRemoteHost);
353
public void testListToCommaDelimitedString() {
354
String[] actual = RemoteIpValve.commaDelimitedListToStringArray("element1, element2, element3");
355
String[] expected = new String[] {
356
"element1", "element2", "element3"
358
assertArrayEquals(expected, actual);
361
public void testListToCommaDelimitedStringMixedSpaceChars() {
362
String[] actual = RemoteIpValve.commaDelimitedListToStringArray("element1 , element2,\t element3");
363
String[] expected = new String[] {
364
"element1", "element2", "element3"
366
assertArrayEquals(expected, actual);
369
private void assertArrayEquals(String[] expected, String[] actual) {
370
if (expected == null) {
374
assertNotNull(actual);
375
assertEquals(expected.length, actual.length);
376
List<String> e = new ArrayList<String>();
377
e.addAll(Arrays.asList(expected));
378
List<String> a = new ArrayList<String>();
379
a.addAll(Arrays.asList(actual));
381
for (String entry : e) {
382
assertTrue(a.remove(entry));
384
assertTrue(a.isEmpty());