From 79395c5f6197aef6e3eddf505d5b5c4f11f761ea Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 17 Sep 2021 16:13:58 +1000 Subject: [PATCH 1/8] Fix #6860 IPv6 Format Fix #6860 IPv6 format by adding a per context configuration. Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/server/Request.java | 127 +++++++----------- .../jetty/server/handler/ContextHandler.java | 97 +++++-------- .../java/org/eclipse/jetty/util/HostPort.java | 18 +++ 3 files changed, 100 insertions(+), 142 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 635550aec58e..9163063e625e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -18,13 +18,20 @@ package org.eclipse.jetty.server; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; +import org.eclipse.jetty.http.*; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.RuntimeIOException; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandler.Context; +import org.eclipse.jetty.server.session.Session; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.util.*; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +import javax.servlet.*; +import javax.servlet.http.*; +import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; @@ -32,68 +39,9 @@ import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.security.Principal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.function.Supplier; import java.util.stream.Collectors; -import javax.servlet.AsyncContext; -import javax.servlet.AsyncListener; -import javax.servlet.DispatcherType; -import javax.servlet.MultipartConfigElement; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletRequestAttributeEvent; -import javax.servlet.ServletRequestAttributeListener; -import javax.servlet.ServletRequestWrapper; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; - -import org.eclipse.jetty.http.BadMessageException; -import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpCompliance; -import org.eclipse.jetty.http.HttpCookie; -import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpHeaderValue; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpScheme; -import org.eclipse.jetty.http.HttpStatus; -import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.http.MetaData; -import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.RuntimeIOException; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.handler.ContextHandler.Context; -import org.eclipse.jetty.server.session.Session; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.util.Attributes; -import org.eclipse.jetty.util.AttributesMap; -import org.eclipse.jetty.util.HostPort; -import org.eclipse.jetty.util.IO; -import org.eclipse.jetty.util.MultiMap; -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.URIUtil; -import org.eclipse.jetty.util.UrlEncoded; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; /** * Jetty Request. @@ -998,7 +946,7 @@ public String getLocalAddr() String name = InetAddress.getLocalHost().getHostAddress(); if (StringUtil.ALL_INTERFACES.equals(name)) return null; - return HostPort.normalizeHost(name); + return formatAddrOrHost(name); } catch (UnknownHostException e) { @@ -1014,7 +962,7 @@ public String getLocalAddr() String result = address == null ? local.getHostString() : address.getHostAddress(); - return HostPort.normalizeHost(result); + return formatAddrOrHost(result); } /* @@ -1027,7 +975,7 @@ public String getLocalName() { InetSocketAddress local = _channel.getLocalAddress(); if (local != null) - return HostPort.normalizeHost(local.getHostString()); + return formatAddrOrHost(local.getHostString()); } try @@ -1035,7 +983,7 @@ public String getLocalName() String name = InetAddress.getLocalHost().getHostName(); if (StringUtil.ALL_INTERFACES.equals(name)) return null; - return HostPort.normalizeHost(name); + return formatAddrOrHost(name); } catch (UnknownHostException e) { @@ -1247,8 +1195,7 @@ public InetSocketAddress getRemoteInetSocketAddress() * @see javax.servlet.ServletRequest#getRemoteAddr() */ @Override - public String getRemoteAddr() - { + public String getRemoteAddr() { InetSocketAddress remote = _remote; if (remote == null) remote = _channel.getRemoteAddress(); @@ -1257,12 +1204,10 @@ public String getRemoteAddr() InetAddress address = remote.getAddress(); String result = address == null - ? remote.getHostString() - : address.getHostAddress(); - // Add IPv6 brackets if necessary, to be consistent - // with cases where _remote has been built from other - // sources such as forward headers or PROXY protocol. - return HostPort.normalizeHost(result); + ? remote.getHostString() + : address.getHostAddress(); + + return formatAddrOrHost(result); } /* @@ -1276,8 +1221,9 @@ public String getRemoteHost() remote = _channel.getRemoteAddress(); if (remote == null) return ""; + // We want the URI host, so add IPv6 brackets if necessary. - return HostPort.normalizeHost(remote.getHostString()); + return formatAddrOrHost(remote.getHostString()); } /* @@ -1432,12 +1378,12 @@ private String findServerName() // Return host from connection String name = getLocalName(); if (name != null) - return HostPort.normalizeHost(name); + return formatAddrOrHost(name); // Return the local host try { - return HostPort.normalizeHost(InetAddress.getLocalHost().getHostAddress()); + return formatAddrOrHost(InetAddress.getLocalHost().getHostAddress()); } catch (UnknownHostException e) { @@ -2604,4 +2550,21 @@ public T upgrade(Class handlerClass) throws IO { throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty"); } + + private String formatAddrOrHost(String addr) + { + if (addr == null) + return addr; + if (getContext() == null || getContext().getContextHandler() == null) + return HostPort.normalizeHost(addr); + switch(getContext().getContextHandler().getIpv6Format()) + { + case BRACKETED: + return HostPort.normalizeHost(addr); + case UNBRACKETED: + return HostPort.denormalizeHost(addr); + default: + return addr; + } + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 97ef7e7442cd..adf2d4b9253d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -18,6 +18,22 @@ package org.eclipse.jetty.server.handler; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.server.*; +import org.eclipse.jetty.util.*; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.component.DumpableCollection; +import org.eclipse.jetty.util.component.Graceful; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; + +import javax.servlet.*; +import javax.servlet.FilterRegistration.Dynamic; +import javax.servlet.descriptor.JspConfigDescriptor; +import javax.servlet.http.*; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -27,68 +43,10 @@ import java.net.URLClassLoader; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.FilterRegistration; -import javax.servlet.FilterRegistration.Dynamic; -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextAttributeEvent; -import javax.servlet.ServletContextAttributeListener; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; -import javax.servlet.ServletRequestAttributeListener; -import javax.servlet.ServletRequestEvent; -import javax.servlet.ServletRequestListener; -import javax.servlet.SessionCookieConfig; -import javax.servlet.SessionTrackingMode; -import javax.servlet.descriptor.JspConfigDescriptor; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSessionAttributeListener; -import javax.servlet.http.HttpSessionIdListener; -import javax.servlet.http.HttpSessionListener; - -import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.server.ClassLoaderDump; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Dispatcher; -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HandlerContainer; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.util.Attributes; -import org.eclipse.jetty.util.AttributesMap; -import org.eclipse.jetty.util.FutureCallback; -import org.eclipse.jetty.util.Loader; -import org.eclipse.jetty.util.MultiException; -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.URIUtil; -import org.eclipse.jetty.util.annotation.ManagedAttribute; -import org.eclipse.jetty.util.annotation.ManagedObject; -import org.eclipse.jetty.util.component.DumpableCollection; -import org.eclipse.jetty.util.component.Graceful; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.resource.Resource; /** * ContextHandler. @@ -188,7 +146,14 @@ public enum ContextStatus INITIALIZED, DESTROYED } - + + public enum IPV6_FORMAT + { + BRACKETED, + UNBRACKETED, + UNCHANGED + }; + protected ContextStatus _contextStatus = ContextStatus.NOTSET; protected Context _scontext; private final AttributesMap _attributes; @@ -227,6 +192,7 @@ public enum ContextStatus private final List _durableListeners = new CopyOnWriteArrayList<>(); private String[] _protectedTargets; private final CopyOnWriteArrayList _aliasChecks = new CopyOnWriteArrayList<>(); + private IPV6_FORMAT _ipv6Format = IPV6_FORMAT.BRACKETED; public enum Availability { @@ -292,6 +258,17 @@ public Context getServletContext() return _scontext; } + @ManagedAttribute("The format of IPv6 addresses return from the servlet API") + public IPV6_FORMAT getIpv6Format() + { + return _ipv6Format; + } + + public void setIpv6Format(IPV6_FORMAT ipv6Format) + { + _ipv6Format = _ipv6Format; + } + /** * @return the allowNullPathInfo true if /context is not redirected to /context/ */ diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java b/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java index a1aebd72e315..83b8b47cc3fd 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java @@ -156,6 +156,24 @@ public static String normalizeHost(String host) return "[" + host + "]"; } + /** + * Denormalizes IPv6 address as per https://tools.ietf.org/html/rfc2732 + * and https://tools.ietf.org/html/rfc6874, + * removing square brackets if they are present. + * + * @param host a host name, IPv4 address, IPv6 address or IPv6 literal + * @return a host name or an IPv4 address or an IPv6 address + */ + public static String denormalizeHost(String host) + { + // if it is normalized IPv6 or could not be IPv6, return + if (host.isEmpty() || host.charAt(0) != '[' || host.charAt(host.length() - 1) != ']') + return host; + + // normalize with [ ] + return host.substring(1, host.length() - 2); + } + /** * Parse a string representing a port validating it is a valid port value. * From de46e0a76a64cf62251ea059d2404c0c67b90cae Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Fri, 17 Sep 2021 16:51:02 +1000 Subject: [PATCH 2/8] Fix checkstyle errors after IPv6 Format changes. Signed-off-by: Lachlan Roberts --- .../org/eclipse/jetty/server/Request.java | 87 +++++++++++++++---- .../jetty/server/handler/ContextHandler.java | 86 +++++++++++++----- 2 files changed, 134 insertions(+), 39 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 9163063e625e..16b77df261e7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -18,20 +18,13 @@ package org.eclipse.jetty.server; -import org.eclipse.jetty.http.*; -import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.RuntimeIOException; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.handler.ContextHandler.Context; -import org.eclipse.jetty.server.session.Session; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.util.*; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; @@ -39,9 +32,68 @@ import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.security.Principal; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.function.Supplier; import java.util.stream.Collectors; +import javax.servlet.AsyncContext; +import javax.servlet.AsyncListener; +import javax.servlet.DispatcherType; +import javax.servlet.MultipartConfigElement; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletRequestAttributeEvent; +import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestWrapper; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +import org.eclipse.jetty.http.BadMessageException; +import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpCompliance; +import org.eclipse.jetty.http.HttpCookie; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpHeaderValue; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.MetaData; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.RuntimeIOException; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandler.Context; +import org.eclipse.jetty.server.session.Session; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.util.Attributes; +import org.eclipse.jetty.util.AttributesMap; +import org.eclipse.jetty.util.HostPort; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.UrlEncoded; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; /** * Jetty Request. @@ -1195,7 +1247,8 @@ public InetSocketAddress getRemoteInetSocketAddress() * @see javax.servlet.ServletRequest#getRemoteAddr() */ @Override - public String getRemoteAddr() { + public String getRemoteAddr() + { InetSocketAddress remote = _remote; if (remote == null) remote = _channel.getRemoteAddress(); @@ -2557,7 +2610,7 @@ private String formatAddrOrHost(String addr) return addr; if (getContext() == null || getContext().getContextHandler() == null) return HostPort.normalizeHost(addr); - switch(getContext().getContextHandler().getIpv6Format()) + switch (getContext().getContextHandler().getIpv6Format()) { case BRACKETED: return HostPort.normalizeHost(addr); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index adf2d4b9253d..b20b4e7e7511 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -18,22 +18,6 @@ package org.eclipse.jetty.server.handler; -import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.server.*; -import org.eclipse.jetty.util.*; -import org.eclipse.jetty.util.annotation.ManagedAttribute; -import org.eclipse.jetty.util.annotation.ManagedObject; -import org.eclipse.jetty.util.component.DumpableCollection; -import org.eclipse.jetty.util.component.Graceful; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.resource.Resource; - -import javax.servlet.*; -import javax.servlet.FilterRegistration.Dynamic; -import javax.servlet.descriptor.JspConfigDescriptor; -import javax.servlet.http.*; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -43,10 +27,68 @@ import java.net.URLClassLoader; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.FilterRegistration.Dynamic; +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextAttributeEvent; +import javax.servlet.ServletContextAttributeListener; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSessionAttributeListener; +import javax.servlet.http.HttpSessionIdListener; +import javax.servlet.http.HttpSessionListener; + +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.server.ClassLoaderDump; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Dispatcher; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HandlerContainer; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.Attributes; +import org.eclipse.jetty.util.AttributesMap; +import org.eclipse.jetty.util.FutureCallback; +import org.eclipse.jetty.util.Loader; +import org.eclipse.jetty.util.MultiException; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.component.DumpableCollection; +import org.eclipse.jetty.util.component.Graceful; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; /** * ContextHandler. @@ -147,12 +189,12 @@ public enum ContextStatus DESTROYED } - public enum IPV6_FORMAT + public enum IPV6Format { BRACKETED, UNBRACKETED, UNCHANGED - }; + } protected ContextStatus _contextStatus = ContextStatus.NOTSET; protected Context _scontext; @@ -192,7 +234,7 @@ public enum IPV6_FORMAT private final List _durableListeners = new CopyOnWriteArrayList<>(); private String[] _protectedTargets; private final CopyOnWriteArrayList _aliasChecks = new CopyOnWriteArrayList<>(); - private IPV6_FORMAT _ipv6Format = IPV6_FORMAT.BRACKETED; + private IPV6Format _ipv6Format = IPV6Format.BRACKETED; public enum Availability { @@ -259,12 +301,12 @@ public Context getServletContext() } @ManagedAttribute("The format of IPv6 addresses return from the servlet API") - public IPV6_FORMAT getIpv6Format() + public IPV6Format getIpv6Format() { return _ipv6Format; } - public void setIpv6Format(IPV6_FORMAT ipv6Format) + public void setIpv6Format(IPV6Format ipv6Format) { _ipv6Format = _ipv6Format; } From 316b4bffbc65b7adf01bc0291acdf36365667690 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 17 Sep 2021 18:13:56 +1000 Subject: [PATCH 3/8] Fix #6860 IPv6 Format updates from review Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/server/Request.java | 6 ++++-- .../org/eclipse/jetty/server/handler/ContextHandler.java | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 16b77df261e7..813b85edce9e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -2610,14 +2610,16 @@ private String formatAddrOrHost(String addr) return addr; if (getContext() == null || getContext().getContextHandler() == null) return HostPort.normalizeHost(addr); - switch (getContext().getContextHandler().getIpv6Format()) + switch (getContext().getContextHandler().getIPv6Format()) { case BRACKETED: return HostPort.normalizeHost(addr); case UNBRACKETED: return HostPort.denormalizeHost(addr); - default: + case UNCHANGED: return addr; + default: + throw new IllegalStateException(); } } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index b20b4e7e7511..7775d8ff82d9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -189,6 +189,9 @@ public enum ContextStatus DESTROYED } + /** + * The IPv6 Format to use in the servlet request API + */ public enum IPV6Format { BRACKETED, @@ -300,13 +303,13 @@ public Context getServletContext() return _scontext; } - @ManagedAttribute("The format of IPv6 addresses return from the servlet API") - public IPV6Format getIpv6Format() + @ManagedAttribute("The format of IPv6 addresses returned from the servlet API") + public IPV6Format getIPv6Format() { return _ipv6Format; } - public void setIpv6Format(IPV6Format ipv6Format) + public void setIPv6Format(IPV6Format ipv6Format) { _ipv6Format = _ipv6Format; } From 11720f7e7aa3bc56eb0fa75fe83a8711406276cb Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Sun, 19 Sep 2021 13:42:56 +1000 Subject: [PATCH 4/8] Fix #6860 IPv6 Format unit test and fixes Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/server/Request.java | 4 +- .../jetty/server/handler/ContextHandler.java | 2 +- .../org/eclipse/jetty/server/RequestTest.java | 88 ++++++++++++++++++- .../java/org/eclipse/jetty/util/HostPort.java | 2 +- 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 813b85edce9e..47b657d83d60 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1402,7 +1402,7 @@ public String getScheme() public String getServerName() { MetaData.Request metadata = _metaData; - String name = metadata == null ? null : metadata.getURI().getHost(); + String name = metadata == null ? null : formatAddrOrHost(metadata.getURI().getHost()); // Return already determined host if (name != null) @@ -1424,7 +1424,7 @@ private String findServerName() { HostPortHttpField authority = (HostPortHttpField)host; metadata.getURI().setAuthority(authority.getHost(), authority.getPort()); - return authority.getHost(); + return formatAddrOrHost(authority.getHost()); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 7775d8ff82d9..b4cd3a9acca7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -311,7 +311,7 @@ public IPV6Format getIPv6Format() public void setIPv6Format(IPV6Format ipv6Format) { - _ipv6Format = _ipv6Format; + _ipv6Format = ipv6Format; } /** diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 8b6eeed62102..1ac6b5b9191f 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -26,6 +26,9 @@ import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -95,6 +98,7 @@ public class RequestTest public WorkDir workDir; private Server _server; private LocalConnector _connector; + private ContextHandler _context; private RequestHandler _handler; @BeforeEach @@ -110,8 +114,10 @@ public void init() throws Exception _connector = new LocalConnector(_server, http); _server.addConnector(_connector); _connector.setIdleTimeout(500); + _context = new ContextHandler(); + _server.setHandler(_context); _handler = new RequestHandler(); - _server.setHandler(_handler); + _context.setHandler(_handler); ErrorHandler errors = new ErrorHandler(); errors.setServer(_server); @@ -933,6 +939,84 @@ public boolean check(HttpServletRequest request, HttpServletResponse response) assertEquals("8888", results.get(i++)); } + + @Test + public void testIPv6() throws Exception + { + final ArrayList results = new ArrayList<>(); + final InetAddress local = Inet6Address.getByAddress("localIPv6", new byte[] {0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8}); + final InetSocketAddress localAddr = new InetSocketAddress(local, 32768); + _handler._checker = new RequestTester() + { + @Override + public boolean check(HttpServletRequest request, HttpServletResponse response) + { + ((Request)request).setRemoteAddr(localAddr); + results.add(request.getRemoteAddr()); + results.add(request.getRemoteHost()); + results.add(Integer.toString(request.getRemotePort())); + results.add(request.getServerName()); + results.add(Integer.toString(request.getServerPort())); + results.add(request.getLocalAddr()); + results.add(Integer.toString(request.getLocalPort())); + return true; + } + }; + + _context.setIPv6Format(ContextHandler.IPV6Format.BRACKETED); + results.clear(); + String response = _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: [::1]:8888\n" + + "Connection: close\n" + + "\n"); + int i = 0; + assertThat(response, containsString("200 OK")); + assertEquals("[1:2:3:4:5:6:7:8]", results.get(i++)); + assertEquals("localIPv6", results.get(i++)); + assertEquals("32768", results.get(i++)); + assertEquals("[::1]", results.get(i++)); + assertEquals("8888", results.get(i++)); + assertEquals("0.0.0.0", results.get(i++)); + assertEquals("0", results.get(i++)); + + _context.setIPv6Format(ContextHandler.IPV6Format.UNBRACKETED); + results.clear(); + response = _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: [::1]:8888\n" + + "Connection: close\n" + + "\n"); + i = 0; + assertThat(response, containsString("200 OK")); + assertEquals("1:2:3:4:5:6:7:8", results.get(i++)); + assertEquals("localIPv6", results.get(i++)); + assertEquals("32768", results.get(i++)); + assertEquals("::1", results.get(i++)); + assertEquals("8888", results.get(i++)); + assertEquals("0.0.0.0", results.get(i++)); + assertEquals("0", results.get(i++)); + + _context.setIPv6Format(ContextHandler.IPV6Format.UNCHANGED); + results.clear(); + response = _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: [::1]:8888\n" + + "Connection: close\n" + + "\n"); + i = 0; + assertThat(response, containsString("200 OK")); + assertEquals("1:2:3:4:5:6:7:8", results.get(i++)); + assertEquals("localIPv6", results.get(i++)); + assertEquals("32768", results.get(i++)); + assertEquals("[::1]", results.get(i++)); + assertEquals("8888", results.get(i++)); + assertEquals("0.0.0.0", results.get(i++)); + assertEquals("0", results.get(i++)); + } + + + @Test public void testContent() throws Exception { @@ -1686,6 +1770,8 @@ public void testHashDOSSize() throws Exception try (StacklessLogging stackless = new StacklessLogging(HttpChannel.class)) { LOG.info("Expecting maxFormSize limit and too much data exceptions..."); + _context.setMaxFormContentSize(3396); + _context.setMaxFormKeys(1000); _server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", 3396); _server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys", 1000); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java b/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java index 83b8b47cc3fd..79f0f7d01afd 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java @@ -171,7 +171,7 @@ public static String denormalizeHost(String host) return host; // normalize with [ ] - return host.substring(1, host.length() - 2); + return host.substring(1, host.length() - 1); } /** From 38192fcae5c31504a398016c9a4ad1e1845b23f0 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Sep 2021 09:05:51 +1000 Subject: [PATCH 5/8] Fix #6860 IPv6 Format fix style Signed-off-by: Greg Wilkins --- .../test/java/org/eclipse/jetty/server/RequestTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 1ac6b5b9191f..9816706c2af6 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -939,12 +939,13 @@ public boolean check(HttpServletRequest request, HttpServletResponse response) assertEquals("8888", results.get(i++)); } - @Test public void testIPv6() throws Exception { final ArrayList results = new ArrayList<>(); - final InetAddress local = Inet6Address.getByAddress("localIPv6", new byte[] {0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8}); + final InetAddress local = Inet6Address.getByAddress("localIPv6", new byte[]{ + 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 + }); final InetSocketAddress localAddr = new InetSocketAddress(local, 32768); _handler._checker = new RequestTester() { @@ -1015,8 +1016,6 @@ public boolean check(HttpServletRequest request, HttpServletResponse response) assertEquals("0", results.get(i++)); } - - @Test public void testContent() throws Exception { From 1ddeeedbafa9c3de6403d42112de5225e0f9b011 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Sep 2021 16:43:46 +1000 Subject: [PATCH 6/8] simplified solution to avoid adding new public APIs Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/server/HttpChannel.java | 10 ++++ .../org/eclipse/jetty/server/Request.java | 40 ++++---------- .../jetty/server/handler/ContextHandler.java | 22 -------- .../org/eclipse/jetty/server/RequestTest.java | 55 +++++++++++-------- .../java/org/eclipse/jetty/util/HostPort.java | 20 +------ 5 files changed, 53 insertions(+), 94 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index c46236a7a242..492c23cf5ab1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -57,6 +57,7 @@ import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.SharedBlockingCallback.Blocker; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; @@ -132,6 +133,15 @@ public boolean isSendError() return _state.isSendError(); } + /** Format the address or host returned from Request methods + * @param addr The address or host + * @return Default implementation returns {@link HostPort#normalizeHost(String)} + */ + protected String formatAddrOrHost(String addr) + { + return HostPort.normalizeHost(addr); + } + protected HttpInput newHttpInput(HttpChannelState state) { return new HttpInput(state); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 47b657d83d60..eeaf3653e1d1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -86,7 +86,6 @@ import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.AttributesMap; -import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; @@ -998,7 +997,7 @@ public String getLocalAddr() String name = InetAddress.getLocalHost().getHostAddress(); if (StringUtil.ALL_INTERFACES.equals(name)) return null; - return formatAddrOrHost(name); + return _channel.formatAddrOrHost(name); } catch (UnknownHostException e) { @@ -1014,7 +1013,7 @@ public String getLocalAddr() String result = address == null ? local.getHostString() : address.getHostAddress(); - return formatAddrOrHost(result); + return _channel.formatAddrOrHost(result); } /* @@ -1027,7 +1026,7 @@ public String getLocalName() { InetSocketAddress local = _channel.getLocalAddress(); if (local != null) - return formatAddrOrHost(local.getHostString()); + return _channel.formatAddrOrHost(local.getHostString()); } try @@ -1035,7 +1034,7 @@ public String getLocalName() String name = InetAddress.getLocalHost().getHostName(); if (StringUtil.ALL_INTERFACES.equals(name)) return null; - return formatAddrOrHost(name); + return _channel.formatAddrOrHost(name); } catch (UnknownHostException e) { @@ -1260,7 +1259,7 @@ public String getRemoteAddr() ? remote.getHostString() : address.getHostAddress(); - return formatAddrOrHost(result); + return _channel.formatAddrOrHost(result); } /* @@ -1276,7 +1275,7 @@ public String getRemoteHost() return ""; // We want the URI host, so add IPv6 brackets if necessary. - return formatAddrOrHost(remote.getHostString()); + return _channel.formatAddrOrHost(remote.getHostString()); } /* @@ -1402,7 +1401,7 @@ public String getScheme() public String getServerName() { MetaData.Request metadata = _metaData; - String name = metadata == null ? null : formatAddrOrHost(metadata.getURI().getHost()); + String name = metadata == null ? null : _channel.formatAddrOrHost(metadata.getURI().getHost()); // Return already determined host if (name != null) @@ -1424,19 +1423,19 @@ private String findServerName() { HostPortHttpField authority = (HostPortHttpField)host; metadata.getURI().setAuthority(authority.getHost(), authority.getPort()); - return formatAddrOrHost(authority.getHost()); + return _channel.formatAddrOrHost(authority.getHost()); } } // Return host from connection String name = getLocalName(); if (name != null) - return formatAddrOrHost(name); + return _channel.formatAddrOrHost(name); // Return the local host try { - return formatAddrOrHost(InetAddress.getLocalHost().getHostAddress()); + return _channel.formatAddrOrHost(InetAddress.getLocalHost().getHostAddress()); } catch (UnknownHostException e) { @@ -2603,23 +2602,4 @@ public T upgrade(Class handlerClass) throws IO { throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty"); } - - private String formatAddrOrHost(String addr) - { - if (addr == null) - return addr; - if (getContext() == null || getContext().getContextHandler() == null) - return HostPort.normalizeHost(addr); - switch (getContext().getContextHandler().getIPv6Format()) - { - case BRACKETED: - return HostPort.normalizeHost(addr); - case UNBRACKETED: - return HostPort.denormalizeHost(addr); - case UNCHANGED: - return addr; - default: - throw new IllegalStateException(); - } - } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index b4cd3a9acca7..45cef634bccc 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -189,16 +189,6 @@ public enum ContextStatus DESTROYED } - /** - * The IPv6 Format to use in the servlet request API - */ - public enum IPV6Format - { - BRACKETED, - UNBRACKETED, - UNCHANGED - } - protected ContextStatus _contextStatus = ContextStatus.NOTSET; protected Context _scontext; private final AttributesMap _attributes; @@ -237,7 +227,6 @@ public enum IPV6Format private final List _durableListeners = new CopyOnWriteArrayList<>(); private String[] _protectedTargets; private final CopyOnWriteArrayList _aliasChecks = new CopyOnWriteArrayList<>(); - private IPV6Format _ipv6Format = IPV6Format.BRACKETED; public enum Availability { @@ -303,17 +292,6 @@ public Context getServletContext() return _scontext; } - @ManagedAttribute("The format of IPv6 addresses returned from the servlet API") - public IPV6Format getIPv6Format() - { - return _ipv6Format; - } - - public void setIPv6Format(IPV6Format ipv6Format) - { - _ipv6Format = ipv6Format; - } - /** * @return the allowNullPathInfo true if /context is not redirected to /context/ */ diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 9816706c2af6..39237e708500 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -55,6 +55,8 @@ import org.eclipse.jetty.http.HttpComplianceSection; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.LocalConnector.LocalEndPoint; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler; @@ -100,12 +102,37 @@ public class RequestTest private LocalConnector _connector; private ContextHandler _context; private RequestHandler _handler; + private boolean _normalizeAddress = true; @BeforeEach public void init() throws Exception { _server = new Server(); - HttpConnectionFactory http = new HttpConnectionFactory(); + HttpConnectionFactory http = new HttpConnectionFactory() + { + @Override + public Connection newConnection(Connector connector, EndPoint endPoint) + { + HttpConnection conn = new HttpConnection(getHttpConfiguration(), connector, endPoint, getHttpCompliance(), isRecordHttpComplianceViolations()) + { + @Override + protected HttpChannelOverHttp newHttpChannel() + { + return new HttpChannelOverHttp(this, getConnector(), getHttpConfiguration(), getEndPoint(), this) + { + @Override + protected String formatAddrOrHost(String addr) + { + if (_normalizeAddress) + return super.formatAddrOrHost(addr); + return addr; + } + }; + } + }; + return configure(conn, connector, endPoint); + } + }; http.setInputBufferSize(1024); http.getHttpConfiguration().setRequestHeaderSize(512); http.getHttpConfiguration().setResponseHeaderSize(512); @@ -964,8 +991,7 @@ public boolean check(HttpServletRequest request, HttpServletResponse response) } }; - _context.setIPv6Format(ContextHandler.IPV6Format.BRACKETED); - results.clear(); + _normalizeAddress = true; String response = _connector.getResponse( "GET / HTTP/1.1\n" + "Host: [::1]:8888\n" + @@ -979,26 +1005,9 @@ public boolean check(HttpServletRequest request, HttpServletResponse response) assertEquals("[::1]", results.get(i++)); assertEquals("8888", results.get(i++)); assertEquals("0.0.0.0", results.get(i++)); - assertEquals("0", results.get(i++)); - - _context.setIPv6Format(ContextHandler.IPV6Format.UNBRACKETED); - results.clear(); - response = _connector.getResponse( - "GET / HTTP/1.1\n" + - "Host: [::1]:8888\n" + - "Connection: close\n" + - "\n"); - i = 0; - assertThat(response, containsString("200 OK")); - assertEquals("1:2:3:4:5:6:7:8", results.get(i++)); - assertEquals("localIPv6", results.get(i++)); - assertEquals("32768", results.get(i++)); - assertEquals("::1", results.get(i++)); - assertEquals("8888", results.get(i++)); - assertEquals("0.0.0.0", results.get(i++)); - assertEquals("0", results.get(i++)); + assertEquals("0", results.get(i)); - _context.setIPv6Format(ContextHandler.IPV6Format.UNCHANGED); + _normalizeAddress = false; results.clear(); response = _connector.getResponse( "GET / HTTP/1.1\n" + @@ -1013,7 +1022,7 @@ public boolean check(HttpServletRequest request, HttpServletResponse response) assertEquals("[::1]", results.get(i++)); assertEquals("8888", results.get(i++)); assertEquals("0.0.0.0", results.get(i++)); - assertEquals("0", results.get(i++)); + assertEquals("0", results.get(i)); } @Test diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java b/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java index 79f0f7d01afd..9888e2e9d646 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/HostPort.java @@ -149,31 +149,13 @@ public String toString() public static String normalizeHost(String host) { // if it is normalized IPv6 or could not be IPv6, return - if (host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0) + if (host == null || host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0) return host; // normalize with [ ] return "[" + host + "]"; } - /** - * Denormalizes IPv6 address as per https://tools.ietf.org/html/rfc2732 - * and https://tools.ietf.org/html/rfc6874, - * removing square brackets if they are present. - * - * @param host a host name, IPv4 address, IPv6 address or IPv6 literal - * @return a host name or an IPv4 address or an IPv6 address - */ - public static String denormalizeHost(String host) - { - // if it is normalized IPv6 or could not be IPv6, return - if (host.isEmpty() || host.charAt(0) != '[' || host.charAt(host.length() - 1) != ']') - return host; - - // normalize with [ ] - return host.substring(1, host.length() - 1); - } - /** * Parse a string representing a port validating it is a valid port value. * From 8674bfd6d07788622775ea7bae428c4ec412ba6e Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Sep 2021 16:51:15 +1000 Subject: [PATCH 7/8] protect from NPE Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/server/Request.java | 25 +++++++++++-------- .../org/eclipse/jetty/server/RequestTest.java | 7 +----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index eeaf3653e1d1..326a80316534 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -997,7 +997,7 @@ public String getLocalAddr() String name = InetAddress.getLocalHost().getHostAddress(); if (StringUtil.ALL_INTERFACES.equals(name)) return null; - return _channel.formatAddrOrHost(name); + return formatAddrOrHost(name); } catch (UnknownHostException e) { @@ -1013,7 +1013,7 @@ public String getLocalAddr() String result = address == null ? local.getHostString() : address.getHostAddress(); - return _channel.formatAddrOrHost(result); + return formatAddrOrHost(result); } /* @@ -1026,7 +1026,7 @@ public String getLocalName() { InetSocketAddress local = _channel.getLocalAddress(); if (local != null) - return _channel.formatAddrOrHost(local.getHostString()); + return formatAddrOrHost(local.getHostString()); } try @@ -1034,7 +1034,7 @@ public String getLocalName() String name = InetAddress.getLocalHost().getHostName(); if (StringUtil.ALL_INTERFACES.equals(name)) return null; - return _channel.formatAddrOrHost(name); + return formatAddrOrHost(name); } catch (UnknownHostException e) { @@ -1259,7 +1259,7 @@ public String getRemoteAddr() ? remote.getHostString() : address.getHostAddress(); - return _channel.formatAddrOrHost(result); + return formatAddrOrHost(result); } /* @@ -1275,7 +1275,7 @@ public String getRemoteHost() return ""; // We want the URI host, so add IPv6 brackets if necessary. - return _channel.formatAddrOrHost(remote.getHostString()); + return formatAddrOrHost(remote.getHostString()); } /* @@ -1401,7 +1401,7 @@ public String getScheme() public String getServerName() { MetaData.Request metadata = _metaData; - String name = metadata == null ? null : _channel.formatAddrOrHost(metadata.getURI().getHost()); + String name = metadata == null ? null : formatAddrOrHost(metadata.getURI().getHost()); // Return already determined host if (name != null) @@ -1423,19 +1423,19 @@ private String findServerName() { HostPortHttpField authority = (HostPortHttpField)host; metadata.getURI().setAuthority(authority.getHost(), authority.getPort()); - return _channel.formatAddrOrHost(authority.getHost()); + return formatAddrOrHost(authority.getHost()); } } // Return host from connection String name = getLocalName(); if (name != null) - return _channel.formatAddrOrHost(name); + return formatAddrOrHost(name); // Return the local host try { - return _channel.formatAddrOrHost(InetAddress.getLocalHost().getHostAddress()); + return formatAddrOrHost(InetAddress.getLocalHost().getHostAddress()); } catch (UnknownHostException e) { @@ -2602,4 +2602,9 @@ public T upgrade(Class handlerClass) throws IO { throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty"); } + + private String formatAddrOrHost(String name) + { + return _channel == null ? name : _channel.formatAddrOrHost(name); + } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 39237e708500..02ff5ba48314 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -100,7 +100,6 @@ public class RequestTest public WorkDir workDir; private Server _server; private LocalConnector _connector; - private ContextHandler _context; private RequestHandler _handler; private boolean _normalizeAddress = true; @@ -141,10 +140,8 @@ protected String formatAddrOrHost(String addr) _connector = new LocalConnector(_server, http); _server.addConnector(_connector); _connector.setIdleTimeout(500); - _context = new ContextHandler(); - _server.setHandler(_context); _handler = new RequestHandler(); - _context.setHandler(_handler); + _server.setHandler(_handler); ErrorHandler errors = new ErrorHandler(); errors.setServer(_server); @@ -1778,8 +1775,6 @@ public void testHashDOSSize() throws Exception try (StacklessLogging stackless = new StacklessLogging(HttpChannel.class)) { LOG.info("Expecting maxFormSize limit and too much data exceptions..."); - _context.setMaxFormContentSize(3396); - _context.setMaxFormKeys(1000); _server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", 3396); _server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys", 1000); From 6ff3c04165f93d08c08f54f603a37b8088de586d Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Sep 2021 12:32:39 +1000 Subject: [PATCH 8/8] normalize if no channel Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/server/Request.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 326a80316534..a3e06d9fd347 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -86,6 +86,7 @@ import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.AttributesMap; +import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.StringUtil; @@ -2605,6 +2606,6 @@ public T upgrade(Class handlerClass) throws IO private String formatAddrOrHost(String name) { - return _channel == null ? name : _channel.formatAddrOrHost(name); + return _channel == null ? HostPort.normalizeHost(name) : _channel.formatAddrOrHost(name); } }