--- 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