[SERVER-85910] Setting allowConnectionsWithoutCertificates is ignored Created: 30/Jan/24  Updated: 05/Feb/24

Status: Investigating
Project: Core Server
Component/s: None
Affects Version/s: 7.0.5
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Wernfried Domscheit Assignee: Brad Moore
Resolution: Unresolved Votes: 0
Labels: TLS/SSL, security
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File mongo-ca.cer     File mongo.client-bad.pem     File mongo.client.pem     File mongo.server.pem    
Issue Links:
Related
related to DOCS-16619 [Server] Clarify scope of parameters ... Closed
Operating System: ALL
Sprint: Security 2024-02-05, Security 2024-02-19
Participants:

 Description   

I have setup a stand-alone mongod like this:

 

net:
  port: 27017
  bindIpAll: true
  tls:
    mode: requireTLS
    certificateKeyFile: mongo.server.pem
    CAFile: mongo-ca.cer
    allowConnectionsWithoutCertificates: false
    allowInvalidCertificates: false
 
security:
  authorization: enabled

 

Documentation says:

  • For clients that don't provide certificates, mongod or mongos encrypts the TLS/SSL connection, assuming the connection is successfully made.
  • For clients that present a certificate, mongos or mongod performs certificate validation using the root certificate chain specified by CAFile and reject clients with invalid certificates.

 

However, the behavior is different.

If I don't provide a client certificate, then the connection is rejected (instead of encrypts the TLS/SSL connection, assuming the connection is successfully made):

mongosh "mongodb://localhost:27017/?tls=true&tlsCAFile=mongo-ca.cer"
Current Mongosh Log ID: 65b8afb4924b39f4ec3b77f5
Connecting to:          mongodb://localhost:27017/?tls=true&tlsCAFile=mongo-ca.cer&directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.1.1
MongoServerSelectionError: connection <monitor> to 127.0.0.1:27017 closed 

If I provide an invalid client certificate, then the connection is successful (instead of reject clients):

openssl verify -CAfile mongo-ca.cer mongo.client-bad.pem
CN = admin
error 20 at 0 depth lookup: unable to get local issuer certificate
error mongo.client-bad.pem: verification failed
 
 
mongosh "mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=mongo.client-bad.pem&tlsCAFile=mongo-ca.cer"
Current Mongosh Log ID: 65b8b0987645903dc9cc5ecd
Connecting to:          mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=mongo.client-bad.pem&tlsCAFile=mongo-ca.cer&directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.1.1
Using MongoDB:          7.0.5
Using Mongosh:          2.1.1
 
test> db.getMongo()
mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=mongo.client-bad.pem&tlsCAFile=mongo-ca.cer&directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.1.1

If the client provides a valid certificate, then of course everything is working fine and as expected:

openssl verify -CAfile mongo-ca.cer mongo.client.pem
mongo.client.pem: OK
 
openssl verify -CAfile mongo-ca.cer mongo.server.pem
mongo.server.pem: OK
 
 
mongosh "mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=mongo.client.pem&tlsCAFile=mongo-ca.cer"
Current Mongosh Log ID: 65b8b213027a4c163908974c
Connecting to:          mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=mongo.client.pem&tlsCAFile=mongo-ca.cer&directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.1.1
Using MongoDB:          7.0.5
Using Mongosh:          2.1.1
 
test> db.getMongo()
mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=mongo.client.pem&tlsCAFile=mongo-ca.cer&directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.1.1

Tested in Windows 10 environment.

 

 

 

 



 Comments   
Comment by Wernfried Domscheit [ 04/Feb/24 ]

I did a mistake in my initial description. The mongo-ca.cer certificate is stored in my system certificate store, thus client certificate  mongo.client-bad.pem was accepted.

It works as is should work, just the documentation is wrong.

Here the relevant information of uploaded certificates:

 

$ openssl x509 -in mongo.server.pem -noout -subject -issuer -ext extendedKeyUsage
subject=C = CH, O = Sunrise, OU = OSS, OU = MongoDB, CN = server
issuer=C = CH, O = Sunrise, OU = OSS, OU = MongoDB, CN = Jira Issuing CA
X509v3 Extended Key Usage:
    TLS Web Server Authentication
 
$ openssl x509 -in mongo.client.pem -noout -subject -issuer -ext extendedKeyUsage
subject=C = CH, O = Sunrise, OU = OSS, OU = MongoDB, OU = Client, CN = Jira
issuer=C = CH, O = Sunrise, OU = OSS, OU = MongoDB, CN = Jira Issuing CA
X509v3 Extended Key Usage:
    TLS Web Client Authentication
 
