src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java

Print this page
8144566 Custom HostnameVerifier disables SNI extension


 193     private boolean             enableSessionCreation = true;
 194     private String              host;
 195     private boolean             autoClose = true;
 196     private AccessControlContext acc;
 197 
 198     // The cipher suites enabled for use on this connection.
 199     private CipherSuiteList     enabledCipherSuites;
 200 
 201     // The endpoint identification protocol
 202     private String              identificationProtocol = null;
 203 
 204     // The cryptographic algorithm constraints
 205     private AlgorithmConstraints    algorithmConstraints = null;
 206 
 207     // The server name indication and matchers
 208     List<SNIServerName>         serverNames =
 209                                     Collections.<SNIServerName>emptyList();
 210     Collection<SNIMatcher>      sniMatchers =
 211                                     Collections.<SNIMatcher>emptyList();
 212 






 213     // Configured application protocol values
 214     String[] applicationProtocols = new String[0];
 215 
 216     // Negotiated application protocol value.
 217     //
 218     // The value under negotiation will be obtained from handshaker.
 219     String applicationProtocol = null;
 220 
 221     /*
 222      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
 223      * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
 224      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
 225      *
 226      * There are several locks here.
 227      *
 228      * The primary lock is the per-instance lock used by
 229      * synchronized(this) and the synchronized methods.  It controls all
 230      * access to things such as the connection state and variables which
 231      * affect handshaking.  If we are inside a synchronized method, we
 232      * can access the state directly, otherwise, we must use the


 637      *
 638      * @param   endpoint the <code>SocketAddress</code>
 639      * @param   timeout  the timeout value to be used, 0 is no timeout
 640      * @throws  IOException if an error occurs during the connection
 641      * @throws  SocketTimeoutException if timeout expires before connecting
 642      */
 643     @Override
 644     public void connect(SocketAddress endpoint, int timeout)
 645             throws IOException {
 646 
 647         if (isLayered()) {
 648             throw new SocketException("Already connected");
 649         }
 650 
 651         if (!(endpoint instanceof InetSocketAddress)) {
 652             throw new SocketException(
 653                                   "Cannot handle non-Inet socket addresses.");
 654         }
 655 
 656         super.connect(endpoint, timeout);





 657         doneConnect();
 658     }
 659 
 660     /**
 661      * Initialize the handshaker and socket streams.
 662      *
 663      * Called by connect, the layered constructor, and SSLServerSocket.
 664      */
 665     void doneConnect() throws IOException {
 666         /*
 667          * Save the input and output streams.  May be done only after
 668          * java.net actually connects using the socket "self", else
 669          * we get some pretty bizarre failure modes.
 670          */
 671         sockInput = super.getInputStream();
 672         sockOutput = super.getOutputStream();
 673 
 674         inputRecord.setDeliverStream(sockOutput);
 675         outputRecord.setDeliverStream(sockOutput);
 676 


2068         CipherBox writeCipher;
2069         try {
2070             writeCipher = handshaker.newWriteCipher();
2071             writeAuthenticator = handshaker.newWriteAuthenticator();
2072         } catch (GeneralSecurityException e) {
2073             // "can't happen"
2074             throw new SSLException("Algorithm missing:  ", e);
2075         }
2076         outputRecord.changeWriteCiphers(writeAuthenticator, writeCipher);
2077     }
2078 
2079     /*
2080      * Updates the SSL version associated with this connection.
2081      * Called from Handshaker once it has determined the negotiated version.
2082      */
2083     synchronized void setVersion(ProtocolVersion protocolVersion) {
2084         this.protocolVersion = protocolVersion;
2085         outputRecord.setVersion(protocolVersion);
2086     }
2087 



