[Solved-5 Solutions] SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0



Error Description:

After upgrading from Java 1.6 to Java 1.7, an error occurs when we try to establish a connection to the webserver over SSL:

javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name
    at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1288)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1904)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1027)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1262)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1289)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1273)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:523)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at java.net.URL.openStream(URL.java:1035)
click below button to copy the code. By - Java tutorial - team

Here is the code:

SAXBuilder builder = new SAXBuilder();
Document document = null;

try {
    url = new URL(https://some url);
    document = (Document) builder.build(url.openStream());
} catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(DownloadLoadiciousComputer.class.getName()).log(Level.SEVERE, null, ex);  
}

click below button to copy the code. By - Java tutorial - team

Solution 1:

  • Java 7 introduced SNI support which is enabled by default.
  • Certain misconfigured servers send an "Unrecognized Name" warning in the SSL handshake which is ignored by most clients... except for Java.The Oracle engineers refuse to "fix" this bug/feature.

As workaround, they suggest to set the jsse.enableSNIExtension property. To allow your programs to work without re-compiling, run your app as:

java -Djsse.enableSNIExtension=false yourClass
click below button to copy the code. By - Java tutorial - team
  • The property can also be set in the Java code, but it must be set before any SSL actions.
  • Once the SSL library has loaded, you can change the property, but it won't have any effect on the SNI status.

To disable SNI on runtime (with the aforementioned limitations), use:

System.setProperty("jsse.enableSNIExtension", "false");
click below button to copy the code. By - Java tutorial - team

The disadvantage of setting this flag is that SNI is disabled everywhere in the application. In order to make use of SNI and still support misconfigured servers:

  1. Create a SSLSocket with the host name you want to connect to. Let's name this sslsock.
  2. Try to run sslsock.startHandshake(). This will block until it is done or throw an exception on error. Whenever an error occurred in startHandshake(), get the exception message. If it equals to handshake alert: unrecognized_name, then you have found a misconfigured server.
  3. When you have received the unrecognized_name warning (fatal in Java), retry opening a SSLSocket, but this time without a host name. This effectively disables SNI (after all, the SNI extension is about adding a host name to the ClientHello message).

For the Webscarab SSL proxy, this commit implements the fall-back setup.

Solution 2:

We need to adjust the Apache configuration to include a ServerName or ServerAlias for the host.

This code fails:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://mydomain.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}
click below button to copy the code. By - Java tutorial - team

And this code works:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://google.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}
click below button to copy the code. By - Java tutorial - team

Solution 3:

You can disable sending SNI records with the System property

jsse.enableSNIExtension=false.
click below button to copy the code. By - Java tutorial - team
  • If you can change the code it helps to use SSLCocketFactory#createSocket() (with no host parameter or with a connected socket). In this case it will not send a server_name indication.

Solution 4:

Instead of relying on the default virtual host mechanism in apache, you can define one last catchall virtualhost that uses an arbitrary ServerName and a wildcard ServerAlias, e.g.

ServerName catchall.mydomain.com
ServerAlias *.mydomain.com
click below button to copy the code. By - Java tutorial - team
  • In that way you can use SNI and apache will not send back the SSL warning.
  • Of course, this only works if you can describe all of your domains easily using a wildcard syntax.

Solution 5:

Use:

  • System.setProperty("jsse.enableSNIExtension", "false");
  • Restart your Tomcat (important)

Related Searches to SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0