http-client-branch: only add h2 ALPN if TLSv1.2 or greater http-client-branch
authorchegar
Wed, 31 Jan 2018 11:49:50 +0000
branchhttp-client-branch
changeset 56049 cf81ddfb20a8
parent 56048 f9b6016727b5
child 56050 e4877b1aa02f
http-client-branch: only add h2 ALPN if TLSv1.2 or greater
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java
test/jdk/java/net/httpclient/http2/TLSConnection.java
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java	Tue Jan 30 20:43:32 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java	Wed Jan 31 11:49:50 2018 +0000
@@ -31,6 +31,7 @@
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
+import java.util.Arrays;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
@@ -39,6 +40,7 @@
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.Flow;
+import java.util.function.Predicate;
 import jdk.incubator.http.HttpClient.Version;
 import jdk.incubator.http.internal.common.Demand;
 import jdk.incubator.http.internal.common.FlowTube;
@@ -135,6 +137,23 @@
      */
     abstract HttpPublisher publisher();
 
+    // HTTP/2 MUST use TLS version 1.2 or higher for HTTP/2 over TLS
+    private static final Predicate<String> testRequiredHTTP2TLSVersion = proto ->
+            proto.equals("TLSv1.2") || proto.equals("TLSv1.3");
+
+   /**
+    * Returns true if the given client's SSL parameter protocols contains at
+    * least one TLS version that HTTP/2 requires.
+    */
+   private static final boolean hasRequiredHTTP2TLSVersion(HttpClient client) {
+       String[] protos = client.sslParameters().getProtocols();
+       if (protos != null) {
+           return Arrays.stream(protos).filter(testRequiredHTTP2TLSVersion).findAny().isPresent();
+       } else {
+           return false;
+       }
+   }
+
     /**
      * Factory for retrieving HttpConnections. A connection can be retrieved
      * from the connection pool, or a new one created if none available.
@@ -184,7 +203,7 @@
                 return c;
             } else {
                 String[] alpn = null;
-                if (version == HTTP_2) {
+                if (version == HTTP_2 && hasRequiredHTTP2TLSVersion(client)) {
                     alpn = new String[] { "h2", "http/1.1" };
                 }
                 return getSSLConnection(addr, proxy, alpn, request, client);
--- a/test/jdk/java/net/httpclient/http2/TLSConnection.java	Tue Jan 30 20:43:32 2018 +0000
+++ b/test/jdk/java/net/httpclient/http2/TLSConnection.java	Wed Jan 31 11:49:50 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,13 +44,18 @@
  *          jdk.incubator.httpclient/jdk.incubator.http.internal.common
  *          jdk.incubator.httpclient/jdk.incubator.http.internal.frame
  *          jdk.incubator.httpclient/jdk.incubator.http.internal.hpack
- * @run main/othervm TLSConnection
+ * @run main/othervm
+ *       -Djdk.internal.httpclient.debug=true
+ *       -Djdk.httpclient.HttpClient.log=all
+ *       TLSConnection
  */
 public class TLSConnection {
 
     private static final String KEYSTORE = System.getProperty("test.src")
             + File.separator + "keystore.p12";
-   private static final String PASSWORD = "password";
+    private static final String PASSWORD = "password";
+
+    private static final SSLParameters USE_DEFAULT_SSL_PARAMETERS = new SSLParameters();
 
     public static void main(String[] args) throws Exception {
 
@@ -77,39 +82,40 @@
 
             SSLParameters parameters = null;
             success &= expectFailure(
-                    "Test #1: SSL parameters is null, expect NPE",
+                    "---\nTest #1: SSL parameters is null, expect NPE",
                     () -> connect(uriString, parameters),
                     NullPointerException.class);
 
             success &= expectSuccess(
-                    "Test #2: default SSL parameters, "
+                    "---\nTest #2: default SSL parameters, "
                             + "expect successful connection",
-                    () -> connect(uriString, new SSLParameters()));
+                    () -> connect(uriString, USE_DEFAULT_SSL_PARAMETERS));
             success &= checkProtocol(handler.getSSLSession(), "TLSv1.2");
 
             // set SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite
             // which has less priority in default cipher suite list
             success &= expectSuccess(
-                    "Test #3: SSL parameters with "
+                    "---\nTest #3: SSL parameters with "
                             + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite, "
                             + "expect successful connection",
                     () -> connect(uriString, new SSLParameters(
-                            new String[] { "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" })));
+                            new String[] { "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" },
+                            new String[] { "TLSv1.2" })));
             success &= checkProtocol(handler.getSSLSession(), "TLSv1.2");
             success &= checkCipherSuite(handler.getSSLSession(),
                     "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
 
             // set TLS_RSA_WITH_AES_128_CBC_SHA cipher suite
             // which has less priority in default cipher suite list
-            // also set TLSv11 protocol
+            // also set TLSv1.2 protocol
             success &= expectSuccess(
-                    "Test #4: SSL parameters with "
+                    "---\nTest #4: SSL parameters with "
                             + "TLS_RSA_WITH_AES_128_CBC_SHA cipher suite,"
                             + " expect successful connection",
                     () -> connect(uriString, new SSLParameters(
                             new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA" },
-                            new String[] { "TLSv1.1" })));
-            success &= checkProtocol(handler.getSSLSession(), "TLSv1.1");
+                            new String[] { "TLSv1.2" })));
+            success &= checkProtocol(handler.getSSLSession(), "TLSv1.2");
             success &= checkCipherSuite(handler.getSSLSession(),
                     "TLS_RSA_WITH_AES_128_CBC_SHA");
 
@@ -158,15 +164,17 @@
     }
 
     private static void connect(String uriString, SSLParameters sslParameters)
-        throws URISyntaxException, IOException, InterruptedException
+            throws URISyntaxException, IOException, InterruptedException
     {
-        HttpClient client = HttpClient.newBuilder()
-                                      .sslParameters(sslParameters)
-                                      .version(HttpClient.Version.HTTP_2)
-                                      .build();
+        HttpClient.Builder builder = HttpClient.newBuilder()
+                .version(HttpClient.Version.HTTP_2);
+        if (sslParameters != USE_DEFAULT_SSL_PARAMETERS)
+            builder.sslParameters(sslParameters);
+        HttpClient client = builder.build();
+
         HttpRequest request = HttpRequest.newBuilder(new URI(uriString))
-                                         .POST(fromString("body"))
-                                         .build();
+                .POST(fromString("body"))
+                .build();
         String body = client.send(request, asString()).body();
 
         System.out.println("Response: " + body);
@@ -222,7 +230,7 @@
     }
 
     private static boolean expectFailure(String message, Test test,
-            Class<? extends Throwable> expectedException) {
+                                         Class<? extends Throwable> expectedException) {
 
         System.out.println(message);
         try {
@@ -244,4 +252,4 @@
         }
     }
 
-}
+}
\ No newline at end of file