Merge branch 'jetty-11.0.x' into jetty-12.0.x-merg
This commit is contained in:
commit
4812eb1c89
|
@ -103,7 +103,21 @@ public final class HttpCompliance implements ComplianceViolation.Mode
|
|||
* line of a single token with neither a colon nor value following, to be interpreted as a field name with no value.
|
||||
* A deployment may include this violation to allow such fields to be in a received request.
|
||||
*/
|
||||
NO_COLON_AFTER_FIELD_NAME("https://tools.ietf.org/html/rfc7230#section-3.2", "Fields must have a Colon");
|
||||
NO_COLON_AFTER_FIELD_NAME("https://tools.ietf.org/html/rfc7230#section-3.2", "Fields must have a Colon"),
|
||||
|
||||
/**
|
||||
* Since <a href="https://www.rfc-editor.org/rfc/rfc7230#section-5.4">RFC 7230: Section 5.4</a>, the HTTP protocol
|
||||
* says that a Server must reject a request duplicate host headers.
|
||||
* A deployment may include this violation to allow duplicate host headers on a received request.
|
||||
*/
|
||||
DUPLICATE_HOST_HEADERS("https://www.rfc-editor.org/rfc/rfc7230#section-5.4", "Duplicate Host Header"),
|
||||
|
||||
/**
|
||||
* Since <a href="https://www.rfc-editor.org/rfc/rfc7230#section-2.7.1">RFC 7230</a>, the HTTP protocol
|
||||
* should reject a request if the Host headers contains an invalid / unsafe authority.
|
||||
* A deployment may include this violation to allow unsafe host headesr on a received request.
|
||||
*/
|
||||
UNSAFE_HOST_HEADER("https://www.rfc-editor.org/rfc/rfc7230#section-2.7.1", "Invalid Authority");
|
||||
|
||||
private final String url;
|
||||
private final String description;
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.jetty.http.HttpTokens.EndOfContent;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.HostPort;
|
||||
import org.eclipse.jetty.util.Index;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
@ -33,10 +34,12 @@ import org.slf4j.LoggerFactory;
|
|||
import static org.eclipse.jetty.http.HttpCompliance.RFC7230;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_SENSITIVE_FIELD_NAME;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.DUPLICATE_HOST_HEADERS;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.HTTP_0_9;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.MULTIPLE_CONTENT_LENGTHS;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.NO_COLON_AFTER_FIELD_NAME;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.TRANSFER_ENCODING_WITH_CONTENT_LENGTH;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.UNSAFE_HOST_HEADER;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.WHITESPACE_AFTER_FIELD_NAME;
|
||||
import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN;
|
||||
import static org.eclipse.jetty.http.HttpTokens.LINE_FEED;
|
||||
|
@ -236,7 +239,7 @@ public class HttpParser
|
|||
private String _valueString;
|
||||
private int _responseStatus;
|
||||
private int _headerBytes;
|
||||
private boolean _host;
|
||||
private String _parsedHost;
|
||||
private boolean _headerComplete;
|
||||
private volatile State _state = State.START;
|
||||
private volatile FieldState _fieldState = FieldState.FIELD;
|
||||
|
@ -1044,14 +1047,28 @@ public class HttpParser
|
|||
break;
|
||||
|
||||
case HOST:
|
||||
if (_host)
|
||||
throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "Bad Host: multiple headers");
|
||||
_host = true;
|
||||
if (_parsedHost != null)
|
||||
{
|
||||
if (LOG.isWarnEnabled())
|
||||
LOG.warn("Encountered multiple `Host` headers. Previous `Host` header already seen as `{}`, new `Host` header has appeared as `{}`", _parsedHost, _valueString);
|
||||
checkViolation(DUPLICATE_HOST_HEADERS);
|
||||
}
|
||||
_parsedHost = _valueString;
|
||||
if (!(_field instanceof HostPortHttpField) && _valueString != null && !_valueString.isEmpty())
|
||||
{
|
||||
_field = new HostPortHttpField(_header,
|
||||
CASE_SENSITIVE_FIELD_NAME.isAllowedBy(_complianceMode) ? _headerString : _header.asString(),
|
||||
_valueString);
|
||||
HostPort hostPort;
|
||||
if (UNSAFE_HOST_HEADER.isAllowedBy(_complianceMode))
|
||||
{
|
||||
_field = new HostPortHttpField(_header,
|
||||
CASE_SENSITIVE_FIELD_NAME.isAllowedBy(_complianceMode) ? _headerString : _header.asString(),
|
||||
HostPort.unsafe(_valueString));
|
||||
}
|
||||
else
|
||||
{
|
||||
_field = new HostPortHttpField(_header,
|
||||
CASE_SENSITIVE_FIELD_NAME.isAllowedBy(_complianceMode) ? _headerString : _header.asString(),
|
||||
_valueString);
|
||||
}
|
||||
addToFieldCache = _fieldCache.isEnabled();
|
||||
}
|
||||
break;
|
||||
|
@ -1088,6 +1105,8 @@ public class HttpParser
|
|||
_fieldCache.add(_field);
|
||||
}
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("parsedHeader({}) header={}, headerString=[{}], valueString=[{}]", _field, _header, _headerString, _valueString);
|
||||
_handler.parsedHeader(_field != null ? _field : new HttpField(_header, _headerString, _valueString));
|
||||
}
|
||||
|
||||
|
@ -1199,7 +1218,7 @@ public class HttpParser
|
|||
}
|
||||
|
||||
// Was there a required host header?
|
||||
if (!_host && _version == HttpVersion.HTTP_1_1 && _requestHandler != null)
|
||||
if (_parsedHost == null && _version == HttpVersion.HTTP_1_1 && _requestHandler != null)
|
||||
{
|
||||
throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "No Host");
|
||||
}
|
||||
|
@ -1891,7 +1910,7 @@ public class HttpParser
|
|||
_responseStatus = 0;
|
||||
_contentChunk = null;
|
||||
_headerBytes = 0;
|
||||
_host = false;
|
||||
_parsedHost = null;
|
||||
_headerComplete = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser.State;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
|
@ -28,6 +29,8 @@ import org.junit.jupiter.api.Assumptions;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_INSENSITIVE_METHOD;
|
||||
|
@ -39,6 +42,7 @@ import static org.hamcrest.Matchers.contains;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -2242,17 +2246,95 @@ public class HttpParserTest
|
|||
assertEquals(8888, _port);
|
||||
}
|
||||
|
||||
public static Stream<String> badHostHeaderSource()
|
||||
{
|
||||
return List.of(
|
||||
":80", // no host, port only
|
||||
"host:", // no port
|
||||
"127.0.0.1:", // no port
|
||||
"[0::0::0::0::1", // no IP literal ending bracket
|
||||
"0::0::0::0::1]", // no IP literal starting bracket
|
||||
"[0::0::0::0::1]:", // no port
|
||||
"[0::0::0::1]", // not valid to Java (InetAddress, InetSocketAddress, or URI) : "Expected hex digits or IPv4 address"
|
||||
"[0::0::0::1]:80", // not valid to Java (InetAddress, InetSocketAddress, or URI) : "Expected hex digits or IPv4 address"
|
||||
"0:1:2:3:4:5:6", // not valid to Java (InetAddress, InetSocketAddress, or URI) : "IPv6 address too short"
|
||||
"host:xxx", // invalid port
|
||||
"127.0.0.1:xxx", // host + invalid port
|
||||
"[0::0::0::0::1]:xxx", // ipv6 + invalid port
|
||||
"host:-80", // host + invalid port
|
||||
"127.0.0.1:-80", // ipv4 + invalid port
|
||||
"[0::0::0::0::1]:-80", // ipv6 + invalid port
|
||||
"127.0.0.1:65536", // ipv4 + port value too high
|
||||
"a b c d", // whitespace in reg-name
|
||||
"a\to\tz", // tabs in reg-name
|
||||
"hosta, hostb, hostc", // space sin reg-name
|
||||
"[ab:cd:ef:gh:ij:kl:mn]", // invalid ipv6 address
|
||||
// Examples of bad Host header values (usually client bugs that shouldn't allow them)
|
||||
"Group - Machine", // spaces
|
||||
"<calculated when request is sent>",
|
||||
"[link](https://example.org/)",
|
||||
"example.org/zed", // has slash
|
||||
// common hacking attempts, seen as values on the `Host:` request header
|
||||
"| ping 127.0.0.1 -n 10",
|
||||
"%uf%80%ff%xx%uffff",
|
||||
"[${jndi${:-:}ldap${:-:}]", // log4j hacking
|
||||
"[${jndi:ldap://example.org:59377/nessus}]", // log4j hacking
|
||||
"${ip}", // variation of log4j hack
|
||||
"' *; host xyz.hacking.pro; '",
|
||||
"'/**/OR/**/1/**/=/**/1",
|
||||
"AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT('x',(SELECT (ELT(1=1,1))),'x',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)"
|
||||
).stream();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"Host: whatever.com:xxxx",
|
||||
"Host: myhost:testBadPort",
|
||||
"Host: a b c d", // whitespace in reg-name
|
||||
"Host: a\to\tz", // tabs in reg-name
|
||||
"Host: hosta, hostb, hostc", // spaces in reg-name
|
||||
"Host: [sd ajklf;d sajklf;d sajfkl;d]", // not a valid IPv6 address
|
||||
"Host: hosta\nHost: hostb\nHost: hostc" // multi-line
|
||||
})
|
||||
public void testBadHost(String hostline)
|
||||
@MethodSource("badHostHeaderSource")
|
||||
public void testBadHostReject(String hostline)
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET / HTTP/1.1\n" +
|
||||
"Host: " + hostline + "\n" +
|
||||
"Connection: close\n" +
|
||||
"\n");
|
||||
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser = new HttpParser(handler);
|
||||
parser.parseNext(buffer);
|
||||
assertThat(_bad, startsWith("Bad "));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("badHostHeaderSource")
|
||||
public void testBadHostAllow(String hostline)
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET / HTTP/1.1\n" +
|
||||
"Host: " + hostline + "\n" +
|
||||
"Connection: close\n" +
|
||||
"\n");
|
||||
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpCompliance httpCompliance = HttpCompliance.from("RFC7230,UNSAFE_HOST_HEADER");
|
||||
HttpParser parser = new HttpParser(handler, httpCompliance);
|
||||
parser.parseNext(buffer);
|
||||
assertNull(_bad);
|
||||
assertNotNull(_host);
|
||||
}
|
||||
|
||||
public static Stream<Arguments> duplicateHostHeadersSource()
|
||||
{
|
||||
return Stream.of(
|
||||
// different values
|
||||
Arguments.of("Host: hosta\nHost: hostb\nHost: hostc"),
|
||||
// same values
|
||||
Arguments.of("Host: foo\nHost: foo"),
|
||||
// separated by another header
|
||||
Arguments.of("Host: bar\nX-Zed: zed\nHost: bar")
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("duplicateHostHeadersSource")
|
||||
public void testDuplicateHostReject(String hostline)
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET / HTTP/1.1\n" +
|
||||
|
@ -2263,7 +2345,25 @@ public class HttpParserTest
|
|||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser = new HttpParser(handler);
|
||||
parser.parseNext(buffer);
|
||||
assertThat(_bad, startsWith("Bad"));
|
||||
assertThat(_bad, startsWith("Duplicate Host Header"));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("duplicateHostHeadersSource")
|
||||
public void testDuplicateHostAllow(String hostline)
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET / HTTP/1.1\n" +
|
||||
hostline + "\n" +
|
||||
"Connection: close\n" +
|
||||
"\n");
|
||||
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpCompliance httpCompliance = HttpCompliance.from("RFC7230,DUPLICATE_HOST_HEADERS");
|
||||
HttpParser parser = new HttpParser(handler, httpCompliance);
|
||||
parser.parseNext(buffer);
|
||||
assertNull(_bad);
|
||||
assertNotNull(_host);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
@{argLine} ${jetty.surefire.argLine} --add-reads org.eclipse.jetty.io=org.eclipse.jetty.logging
|
||||
@{argLine} ${jetty.surefire.argLine}
|
||||
--add-reads org.eclipse.jetty.io=org.eclipse.jetty.logging
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -16,17 +16,38 @@ package org.eclipse.jetty.util;
|
|||
import java.net.InetAddress;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>Parse an authority string (in the form {@code host:port}) into
|
||||
* {@code host} and {@code port}, handling IPv4 and IPv6 host formats
|
||||
* as defined in https://www.ietf.org/rfc/rfc2732.txt</p>
|
||||
* as defined in <a href="https://www.ietf.org/rfc/rfc2732.txt">RFC 2732</a></p>
|
||||
*/
|
||||
public class HostPort
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HostPort.class);
|
||||
private static final int BAD_PORT = -1;
|
||||
private final String _host;
|
||||
private final int _port;
|
||||
|
||||
/**
|
||||
* Create a HostPort from an unsafe (and not validated) authority.
|
||||
*
|
||||
* <p>
|
||||
* There are no validations performed against the provided authority.
|
||||
* It is quite possible to end up with HostPort that cannot be used
|
||||
* to generate valid URL, URI, InetSocketAddress, Location header, etc.
|
||||
* </p>
|
||||
*
|
||||
* @param authority raw authority
|
||||
* @return the HostPort
|
||||
*/
|
||||
public static HostPort unsafe(String authority)
|
||||
{
|
||||
return new HostPort(authority, true);
|
||||
}
|
||||
|
||||
public HostPort(String host, int port)
|
||||
{
|
||||
_host = normalizeHost(host);
|
||||
|
@ -35,35 +56,83 @@ public class HostPort
|
|||
|
||||
public HostPort(String authority) throws IllegalArgumentException
|
||||
{
|
||||
this(authority, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ReassignedVariable", "DataFlowIssue"})
|
||||
private HostPort(String authority, boolean unsafe)
|
||||
{
|
||||
String host;
|
||||
//noinspection UnusedAssignment
|
||||
int port = 0;
|
||||
|
||||
if (authority == null)
|
||||
throw new IllegalArgumentException("No Authority");
|
||||
{
|
||||
LOG.warn("Bad Authority [<null>]");
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("No Authority");
|
||||
_host = "";
|
||||
_port = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (authority.isEmpty())
|
||||
{
|
||||
_host = authority;
|
||||
_port = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (authority.isEmpty())
|
||||
{
|
||||
_host = authority;
|
||||
_port = 0;
|
||||
}
|
||||
else if (authority.charAt(0) == '[')
|
||||
if (authority.charAt(0) == '[')
|
||||
{
|
||||
// ipv6reference
|
||||
int close = authority.lastIndexOf(']');
|
||||
if (close < 0)
|
||||
throw new IllegalArgumentException("Bad IPv6 host");
|
||||
_host = authority.substring(0, close + 1);
|
||||
if (!isValidIpAddress(_host))
|
||||
throw new IllegalArgumentException("Bad IPv6 host");
|
||||
{
|
||||
LOG.warn("Bad IPv6 host: [{}]", authority);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad IPv6 host");
|
||||
host = authority;
|
||||
}
|
||||
else
|
||||
{
|
||||
host = authority.substring(0, close + 1);
|
||||
}
|
||||
|
||||
if (!isValidIpAddress(host))
|
||||
{
|
||||
LOG.warn("Bad IPv6 host: [{}]", host);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad IPv6 host");
|
||||
}
|
||||
|
||||
if (authority.length() > close + 1)
|
||||
{
|
||||
// ipv6 with port
|
||||
if (authority.charAt(close + 1) != ':')
|
||||
throw new IllegalArgumentException("Bad IPv6 port");
|
||||
_port = parsePort(authority.substring(close + 2));
|
||||
{
|
||||
LOG.warn("Bad IPv6 port: [{}]", authority);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad IPv6 port");
|
||||
host = authority; // whole authority (no substring)
|
||||
port = 0; // no port
|
||||
}
|
||||
else
|
||||
{
|
||||
port = parsePort(authority.substring(close + 2), unsafe);
|
||||
// horribly bad port during unsafe
|
||||
if (unsafe && (port == BAD_PORT))
|
||||
{
|
||||
host = authority; // whole authority (no substring)
|
||||
port = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_port = 0;
|
||||
port = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -75,38 +144,76 @@ public class HostPort
|
|||
if (c != authority.indexOf(':'))
|
||||
{
|
||||
// ipv6address no port
|
||||
_host = "[" + authority + "]";
|
||||
if (!isValidIpAddress(_host))
|
||||
throw new IllegalArgumentException("Bad IPv6 host");
|
||||
_port = 0;
|
||||
port = 0;
|
||||
host = "[" + authority + "]";
|
||||
if (!isValidIpAddress(host))
|
||||
{
|
||||
LOG.warn("Bad IPv6Address: [{}]", host);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad IPv6 host");
|
||||
host = authority; // whole authority (no substring)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// host/ipv4 with port
|
||||
_host = authority.substring(0, c);
|
||||
if (StringUtil.isBlank(_host) || !isValidHostName(_host))
|
||||
throw new IllegalArgumentException("Bad Authority");
|
||||
_port = parsePort(authority.substring(c + 1));
|
||||
host = authority.substring(0, c);
|
||||
if (StringUtil.isBlank(host))
|
||||
{
|
||||
LOG.warn("Bad Authority: [{}]", host);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad Authority");
|
||||
// unsafe - allow host to be empty
|
||||
host = "";
|
||||
}
|
||||
else if (!isValidHostName(host))
|
||||
{
|
||||
LOG.warn("Bad Authority: [{}]", host);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad Authority");
|
||||
// unsafe - bad hostname
|
||||
host = authority; // whole authority (no substring)
|
||||
}
|
||||
|
||||
port = parsePort(authority.substring(c + 1), unsafe);
|
||||
// horribly bad port during unsafe
|
||||
if (unsafe && (port == BAD_PORT))
|
||||
{
|
||||
host = authority; // whole authority (no substring)
|
||||
port = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// host/ipv4 without port
|
||||
_host = authority;
|
||||
if (StringUtil.isBlank(_host) || !isValidHostName(_host))
|
||||
throw new IllegalArgumentException("Bad Authority");
|
||||
_port = 0;
|
||||
host = authority;
|
||||
if (StringUtil.isBlank(host) || !isValidHostName(host))
|
||||
{
|
||||
LOG.warn("Bad Authority: [{}]", host);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad Authority");
|
||||
}
|
||||
port = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException iae)
|
||||
{
|
||||
throw iae;
|
||||
if (!unsafe)
|
||||
throw iae;
|
||||
host = authority;
|
||||
port = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new IllegalArgumentException("Bad HostPort", ex);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad HostPort", ex);
|
||||
host = authority;
|
||||
port = 0;
|
||||
}
|
||||
_host = host;
|
||||
_port = port;
|
||||
}
|
||||
|
||||
protected boolean isValidIpAddress(String ip)
|
||||
|
@ -181,8 +288,8 @@ public class HostPort
|
|||
}
|
||||
|
||||
/**
|
||||
* Normalizes IPv6 address as per https://tools.ietf.org/html/rfc2732
|
||||
* and https://tools.ietf.org/html/rfc6874,
|
||||
* Normalizes IPv6 address as per <a href="https://tools.ietf.org/html/rfc2732">RFC 2732</a>
|
||||
* and <a href="https://tools.ietf.org/html/rfc6874">RFC 6874</a>,
|
||||
* surrounding with square brackets if they are absent.
|
||||
*
|
||||
* @param host a host name, IPv4 address, IPv6 address or IPv6 literal
|
||||
|
@ -216,4 +323,43 @@ public class HostPort
|
|||
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a potential port.
|
||||
*
|
||||
* @param rawPort the raw port string to parse
|
||||
* @param unsafe true to always return a port in the range 0 to 65535 (or -1 for undefined if rawPort is horribly bad), false to return
|
||||
* the provided port (or {@link IllegalArgumentException} if it is horribly bad)
|
||||
* @return the port
|
||||
* @throws IllegalArgumentException if unable to parse a valid port and {@code unsafe} is false
|
||||
*/
|
||||
private int parsePort(String rawPort, boolean unsafe)
|
||||
{
|
||||
if (StringUtil.isEmpty(rawPort))
|
||||
{
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad port [" + rawPort + "]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int port = Integer.parseInt(rawPort);
|
||||
if (port <= 0 || port > 65535)
|
||||
{
|
||||
LOG.warn("Bad port [{}]", port);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad port");
|
||||
return BAD_PORT;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
LOG.warn("Bad port [{}]", rawPort);
|
||||
if (!unsafe)
|
||||
throw new IllegalArgumentException("Bad Port");
|
||||
return BAD_PORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,95 +21,122 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class HostPortTest
|
||||
{
|
||||
public static Stream<Arguments> validAuthorityProvider()
|
||||
{
|
||||
|
||||
return Stream.of(
|
||||
Arguments.of("", "", null),
|
||||
Arguments.of("host", "host", null),
|
||||
Arguments.of("host:80", "host", "80"),
|
||||
Arguments.of("10.10.10.1", "10.10.10.1", null),
|
||||
Arguments.of("10.10.10.1:80", "10.10.10.1", "80"),
|
||||
Arguments.of("127.0.0.1:65535", "127.0.0.1", "65535"),
|
||||
Arguments.of("", "", 0),
|
||||
Arguments.of("host", "host", 0),
|
||||
Arguments.of("host:80", "host", 80),
|
||||
Arguments.of("10.10.10.1", "10.10.10.1", 0),
|
||||
Arguments.of("10.10.10.1:80", "10.10.10.1", 80),
|
||||
Arguments.of("127.0.0.1:65535", "127.0.0.1", 65535),
|
||||
// Localhost tests
|
||||
Arguments.of("localhost:80", "localhost", "80"),
|
||||
Arguments.of("127.0.0.1:80", "127.0.0.1", "80"),
|
||||
Arguments.of("::1", "[::1]", null),
|
||||
Arguments.of("[::1]:443", "[::1]", "443"),
|
||||
Arguments.of("localhost:80", "localhost", 80),
|
||||
Arguments.of("127.0.0.1:80", "127.0.0.1", 80),
|
||||
Arguments.of("::1", "[::1]", 0),
|
||||
Arguments.of("[::1]:443", "[::1]", 443),
|
||||
// Examples from https://tools.ietf.org/html/rfc2732#section-2
|
||||
Arguments.of("[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80", "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", "80"),
|
||||
Arguments.of("[1080:0:0:0:8:800:200C:417A]", "[1080:0:0:0:8:800:200C:417A]", null),
|
||||
Arguments.of("[3ffe:2a00:100:7031::1]", "[3ffe:2a00:100:7031::1]", null),
|
||||
Arguments.of("[1080::8:800:200C:417A]", "[1080::8:800:200C:417A]", null),
|
||||
Arguments.of("[::192.9.5.5]", "[::192.9.5.5]", null),
|
||||
Arguments.of("[::FFFF:129.144.52.38]:80", "[::FFFF:129.144.52.38]", "80"),
|
||||
Arguments.of("[2010:836B:4179::836B:4179]", "[2010:836B:4179::836B:4179]", null),
|
||||
Arguments.of("[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80", "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 80),
|
||||
Arguments.of("[1080:0:0:0:8:800:200C:417A]", "[1080:0:0:0:8:800:200C:417A]", 0),
|
||||
Arguments.of("[3ffe:2a00:100:7031::1]", "[3ffe:2a00:100:7031::1]", 0),
|
||||
Arguments.of("[1080::8:800:200C:417A]", "[1080::8:800:200C:417A]", 0),
|
||||
Arguments.of("[::192.9.5.5]", "[::192.9.5.5]", 0),
|
||||
Arguments.of("[::FFFF:129.144.52.38]:80", "[::FFFF:129.144.52.38]", 80),
|
||||
Arguments.of("[2010:836B:4179::836B:4179]", "[2010:836B:4179::836B:4179]", 0),
|
||||
// Modified Examples from above, not using square brackets (valid, but should never have a port)
|
||||
Arguments.of("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", null),
|
||||
Arguments.of("1080:0:0:0:8:800:200C:417A", "[1080:0:0:0:8:800:200C:417A]", null),
|
||||
Arguments.of("3ffe:2a00:100:7031::1", "[3ffe:2a00:100:7031::1]", null),
|
||||
Arguments.of("1080::8:800:200C:417A", "[1080::8:800:200C:417A]", null),
|
||||
Arguments.of("::192.9.5.5", "[::192.9.5.5]", null),
|
||||
Arguments.of("::FFFF:129.144.52.38", "[::FFFF:129.144.52.38]", null),
|
||||
Arguments.of("2010:836B:4179::836B:4179", "[2010:836B:4179::836B:4179]", null)
|
||||
Arguments.of("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", 0),
|
||||
Arguments.of("1080:0:0:0:8:800:200C:417A", "[1080:0:0:0:8:800:200C:417A]", 0),
|
||||
Arguments.of("3ffe:2a00:100:7031::1", "[3ffe:2a00:100:7031::1]", 0),
|
||||
Arguments.of("1080::8:800:200C:417A", "[1080::8:800:200C:417A]", 0),
|
||||
Arguments.of("::192.9.5.5", "[::192.9.5.5]", 0),
|
||||
Arguments.of("::FFFF:129.144.52.38", "[::FFFF:129.144.52.38]", 0),
|
||||
Arguments.of("2010:836B:4179::836B:4179", "[2010:836B:4179::836B:4179]", 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("validAuthorityProvider")
|
||||
public void testValidAuthority(String authority, String expectedHost, int expectedPort)
|
||||
{
|
||||
HostPort hostPort = new HostPort(authority);
|
||||
assertThat("Host for: " + authority, hostPort.getHost(), is(expectedHost));
|
||||
assertThat("Port for: " + authority, hostPort.getPort(), is(expectedPort));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("validAuthorityProvider")
|
||||
public void testValidAuthorityViaUnsafe(String authority, String expectedHost, Integer expectedPort)
|
||||
{
|
||||
HostPort hostPort = HostPort.unsafe(authority);
|
||||
assertThat("(unsafe) Host for: " + authority, hostPort.getHost(), is(expectedHost));
|
||||
assertThat("(unsafe) Port for: " + authority, hostPort.getPort(), is(expectedPort));
|
||||
}
|
||||
|
||||
public static Stream<Arguments> invalidAuthorityProvider()
|
||||
{
|
||||
return Stream.of(
|
||||
null,
|
||||
":80", // no host, port only
|
||||
"host:", // no port
|
||||
"127.0.0.1:", // no port
|
||||
"[0::0::0::0::1]:", // no port
|
||||
"[0::0::0::1]", // not valid to Java (InetAddress, InetSocketAddress, or URI) : "Expected hex digits or IPv4 address"
|
||||
"[0::0::0::1]:80", // not valid to Java (InetAddress, InetSocketAddress, or URI) : "Expected hex digits or IPv4 address"
|
||||
"0:1:2:3:4:5:6", // not valid to Java (InetAddress, InetSocketAddress, or URI) : "IPv6 address too short"
|
||||
"host:xxx", // invalid port
|
||||
"127.0.0.1:xxx", // host + invalid port
|
||||
"[0::0::0::0::1]:xxx", // ipv6 + invalid port
|
||||
"host:-80", // host + invalid port
|
||||
"127.0.0.1:-80", // ipv4 + invalid port
|
||||
"[0::0::0::0::1]:-80", // ipv6 + invalid port
|
||||
"127.0.0.1:65536" // ipv4 + port value too high
|
||||
).map(Arguments::of);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("validAuthorityProvider")
|
||||
public void testValidAuthority(String authority, String expectedHost, Integer expectedPort)
|
||||
{
|
||||
try
|
||||
{
|
||||
HostPort hostPort = new HostPort(authority);
|
||||
assertThat(authority, hostPort.getHost(), is(expectedHost));
|
||||
|
||||
if (expectedPort == null)
|
||||
assertThat(authority, hostPort.getPort(), is(0));
|
||||
else
|
||||
assertThat(authority, hostPort.getPort(), is(expectedPort));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (expectedHost != null)
|
||||
e.printStackTrace();
|
||||
assertNull(authority, expectedHost);
|
||||
}
|
||||
Arguments.of(null, "", 0), // null authority
|
||||
Arguments.of(":", "", 0), // no host, no port, port delimiter only
|
||||
Arguments.of(":::::", ":::::", 0), // host is only port delimiters, no port, port delimiter only
|
||||
Arguments.of(":80", "", 80), // no host, port only
|
||||
Arguments.of("::::::80", "::::::80", 0), // no host, port only
|
||||
Arguments.of("host:", "host", 0), // host, port delimiter, but empty
|
||||
Arguments.of("host:::::", "host:::::", 0), // host, port delimiter, but empty
|
||||
Arguments.of("127.0.0.1:", "127.0.0.1", 0), // IPv4, port delimiter, but empty
|
||||
Arguments.of("[0::0::0::0::1", "[0::0::0::0::1", 0), // no ending bracket for IP literal
|
||||
Arguments.of("0::0::0::0::1]", "0::0::0::0::1]", 0), // no starting bracket for IP literal
|
||||
Arguments.of("[0::0::0::0::1]:", "[0::0::0::0::1]", 0), // IP literal, port delimiter, but empty
|
||||
// forbidden characters in reg-name
|
||||
Arguments.of("\"\"", "\"\"", 0), // just quotes
|
||||
// not valid to Java (InetAddress, InetSocketAddress, or URI) : "Expected hex digits or IPv4 address"
|
||||
Arguments.of("[0::0::0::1]", "[0::0::0::1]", 0),
|
||||
Arguments.of("[0::0::0::1]:80", "[0::0::0::1]", 80),
|
||||
// not valid to Java (InetAddress, InetSocketAddress, or URI) : "IPv6 address too short"
|
||||
Arguments.of("0:1:2:3:4:5:6", "0:1:2:3:4:5:6", 0),
|
||||
// Bad ports declarations (should all end up with -1 port)
|
||||
Arguments.of("host:xxx", "host:xxx", 0), // invalid port
|
||||
Arguments.of("127.0.0.1:xxx", "127.0.0.1:xxx", 0), // host + invalid port
|
||||
Arguments.of("[0::0::0::0::1]:xxx", "[0::0::0::0::1]:xxx", 0), // ipv6 + invalid port
|
||||
Arguments.of("[0::0::0::0::1].80", "[0::0::0::0::1].80", 0), // ipv6 with bogus port delimiter
|
||||
Arguments.of("host:-80", "host:-80", 0), // host + invalid negative port
|
||||
Arguments.of("127.0.0.1:-80", "127.0.0.1:-80", 0), // ipv4 + invalid port
|
||||
Arguments.of("[0::0::0::0::1]:-80", "[0::0::0::0::1]:-80", 0), // ipv6 + invalid port
|
||||
Arguments.of("127.0.0.1:65536", "127.0.0.1:65536", 0), // ipv4 + port value too high
|
||||
Arguments.of("example.org:112233445566778899", "example.org:112233445566778899", 0), // ipv4 + port value too high
|
||||
// Examples of bad Host header values (usually client bugs that shouldn't allow them to be sent)
|
||||
Arguments.of("Group - Machine", "Group - Machine", 0), // spaces
|
||||
Arguments.of("<calculated when request is sent>", "<calculated when request is sent>", 0), // spaces and forbidden characters in reg-name
|
||||
Arguments.of("[link](https://example.org/)", "[link](https://example.org/)", 0), // forbidden characters in reg-name
|
||||
Arguments.of("example.org/zed", "example.org/zed", 0), // forbidden character in reg-name (slash)
|
||||
// common hacking attempts, seen as values on the `Host:` request header
|
||||
Arguments.of("| ping 127.0.0.1 -n 10", "| ping 127.0.0.1 -n 10", 0), // forbidden characters in reg-name
|
||||
Arguments.of("%uf%80%ff%xx%uffff", "%uf%80%ff%xx%uffff", 0), // (invalid encoding)
|
||||
Arguments.of("[${jndi${:-:}ldap${:-:}]", "[${jndi${:-:}ldap${:-:}]", 0), // log4j hacking (forbidden chars in reg-name)
|
||||
Arguments.of("[${jndi:ldap://example.org:59377/nessus}]", "[${jndi:ldap://example.org:59377/nessus}]", 0), // log4j hacking (forbidden chars in reg-name)
|
||||
Arguments.of("${ip}", "${ip}", 0), // variation of log4j hack (forbidden chars in reg-name)
|
||||
Arguments.of("' *; host xyz.hacking.pro; '", "' *; host xyz.hacking.pro; '", 0), // forbidden chars in reg-name
|
||||
Arguments.of("'/**/OR/**/1/**/=/**/1", "'/**/OR/**/1/**/=/**/1", 0), // forbidden chars in reg-name
|
||||
Arguments.of("AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT('x',(SELECT (ELT(1=1,1))),'x',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)", "AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT('x',(SELECT (ELT(1=1,1))),'x',FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)", 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidAuthorityProvider")
|
||||
public void testInvalidAuthority(String authority)
|
||||
public void testInvalidAuthority(String rawAuthority, String ignoredExpectedHost, int ignoredExpectedPort)
|
||||
{
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
{
|
||||
new HostPort(authority);
|
||||
});
|
||||
assertThrows(IllegalArgumentException.class, () -> new HostPort(rawAuthority));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidAuthorityProvider")
|
||||
public void testInvalidAuthorityViaUnsafe(String rawAuthority, String expectedHost, int expectedPort)
|
||||
{
|
||||
HostPort hostPort = HostPort.unsafe(rawAuthority);
|
||||
assertThat("(unsafe) Host for: " + rawAuthority, hostPort.getHost(), is(expectedHost));
|
||||
assertThat("(unsafe) Port for: " + rawAuthority, hostPort.getPort(), is(expectedPort));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
@{argLine} ${jetty.surefire.argLine}
|
||||
--add-modules org.eclipse.jetty.util.ajax
|
||||
--add-reads org.eclipse.jetty.ee10.servlet=org.eclipse.jetty.logging
|
||||
--add-reads org.eclipse.jetty.http2.client=org.eclipse.jetty.http2.hpack
|
||||
--add-reads org.eclipse.jetty.http2.client=org.eclipse.jetty.logging
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -129,15 +129,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
public static final int SERVLET_MAJOR_VERSION = 5;
|
||||
public static final int SERVLET_MINOR_VERSION = 0;
|
||||
public static final Class<?>[] SERVLET_LISTENER_TYPES =
|
||||
{
|
||||
ServletContextListener.class,
|
||||
ServletContextAttributeListener.class,
|
||||
ServletRequestListener.class,
|
||||
ServletRequestAttributeListener.class,
|
||||
HttpSessionIdListener.class,
|
||||
HttpSessionListener.class,
|
||||
HttpSessionAttributeListener.class
|
||||
};
|
||||
{
|
||||
ServletContextListener.class,
|
||||
ServletContextAttributeListener.class,
|
||||
ServletRequestListener.class,
|
||||
ServletRequestAttributeListener.class,
|
||||
HttpSessionIdListener.class,
|
||||
HttpSessionListener.class,
|
||||
HttpSessionAttributeListener.class
|
||||
};
|
||||
|
||||
public static final int DEFAULT_LISTENER_TYPE_INDEX = 1;
|
||||
|
||||
|
@ -1629,8 +1629,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
if (servletContext != null)
|
||||
{
|
||||
String encodedContextPath = servletContext instanceof APIContext
|
||||
? ((APIContext)servletContext).getContextHandler().getContextPathEncoded()
|
||||
: URIUtil.encodePath(servletContext.getContextPath());
|
||||
? ((APIContext)servletContext).getContextHandler().getContextPathEncoded()
|
||||
: URIUtil.encodePath(servletContext.getContextPath());
|
||||
if (!StringUtil.isEmpty(encodedContextPath))
|
||||
{
|
||||
encodedPathQuery = URIUtil.normalizePath(URIUtil.addEncodedPaths(encodedContextPath, encodedPathQuery));
|
||||
|
@ -2501,7 +2501,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
Thread.currentThread().setContextClassLoader(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void insertHandler(Nested handler)
|
||||
{
|
||||
|
@ -2510,11 +2510,11 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
tail = (Handler.Wrapper)tail.getHandler();
|
||||
if (tail.getHandler() != null)
|
||||
throw new IllegalArgumentException("bad tail of inserted wrapper chain");
|
||||
|
||||
|
||||
tail.setHandler(getHandler());
|
||||
super.setHandler(handler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setHandler(Handler handler)
|
||||
{
|
||||
|
@ -2564,8 +2564,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
__context.set(_apiContext);
|
||||
super.notifyEnterScope(coreRequest);
|
||||
Request request = (coreRequest instanceof CoreContextRequest coreContextRequest)
|
||||
? coreContextRequest.getHttpChannel().getRequest()
|
||||
: null;
|
||||
? coreContextRequest.getHttpChannel().getRequest()
|
||||
: null;
|
||||
ContextHandler.this.enterScope(request, "Entered core context");
|
||||
}
|
||||
|
||||
|
@ -2575,8 +2575,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
try
|
||||
{
|
||||
Request request = (coreRequest instanceof CoreContextRequest coreContextRequest)
|
||||
? coreContextRequest.getHttpChannel().getRequest()
|
||||
: null;
|
||||
? coreContextRequest.getHttpChannel().getRequest()
|
||||
: null;
|
||||
ContextHandler.this.exitScope(request);
|
||||
super.notifyExitScope(coreRequest);
|
||||
}
|
||||
|
@ -2591,7 +2591,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
|
||||
return ContextHandler.this;
|
||||
}
|
||||
|
||||
|
||||
class CoreContext extends ScopedContext
|
||||
{
|
||||
public APIContext getAPIContext()
|
||||
|
@ -2612,4 +2612,4 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,8 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
@{argLine} ${jetty.surefire.argLine} --add-reads org.eclipse.jetty.ee9.proxy=org.eclipse.jetty.logging
|
||||
@{argLine} ${jetty.surefire.argLine}
|
||||
--add-reads org.eclipse.jetty.ee9.proxy=org.eclipse.jetty.logging
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -22,7 +22,17 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
@{argLine} ${jetty.surefire.argLine} --add-modules jetty.servlet.api --add-modules org.eclipse.jetty.util --add-modules org.eclipse.jetty.io --add-modules org.eclipse.jetty.http --add-modules org.eclipse.jetty.server --add-modules org.eclipse.jetty.session --add-modules org.eclipse.jetty.ee9.nested --add-reads org.eclipse.jetty.ee9.servlets=java.management --add-reads org.eclipse.jetty.ee9.servlets=org.eclipse.jetty.jmx --add-reads org.eclipse.jetty.ee9.servlets=org.eclipse.jetty.logging
|
||||
@{argLine} ${jetty.surefire.argLine}
|
||||
--add-modules jetty.servlet.api
|
||||
--add-modules org.eclipse.jetty.util
|
||||
--add-modules org.eclipse.jetty.io
|
||||
--add-modules org.eclipse.jetty.http
|
||||
--add-modules org.eclipse.jetty.server
|
||||
--add-modules org.eclipse.jetty.session
|
||||
--add-modules org.eclipse.jetty.ee9.nested
|
||||
--add-reads org.eclipse.jetty.ee9.servlets=java.management
|
||||
--add-reads org.eclipse.jetty.ee9.servlets=org.eclipse.jetty.jmx
|
||||
--add-reads org.eclipse.jetty.ee9.servlets=org.eclipse.jetty.logging
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
24
pom.xml
24
pom.xml
|
@ -53,6 +53,29 @@
|
|||
<infinispan.protostream.version>4.6.0.Final</infinispan.protostream.version>
|
||||
<infinispan.version>11.0.17.Final</infinispan.version>
|
||||
<jackson.version>2.14.2</jackson.version>
|
||||
<jakarta.activation.api.version>2.0.1</jakarta.activation.api.version>
|
||||
<jakarta.annotation.api.version>2.1.1</jakarta.annotation.api.version>
|
||||
<jakarta.authentication.api.version>2.0.0</jakarta.authentication.api.version>
|
||||
<jakarta.el.api.version>4.0.0</jakarta.el.api.version>
|
||||
<jakarta.enterprise.cdi.api.version>3.0.0</jakarta.enterprise.cdi.api.version>
|
||||
<jakarta.inject.api.version>2.0.1</jakarta.inject.api.version>
|
||||
<jakarta.interceptor.api.version>2.0.0</jakarta.interceptor.api.version>
|
||||
<jakarta.mail.api.version>2.0.1</jakarta.mail.api.version>
|
||||
<jakarta.servlet.api.version>5.0.0</jakarta.servlet.api.version>
|
||||
<jakarta.servlet.jsp.api.version>3.0.0</jakarta.servlet.jsp.api.version>
|
||||
<jakarta.servlet.jsp.jstl.api.version>2.0.0</jakarta.servlet.jsp.jstl.api.version>
|
||||
<jakarta.servlet.jsp.jstl.impl.version>2.0.0</jakarta.servlet.jsp.jstl.impl.version> <!-- TODO: remove? -->
|
||||
<jakarta.transaction-api.version>2.0.0</jakarta.transaction-api.version>
|
||||
<jakarta.websocket.api.version>2.0.0</jakarta.websocket.api.version>
|
||||
<jakarta.ws.rs.api.version>3.1.0</jakarta.ws.rs.api.version>
|
||||
<jakarta.xml.bind.api.version>3.0.1</jakarta.xml.bind.api.version>
|
||||
<jakarta.xml.bind.impl.version>3.0.2</jakarta.xml.bind.impl.version>
|
||||
<jakarta.xml.jaxws.impl.version>3.0.2</jakarta.xml.jaxws.impl.version>
|
||||
<jakarta.xml.ws.api.version>3.0.1</jakarta.xml.ws.api.version>
|
||||
<javax.activation.impl.version>1.1.0.v201105071233</javax.activation.impl.version> <!-- TODO: remove? -->
|
||||
<javax.cdi.api.version>2.0</javax.cdi.api.version> <!-- TODO: remove? -->
|
||||
<javax.mail.glassfish.version>1.4.1.v201005082020</javax.mail.glassfish.version> <!-- TODO: remove? -->
|
||||
<javax.security.auth.message.version>1.0.0.v201108011116</javax.security.auth.message.version> <!-- TODO: remove? -->
|
||||
<jboss.logging.annotations.version>2.2.1.Final</jboss.logging.annotations.version>
|
||||
<jboss.logging.processor.version>2.2.1.Final</jboss.logging.processor.version>
|
||||
<jboss.logging.version>3.5.0.Final</jboss.logging.version>
|
||||
|
@ -149,7 +172,6 @@
|
|||
<maven.remote-resources-plugin.version>3.0.0</maven.remote-resources-plugin.version>
|
||||
<maven.resources.plugin.version>3.3.0</maven.resources.plugin.version>
|
||||
<maven.shade.plugin.version>3.4.1</maven.shade.plugin.version>
|
||||
<maven.site.plugin.version>3.12.0</maven.site.plugin.version>
|
||||
<maven.surefire.plugin.version>3.0.0-M8</maven.surefire.plugin.version>
|
||||
<maven.source.plugin.version>3.2.1</maven.source.plugin.version>
|
||||
<maven.war.plugin.version>3.3.2</maven.war.plugin.version>
|
||||
|
|
Loading…
Reference in New Issue