Skip to content

Commit 0fda4e6

Browse files
Merge pull request #1317 from kali834x/happyaxis-probe-address
build the HappyAxis.jsp probe address from the local connector
2 parents d4d298a + 35149d3 commit 0fda4e6

2 files changed

Lines changed: 102 additions & 11 deletions

File tree

‎modules/webapp/src/main/webapp/axis2-web/HappyAxis.jsp‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,13 @@
4646
<body>
4747
<jsp:include page="/WEB-INF/include/header.inc"/>
4848
<jsp:include page="/WEB-INF/include/link-footer.jsp"/>
49-
<%IP = request.getRequestURL().toString();%>
5049
<%!
5150
/*
5251
* Happiness tests for axis2. These look at the classpath and warn if things
5352
* are missing. Normally addng this much code in a JSP page is mad
5453
* but here we want to validate JSP compilation too, and have a drop-in
5554
* page for easy re-use
5655
*/
57-
String IP;
58-
5956
/**
6057
* Get a string providing install information.
6158
* TODO: make this platform aware and give specific hints
@@ -325,20 +322,24 @@
325322
return method;
326323
}
327324
328-
public boolean invokeTheService() {
325+
public boolean invokeTheService(HttpServletRequest request) {
329326
try {
330327
// since this one is an internal request we do not use public frontendHostUrl
331-
// for it
332-
int lastindex = IP.lastIndexOf('/');
333-
IP = IP.substring(0, lastindex);
334-
///axis2/axis2-web/services/version
335-
IP = IP.replaceAll("axis2-web", "");
328+
// for it. The address is that of the connector this request arrived on, not
329+
// request.getRequestURL(): that is built from the client's Host header, which
330+
// would let an anonymous caller choose the host and port the server connects to.
331+
String host = request.getLocalAddr();
332+
if (host.indexOf(':') >= 0) {
333+
host = "[" + host + "]";
334+
}
335+
String address = request.getScheme() + "://" + host + ":" + request.getLocalPort()
336+
+ request.getContextPath() + "/";
336337
337338
OMElement payload = createEnvelope();
338339
ConfigurationContext configctx =
339340
ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
340341
ServiceClient client = new ServiceClient(configctx, null);
341-
EndpointReference targetEPR = new EndpointReference(IP + configctx.getServicePath() + "/Version");
342+
EndpointReference targetEPR = new EndpointReference(address + configctx.getServicePath() + "/Version");
342343
Options options = new Options();
343344
client.setOptions(options);
344345
options.setTo(targetEPR);
@@ -438,7 +439,7 @@
438439

439440
<h2>Examining Version Service</h2>
440441
<%
441-
boolean serviceStatus = invokeTheService();
442+
boolean serviceStatus = invokeTheService(request);
442443
if (serviceStatus) {
443444
%>
444445
<div>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.axis2.webapp;
20+
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
23+
import java.io.ByteArrayOutputStream;
24+
import java.io.InputStream;
25+
import java.io.OutputStream;
26+
import java.net.InetSocketAddress;
27+
import java.net.Socket;
28+
import java.nio.charset.StandardCharsets;
29+
import java.util.List;
30+
import java.util.concurrent.CopyOnWriteArrayList;
31+
32+
import org.junit.After;
33+
import org.junit.Before;
34+
import org.junit.Test;
35+
36+
import com.sun.net.httpserver.HttpServer;
37+
38+
/**
39+
* HappyAxis.jsp probes the Version service with a request the server sends to itself.
40+
* The address of that request used to come from the client's Host header, so an
41+
* anonymous caller could make the server connect to a host and port of their choosing.
42+
*/
43+
public class HappyAxisHostHeaderITCase {
44+
private final List<String> received = new CopyOnWriteArrayList<>();
45+
private HttpServer listener;
46+
47+
@Before
48+
public void startListener() throws Exception {
49+
listener = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
50+
listener.createContext("/", exchange -> {
51+
received.add(exchange.getRequestMethod() + " " + exchange.getRequestURI());
52+
exchange.sendResponseHeaders(404, -1);
53+
exchange.close();
54+
});
55+
listener.start();
56+
}
57+
58+
@After
59+
public void stopListener() {
60+
listener.stop(0);
61+
}
62+
63+
@Test
64+
public void testHostHeaderDoesNotChooseProbeTarget() throws Exception {
65+
int port = Integer.getInteger("jetty.httpPort", 8080);
66+
String hostileHost = "127.0.0.1:" + listener.getAddress().getPort();
67+
String response;
68+
try (Socket socket = new Socket("localhost", port)) {
69+
socket.setSoTimeout(120000);
70+
OutputStream out = socket.getOutputStream();
71+
out.write(("GET /axis2/axis2-web/HappyAxis.jsp HTTP/1.0\r\n"
72+
+ "Host: " + hostileHost + "\r\n\r\n").getBytes(StandardCharsets.ISO_8859_1));
73+
out.flush();
74+
InputStream in = socket.getInputStream();
75+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
76+
byte[] chunk = new byte[8192];
77+
int n;
78+
while ((n = in.read(chunk)) != -1) {
79+
buffer.write(chunk, 0, n);
80+
}
81+
response = buffer.toString("UTF-8");
82+
}
83+
String statusLine = response.substring(0, Math.max(response.indexOf("\r\n"), 0));
84+
assertThat(statusLine).contains(" 200 ");
85+
// The probe must never go to the host the request named...
86+
assertThat(received).isEmpty();
87+
// ...and must still reach the Version service on this server.
88+
assertThat(response).contains("Found Axis2 default Version service");
89+
}
90+
}

0 commit comments

Comments
 (0)