diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java index c4529d7e845..1a11309fa39 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, 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 @@ -31,6 +31,7 @@ import java.util.ArrayDeque; import java.util.List; import java.util.concurrent.CompletableFuture; import javax.net.ssl.SNIHostName; +import javax.net.ssl.SNIServerName; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -61,8 +62,8 @@ import static jdk.internal.net.http.common.Utils.ServerName; abstract class AbstractAsyncSSLConnection extends HttpConnection { protected final SSLEngine engine; - protected final String serverName; protected final SSLParameters sslParameters; + private final List sniServerNames; // Setting this property disables HTTPS hostname verification. Use with care. private static final boolean disableHostnameVerification @@ -73,11 +74,11 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection ServerName serverName, int port, String[] alpn) { super(addr, client); - this.serverName = serverName.getName(); + this.sniServerNames = formSNIServerNames(serverName); SSLContext context = client.theSSLContext(); - sslParameters = createSSLParameters(client, serverName, alpn); + sslParameters = createSSLParameters(client, this.sniServerNames, alpn); Log.logParams(sslParameters); - engine = createEngine(context, serverName.getName(), port, sslParameters); + engine = createEngine(context, serverName.name(), port, sslParameters); } abstract SSLTube getConnectionFlow(); @@ -88,6 +89,11 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection final SSLEngine getEngine() { return engine; } + @Override + public final List getSNIServerNames() { + return this.sniServerNames; + } + private static boolean contains(String[] rr, String target) { for (String s : rr) if (target.equalsIgnoreCase(s)) @@ -96,7 +102,7 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection } private static SSLParameters createSSLParameters(HttpClientImpl client, - ServerName serverName, + List sniServerNames, String[] alpn) { SSLParameters sslp = client.sslParameters(); SSLParameters sslParameters = Utils.copySSLParameters(sslp); @@ -116,20 +122,27 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); if (alpn != null) { Log.logSSL("AbstractAsyncSSLConnection: Setting application protocols: {0}", - Arrays.toString(alpn)); + Arrays.toString(alpn)); sslParameters.setApplicationProtocols(alpn); } else { Log.logSSL("AbstractAsyncSSLConnection: no applications set!"); } - if (!serverName.isLiteral()) { - String name = serverName.getName(); - if (name != null && name.length() > 0) { - sslParameters.setServerNames(List.of(new SNIHostName(name))); - } - } + sslParameters.setServerNames(sniServerNames); return sslParameters; } + private static List formSNIServerNames(final ServerName serverName) { + if (serverName == null) { + return List.of(); + } + if (!serverName.isLiteral()) { + String name = serverName.name(); + if (name != null && name.length() > 0) { + return List.of(new SNIHostName(name)); + } + } + return List.of(); + } private static SSLEngine createEngine(SSLContext context, String serverName, int port, SSLParameters sslParameters) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java index be33469c052..7526dbffca5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java @@ -44,6 +44,9 @@ import java.util.function.Predicate; import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpHeaders; + +import javax.net.ssl.SNIServerName; + import jdk.internal.net.http.common.Demand; import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.Logger; @@ -424,6 +427,17 @@ abstract class HttpConnection implements Closeable { return address; } + /** + * Returns an unmodifiable list of {@link SNIServerName}s that were used during TLS handshake + * of this connection. If this connection doesn't represent a TLS based connection or if no SNI + * server names were used during the handshake, then this method returns an empty list. + * + * @return the SNI server names + */ + public List getSNIServerNames() { + return List.of(); + } + abstract ConnectionPool.CacheKey cacheKey(); /** diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index 812b8c5374c..a30fa195433 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -477,22 +477,7 @@ public final class Utils { return !token.isEmpty(); } - public static class ServerName { - ServerName(String name, boolean isLiteral) { - this.name = name; - this.isLiteral = isLiteral; - } - - final String name; - final boolean isLiteral; - - public String getName() { - return name; - } - - public boolean isLiteral() { - return isLiteral; - } + public record ServerName (String name, boolean isLiteral) { } /**