Reputation: 18762
In our application, we are making HTTP call to auth service over HTTPS. I need to ensure that we do all the necessary checks to make sure connection is secure. As part of it I have to implement following:
I do not have any issue with item 1.
For item 2, I am trying to make use of HostNameVerifier implementation.
My code so far:
package com.company;
import sun.security.x509.X500Name;
import javax.net.ssl.*;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class Main {
public static void main(String[] args) throws Exception {
URL endpoint = new URL("https://example.com");
HttpsURLConnection conn = (HttpsURLConnection) endpoint.openConnection();
conn.setHostnameVerifier(new MyHostNameVerifier());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {trustAll}, null);
conn.setSSLSocketFactory(sslContext.getSocketFactory());
System.out.println("HTTP Response: " + conn.getResponseCode());
}
public static final X509TrustManager trustAll = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates,
String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates,
String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
public static class MyHostNameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostName, SSLSession sslSession) {
System.out.println("*** Validating host name for " + hostName);
return false;
}
}
}
My expectation was that MyHostNameVerifier#verify
will always be invoked, and I can make certain checks there.
However, I have observed that HostNameVerifier#verify
method is called only if I used IP address of the site, or only if the hostname does not match with Subject of certificate or any of the Subject Alternate Names.
HostNameVerifier#verify
is not called in below cases:
For example:
In the above code, I am trying to connect to "example.com".
The SSL certificate of "example.com" is issued to CN "www.example.org".
However, "example.com" is listed in "Subject Alternate Names" (SAN) of certificate.
If I instead use IP address of "example.com", then, my host name verifier is invoked.
URL endpoint = new URL("https://93.184.216.34/");
Can anyone confirm to me that Java internally handles wild card certificates and SAN certificate checks? If yes, then, I may not have to do any additional code changes.
Upvotes: 3
Views: 2810
Reputation: 69
I might step a bit out of my boundries quoting the Java documentation but it's our purest source.
During handshaking, if the URL's hostname and the server's identification hostname mismatch, the verification mechanism can call back to implementers of this interface to determine if this connection should be allowed.
These callbacks are used when the default rules for URL hostname verification fail.
Which basicly confirms your observation that once you enter a non valid certificate it will then and only then call the function to see if you still want to allow it. Through your own test that the correct wildcard certificate didn't call the function we can say that he definitly confirmed it valid and doesen't need your help with it. It's the same with the SAN certificate.
Upvotes: 1