$ openssl x509 -in mongo.client-bad.pem -noout -subject -issuer -ext extendedKeyUsage
subject=C = CH, O = Sunrise, OU = OSS, OU = other, OU = Client, CN = something else
issuer=C = CH, O = Sunrise, OU = OSS, CN = something else
X509v3 Extended Key Usage:
    TLS Web Client Authentication
 
$ openssl x509 -in mongo-ca.cer -noout -subject -issuer -ext keyUsage
subject=C = CH, O = Sunrise, OU = OSS, OU = MongoDB, CN = Jira Issuing CA
issuer=C = CH, O = Sunrise, OU = OSS, CN = Jira CA
X509v3 Key Usage:
    Digital Signature, Certificate Sign, CRL Sign
 
$ openssl crl2pkcs7 -nocrl -certfile mongo-ca.cer | openssl pkcs7 -print_certs -noout
subject=C = CH, O = Sunrise, OU = OSS, OU = MongoDB, CN = Jira Issuing CA
issuer=C = CH, O = Sunrise, OU = OSS, CN = Jira CAsubject=C = CH, O = Sunrise, OU = OSS, CN = Jira CA
issuer=C = CH, O = Sunrise, OU = OSS, CN = Jira CA
 
$ openssl verify -CAfile mongo-ca.cer mongo.client.pem mongo.server.pem mongo.client-bad.pem
mongo.client.pem: OK
mongo.server.pem: OK
C = CH, O = Sunrise, OU = OSS, OU = other, OU = Client, CN = something else
error 20 at 0 depth lookup: unable to get local issuer certificate
error mongo.client-bad.pem: verification failed
 

 

 

And here are again the test cases:

 

# valid client certificate -> working as expected
 
$ mongosh localhost --quiet --norc --tls --tlsCAFile=mongo-ca.cer --tlsCertificateKeyFile=mongo.client.pem --eval "print(db.serverCmdLineOpts().parsed.net.tls); db.getMongo()"
{
  CAFile: 'c:\\MongoDB\\certs\\mongo-ca.cer',
  allowConnectionsWithoutCertificates: false,
  allowInvalidCertificates: false,
  certificateKeyFile: 'c:\\MongoDB\\certs\\mongo.server.pem',
  mode: 'requireTLS'
}
mongodb://127.0.0.1:27017/localhost?directConnection=true&serverSelectionTimeoutMS=2000&tls=true&tlsCAFile=mongo-ca.cer&tlsCertificateKeyFile=mongo.client.pem&appName=mongosh+2.1.1
 
 
 
# invalid client certificate -> connection refused, working as documented
 
$ mongosh localhost --quiet --norc --tls --tlsCAFile=mongo-ca.cer --tlsCertificateKeyFile=mongo.client-bad.pem --eval "db.getMongo()"
MongoServerSelectionError: connection <monitor> to 127.0.0.1:27017 closed
 
 
 
# no client certificate -> connection refused (documentation says, it should connect)
 
$ mongosh localhost --quiet --norc --tls --tlsCAFile=mongo-ca.cer --eval "db.getMongo()"
MongoServerSelectionError: connection <monitor> to 127.0.0.1:27017 closed

 

 

As already stated Documentation says:

  • For clients that don't provide certificates, mongod or mongos encrypts the TLS/SSL connection, assuming the connection is successfully made.

 

That's not correct. For clients that don't provide a (client) certificate, the connection is rejected if net.tls.allowConnectionsWithoutCertificates = false

 

Kind Regards
Wernfried

 

 

 

 

 

Comment by Brad Moore [ 04/Feb/24 ]

wernfried.domscheit@sunrise.net I've attempted to reproduce the issue you're seeing but am not seeing the same behavior. In case some small difference in the certs is somehow causing different behavior, could you attach a set of certs (mongo-ca.cer, mongo.server.pem, mongo.client.pem, mongo.client-bad.pem) that you've confirmed exhibit this behavior?

 

Of course, please don't upload any cert that you actually use anywhere

Comment by Wernfried Domscheit [ 03/Feb/24 ]

I think this part of documentation is misleading:

  • For clients that don't provide certificates, mongod or mongos encrypts the TLS/SSL connection, assuming the connection is successfully made.

TLS/SSL encryption of the connection is managed by the server certificate (an invalid server certificate is still used to encrypt the connection, that's properly documented). However, the client certificate does not have any influence whether a connection is TLS/SSL encrypted or not.

Yes, if the client does not provide a certificate then the mongod or mongos encrypts the TLS/SSL connection.
However, if the client provides a certificate, then the mongod or mongos encrypts the TLS/SSL connection as well, no matter whether the client certificate can be verified or not. So, above statement does not make much sense.

 

 

 

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