Thursday, November 24, 2005

Host name verification in HTTPS

As I mentioned in my blog on Missing images in CFDocument, in case you are using HTTPS, you must ensure that the certicate host name matches the host name in the URL. Lets say your certificate is issued to "www.mysite.com" then the request URL must have the host as "www.mysite.com". It can not be accessed using 'localhost', '127.0.0.1', that machine's IP address or machine's name.
Till JDK1.3, Sun's SSL implementation never used to verify the host name of the certificate. Since JDK1.4, it now verifies the hostname to prevent URL spoofing (When I request for some URL, some other guy in between intercepts and sends his own certificate and I will remain under the impression that I was getting the certificate of the requested server and hence a threat).

In case you want to access the URL using localhost or IP address or using machine's name, there is a workaround possible but that would invlove wrting some java code.
HttpsURLConnection that is used to make the connection, uses an interface HostnameVerifier to verify the host name of the certificate. A default implementation is used by default. You can provide your own implementation of this interface and set it on HttpsURLConnection. That will give the control of host name verification in your hand and you can verifiy it the way you want.

Unfortunately, this interface and HttpsURLConnection are present in both javax.net.ssl and com.sun.net.ssl package. So depending on which SSL packages are being used, you will have to implement appropriate interface and you will have to set this on appropriate HttpsURLConnection. To be sure, let your implementation class implement both the interface and set it on both the HttpsURLConnection by calling the static method
setDefaultHostnameVerifier(HostnameVerifier)

A simplistic implementation which disables any host name verification could be like

class MyHostnameVerifier implements com.sun.net.ssl.HostnameVerifier, javax.net.ssl.HostnameVerifier{
public boolean verify(String urlHostName, String certHostName){
return true;
}

public boolean verify(String urlHost, SSLSession sslSession){
return true;
}
}

set this verifier to both HttpsURLConnection at appropriate place.

MyHostnameVerifier verifier = new MyHostnameVerifier();
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(verifier);
com.sun.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(verifier);

4 comments:

Anonymous said...

Excellent posts Rupesh! Keep them coming.

Anonymous said...

Using com.sun.net.ssl.HttpsURLConnection instead of javax.net.ssl.HttpsURLConnection did the trick for me. Thanks a lot!

Marco Antonio said...

Rupesh, great! How to migrate this code to use with ColdFusion?

Marco Antonio said...

Hi Rupesh... how to say to CF 8 to ignore host name validation using setDefaultHostnameVerifier.
Cheers