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.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.logging.Level; import java.util.logging.Level;
Expand Down Expand Up @@ -311,25 +312,80 @@ protected GeoServer getGeoServer() {
return (GeoServer) GeoServerExtensions.bean("geoServer"); 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 (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( throw new IllegalArgumentException(
"Invalid url requested, the demo requests should be hitting: " + proxyBase); "Invalid Proxy Base URL; not a URL: " + proxyBase, e);
} }
} else { } else {
// use the requested url then, and remove the TestWfsPort if (!url.getHost().equals(requestUrl.getHost())) {
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)) {
throw new IllegalStateException( throw new IllegalStateException(
"Unepected, the TestWfsPost was accessed by a path not ending with TestWfsPost: " "Invalid url requested, the demo requests should be hitting: "
+ requestedUrl); + requestString.substring(
} 0, requestString.lastIndexOf(TEST_WFS_POST_PATH)));
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);
} }
} }
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;


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


public class TestWfsPostTest { public class TestWfsPostTest {


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


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


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


@Test @Test
public void testDisallowOpenProxyWithProxyBase() throws Exception { public void testDisallowOpenProxyWithProxyBase() throws Exception {
TestWfsPost servlet = TestWfsPost servlet = buildMockServlet("http://geoserver.org/geoserver");
new TestWfsPost() {
String getProxyBaseURL() {
return "http://geoserver.org/geoserver";
}
};
MockHttpServletRequest request = buildMockRequest(); MockHttpServletRequest request = buildMockRequest();
request.setParameter("url", "http://localhost:1234/internalApp"); request.setParameter("url", "http://localhost:1234/internalApp");
request.setMethod("GET"); request.setMethod("GET");
Expand All @@ -78,9 +76,25 @@ String getProxyBaseURL() {
"Invalid url requested, the demo requests should be hitting: http://geoserver.org/geoserver")); "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 @Test
public void testValidateURL() throws Exception { public void testValidateURL() throws Exception {
TestWfsPost servlet = new TestWfsPost(); TestWfsPost servlet = buildMockServlet();
MockHttpServletRequest request = buildMockRequest(); MockHttpServletRequest request = buildMockRequest();
request.setParameter("url", "http://localhost:1234/internalApp"); request.setParameter("url", "http://localhost:1234/internalApp");
request.setMethod("GET"); request.setMethod("GET");
Expand Down Expand Up @@ -124,10 +138,36 @@ protected static MockHttpServletRequest buildMockRequest() {
request.setScheme("http"); request.setScheme("http");
request.setServerName("localhost"); request.setServerName("localhost");
request.setServerPort(8080); request.setServerPort(8080);
request.setContextPath("/geoserver/TestWfsPost"); request.setContextPath("/geoserver");
request.setServletPath("/TestWfsPost");
request.setRequestURI( request.setRequestURI(
ResponseUtils.stripQueryString(ResponseUtils.appendPath("/geoserver/TestWfsPost"))); ResponseUtils.stripQueryString(ResponseUtils.appendPath("/geoserver/TestWfsPost")));
request.setRemoteAddr("127.0.0.1"); request.setRemoteAddr("127.0.0.1");
return request; 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.