diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java index 0a5b1f85281..dca0334d49c 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java @@ -53,12 +53,15 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration) { - this(httpConfiguration,"h2","h2-17","h2-16","h2-15","h2-14"); + this(httpConfiguration,"h2"); } protected AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration, String... protocols) { super(protocols); + for (String p:protocols) + if (!HTTP2ServerConnection.isSupportedProtocol(p)) + throw new IllegalArgumentException("Unsupported HTTP2 Protocol variant: "+p); this.httpConfiguration = Objects.requireNonNull(httpConfiguration); addBean(httpConfiguration); } diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java index 874e4ea360b..676ce9b88fd 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java @@ -51,7 +51,15 @@ public class HTTP2CServerConnectionFactory extends HTTP2ServerConnectionFactory public HTTP2CServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration) { - super(httpConfiguration,"h2c","h2c-17","h2c-16","h2c-15","h2c-14"); + this(httpConfiguration,"h2c"); + } + + public HTTP2CServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration, String... protocols) + { + super(httpConfiguration,protocols); + for (String p:protocols) + if (!HTTP2ServerConnection.isSupportedProtocol(p)) + throw new IllegalArgumentException("Unsupported HTTP2 Protocol variant: "+p); } @Override diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java index a2429a12919..a7e745fb537 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java @@ -58,6 +58,31 @@ import org.eclipse.jetty.util.thread.ExecutionStrategy; public class HTTP2ServerConnection extends HTTP2Connection implements Connection.UpgradeTo { + + /** + * @param protocol A HTTP2 protocol variant + * @return True if the protocol version is supported + */ + public static boolean isSupportedProtocol(String protocol) + { + switch(protocol) + { + case "h2": + case "h2-17": + case "h2-16": + case "h2-15": + case "h2-14": + case "h2c": + case "h2c-17": + case "h2c-16": + case "h2c-15": + case "h2c-14": + return true; + default: + return false; + } + } + private final Queue channels = new ConcurrentArrayQueue<>(); private final ServerSessionListener listener; private final HttpConfiguration httpConfig; diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java index 301431c9980..e69ef2efaa8 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java @@ -64,8 +64,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF @Override public boolean isAcceptable(String protocol, String tlsProtocol, String tlsCipher) { - // TODO remove this draft 14 protection - // Implement 9.2.2 + // Implement 9.2.2 for draft 14 boolean acceptable = "h2-14".equals(protocol) || !(HTTP2Cipher.isBlackListProtocol(tlsProtocol) && HTTP2Cipher.isBlackListCipher(tlsCipher)); if (LOG.isDebugEnabled()) LOG.debug("proto={} tls={} cipher={} 9.2.2-acceptable={}",protocol,tlsProtocol,tlsCipher,acceptable); diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java index 181b40be618..b5bb983d2df 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java @@ -86,6 +86,7 @@ public class JettyEffectiveWebXml extends JettyRunMojo applyJettyXml (); ServerSupport.configureHandlers(server, null); + ServerSupport.configureDefaultConfigurationClasses(server); //ensure config of the webapp based on settings in plugin configureWebApplication(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java index 2532be37bc5..70a55dc8658 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java @@ -271,7 +271,7 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer request.setAttribute("javax.servlet.request.key_size",keySize); request.setAttribute("javax.servlet.request.ssl_session_id", idStr); String sessionAttribute = getSslSessionAttribute(); - if (sessionAttribute != null && sessionAttribute.isEmpty()) + if (sessionAttribute != null && !sessionAttribute.isEmpty()) request.setAttribute(sessionAttribute, sslSession); } catch (Exception e) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java index 333ebad8d98..2f8ae4e808d 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java @@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.eclipse.jetty.server.handler.HotSwapHandler; import org.eclipse.jetty.toolchain.test.PropertyFlag; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -71,7 +72,7 @@ public class HttpServerTestFixture protected void startServer(ServerConnector connector) throws Exception { - startServer(connector,new HandlerWrapper()); + startServer(connector,new HotSwapHandler()); } protected void startServer(ServerConnector connector, Handler handler) throws Exception @@ -96,10 +97,9 @@ public class HttpServerTestFixture protected void configureServer(Handler handler) throws Exception { - HandlerWrapper current = (HandlerWrapper)_server.getHandler(); - current.stop(); - current.setHandler(handler); - current.start(); + HotSwapHandler swapper = (HotSwapHandler)_server.getHandler(); + swapper.setHandler(handler); + handler.start(); } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java index 6ddfd3c4624..c0431dc1f23 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java @@ -18,20 +18,33 @@ package org.eclipse.jetty.server.ssl; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyOrNullString; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.security.KeyStore; import java.util.Arrays; import java.util.concurrent.Executor; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManagerFactory; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.LeakTrackingByteBufferPool; @@ -40,11 +53,16 @@ import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.server.AbstractConnectionFactory; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.HttpServerTestBase; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.Scheduler; +import org.hamcrest.Matchers; +import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Ignore; @@ -121,8 +139,12 @@ public class SelectChannelServerSslTest extends HttpServerTestBase sslContextFactory.setTrustStorePath(keystorePath); sslContextFactory.setTrustStorePassword("storepwd"); ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); - ServerConnector connector = new ServerConnector(_server,(Executor)null,(Scheduler)null,pool, 1, 1, AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); - + + HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(); + ServerConnector connector = new ServerConnector(_server,(Executor)null,(Scheduler)null,pool, 1, 1, AbstractConnectionFactory.getFactories(sslContextFactory,httpConnectionFactory)); + SecureRequestCustomizer secureRequestCustomer = new SecureRequestCustomizer(); + secureRequestCustomer.setSslSessionAttribute("SSL_SESSION"); + httpConnectionFactory.getHttpConfiguration().addCustomizer(secureRequestCustomer); startServer(connector); @@ -222,5 +244,67 @@ public class SelectChannelServerSslTest extends HttpServerTestBase { } + @Test + public void testSecureRequestCustomizer() throws Exception + { + configureServer(new SecureRequestHandler()); + try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort())) + { + OutputStream os = client.getOutputStream(); + + os.write("GET / HTTP/1.0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1)); + os.flush(); + + // Read the response. + String response = readResponse(client); + + System.err.println(response); + + assertThat(response, containsString("HTTP/1.1 200 OK")); + assertThat(response, containsString("Hello world")); + assertThat(response, containsString("scheme='https'")); + assertThat(response, containsString("isSecure='true'")); + assertThat(response, containsString("X509Certificate='null'")); + + Matcher matcher=Pattern.compile("cipher_suite='([^']*)'").matcher(response); + matcher.find(); + assertThat(matcher.group(1), Matchers.allOf(not(isEmptyOrNullString()),not(is("null")))); + + matcher=Pattern.compile("key_size='([^']*)'").matcher(response); + matcher.find(); + assertThat(matcher.group(1), Matchers.allOf(not(isEmptyOrNullString()),not(is("null")))); + + matcher=Pattern.compile("ssl_session_id='([^']*)'").matcher(response); + matcher.find(); + assertThat(matcher.group(1), Matchers.allOf(not(isEmptyOrNullString()),not(is("null")))); + + matcher=Pattern.compile("ssl_session='([^']*)'").matcher(response); + matcher.find(); + assertThat(matcher.group(1), Matchers.allOf(not(isEmptyOrNullString()),not(is("null")))); + } + } + + public static class SecureRequestHandler extends AbstractHandler + { + + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + baseRequest.setHandled(true); + response.setStatus(200); + response.getOutputStream().println("Hello world"); + response.getOutputStream().println("scheme='"+request.getScheme()+"'"); + response.getOutputStream().println("isSecure='"+request.isSecure()+"'"); + response.getOutputStream().println("X509Certificate='"+request.getAttribute("javax.servlet.request.X509Certificate")+"'"); + response.getOutputStream().println("cipher_suite='"+request.getAttribute("javax.servlet.request.cipher_suite")+"'"); + response.getOutputStream().println("key_size='"+request.getAttribute("javax.servlet.request.key_size")+"'"); + response.getOutputStream().println("ssl_session_id='"+request.getAttribute("javax.servlet.request.ssl_session_id")+"'"); + SSLSession sslSession=(SSLSession)request.getAttribute("SSL_SESSION"); + response.getOutputStream().println("ssl_session='"+sslSession+"'"); + + } + + } + } diff --git a/jetty-util/src/main/config/modules/slf4j-jcl.mod b/jetty-util/src/main/config/modules/slf4j-jcl.mod index 8ff9cdd7ded..6a9773a048c 100644 --- a/jetty-util/src/main/config/modules/slf4j-jcl.mod +++ b/jetty-util/src/main/config/modules/slf4j-jcl.mod @@ -15,6 +15,3 @@ maven://org.slf4j/slf4j-jcl/${slf4j.version}|lib/slf4j/slf4j-jcl-${slf4j.version [lib] lib/slf4j/slf4j-jcl-${slf4j.version}.jar - -[exec] --Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog diff --git a/jetty-util/src/main/config/modules/slf4j-jul.mod b/jetty-util/src/main/config/modules/slf4j-jul.mod new file mode 100644 index 00000000000..fc858778d2f --- /dev/null +++ b/jetty-util/src/main/config/modules/slf4j-jul.mod @@ -0,0 +1,15 @@ +[description] +Provides a SLF4J implementation that logs to the Java Util Logging API. +To receive jetty logs enable the jetty-slf4j module. + +[depend] +slf4j-api + +[provide] +slf4j-impl + +[files] +maven://org.slf4j/slf4j-jdk14/${slf4j.version}|lib/slf4j/slf4j-jdk14-${slf4j.version}.jar + +[lib] +lib/slf4j/slf4j-jdk14-${slf4j.version}.jar diff --git a/jetty-util/src/main/config/modules/slf4j-simple.mod b/jetty-util/src/main/config/modules/slf4j-simple.mod index 9bdf38c6df0..804cde01a03 100644 --- a/jetty-util/src/main/config/modules/slf4j-simple.mod +++ b/jetty-util/src/main/config/modules/slf4j-simple.mod @@ -13,6 +13,3 @@ maven://org.slf4j/slf4j-simple/${slf4j.version}|lib/slf4j/slf4j-simple-${slf4j.v [lib] lib/slf4j/slf4j-simple-${slf4j.version}.jar - -[exec] --Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog