Why am I getting "No name match found" "Certificate Exception"?

As I understand it, in most cases, this exception indicates that the owner of the CN certificate (common name) is not the same as the hostname in the URL. However, in my case they match, but the exception is thrown anyway.

Remote Server Certificate Hierarchy:

  • self-signed certificate with CN=sms.main.ru

  • the certificate signed with the first one, and CN=client.sms.main.ru

My java client runs under apache-tomcat 6 and tries to connect to https://client.sms.main.ru/

and the following exception is thrown:

No name matching client.sms.main.ru found

      

Both certificates are added in $JAVA_HOME/jre/lib/security/cacerts

via $JAVA_HOME/bin/keytool

as shown in How to Configure Apache / Tomcat to Trust Internal Certification Authorities for Server-to-Server HTTPS Requests in the unixtippse response.

The Java code is pretty trivial:

URL url = new URL(strurl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Connection", "close");
con.setDoOutput(true);
con.connect();

      

What am I missing?


Interestingly, when I try to access this URL with a browser on Windows PC, it says the certificate is not trusted, I add it to the browser exception list and it works fine. So it looks like I added these certificates on the cacerts

wrong way so that java cannot use them. But I can easily find them by alias or CN with:

$JAVA_HOME/bin/keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts | less

      

+3


source to share


3 answers


In the end, all I had to do was:

  • Disable hostname checking:

    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    
          

  • Make sure to use the cacerts

    default file as while researching I tried to disable the ssl certificate validation and the code used which can be found in a lot of threads on SO (implementation of my own X509TrustManager

    ) i.e. in Java: Override function to disable SSL certificate validation . This code has replaced the default SSLSocketFactory

    which I need. So I had to remove all of these things and only use code to disable hostname validation.



I left HttpURLConnection

. Don't need to replace it with HttpsURLConnection

.

It would definitely be much better if I could manage to disable hostname checking as well, but I couldn't. There might be something wrong with the certificates.

+3


source


This is earlier how I trusted self signed certificates on tomcat



static private SSLSocketFactory newSslSocketFactory(String jksFile, char[] password) {

    try {
        KeyStore trusted = KeyStore.getInstance("JKS");
        InputStream in = StaticHttpsClient.class.getClassLoader().getResourceAsStream(jksFile);
        try {
            trusted.load(in, password);
        } finally {
            in.close();
        }

        SSLSocketFactory socketFactory = new SSLSocketFactory(trusted);
        HostnameVerifier hostnameVerifier =    org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
        socketFactory .setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
        return socketFactory;
    } catch (Exception e) {
        throw new AssertionError(e);
    }
}

static protected ClientConnectionManager createClientConnectionManager(String jksFile, char[] password) {
    SchemeRegistry registry = new SchemeRegistry();

    registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    registry.register(new Scheme("https", 443, newSslSocketFactory(jksFile, password)));
    return new SingleClientConnManager(registry);

}   

      

+1


source


Use HttpsURLConnection

and SSLSocketFactory

to perform SSL handshake.

-4


source







All Articles