src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java
Print this page
8144566 Custom HostnameVerifier disables SNI extension
@@ -208,10 +208,16 @@
List<SNIServerName> serverNames =
Collections.<SNIServerName>emptyList();
Collection<SNIMatcher> sniMatchers =
Collections.<SNIMatcher>emptyList();
+ // Is the serverNames set to empty with SSLParameters.setServerNames()?
+ private boolean noSniExtension = false;
+
+ // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()?
+ private boolean noSniMatcher = false;
+
// Configured application protocol values
String[] applicationProtocols = new String[0];
// Negotiated application protocol value.
//
@@ -652,10 +658,15 @@
throw new SocketException(
"Cannot handle non-Inet socket addresses.");
}
super.connect(endpoint, timeout);
+
+ if (host == null || host.length() == 0) {
+ useImplicitHost(false);
+ }
+
doneConnect();
}
/**
* Initialize the handshaker and socket streams.
@@ -2083,57 +2094,85 @@
synchronized void setVersion(ProtocolVersion protocolVersion) {
this.protocolVersion = protocolVersion;
outputRecord.setVersion(protocolVersion);
}
+ //
+ // ONLY used by ClientHandshaker for the server hostname during handshaling
+ //
synchronized String getHost() {
// Note that the host may be null or empty for localhost.
if (host == null || host.length() == 0) {
- if (!trustNameService) {
- // If the local name service is not trustworthy, reverse host
- // name resolution should not be performed for endpoint
- // identification. Use the application original specified
- // hostname or IP address instead.
- host = getOriginalHostname(getInetAddress());
- } else {
- host = getInetAddress().getHostName();
+ useImplicitHost(true);
}
- }
return host;
}
/*
- * Get the original application specified hostname.
+ * Try to set and use the implicit specified hostname
*/
- private static String getOriginalHostname(InetAddress inetAddress) {
- /*
- * Get the original hostname via jdk.internal.misc.SharedSecrets.
- */
- JavaNetInetAddressAccess jna = SharedSecrets.getJavaNetInetAddressAccess();
+ synchronized private void useImplicitHost(boolean noSniUpdate) {
+ if ((host != null) && (host.length() != 0)) {
+ return;
+ }
+
+ // Note: If the local name service is not trustworthy, reverse
+ // host name resolution should not be performed for endpoint
+ // identification. Use the application original specified
+ // hostname or IP address instead.
+
+ // Get the original hostname via jdk.internal.misc.SharedSecrets
+ InetAddress inetAddress = getInetAddress();
+ if (inetAddress == null) { // not connected
+ return;
+ }
+
+ JavaNetInetAddressAccess jna =
+ SharedSecrets.getJavaNetInetAddressAccess();
String originalHostname = jna.getOriginalHostName(inetAddress);
+ if ((originalHostname != null) &&
+ (originalHostname.length() != 0)) {
- /*
- * If no application specified hostname, use the IP address.
- */
- if (originalHostname == null || originalHostname.length() == 0) {
- originalHostname = inetAddress.getHostAddress();
+ host = originalHostname;
+ if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) {
+ serverNames =
+ Utilities.addToSNIServerNameList(serverNames, host);
+
+ if (!roleIsServer &&
+ (handshaker != null) && !handshaker.started()) {
+ handshaker.setSNIServerNames(serverNames);
}
+ }
- return originalHostname;
+ return;
}
+ // No explicitly specified hostname, no sserver name indication.
+ if (!trustNameService) {
+ // The local name service is not trustworthy, use IP address.
+ host = inetAddress.getHostAddress();
+ } else {
+ // Use the underlying reverse host name resolution service.
+ host = getInetAddress().getHostName();
+ }
+ }
+
// ONLY used by HttpsClient to setup the URI specified hostname
//
// Please NOTE that this method MUST be called before calling to
// SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
// may override SNIHostName in the customized server name indication.
public synchronized void setHost(String host) {
this.host = host;
this.serverNames =
Utilities.addToSNIServerNameList(this.serverNames, this.host);
+
+ if (!roleIsServer && (handshaker != null) && !handshaker.started()) {
+ handshaker.setSNIServerNames(serverNames);
}
+ }
/**
* Gets an input stream to read from the peer on the other side.
* Data read from this stream was always integrity protected in
* transit, and will usually have been confidentiality protected.
@@ -2518,12 +2557,25 @@
SSLParameters params = super.getSSLParameters();
// the super implementation does not handle the following parameters
params.setEndpointIdentificationAlgorithm(identificationProtocol);
params.setAlgorithmConstraints(algorithmConstraints);
+
+ if (sniMatchers.isEmpty() && !noSniMatcher) {
+ // 'null' indicates none has been set
+ params.setSNIMatchers(null);
+ } else {
params.setSNIMatchers(sniMatchers);
+ }
+
+ if (serverNames.isEmpty() && !noSniExtension) {
+ // 'null' indicates none has been set
+ params.setServerNames(null);
+ } else {
params.setServerNames(serverNames);
+ }
+
params.setUseCipherSuitesOrder(preferLocalCipherSuites);
params.setMaximumPacketSize(maximumPacketSize);
params.setApplicationProtocols(applicationProtocols);
// DTLS handshake retransmissions parameter does not apply here.
@@ -2553,15 +2605,25 @@
maximumPacketSize = outputRecord.getMaxPacketSize();
}
List<SNIServerName> sniNames = params.getServerNames();
if (sniNames != null) {
+ if (sniNames.isEmpty()) {
+ // need no SNI extension
+ noSniExtension = true;
+ } // Otherwise, need not to set noSniExtension
+
serverNames = sniNames;
}
Collection<SNIMatcher> matchers = params.getSNIMatchers();
if (matchers != null) {
+ if (matchers.isEmpty()) {
+ // need no SNI matcher
+ noSniMatcher = true;
+ } // Otherwise, need not to set noSniMatcher
+
sniMatchers = matchers;
}
applicationProtocols = params.getApplicationProtocols();