Tuesday, 22 July 2014

javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name

Caused by: javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name

at sun.security.ssl.ClientHandshaker.handshakeAlert(Unknown Source)

at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)

at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)

at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)

at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)

at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)

at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)

at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)

at java.net.URL.openStream(Unknown Source)

Issue :
I got this exception when I am trying to connect to WebService using https. You may also get this while connecting to any HTTPS url .

It is issue with Server , because in their certificate the common name doesn’t match with  url domain.
It's possible to put multiple hostnames in a modern certificate and just use that one certificate in the default vhost, there are many hosting providers who are hosting for too many sites on a single address for that to be practical for them

In two ways we can fix the issue :
Http Client Side:

Java 7 introduced SNI support which is enabled by default. I have found out that certain misconfigured servers send an "Unrecognized Name" warning in the SSL handshake which is ignored by most clients... except for Java.
As workaround, I 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
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");
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).

HttpServer Side:

On the server side we have to create certificate with matching Domain name as Server Name or define where we have ServerName / ServerAlias as same name mentione din certificate common name.

  1. https://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI


Please comment here