Wand Maker
Wand Maker

Reputation: 18762

HostNameVerifier is not called for sites with wildcard or SAN certificate

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:

  1. Verify that certificate of auth server is issued by well-known CA.
  2. Verify that host name present in certificate of auth server matches the host name that we are using to connect to auth server.

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:

  1. If the site's certificate is wild card certificate, and it matches the hostname used.
  2. If the site's certificate is SAN certificate and if host name I am using is either the subject's CN or is listed as one of the Subject Alternate Name value.

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

Answers (1)

NotAdrian
NotAdrian

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

Related Questions