4

I'm sending an https POST on some url using Apache HttpClient.

HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);

And I get:

javax.net.ssl.SSLException: hostname in certificate didn't match: <*.*.*.*> != <*.url 

Now after searching, I found the solution on stackoverflow:

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
HttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

And the POST is succesfully done.

But I don't understand what's happening here! Is my connection still secure? Is this the right solution? If not, what's the best solution?

braincell
  • 562
  • 1
  • 13
  • 26

2 Answers2

3

If you're not verifying the host name, you're simply not checking that you're talking to the entity you intended to talk to: it could be a MITM instead. It's the same issue as disabling VERIFYHOST with Curl, for example. You may also be interested in this question on Security.SE.

Regarding your initial problem, the host name (or IP address) in the certificate needs to match the host name you intended to contact, that is, the one in the URL. If you're using an IP address, that IP address needs to be in the Subject Alternative Name of the certificate. (See this question.) In general, it's easier to use names rather than IP addresses, even on a LAN.

EDIT: Considering you're using Apache Http Client 4.0.2, the release notes for 4.0.3 say:

This is an emergency release fixing a critical regression in the SSL connection management code. HttpClient 4.0.2 release included an improved support for multihome hosts, which unfortunately had a bug causing the default SSL hostname verification logic to fail. An attempt to establish an SSL connection with HttpClient 4.0.2 can result in javax.net.ssl.SSLException: "hostname in certificate didn't match ..." error.

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • Thanks, But I don't completely understand your answer. If I browse with browser the url(host name), it browses fine with green https. If I use IP address instead, it shows "Identity not verified" with red https. What does this mean? On the code I'm using host name and get the exception. – braincell Mar 19 '13 at 12:40
  • Which version of Apache Http Client are you using? Do you register a Scheme too? – Bruno Mar 19 '13 at 12:50
  • Great. Thanks for your question, the exception doesn't happen now that I updated to 4.2.3 :) – braincell Mar 19 '13 at 13:05
1

Important - if you are allowing all hosts (that is, disabling host name verification), then it is certainly NOT safe. You shouldn't be doing this in production.

I think you are probably using self-signed certificates which may be the root cause of this exception. If yes, create a certificate with host as localhost (or your IP) and then try. On production, just enable host name verification and your code would run fine.

Sudhanshu Umalkar
  • 4,174
  • 1
  • 23
  • 33