2088     synchronized String getHost() {
2089         // Note that the host may be null or empty for localhost.
2090         if (host == null || host.length() == 0) {
2091             if (!trustNameService) {
2092                 // If the local name service is not trustworthy, reverse host
2093                 // name resolution should not be performed for endpoint
2094                 // identification.  Use the application original specified
2095                 // hostname or IP address instead.
2096                 host = getOriginalHostname(getInetAddress());
2097             } else {
2098                 host = getInetAddress().getHostName();
2099             }
2100         }
2101 
2102         return host;
2103     }
2104 
2105     /*
2106      * Get the original application specified hostname.
2107      */
2108     private static String getOriginalHostname(InetAddress inetAddress) {
2109         /*
2110          * Get the original hostname via jdk.internal.misc.SharedSecrets.
2111          */
2112         JavaNetInetAddressAccess jna = SharedSecrets.getJavaNetInetAddressAccess();













2113         String originalHostname = jna.getOriginalHostName(inetAddress);


2114 
2115         /*
2116          * If no application specified hostname, use the IP address.
2117          */
2118         if (originalHostname == null || originalHostname.length() == 0) {
2119             originalHostname = inetAddress.getHostAddress();



2120         }

2121 
2122         return originalHostname;
2123     }
2124 










2125     // ONLY used by HttpsClient to setup the URI specified hostname
2126     //
2127     // Please NOTE that this method MUST be called before calling to
2128     // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
2129     // may override SNIHostName in the customized server name indication.
2130     public synchronized void setHost(String host) {
2131         this.host = host;
2132         this.serverNames =
2133             Utilities.addToSNIServerNameList(this.serverNames, this.host);



2134     }

