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
source to share
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 ownX509TrustManager
) i.e. in Java: Override function to disable SSL certificate validation . This code has replaced the defaultSSLSocketFactory
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.
source to share
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);
}
source to share