Skip to content

Commit

Permalink
TestWfsPost - improve url validation
Browse files Browse the repository at this point in the history
  • Loading branch information
tbarsballe committed Jun 10, 2019
1 parent 4aa0249 commit 5facd7a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 24 deletions.
Expand Up @@ -13,6 +13,7 @@
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.logging.Level;
Expand Down Expand Up @@ -311,25 +312,80 @@ protected GeoServer getGeoServer() {
return (GeoServer) GeoServerExtensions.bean("geoServer");
}

void validateURL(HttpServletRequest request, String url, String proxyBase) {
/**
* Validates the destination URL parameter sent to the TestWfsPost to execute, to verify it is
* valid, and the request is actually coming from geoserver.
*
* <p>Two cases are checked, depending on whether or not GeoServer's Proxy Base URL is set.
*
* <p>If the Proxy Base URL is set, the host of the url parameter should match that of the Proxy
* Base URL (since the HTTP request is coming from inside GeoServer, while the url parameter is
* external)
*
* <p>Otherwise, the host of the url parameter should match that of the HTTP request.
*
* <p>In both cases, the path of the request url should be that of the TestWfsPost servlet
* endpoint.
*
* @param request The HTTP request sent from Wicket to the TestWfsPost servlet
* @param urlString The url that the TestWfsPost servlet is being asked to send an OWS request
* to.
* @param proxyBase The proxy base URL of GeoServer
* @throws IllegalArgumentException - If the arguments are malformed or otherwise invalid
* @throws IllegalStateException - If something else is wrong
*/
void validateURL(HttpServletRequest request, String urlString, String proxyBase) {
URL url;
URL requestUrl;

try {
url = new URL(urlString);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid url requested; not a URL: " + urlString, e);
}
String requestString = request.getRequestURL().toString();
try {
requestUrl = new URL(requestString);
} catch (MalformedURLException e) {
throw new IllegalStateException("Invalid request url; not a URL: " + requestString, e);
}

// this should not happen, but let's not make it an open proxy if it does
if (!request.getServletPath().equals(TEST_WFS_POST_PATH)) {
throw new IllegalStateException(
"Unepected, the TestWfsPost was accessed by a path not ending with TestWfsPost: "
+ requestString);
}
if (null != requestUrl.getQuery()) {
throw new IllegalStateException(
"Unepected, the TestWfsPost was accessed by a path not ending with TestWfsPost: "
+ requestString);
}
if (!request.getContextPath().equals(this.getServletContext().getContextPath())) {
throw new IllegalStateException(
"Unepected, the TestWfsPost was accessed by a path from a different servlet context: "
+ requestString);
}

if (proxyBase != null) {
if (!url.startsWith(proxyBase)) {
try {
URL proxyBaseUrl = new URL(proxyBase);

if (!url.getHost().equals(proxyBaseUrl.getHost())) {
throw new IllegalArgumentException(
"Invalid url requested, the demo requests should be hitting: "
+ proxyBase);
}
} catch (MalformedURLException e) {
throw new IllegalArgumentException(
"Invalid url requested, the demo requests should be hitting: " + proxyBase);
"Invalid Proxy Base URL; not a URL: " + proxyBase, e);
}
} else {
// use the requested url then, and remove the TestWfsPort
String requestedUrl = request.getRequestURL().toString();
// this should not happen, but let's not make it an open proxy if it does
if (!requestedUrl.endsWith(TEST_WFS_POST_PATH)) {
if (!url.getHost().equals(requestUrl.getHost())) {
throw new IllegalStateException(
"Unepected, the TestWfsPost was accessed by a path not ending with TestWfsPost: "
+ requestedUrl);
}
String base = requestedUrl.substring(0, requestedUrl.lastIndexOf(TEST_WFS_POST_PATH));
if (!url.startsWith(base)) {
throw new IllegalArgumentException(
"Invalid url requested, the demo requests should be hitting: " + base);
"Invalid url requested, the demo requests should be hitting: "
+ requestString.substring(
0, requestString.lastIndexOf(TEST_WFS_POST_PATH)));
}
}
}
Expand Down
Expand Up @@ -8,6 +8,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import javax.servlet.ServletException;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.SettingsInfo;
Expand All @@ -18,6 +19,8 @@
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.mock.web.MockServletContext;

public class TestWfsPostTest {

Expand All @@ -26,7 +29,7 @@ public class TestWfsPostTest {

@Test
public void testEscapeXMLReservedChars() throws Exception {
TestWfsPost servlet = new TestWfsPost();
TestWfsPost servlet = buildMockServlet();
MockHttpServletRequest request = buildMockRequest();
request.addHeader("Host", "localhost:8080");
request.setQueryString(ResponseUtils.getQueryString("form_hf_0=&url=vjoce<>:garbage"));
Expand All @@ -44,7 +47,7 @@ public void testEscapeXMLReservedChars() throws Exception {

@Test
public void testDisallowOpenProxy() throws Exception {
TestWfsPost servlet = new TestWfsPost();
TestWfsPost servlet = buildMockServlet();
MockHttpServletRequest request = buildMockRequest();
request.setParameter("url", "http://www.google.com");
request.setMethod("GET");
Expand All @@ -59,12 +62,7 @@ public void testDisallowOpenProxy() throws Exception {

@Test
public void testDisallowOpenProxyWithProxyBase() throws Exception {
TestWfsPost servlet =
new TestWfsPost() {
String getProxyBaseURL() {
return "http://geoserver.org/geoserver";
}
};
TestWfsPost servlet = buildMockServlet("http://geoserver.org/geoserver");
MockHttpServletRequest request = buildMockRequest();
request.setParameter("url", "http://localhost:1234/internalApp");
request.setMethod("GET");
Expand All @@ -78,9 +76,25 @@ String getProxyBaseURL() {
"Invalid url requested, the demo requests should be hitting: http://geoserver.org/geoserver"));
}

@Test
public void testDisallowOpenProxyWithSupersetNameWithProxyBase() throws Exception {
TestWfsPost servlet = buildMockServlet("http://geoserver.org");
MockHttpServletRequest request = buildMockRequest();
request.setParameter("url", "http://geoserver.org.other");
request.setMethod("GET");

MockHttpServletResponse response = new MockHttpServletResponse();
servlet.service(request, response);
// checking that request is disallowed
assertTrue(
response.getContentAsString()
.contains(
"Invalid url requested, the demo requests should be hitting: http://geoserver.org"));
}

@Test
public void testValidateURL() throws Exception {
TestWfsPost servlet = new TestWfsPost();
TestWfsPost servlet = buildMockServlet();
MockHttpServletRequest request = buildMockRequest();
request.setParameter("url", "http://localhost:1234/internalApp");
request.setMethod("GET");
Expand Down Expand Up @@ -124,10 +138,36 @@ protected static MockHttpServletRequest buildMockRequest() {
request.setScheme("http");
request.setServerName("localhost");
request.setServerPort(8080);
request.setContextPath("/geoserver/TestWfsPost");
request.setContextPath("/geoserver");
request.setServletPath("/TestWfsPost");
request.setRequestURI(
ResponseUtils.stripQueryString(ResponseUtils.appendPath("/geoserver/TestWfsPost")));
request.setRemoteAddr("127.0.0.1");
return request;
}

protected static TestWfsPost buildMockServlet() throws ServletException {
return buildMockServlet(null);
}

protected static TestWfsPost buildMockServlet(final String proxyBaseUrl)
throws ServletException {
TestWfsPost testWfsPost;
if (proxyBaseUrl == null) {
testWfsPost = new TestWfsPost();
} else {
testWfsPost =
new TestWfsPost() {
String getProxyBaseURL() {
return proxyBaseUrl;
}
};
}
MockServletContext servletContext = new MockServletContext();
servletContext.setContextPath("/geoserver");
MockServletConfig servletConfig = new MockServletConfig(servletContext);
testWfsPost.init(servletConfig);

return testWfsPost;
}
}

0 comments on commit 5facd7a

Please sign in to comment.