[JAVA-3614] Connections now always require a two way trust with no way to disable? Created: 30/Jan/20  Updated: 13/Feb/20  Resolved: 13/Feb/20

Status: Closed
Project: Java Driver
Component/s: Authentication, Connection Management
Affects Version/s: 3.10.0, 3.10.1, 3.10.2, 3.11.0, 3.11.1, 3.11.2, 3.12.0, 3.12.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Josef Haertl Assignee: Jeffrey Yemin
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File MongoDB Instance configuration.7z     File example with workaround.7z     File example.7z    

 Description   

I somewhat guess that this is a bug, or at least, a compatibility issue and/or missing feature.

Using a java driver version between 3.10 and 3.12.1 (more generally, a version supporting MongoDB 4.0), i observe the following:

If i try to connect to a MongoDB 3.6 instance by username and password, secured by ssl, it works as it did in previous versions of the java driver. More precisely, as seen from output with -Djavax.net.debug=all , the server sends his certificate to be validated by the driver. The client (so, my program using the java driver), does not even try to send its own certificate and MongoDB is happy with that.

I also duplicated the same data, users, passwords and all into a newer MongoDB 4.0 instance for testing. If i try to connect with that, it fails. As seen with -Djavax.net.debug=all, it tries several times before exiting with

Database connection verification failed: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[{address=…, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketReadException: Prematurely reached end of stream}}] 

Also, this MongoDB 4.0 instance several times logs the following:

 

I NETWORK  [listener] connection accepted from 10.210.53.230:55362 #368 (1 connection now open)
E NETWORK  [conn368] SSL peer certificate validation failed: (800B0109)A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.
E NETWORK  [conn368] SSL peer certificate validation failed: (800B0109)A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.
D -        [conn368] User Assertion: SSLHandshakeFailed: SSL peer certificate validation failed: (800B0109)A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. C:\data\mci\234eaebb96d72f5e8aef1024be83238a\src\src\mongo/transport/session_asio.h 621
I NETWORK  [conn368] Error receiving request from client: SSLHandshakeFailed: SSL peer certificate validation failed: (800B0109)A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.. Ending connection from 10.210.53.230:55362 (connection id: 368)
I NETWORK  [conn367] end connection 10.210.53.230:55361 (0 connections now open) 

This is consistent with the output from -Djavax.net.debug=all where i can tell that, connecting to the newer MongoDB 4.0 instance, my program now also sends his certificate to MongoDB – which is not happy about that (as seen above). My program trusts the server, but this is not true for the other direction in general. It can be for some environments using my program, but does not have to be.

Furthermore, I’m not sure if it would suffice to tell them to use a trusted certificate on both ends (if even feasible). Sometimes the MongoDB instance will run on a Windows Server with many trusted certification authorities. Since MongoDB 4.0 started to use Windows’ own mechanisms (schannel), every time the driver tries to connect, Windows complains about its limitation that it cannot present all of them to my “client” (Schannel Event 36885). Because of that, it seems possible that even a valid “client” certificate, would not be recognized as valid and this 2-way-trust would be doomed anyhow.

Both points might be resolvable by administrators of some environments, but not for all of them.

I did not find a way to disable this new two-way trust to let the administrator of those environments decide what to do. Did i overlook something or is such a possibility missing at the moment?



 Comments   
Comment by Jeffrey Yemin [ 13/Feb/20 ]

I don't see anything that we can change in the driver to address this issue.

I'm going to close this now, but please comment back if there's anything more that you would like to discuss.

Comment by Josef Haertl [ 05/Feb/20 ]

Thanks for your in-depth research on this.

This sounds like it's a MongoDB4-Windows-SChannel-thing, not something the mongo java driver could solve?

Potentially, one could extend MongoDB's net -> ssl -> allowConnectionsWithoutCertificates to also cover this case where SChannel "extorts" sending a potential invalid certificate?

For now, i constructed some workaround with a custom java.net.ssl.SSLContext.

In short, this workaround extracts the current TrustManagers from the current keystore and constructs a new SSLContext that uses the default TrustManagers, but a nulled KeyManager (so, no private keys). If given to the mongo java driver this results in java noting

"Warning: no suitable certificate found - continuing without client authentication"

which is quite what i want it to do. Then connection succeeds.

I've uploaded an updated example with this workaround. It also contains a new artificial set of rootCA/servercert to verify that the server certificate is still verified by the client (and thus would fail).

A solution more simple would be welcome, but i hope this suffices for now.

Comment by Mark Benvenuto [ 04/Feb/20 ]

Yes, SChannel behaves differently then OpenSSL in that it does not advertise the "Distinguished Names" of certificates it supports in the "Certificate Request" TLS message. I could not find any flags to change it to advertise the supported distinguished names. I think customers will need to use a custom java.nt.ssl.SSLContext to be more explicit.

Also, macOS SecureTransport does not set "Distinguished Names" in 10.14 (Mojave).

Per https://tools.ietf.org/html/rfc5246#section-7.4.4

certificate_authorities
A list of the distinguished names [X501] of acceptable
certificate_authorities, represented in DER-encoded format. These
distinguished names may specify a desired distinguished name for a
root CA or for a subordinate CA; thus, this message can be used to
describe known roots as well as a desired authorization space. If
the certificate_authorities list is empty, then the client MAY
send any certificate of the appropriate ClientCertificateType,
unless there is some external arrangement to the contrary.

Comment by Josef Haertl [ 31/Jan/20 ]

Hi jeff.yemin,

to avoid publishing sensitive internal information, i constructed a working minimal example with artificially created certificates and keystore.

example.7z contains a Maven project, the requested log files and the keystore in full. Also all certificates and keys used in the example.

MongoDB Instance configuration.7z contains the configuration i used for the MongoDB instances derived from that. It should work with MongoDB 3.6 as well as Mongodb 4.0. allowConnectionsWithoutCertificates would be required to allow connection without client certificate in 3.6, allowInvalidHostnames is only contained for this example (because my cert does not reflect the server's name).

Comment by Jeffrey Yemin [ 30/Jan/20 ]

Hi josef.haertl@ldbv.bayern.de

Please attach the javax.net.debug logs for both the 3.6 and the 4.0 scenarios, so we can take a look at what the difference is between them.

Also, using the keytool command please list and print  (–list and --printcert) all the certificates contained therein) all the certificates in the application key store.

 

Generated at Thu Feb 08 09:00:01 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.