2135 
2136     /**
2137      * Gets an input stream to read from the peer on the other side.
2138      * Data read from this stream was always integrity protected in
2139      * transit, and will usually have been confidentiality protected.
2140      */
2141     @Override
2142     public synchronized InputStream getInputStream() throws IOException {
2143         if (isClosed()) {
2144             throw new SocketException("Socket is closed");
2145         }
2146 
2147         /*
2148          * Can't call isConnected() here, because the Handshakers
2149          * do some initialization before we actually connect.
2150          */
2151         if (connectionState == cs_START) {
2152             throw new SocketException("Socket is not connected");
2153         }
2154 


2503             throw new IllegalArgumentException("no listeners");
2504         }
2505         if (handshakeListeners.remove(listener) == null) {
2506             throw new IllegalArgumentException("listener not registered");
2507         }
2508         if (handshakeListeners.isEmpty()) {
2509             handshakeListeners = null;
2510         }
2511     }
2512 
2513     /**
2514      * Returns the SSLParameters in effect for this SSLSocket.
2515      */
2516     @Override
2517     public synchronized SSLParameters getSSLParameters() {
2518         SSLParameters params = super.getSSLParameters();
2519 
2520         // the super implementation does not handle the following parameters
2521         params.setEndpointIdentificationAlgorithm(identificationProtocol);
2522         params.setAlgorithmConstraints(algorithmConstraints);





2523         params.setSNIMatchers(sniMatchers);






2524         params.setServerNames(serverNames);


2525         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
2526         params.setMaximumPacketSize(maximumPacketSize);
2527         params.setApplicationProtocols(applicationProtocols);
2528 
2529         // DTLS handshake retransmissions parameter does not apply here.
2530 
2531         return params;
2532     }
2533 
2534     /**
2535      * Applies SSLParameters to this socket.
2536      */
2537     @Override
2538     public synchronized void setSSLParameters(SSLParameters params) {
2539         super.setSSLParameters(params);
2540 
2541         // the super implementation does not handle the following parameters
2542         identificationProtocol = params.getEndpointIdentificationAlgorithm();
2543         algorithmConstraints = params.getAlgorithmConstraints();
2544         preferLocalCipherSuites = params.getUseCipherSuitesOrder();
2545         maximumPacketSize = params.getMaximumPacketSize();
2546 
2547         // DTLS handshake retransmissions parameter does not apply here.
2548 
2549         if (maximumPacketSize != 0) {
2550             outputRecord.changePacketSize(maximumPacketSize);
2551         } else {
2552             // use the implicit maximum packet size.
2553             maximumPacketSize = outputRecord.getMaxPacketSize();
2554         }
2555 
2556         List<SNIServerName> sniNames = params.getServerNames();
2557         if (sniNames != null) {





2558             serverNames = sniNames;
2559         }
2560 
2561         Collection<SNIMatcher> matchers = params.getSNIMatchers();
2562         if (matchers != null) {





2563             sniMatchers = matchers;
2564         }
2565 
2566         applicationProtocols = params.getApplicationProtocols();
2567 
2568         if ((handshaker != null) && !handshaker.started()) {
2569             handshaker.setIdentificationProtocol(identificationProtocol);
2570             handshaker.setAlgorithmConstraints(algorithmConstraints);
2571             handshaker.setMaximumPacketSize(maximumPacketSize);
2572             handshaker.setApplicationProtocols(applicationProtocols);
2573             if (roleIsServer) {
2574                 handshaker.setSNIMatchers(sniMatchers);
2575                 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
2576             } else {
2577                 handshaker.setSNIServerNames(serverNames);
2578             }
2579         }
2580     }
2581 
2582     @Override




 193     private boolean             enableSessionCreation = true;
 194     private String              host;
 195     private boolean             autoClose = true;
 196     private AccessControlContext acc;
 197 
 198     // The cipher suites enabled for use on this connection.
 199     private CipherSuiteList     enabledCipherSuites;
 200 
 201     // The endpoint identification protocol
 202     private String              identificationProtocol = null;
 203 
 204     // The cryptographic algorithm constraints
 205     private AlgorithmConstraints    algorithmConstraints = null;
 206 
 207     // The server name indication and matchers
 208     List<SNIServerName>         serverNames =
 209                                     Collections.<SNIServerName>emptyList();
 210     Collection<SNIMatcher>      sniMatchers =
 211                                     Collections.<SNIMatcher>emptyList();
 212 
 213     // Is the serverNames set to empty with SSLParameters.setServerNames()?
 214     private boolean             noSniExtension = false;
 215 
 216     // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()?
 217     private boolean             noSniMatcher = false;
 218 
 219     // Configured application protocol values
 220     String[] applicationProtocols = new String[0];
 221 
 222     // Negotiated application protocol value.
 223     //
 224     // The value under negotiation will be obtained from handshaker.
 225     String applicationProtocol = null;
 226 
 227     /*
 228      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
 229      * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
 230      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
 231      *
 232      * There are several locks here.
 233      *
 234      * The primary lock is the per-instance lock used by
 235      * synchronized(this) and the synchronized methods.  It controls all
 236      * access to things such as the connection state and variables which
 237      * affect handshaking.  If we are inside a synchronized method, we
 238      * can access the state directly, otherwise, we must use the


 643      *
 644      * @param   endpoint the <code>SocketAddress</code>
 645      * @param   timeout  the timeout value to be used, 0 is no timeout
 646      * @throws  IOException if an error occurs during the connection
 647      * @throws  SocketTimeoutException if timeout expires before connecting
 648      */
 649     @Override
 650     public void connect(SocketAddress endpoint, int timeout)
 651             throws IOException {
 652 
 653         if (isLayered()) {
 654             throw new SocketException("Already connected");
 655         }
 656 
 657         if (!(endpoint instanceof InetSocketAddress)) {
 658             throw new SocketException(
 659                                   "Cannot handle non-Inet socket addresses.");
 660         }
 661 
 662         super.connect(endpoint, timeout);
 663 
 664         if (host == null || host.length() == 0) {
 665             useImplicitHost(false);
 666         }
 667 
 668         doneConnect();
 669     }
 670 
 671     /**
 672      * Initialize the handshaker and socket streams.
 673      *
 674      * Called by connect, the layered constructor, and SSLServerSocket.
 675      */
 676     void doneConnect() throws IOException {
 677         /*
 678          * Save the input and output streams.  May be done only after
 679          * java.net actually connects using the socket "self", else
 680          * we get some pretty bizarre failure modes.
 681          */
 682         sockInput = super.getInputStream();
 683         sockOutput = super.getOutputStream();
 684 
 685         inputRecord.setDeliverStream(sockOutput);
 686         outputRecord.setDeliverStream(sockOutput);
 687 


2079         CipherBox writeCipher;
2080         try {
2081             writeCipher = handshaker.newWriteCipher();
2082             writeAuthenticator = handshaker.newWriteAuthenticator();
2083         } catch (GeneralSecurityException e) {
2084             // "can't happen"
2085             throw new SSLException("Algorithm missing:  ", e);
2086         }
2087         outputRecord.changeWriteCiphers(writeAuthenticator, writeCipher);
2088     }
2089 
2090     /*
2091      * Updates the SSL version associated with this connection.
2092      * Called from Handshaker once it has determined the negotiated version.
2093      */
2094     synchronized void setVersion(ProtocolVersion protocolVersion) {
2095         this.protocolVersion = protocolVersion;
2096         outputRecord.setVersion(protocolVersion);
2097     }
2098 
2099     //
2100     // ONLY used by ClientHandshaker for the server hostname during handshaling
2101     //
2102     synchronized String getHost() {
2103         // Note that the host may be null or empty for localhost.
2104         if (host == null || host.length() == 0) {
2105             useImplicitHost(true);







2106         }

2107 
2108         return host;
2109     }
2110 
2111     /*
2112      * Try to set and use the implicit specified hostname
2113      */
2114     synchronized private void useImplicitHost(boolean noSniUpdate) {
2115         if ((host != null) && (host.length() != 0)) {
2116             return;
2117         }
2118 
2119         // Note: If the local name service is not trustworthy, reverse
2120         // host name resolution should not be performed for endpoint
2121         // identification.  Use the application original specified
2122         // hostname or IP address instead.
2123 
2124         // Get the original hostname via jdk.internal.misc.SharedSecrets
2125         InetAddress inetAddress = getInetAddress();
2126         if (inetAddress == null) {      // not connected
2127             return;
2128         }
2129 
2130         JavaNetInetAddressAccess jna =
2131                 SharedSecrets.getJavaNetInetAddressAccess();
2132         String originalHostname = jna.getOriginalHostName(inetAddress);
2133         if ((originalHostname != null) &&
2134                 (originalHostname.length() != 0)) {
2135 
2136             host = originalHostname;
2137             if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) {
2138                 serverNames =
2139                         Utilities.addToSNIServerNameList(serverNames, host);
2140 
2141                 if (!roleIsServer &&
2142                         (handshaker != null) && !handshaker.started()) {
2143                     handshaker.setSNIServerNames(serverNames);
2144                 }
2145             }
2146 
2147             return;
2148         }
2149 
2150         // No explicitly specified hostname, no sserver name indication.
2151         if (!trustNameService) {
2152             // The local name service is not trustworthy, use IP address.
2153             host = inetAddress.getHostAddress();
2154         } else {
2155             // Use the underlying reverse host name resolution service.
2156             host = getInetAddress().getHostName();
2157         }
2158     }
2159 
2160     // ONLY used by HttpsClient to setup the URI specified hostname
2161     //
2162     // Please NOTE that this method MUST be called before calling to
2163     // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
2164     // may override SNIHostName in the customized server name indication.
2165     public synchronized void setHost(String host) {
2166         this.host = host;
2167         this.serverNames =
2168             Utilities.addToSNIServerNameList(this.serverNames, this.host);
2169 
2170         if (!roleIsServer && (handshaker != null) && !handshaker.started()) {
2171             handshaker.setSNIServerNames(serverNames);
2172         }
2173     }
2174 
2175     /**
2176      * Gets an input stream to read from the peer on the other side.
2177      * Data read from this stream was always integrity protected in
2178      * transit, and will usually have been confidentiality protected.
2179      */
2180     @Override
2181     public synchronized InputStream getInputStream() throws IOException {
2182         if (isClosed()) {
2183             throw new SocketException("Socket is closed");
2184         }
2185 
2186         /*
2187          * Can't call isConnected() here, because the Handshakers
2188          * do some initialization before we actually connect.
2189          */
2190         if (connectionState == cs_START) {
2191             throw new SocketException("Socket is not connected");
2192         }
2193 


2542             throw new IllegalArgumentException("no listeners");
2543         }
2544         if (handshakeListeners.remove(listener) == null) {
2545             throw new IllegalArgumentException("listener not registered");
2546         }
2547         if (handshakeListeners.isEmpty()) {
2548             handshakeListeners = null;
2549         }
2550     }
2551 
2552     /**
2553      * Returns the SSLParameters in effect for this SSLSocket.
2554      */
2555     @Override
2556     public synchronized SSLParameters getSSLParameters() {
2557         SSLParameters params = super.getSSLParameters();
2558 
2559         // the super implementation does not handle the following parameters
2560         params.setEndpointIdentificationAlgorithm(identificationProtocol);
2561         params.setAlgorithmConstraints(algorithmConstraints);
2562 
2563         if (sniMatchers.isEmpty() && !noSniMatcher) {
2564             // 'null' indicates none has been set
2565             params.setSNIMatchers(null);
2566         } else {
2567             params.setSNIMatchers(sniMatchers);
2568         }
2569 
2570         if (serverNames.isEmpty() && !noSniExtension) {
2571             // 'null' indicates none has been set
2572             params.setServerNames(null);
2573         } else {
2574             params.setServerNames(serverNames);
2575         }
2576 
2577         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
2578         params.setMaximumPacketSize(maximumPacketSize);
2579         params.setApplicationProtocols(applicationProtocols);
2580 
2581         // DTLS handshake retransmissions parameter does not apply here.
2582 
2583         return params;
2584     }
2585 
2586     /**
2587      * Applies SSLParameters to this socket.
2588      */
2589     @Override
2590     public synchronized void setSSLParameters(SSLParameters params) {
2591         super.setSSLParameters(params);
2592 
2593         // the super implementation does not handle the following parameters
2594         identificationProtocol = params.getEndpointIdentificationAlgorithm();
2595         algorithmConstraints = params.getAlgorithmConstraints();
2596         preferLocalCipherSuites = params.getUseCipherSuitesOrder();
2597         maximumPacketSize = params.getMaximumPacketSize();
2598 
2599         // DTLS handshake retransmissions parameter does not apply here.
2600 
2601         if (maximumPacketSize != 0) {
2602             outputRecord.changePacketSize(maximumPacketSize);
2603         } else {
2604             // use the implicit maximum packet size.
2605             maximumPacketSize = outputRecord.getMaxPacketSize();
2606         }
2607 
2608         List<SNIServerName> sniNames = params.getServerNames();
2609         if (sniNames != null) {
2610             if (sniNames.isEmpty()) {
2611                 // need no SNI extension
2612                 noSniExtension = true;
2613             }   // Otherwise, need not to set noSniExtension
2614 
2615             serverNames = sniNames;
2616         }
2617 
2618         Collection<SNIMatcher> matchers = params.getSNIMatchers();
2619         if (matchers != null) {
2620             if (matchers.isEmpty()) {
2621                 // need no SNI matcher
2622                 noSniMatcher = true;
2623             }   // Otherwise, need not to set noSniMatcher
2624 
2625             sniMatchers = matchers;
2626         }
2627 
2628         applicationProtocols = params.getApplicationProtocols();
2629 
2630         if ((handshaker != null) && !handshaker.started()) {
2631             handshaker.setIdentificationProtocol(identificationProtocol);
2632             handshaker.setAlgorithmConstraints(algorithmConstraints);
2633             handshaker.setMaximumPacketSize(maximumPacketSize);
2634             handshaker.setApplicationProtocols(applicationProtocols);
2635             if (roleIsServer) {
2636                 handshaker.setSNIMatchers(sniMatchers);
2637                 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
2638             } else {
2639                 handshaker.setSNIServerNames(serverNames);
2640             }
2641         }
2642     }
2643 
2644     @Override