[JAVA-2184] No subject alternative names matching IP address // Subject Alternative Name only DNS entry Created: 03/May/16  Updated: 11/Sep/19  Resolved: 20/May/16

Status: Closed
Project: Java Driver
Component/s: Connection Management
Affects Version/s: 3.2.1
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Stefan Siegl Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows, Linux


Issue Links:
Related

 Description   

Hello,

I´m trying to connect to a mongod instance on CentOS with the Java driver from my windows-pc. The mongod is configured as follows:

   ssl:
    mode: requireSSL
    PEMKeyFile: /tmp/ssl/mongodb.pem
    CAFile: /tmp/ssl/cert-chain.pem
    allowConnectionsWithoutCertificates: true

A connection from my windows with the commandline works:

mongod <server:port> --ssl --sslCAFile <certicate-ca>

Also from MongoChef, but I get an exception when I try to execute the following snippet:

MongoClientOptions clientOptions = MongoClientOptions.builder().sslEnabled(true).sslInvalidHostNameAllowed(false).build();
MongoClient mongoClient = new MongoClient("<mongod-dnsname>", clientOptions);
 
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection<Document> collection = db.getCollection("testColl");
 
System.out.println(collection.count());

The stacktrace is:

2016-05-03 08:02:28,004 INFO  cluster: Cluster created with settings {hosts=[<mongod-dnsname>], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2016-05-03 08:02:28,086 DEBUG cluster: Updating cluster description to  {type=UNKNOWN, servers=[{address=<mongod-dnsname>, type=UNKNOWN, state=CONNECTING}]
2016-05-03 08:02:28,132 INFO  cluster: No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, all=[ServerDescription{address=<mongod-dnsname>, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out
2016-05-03 08:02:28,147 DEBUG connection: Closing connection connectionId{localValue:1}
2016-05-03 08:02:28,149 DEBUG connection: Closing connection connectionId{localValue:1}
2016-05-03 08:02:28,150 INFO  cluster: Exception in monitor thread while connecting to server <mongod-dnsname>
com.mongodb.MongoSocketWriteException: Exception sending message
	at com.mongodb.connection.InternalStreamConnection.translateWriteException(InternalStreamConnection.java:462)
	at com.mongodb.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:205)
	at com.mongodb.connection.CommandHelper.sendMessage(CommandHelper.java:89)
	at com.mongodb.connection.CommandHelper.executeCommand(CommandHelper.java:32)
	at com.mongodb.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:83)
	at com.mongodb.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:43)
	at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115)
	at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:128)
	at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address <mongod-ip> found
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1506)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
	at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
	at com.mongodb.connection.SocketStream.write(SocketStream.java:75)
	at com.mongodb.connection.InternalStreamConnection.sendMessage(InternalStreamConnection.java:201)
	... 7 more
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address <mongod-ip> found
	at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:167)
	at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)
	... 16 more

The certificate was also used for the application running on the same server without any trouble. It contains following SAN entry:
X509v3 Subject Alternative Name:
DNS:<mongod-dnsname>



 Comments   
Comment by Stefan Siegl [ 20/May/16 ]

Thank you Jeff for your support. You can close this ticket.

BR

Comment by Jeffrey Yemin [ 19/May/16 ]

That's great news, though I've not been able to track down a bug report for the JDK related to this.

Regardless, do you consider the issue resolved then? If so, I'll close this ticket.

Comment by Stefan Siegl [ 19/May/16 ]

Hi Jeff,

I´m using the following version.

java -version
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

EDIT :
In the meantim, I have performed a java update...

With version 1.8.0_92 your test programm runs without any exceptions. And my little test-programm can connect to the mongodb with ssl.

With version 1.8.0_51 your and my test programm exit with an exception.

Comment by Jeffrey Yemin [ 18/May/16 ]

Hi Stefan,

I'm not clear on why your application is taking the code path into sun.security.util.HostnameChecker.matchIP, instead of into sun.security.util.HostnameChecker.matchDNS. If you're specifying the DNS name, or even an IP address that resolves to a DNS name, that shouldn't happen.

Which JDK are you using?

Comment by Stefan Siegl [ 09/May/16 ]

Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address <mongod-ip> found
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1506)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
	at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)
	at de.fhg.iwes.bundle.semiah.vpp.JAVA2184.main(JAVA2184.java:36)
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address <mongod-ip> found
	at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:167)
	at sun.security.util.HostnameChecker.match(HostnameChecker.java:93)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)
	... 9 more

I think the problem is the way how checking the identity of the server. The article from stackoverflow explains very well, how client should check the identity of a server. Link:
http://stackoverflow.com/questions/8443081/how-are-ssl-certificate-server-names-resolved-can-i-add-alternative-names-using?lq=1

He refers to section 3.1 of the RFC 2818 (http://tools.ietf.org/html/rfc2818#section-3.1). The implementation requires an entry for the IP address in the subjectAltName-Field. This is not the case for all certificates in the web. For example microsoft.com has different entries for the subjectAltName and google.de has also one DNS-entry for the subjectAltName, but no entry for the IP-address. According openssl and some certificate checkers from the web, the certificate I use is valid.

Is there a way to modify the way how verify the servers identity without to disabling the check?
Or does this mean that the implementation of the SSLSockect does not exactly follow the RFC?

Comment by Jeffrey Yemin [ 05/May/16 ]

Please try connecting with a simple Java program like this:

public class JAVA2184 {
    public static void main(String[] args) throws IOException {
        String host = "localhost";
        int port = 27017;
 
        SocketFactory factory = SSLSocketFactory.getDefault();
 
        SSLSocket sslSocket = (SSLSocket) factory.createSocket();
 
        SSLParameters sslParameters = sslSocket.getSSLParameters();
        sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
        sslSocket.setSSLParameters(sslParameters);
        sslSocket.connect(new InetSocketAddress(InetAddress.getByName(host), port), 20000);
 
        sslSocket.getOutputStream().write(1);
    }
}

This is basically what the Java driver itself is doing, as it defers all SSL handling to the SSLSocketFactory.

Generated at Thu Feb 08 08:56:33 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.