[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: |
|
| 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
Also, this MongoDB 4.0 instance several times logs the following:
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
|
| 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.
|