Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8144567

SNI does not work with HTTPSUrlConnection and a custom HostnameVerifier

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 8u51, 9
    • security-libs

      FULL PRODUCT VERSION :
      java version "1.8.0_65"
      Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.3.9600]

      A DESCRIPTION OF THE PROBLEM :
      When a custom HostnameVerifier is used, no Server Name Extension is included in the handshake of a HTTPSURLConnection.

      The reason is that SSLSocketImpl.setHost is called in HttpsClient.afterConnect, but SSLSocket.setSSLParameters is not (because of the custom hostname verifier).
      Without the call to setSSLParameters, the method Handshaker.setSNIServerNames is never called in the SSLSocketImpl, so the handshaker keeps using the serverNames it got when it was initialized (which are none).

      Probably SSLSocketImpl.setHost should call Handshaker.setSNIServerNames - alternatively, SSLSocket.setSSLParameters has to be called in any case in HttpsClient.afterConnect.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. set a custom hostnameVerifier with HttpsURLConnection.setDefaultHostnameVerifier()
      2. Open a HTTPSURLConnection
      3. No ServerName Extension is sent


      (see the test case)




      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The HttpsURLConnection should send a Server Name extension
      ACTUAL -
      The HttpsURLConnection did not send a Server Name extension

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.*;
      import java.net.*;
      import javax.net.ssl.*;

      public class TestSNI {
      public static void main(String[] args) throws Exception {
      HostnameVerifier defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

      @Override
      public boolean verify(String hostname, SSLSession session) {
      return defaultHostnameVerifier.verify(hostname, session);
      }
      });

      URL url = new URL("https://server-that-needs-sni");

      URLConnection con = url.openConnection();
      try (BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
      while (true) {
      String line = reader.readLine();
      if (line == null)
      break;
      System.out.println(line);
      }
      }
      }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Set a custom SSLSocketFactory that does not return an SSLSocket in createSocket() - this will force creation of a new SSLSocket with a correctly initialized handshaker.

            xuelei Xuelei Fan
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: