1

I currently have an application that would make HTTP post request to a lot of URLs. Some of the connections are failing with the following exception.

Exception in thread "main" javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1410) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2004) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)

. . .

Hence, I want to set “jsse.enableSNIExtension” to false only for specific connections which throw the above mentioned exception.

How do I do it on an HTTPsURLConnection/SSLSocket level?

Code

URL url = new URL("https://artofskinmd.localgiftcards.com/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();

httpConnection.connect();

I am trying to find a way to change the SSLParameters for the HttpsURLConnection object. But I am unable to find any setSSLParameters() method for setting an empty server names list. I am not able to find anything online on setting SSLParameters for HttpURLConnection, SSLContext etc

Keen Sage
  • 1,899
  • 5
  • 26
  • 44
  • If you [don't know what the security consequences of doing this are](http://stackoverflow.com/q/32067124/207421), why are you asking? – user207421 Aug 18 '15 at 10:02
  • The other question will throw light on the security concerns with setting the jsse system property. This question will be useful in case there are no high security risk with the approach. – Keen Sage Aug 18 '15 at 10:27
  • 1
    According to the slightly older source I have and verified by javap for 7u80 and 8u51, `private final static boolean enableSNIExtension` in `sun.security.ssl.ClientHandshaker` is **initialized only when the class is loaded** and there is no API to change it. Untested, but assuming you're not under a SecurityManager (e.g. browser applet) it *should* work to use reflection to temporarily clobber this. If any other thread(s) could do (client) SSL/TLS concurrently you need to mutex; it's simple and clear to sync on `ClientHandshaker.class`. – dave_thompson_085 Aug 19 '15 at 09:53

2 Answers2

2

Obviously the site depends on SNI, otherwise it would not care about the name sent by the client in the SNI extension. This means that disabling the extension will probably not help, but instead you would then either get some handshake failure or some default site (and certificate) and probably not the site you have intended. To fix the problem you should not disable SNI but instead use the correct name, i.e. the name expected by the site.

Edit: This looks like both a bad server configuration together with a bug in Java7 and Java8. Access to the URL https://artofskinmd.localgiftcards.com/ will result in a unknown_name TLS alert warning which Java7 and Java8 wrongly consider fatal (same as the very old OpenSSL 0.9.8). Disabling SNI will actually help in this case, but there seems to be no way to disable SNI for a single HttpURLConnection object.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Based on my reading, this is an issue with the server configuration. Ref: http://javaresolutions.blogspot.ie/2014/07/javaxnetsslsslprotocolexception.html As I do not have access to the server, i will not be able to modify the server configuration. Is there a way to see what all server name does the host accepts? – Keen Sage Aug 18 '15 at 16:20
  • @Sashwat: the server is configured to only accept some host names and will reject everything else (including no SNI) with unknown_name. This is a valid configuration. And no, you can not determine directly which names the server will accept, but you might try all the names which resolve to the same IP address. Unfortunately there is no easy way to get these names :( – Steffen Ullrich Aug 18 '15 at 17:33
  • @Sashwat: the address you gave (`artofskinmd.localgiftcards.com`) has no problems with SNI. If you get the unknown_name for this URL something else is wrong. – Steffen Ullrich Aug 18 '15 at 17:36
  • I am actually getting `Exception in thread "main" 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) ` – Keen Sage Aug 18 '15 at 19:36
  • \@Steffen: How did you verify that the server do not have problem with SNI? – Keen Sage Aug 18 '15 at 19:39
  • @Sashwat: I've used [my own tool](https://github.com/noxxi/p5-ssl-tools/blob/master/analyze-ssl.pl) but you can also see it with OpenSSL: `openssl s_client -connect artofskinmd.localgiftcards.com:443 -servername artofskinmd.localgiftcards.com`. The last command uses SNI and succeeds. Playing around with servername or omitting it shows that the server accepts anything as name and does not even need SNI. Thus something must be different with how your application does the request. Maybe you could make a packet capture to compare? – Steffen Ullrich Aug 18 '15 at 19:54
  • 1
    @Sashwat: according to [SSLLabs](https://www.ssllabs.com/ssltest/analyze.html?d=artofskinmd.localgiftcards.com) the unknown_name problem seems to be specific to Java7 and Java8 while Java6 (which does not do SNI) works. No other client has problems. Strange. – Steffen Ullrich Aug 18 '15 at 20:02
  • 1
    @Sashwat: actually the server sends a TLS alert level warning when using SNI with the potential wrong name. Java 7 and Java 8 consider this warning fatal and thus fail - all others consider this as a warning only and continue. This is the same bug OpenSSL 0.9.x had many years ago. – Steffen Ullrich Aug 18 '15 at 20:17