Merge pull request #4648 from eclipse/jetty-9.4.x-4645-forwardedPortException
Issue #4645 - better error message for empty X-Forwarded-Port value
This commit is contained in:
commit
b497827df0
|
@ -24,6 +24,7 @@ import java.lang.invoke.MethodType;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.BadMessageException;
|
||||||
import org.eclipse.jetty.http.HostPortHttpField;
|
import org.eclipse.jetty.http.HostPortHttpField;
|
||||||
import org.eclipse.jetty.http.HttpField;
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpFields;
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
|
@ -376,18 +377,18 @@ public class ForwardedRequestCustomizer implements Customizer
|
||||||
|
|
||||||
// Do a single pass through the header fields as it is a more efficient single iteration.
|
// Do a single pass through the header fields as it is a more efficient single iteration.
|
||||||
Forwarded forwarded = new Forwarded(request, config);
|
Forwarded forwarded = new Forwarded(request, config);
|
||||||
try
|
|
||||||
{
|
|
||||||
for (HttpField field : httpFields)
|
for (HttpField field : httpFields)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
MethodHandle handle = _handles.get(field.getName());
|
MethodHandle handle = _handles.get(field.getName());
|
||||||
if (handle != null)
|
if (handle != null)
|
||||||
handle.invoke(forwarded, field);
|
handle.invoke(forwarded, field);
|
||||||
}
|
}
|
||||||
}
|
catch (Throwable t)
|
||||||
catch (Throwable e)
|
|
||||||
{
|
{
|
||||||
throw new RuntimeException(e);
|
onError(field, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forwarded._proto != null)
|
if (forwarded._proto != null)
|
||||||
|
@ -420,6 +421,11 @@ public class ForwardedRequestCustomizer implements Customizer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onError(HttpField field, Throwable t)
|
||||||
|
{
|
||||||
|
throw new BadMessageException("Bad header value for " + field.getName(), t);
|
||||||
|
}
|
||||||
|
|
||||||
protected String getLeftMost(String headerValue)
|
protected String getLeftMost(String headerValue)
|
||||||
{
|
{
|
||||||
if (headerValue == null)
|
if (headerValue == null)
|
||||||
|
@ -623,35 +629,37 @@ public class ForwardedRequestCustomizer implements Customizer
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void handleFor(HttpField field)
|
public void handleFor(HttpField field)
|
||||||
{
|
{
|
||||||
|
String authority = getLeftMost(field.getValue());
|
||||||
if (!getForwardedPortAsAuthority() && !StringUtil.isEmpty(getForwardedPortHeader()))
|
if (!getForwardedPortAsAuthority() && !StringUtil.isEmpty(getForwardedPortHeader()))
|
||||||
{
|
{
|
||||||
if (_for == null)
|
if (_for == null)
|
||||||
_for = new PossiblyPartialHostPort(getLeftMost(field.getValue()));
|
_for = new PossiblyPartialHostPort(authority);
|
||||||
else if (_for instanceof PortSetHostPort)
|
else if (_for instanceof PortSetHostPort)
|
||||||
_for = new HostPort(HostPort.normalizeHost(getLeftMost(field.getValue())), _for.getPort());
|
_for = new HostPort(HostPort.normalizeHost(authority), _for.getPort());
|
||||||
}
|
}
|
||||||
else if (_for == null)
|
else if (_for == null)
|
||||||
{
|
{
|
||||||
_for = new HostPort(getLeftMost(field.getValue()));
|
_for = new HostPort(authority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void handlePort(HttpField field)
|
public void handlePort(HttpField field)
|
||||||
{
|
{
|
||||||
|
int port = HostPort.parsePort(getLeftMost(field.getValue()));
|
||||||
if (!getForwardedPortAsAuthority())
|
if (!getForwardedPortAsAuthority())
|
||||||
{
|
{
|
||||||
if (_for == null)
|
if (_for == null)
|
||||||
_for = new PortSetHostPort(_request.getRemoteHost(), Integer.parseInt(getLeftMost(field.getValue())));
|
_for = new PortSetHostPort(_request.getRemoteHost(), port);
|
||||||
else if (_for instanceof PossiblyPartialHostPort && _for.getPort() <= 0)
|
else if (_for instanceof PossiblyPartialHostPort && _for.getPort() <= 0)
|
||||||
_for = new HostPort(HostPort.normalizeHost(_for.getHost()), Integer.parseInt(getLeftMost(field.getValue())));
|
_for = new HostPort(HostPort.normalizeHost(_for.getHost()), port);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_host == null)
|
if (_host == null)
|
||||||
_host = new PortSetHostPort(_request.getServerName(), Integer.parseInt(getLeftMost(field.getValue())));
|
_host = new PortSetHostPort(_request.getServerName(), port);
|
||||||
else if (_host instanceof PossiblyPartialHostPort && _host.getPort() <= 0)
|
else if (_host instanceof PossiblyPartialHostPort && _host.getPort() <= 0)
|
||||||
_host = new HostPort(HostPort.normalizeHost(_host.getHost()), Integer.parseInt(getLeftMost(field.getValue())));
|
_host = new HostPort(HostPort.normalizeHost(_host.getHost()), port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.eclipse.jetty.http.HttpTester;
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
@ -619,6 +620,25 @@ public class ForwardedRequestCustomizerTest
|
||||||
expectations.accept(actual);
|
expectations.accept(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBadInput() throws Exception
|
||||||
|
{
|
||||||
|
Request request = new Request("Bad port value")
|
||||||
|
.headers(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Host: myhost",
|
||||||
|
"X-Forwarded-Port: "
|
||||||
|
);
|
||||||
|
|
||||||
|
request.configure(customizer);
|
||||||
|
|
||||||
|
String rawRequest = request.getRawRequest((header) -> header);
|
||||||
|
System.out.println(rawRequest);
|
||||||
|
|
||||||
|
HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(rawRequest));
|
||||||
|
assertThat("status", response.getStatus(), is(400));
|
||||||
|
}
|
||||||
|
|
||||||
private static class Request
|
private static class Request
|
||||||
{
|
{
|
||||||
String description;
|
String description;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class HostPort
|
||||||
private final String _host;
|
private final String _host;
|
||||||
private final int _port;
|
private final int _port;
|
||||||
|
|
||||||
public HostPort(String host, int port) throws IllegalArgumentException
|
public HostPort(String host, int port)
|
||||||
{
|
{
|
||||||
_host = host;
|
_host = host;
|
||||||
_port = port;
|
_port = port;
|
||||||
|
@ -61,7 +61,7 @@ public class HostPort
|
||||||
{
|
{
|
||||||
if (authority.charAt(close + 1) != ':')
|
if (authority.charAt(close + 1) != ':')
|
||||||
throw new IllegalArgumentException("Bad IPv6 port");
|
throw new IllegalArgumentException("Bad IPv6 port");
|
||||||
_port = StringUtil.toInt(authority, close + 2);
|
_port = parsePort(authority.substring(close + 2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_port = 0;
|
_port = 0;
|
||||||
|
@ -80,7 +80,7 @@ public class HostPort
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_host = authority.substring(0, c);
|
_host = authority.substring(0, c);
|
||||||
_port = StringUtil.toInt(authority, c + 1);
|
_port = parsePort(authority.substring(c + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -103,10 +103,6 @@ public class HostPort
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (_host == null)
|
|
||||||
throw new IllegalArgumentException("Bad host");
|
|
||||||
if (_port < 0)
|
|
||||||
throw new IllegalArgumentException("Bad port");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,4 +159,23 @@ public class HostPort
|
||||||
// normalize with [ ]
|
// normalize with [ ]
|
||||||
return "[" + host + "]";
|
return "[" + host + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a string representing a port validating it is a valid port value.
|
||||||
|
*
|
||||||
|
* @param rawPort the port string.
|
||||||
|
* @return the integer value for the port.
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
|
public static int parsePort(String rawPort) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
if (StringUtil.isEmpty(rawPort))
|
||||||
|
throw new IllegalArgumentException("Bad port");
|
||||||
|
|
||||||
|
int port = Integer.parseInt(rawPort);
|
||||||
|
if (port <= 0 || port > 65535)
|
||||||
|
throw new IllegalArgumentException("Bad port");
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class HostPortTest
|
||||||
Arguments.of("[0::0::0::1]", "[0::0::0::1]", null),
|
Arguments.of("[0::0::0::1]", "[0::0::0::1]", null),
|
||||||
Arguments.of("[0::0::0::1]:80", "[0::0::0::1]", "80"),
|
Arguments.of("[0::0::0::1]:80", "[0::0::0::1]", "80"),
|
||||||
Arguments.of("0:1:2:3:4:5:6", "[0:1:2:3:4:5:6]", null),
|
Arguments.of("0:1:2:3:4:5:6", "[0:1:2:3:4:5:6]", null),
|
||||||
|
Arguments.of("127.0.0.1:65535", "127.0.0.1", "65535"),
|
||||||
// Localhost tests
|
// Localhost tests
|
||||||
Arguments.of("localhost:80", "localhost", "80"),
|
Arguments.of("localhost:80", "localhost", "80"),
|
||||||
Arguments.of("127.0.0.1:80", "127.0.0.1", "80"),
|
Arguments.of("127.0.0.1:80", "127.0.0.1", "80"),
|
||||||
|
@ -79,7 +80,9 @@ public class HostPortTest
|
||||||
"[0::0::0::0::1]:xxx",
|
"[0::0::0::0::1]:xxx",
|
||||||
"host:-80",
|
"host:-80",
|
||||||
"127.0.0.1:-80",
|
"127.0.0.1:-80",
|
||||||
"[0::0::0::0::1]:-80")
|
"[0::0::0::0::1]:-80",
|
||||||
|
"127.0.0.1:65536"
|
||||||
|
)
|
||||||
.map(Arguments::of);
|
.map(Arguments::of);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue