Skip to content

Commit

Permalink
Issue #5029 Relative Redirection (#5038)
Browse files Browse the repository at this point in the history
* Issue #5029 Relative Redirection

Provide option to allow relative redirection

* Issue #5029 Relative Redirection

Fixed checkstyle

* rename from review
  • Loading branch information
gregw committed Jul 15, 2020
1 parent 6b57654 commit 5c1dda3
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 2 deletions.
1 change: 1 addition & 0 deletions jetty-server/src/main/config/etc/jetty.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Set name="requestCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.requestCookieCompliance" deprecated="jetty.httpConfig.cookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="responseCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.responseCookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="multiPartFormDataCompliance"><Call class="org.eclipse.jetty.server.MultiPartFormDataCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.multiPartFormDataCompliance" default="RFC7578"/></Arg></Call></Set>
<Set name="relativeRedirectAllowed"><Property name="jetty.httpConfig.relativeRedirectAllowed" default="false"/></Set>
</New>

<!-- =========================================================== -->
Expand Down
3 changes: 3 additions & 0 deletions jetty-server/src/main/config/modules/server.mod
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ patch-module: servlet.api=lib/jetty-schemas-3.1.jar
## multipart/form-data compliance mode of: LEGACY(slow), RFC7578(fast)
# jetty.httpConfig.multiPartFormDataCompliance=LEGACY

## Relative Redirect Locations allowed
# jetty.httpConfig.relativeRedirectAllowed=false

### Server configuration
## Whether ctrl+c on the console gracefully stops the Jetty server
# jetty.server.stopAtShutdown=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public class HttpConfiguration implements Dumpable
private CookieCompliance _responseCookieCompliance = CookieCompliance.RFC6265;
private MultiPartFormDataCompliance _multiPartCompliance = MultiPartFormDataCompliance.LEGACY; // TODO change default in jetty-10
private boolean _notifyRemoteAsyncErrors = true;
private boolean _relativeRedirectAllowed;

/**
* <p>An interface that allows a request object to be customized
Expand Down Expand Up @@ -142,6 +143,7 @@ public HttpConfiguration(HttpConfiguration config)
_responseCookieCompliance = config._responseCookieCompliance;
_multiPartCompliance = config._multiPartCompliance;
_notifyRemoteAsyncErrors = config._notifyRemoteAsyncErrors;
_relativeRedirectAllowed = config._relativeRedirectAllowed;
}

/**
Expand Down Expand Up @@ -642,6 +644,23 @@ public boolean isNotifyRemoteAsyncErrors()
return _notifyRemoteAsyncErrors;
}

/**
* @param allowed True if relative redirection locations are allowed
*/
public void setRelativeRedirectAllowed(boolean allowed)
{
_relativeRedirectAllowed = allowed;
}

/**
* @return True if relative redirection locations are allowed
*/
@ManagedAttribute("Whether relative redirection locations are allowed")
public boolean isRelativeRedirectAllowed()
{
return _relativeRedirectAllowed;
}

@Override
public String dump()
{
Expand Down Expand Up @@ -673,7 +692,8 @@ public void dump(Appendable out, String indent) throws IOException
"minResponseDataRate=" + _minResponseDataRate,
"cookieCompliance=" + _requestCookieCompliance,
"setRequestCookieCompliance=" + _responseCookieCompliance,
"notifyRemoteAsyncErrors=" + _notifyRemoteAsyncErrors
"notifyRemoteAsyncErrors=" + _notifyRemoteAsyncErrors,
"relativeRedirectAllowed=" + _relativeRedirectAllowed
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,9 @@ public void sendRedirect(int code, String location) throws IOException

if (!URIUtil.hasScheme(location))
{
StringBuilder buf = _channel.getRequest().getRootURL();
StringBuilder buf = _channel.getHttpConfiguration().isRelativeRedirectAllowed()
? new StringBuilder()
: _channel.getRequest().getRootURL();
if (location.startsWith("/"))
{
// absolute in context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,81 @@ public void testSendRedirect()
}
}

@Test
public void testSendRedirectRelative()
throws Exception
{
String[][] tests = {
// No cookie
{
"http://myhost:8888/other/location;jsessionid=12345?name=value",
"http://myhost:8888/other/location;jsessionid=12345?name=value"
},
{"/other/location;jsessionid=12345?name=value", "/other/location;jsessionid=12345?name=value"},
{"./location;jsessionid=12345?name=value", "/path/location;jsessionid=12345?name=value"},

// From cookie
{"/other/location", "/other/location"},
{"/other/l%20cation", "/other/l%20cation"},
{"location", "/path/location"},
{"./location", "/path/location"},
{"../location", "/location"},
{"/other/l%20cation", "/other/l%20cation"},
{"l%20cation", "/path/l%20cation"},
{"./l%20cation", "/path/l%20cation"},
{"../l%20cation", "/l%20cation"},
{"../locati%C3%abn", "/locati%C3%abn"},
{"../other%2fplace", "/other%2fplace"},
{"http://somehost.com/other/location", "http://somehost.com/other/location"},
};

int[] ports = new int[]{8080, 80};
String[] hosts = new String[]{null, "myhost", "192.168.0.1", "0::1"};
for (int port : ports)
{
for (String host : hosts)
{
for (int i = 0; i < tests.length; i++)
{
// System.err.printf("%s %d %s%n",host,port,tests[i][0]);

Response response = getResponse();
Request request = response.getHttpChannel().getRequest();
request.getHttpChannel().getHttpConfiguration().setRelativeRedirectAllowed(true);

request.setScheme("http");
if (host != null)
request.setAuthority(host, port);
request.setURIPathQuery("/path/info;param;jsessionid=12345?query=0&more=1#target");
request.setContextPath("/path");
request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(i > 2);
SessionHandler handler = new SessionHandler();

NullSessionDataStore ds = new NullSessionDataStore();
DefaultSessionCache ss = new DefaultSessionCache(handler);
handler.setSessionCache(ss);
ss.setSessionDataStore(ds);
DefaultSessionIdManager idMgr = new DefaultSessionIdManager(_server);
idMgr.setWorkerName(null);
handler.setSessionIdManager(idMgr);
request.setSessionHandler(handler);
request.setSession(new TestSession(handler, "12345"));
handler.setCheckingRemoteSessionIdEncoding(false);

response.sendRedirect(tests[i][0]);

String location = response.getHeader("Location");

String expected = tests[i][1]
.replace("@HOST@", host == null ? request.getLocalAddr() : (host.contains(":") ? ("[" + host + "]") : host))
.replace("@PORT@", host == null ? ":8888" : (port == 80 ? "" : (":" + port)));
assertEquals(expected, location, "test-" + i + " " + host + ":" + port);
}
}
}
}

@Test
public void testInvalidSendRedirect() throws Exception
{
Expand Down

0 comments on commit 5c1dda3

Please sign in to comment.