Skip to content

Commit

Permalink
CDRIVER-3508 add OCSP URI options
Browse files Browse the repository at this point in the history
- revert changes to schannel that do not account for CRL
  • Loading branch information
kevinAlbs committed Mar 23, 2020
1 parent 5489fde commit 7f785ff
Show file tree
Hide file tree
Showing 22 changed files with 773 additions and 96 deletions.
8 changes: 8 additions & 0 deletions .evergreen/run-ocsp-test.sh
Expand Up @@ -128,10 +128,18 @@ if [ "TEST_1" = "$TEST_COLUMN" ]; then
elif [ "TEST_2" = "$TEST_COLUMN" ]; then
expect_failure
elif [ "TEST_3" = "$TEST_COLUMN" ]; then
# Window does not soft-fail by default, users can disable revocation checking.
if [ "$OS" = "WINDOWS" ]; then
MONGODB_URI="$MONGODB_URI&tlsDisableCertificateRevocationCheck=true"
fi
expect_success
elif [ "TEST_4" = "$TEST_COLUMN" ]; then
expect_failure
elif [ "SOFT_FAIL_TEST" = "$TEST_COLUMN" ]; then
# Window does not soft-fail by default, users can disable revocation checking.
if [ "$OS" = "WINDOWS" ]; then
MONGODB_URI="$MONGODB_URI&tlsDisableCertificateRevocationCheck=true"
fi
expect_success
elif [ "MALICIOUS_SERVER_TEST_1" = "$TEST_COLUMN" ]; then
expect_failure
Expand Down
58 changes: 36 additions & 22 deletions src/libmongoc/doc/configuring_tls.rst
Expand Up @@ -3,18 +3,6 @@
Configuring TLS
===============

Building libmongoc with TLS support
-----------------------------------

By default, libmongoc will attempt to find a supported TLS library and enable TLS support. This is controlled by the cmake flag ``ENABLE_SSL``, which is set to ``AUTO`` by default. Valid values are:

- ``AUTO`` the default behavior. Link to the system's native TLS library, or attempt to find OpenSSL.
- ``DARWIN`` link to Secure Transport, the native TLS library on macOS.
- ``WINDOWS`` link to Secure Channel, the native TLS on Windows.
- ``OPENSSL`` link to OpenSSL (libssl). An optional install path may be specified with ``OPENSSL_ROOT``.
- ``LIBRESSL`` link to LibreSSL's libtls. (LibreSSL's compatible libssl may be linked to by setting ``OPENSSL``).
- ``OFF`` disable TLS support.

Configuration with URI options
------------------------------

Expand Down Expand Up @@ -54,7 +42,7 @@ Client Authentication

When MongoDB is started with TLS enabled, it will by default require the client to provide a client certificate issued by a certificate authority specified by ``--tlsCAFile``, or an authority trusted by the native certificate store in use on the server.

To provide the client certificate, set the ``tlscertificatekeyfile`` in the URI to a PEM armored certificate file.
To provide the client certificate, set the ``tlsCertificateKeyFile`` in the URI to a PEM armored certificate file.

.. code-block:: c
Expand All @@ -69,10 +57,26 @@ Server Certificate Verification

The MongoDB C Driver will automatically verify the validity of the server certificate, such as issued by configured Certificate Authority, hostname validation, and expiration.

To overwrite this behaviour, it is possible to disable hostname validation, and/or allow otherwise invalid certificates. This behaviour is controlled using the ``tlsallowinvalidhostnames`` and ``tlsallowinvalidcertificates`` options. By default, both are set to ``false``. It is not recommended to change these defaults as it exposes the client to *Man In The Middle* attacks (when ``tlsallowinvalidhostnames`` is set) and otherwise invalid certificates when ``tlsallowinvalidcertificates`` is set to ``true``.
To overwrite this behaviour, it is possible to disable hostname validation, OCSP endpoint revocation checking, revocation checking entirely, and allow invalid certificates.

This behaviour is controlled using the ``tlsAllowInvalidHostnames``, ``tlsDisableOCSPEndpointCheck``, ``tlsDisableCertificateRevocationCheck``, and ``tlsAllowInvalidCertificates`` options respectively. By default, all are set to ``false``.

It is not recommended to change these defaults as it exposes the client to *Man In The Middle* attacks (when ``tlsAllowInvalidHostnames`` is set), invalid certificates (when ``tlsAllowInvalidCertificates`` is set), or potentially revoked certificates (when ``tlsDisableOCSPEndpointCheck`` or ``tlsDisableCertificateRevocationCheck`` are set).

Supported Libraries
-------------------

By default, libmongoc will attempt to find a supported TLS library and enable TLS support. This is controlled by the cmake flag ``ENABLE_SSL``, which is set to ``AUTO`` by default. Valid values are:

- ``AUTO`` the default behavior. Link to the system's native TLS library, or attempt to find OpenSSL.
- ``DARWIN`` link to Secure Transport, the native TLS library on macOS.
- ``WINDOWS`` link to Secure Channel, the native TLS on Windows.
- ``OPENSSL`` link to OpenSSL (libssl). An optional install path may be specified with ``OPENSSL_ROOT``.
- ``LIBRESSL`` link to LibreSSL's libtls. (LibreSSL's compatible libssl may be linked to by setting ``OPENSSL``).
- ``OFF`` disable TLS support.

OpenSSL
-------
```````

The MongoDB C Driver uses OpenSSL, if available, on Linux and Unix platforms (besides macOS). Industry best practices and some regulations require the use of TLS 1.1 or newer, which requires at least OpenSSL 1.0.1. Check your OpenSSL version like so::

Expand All @@ -82,33 +86,43 @@ Ensure your system's OpenSSL is a recent version (at least 1.0.1), or install a

cmake -DOPENSSL_ROOT_DIR=/absolute/path/to/openssl

When compiled against OpenSSL, the driver will attempt to load the system default certificate store, as configured by the distribution. That can be overridden by setting the ``tlscafile`` URI option or with the fields ``ca_file`` and ``ca_dir`` in the :symbol:`mongoc_ssl_opt_t`.
When compiled against OpenSSL, the driver will attempt to load the system default certificate store, as configured by the distribution. That can be overridden by setting the ``tlsCAFile`` URI option or with the fields ``ca_file`` and ``ca_dir`` in the :symbol:`mongoc_ssl_opt_t`.

Setting ``tlsDisableOCSPEndpointCheck`` and ``tlsDisableCertificateRevocationCheck`` has no effect.

LibreSSL / libtls
-----------------
`````````````````

The MongoDB C Driver supports LibreSSL through the use of OpenSSL compatibility checks when configured to compile against ``openssl``. It also supports the new ``libtls`` library when configured to build against ``libressl``.

Setting ``tlsDisableOCSPEndpointCheck`` and ``tlsDisableCertificateRevocationCheck`` has no effect.

Native TLS Support on Windows (Secure Channel)
----------------------------------------------
``````````````````````````````````````````````

The MongoDB C Driver supports the Windows native TLS library (Secure Channel, or SChannel), and its native crypto library (Cryptography API: Next Generation, or CNG).

When compiled against the Windows native libraries, the ``ca_dir`` option of a :symbol:`mongoc_ssl_opt_t` is not supported, and will issue an error if used.

Encrypted PEM files (e.g., setting ``tlscertificatekeypassword``) are also not supported, and will result in error when attempting to load them.
Encrypted PEM files (e.g., setting ``tlsCertificateKeyPassword``) are also not supported, and will result in error when attempting to load them.

When ``tlscafile`` is set, the driver will only allow server certificates issued by the authority (or authorities) provided. When no ``tlscafile`` is set, the driver will look up the Certificate Authority using the ``System Local Machine Root`` certificate store to confirm the provided certificate or the ``Current user certificate store`` if the ``System Local Machine Root`` certificate store is unavailable.
When ``tlsCAFile`` is set, the driver will only allow server certificates issued by the authority (or authorities) provided. When no ``tlsCAFile`` is set, the driver will look up the Certificate Authority using the ``System Local Machine Root`` certificate store to confirm the provided certificate or the ``Current user certificate store`` if the ``System Local Machine Root`` certificate store is unavailable.

When ``crl_file`` is set with :symbol:`mongoc_ssl_opt_t`, the driver will import the revocation list to the ``System Local Machine Root`` certificate store.

Setting ``tlsDisableOCSPEndpointCheck`` has no effect.

Setting ``tlsAllowInvalidHostnames`` additionally consider certificates with no revocation mechanisms specified (CRL / OCSP) a non-error.

.. _Secure Transport:

Native TLS Support on macOS / Darwin (Secure Transport)
-------------------------------------------------------
```````````````````````````````````````````````````````

The MongoDB C Driver supports the Darwin (OS X, macOS, iOS, etc.) native TLS library (Secure Transport), and its native crypto library (Common Crypto, or CC).

When compiled against Secure Transport, the ``ca_dir`` option of a :symbol:`mongoc_ssl_opt_t` is not supported, and will issue an error if used.

When ``tlscafile`` is set, the driver will only allow server certificates issued by the authority (or authorities) provided. When no ``tlscafile`` is set, the driver will use the Certificate Authorities in the currently unlocked keychains.
When ``tlsCAFile`` is set, the driver will only allow server certificates issued by the authority (or authorities) provided. When no ``tlsCAFile`` is set, the driver will use the Certificate Authorities in the currently unlocked keychains.

Setting ``tlsDisableOCSPEndpointCheck`` and ``tlsDisableCertificateRevocationCheck`` has no effect.
8 changes: 7 additions & 1 deletion src/libmongoc/doc/includes/tls-options.txt
Expand Up @@ -24,4 +24,10 @@
- Ignore hostname verification of the certificate (e.g. Man In The Middle, using valid certificate, but issued for another hostname)
* - MONGOC_URI_TLSINSECURE
- tlsinsecure
- {true|false}, indicating if insecure TLS options should be used. Currently this implies MONGOC_URI_TLSALLOWINVALIDCERTIFICATES and MONGOC_URI_TLSALLOWINVALIDHOSTNAMES.
- {true|false}, indicating if insecure TLS options should be used. Currently this implies MONGOC_URI_TLSALLOWINVALIDCERTIFICATES and MONGOC_URI_TLSALLOWINVALIDHOSTNAMES.
* - MONGOC_URI_TLSDISABLECERTIFICATEREVOCATIONCHECK
- tlsdisablecertificaterevocationcheck
- {true|false}, indicates if revocation checking (CRL / OCSP) should be disabled.
* - MONGOC_URI_TLSDISABLEOCSPENDPOINTCHECK
- tlsdisableocspendpointcheck
- {true|false}, indicates if OCSP responder endpoints should not be requested when an OCSP response is not stapled.
3 changes: 2 additions & 1 deletion src/libmongoc/doc/mongoc_ssl_opt_t.rst
Expand Up @@ -16,7 +16,8 @@ Synopsis
const char *crl_file;
bool weak_cert_validation;
bool allow_invalid_hostname;
void *padding[7];
void *internal;
void *padding[6];
} mongoc_ssl_opt_t;
Description
Expand Down
30 changes: 22 additions & 8 deletions src/libmongoc/src/mongoc/mongoc-client-pool.c
Expand Up @@ -15,7 +15,6 @@
*/



#include "mongoc.h"
#include "mongoc-apm-private.h"
#include "mongoc-counters-private.h"
Expand Down Expand Up @@ -58,17 +57,16 @@ void
mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool,
const mongoc_ssl_opt_t *opts)
{
BSON_ASSERT (pool);

bson_mutex_lock (&pool->mutex);

_mongoc_ssl_opts_cleanup (&pool->ssl_opts);
_mongoc_ssl_opts_cleanup (&pool->ssl_opts,
false /* don't free internal opts. */);

memset (&pool->ssl_opts, 0, sizeof pool->ssl_opts);
pool->ssl_opts_set = false;

if (opts) {
_mongoc_ssl_opts_copy_to (opts, &pool->ssl_opts);
_mongoc_ssl_opts_copy_to (
opts, &pool->ssl_opts, false /* don't overwrite internal opts. */);
pool->ssl_opts_set = true;
}

Expand All @@ -77,6 +75,20 @@ mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool,

bson_mutex_unlock (&pool->mutex);
}

void
_mongoc_client_pool_set_internal_tls_opts (
mongoc_client_pool_t *pool, _mongoc_internal_tls_opts_t *internal)
{
bson_mutex_lock (&pool->mutex);
if (!pool->ssl_opts_set) {
return;
}
pool->ssl_opts.internal = bson_malloc (sizeof (_mongoc_internal_tls_opts_t));
memcpy (
pool->ssl_opts.internal, internal, sizeof (_mongoc_internal_tls_opts_t));
bson_mutex_unlock (&pool->mutex);
}
#endif


Expand Down Expand Up @@ -143,10 +155,12 @@ mongoc_client_pool_new (const mongoc_uri_t *uri)
#ifdef MONGOC_ENABLE_SSL
if (mongoc_uri_get_tls (pool->uri)) {
mongoc_ssl_opt_t ssl_opt = {0};
_mongoc_internal_tls_opts_t internal_tls_opts = {0};

_mongoc_ssl_opts_from_uri (&ssl_opt, pool->uri);
_mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, pool->uri);
/* sets use_ssl = true */
mongoc_client_pool_set_ssl_opts (pool, &ssl_opt);
_mongoc_client_pool_set_internal_tls_opts (pool, &internal_tls_opts);
}
#endif
mongoc_counter_client_pools_active_inc ();
Expand Down Expand Up @@ -184,7 +198,7 @@ mongoc_client_pool_destroy (mongoc_client_pool_t *pool)
mongoc_cond_destroy (&pool->cond);

#ifdef MONGOC_ENABLE_SSL
_mongoc_ssl_opts_cleanup (&pool->ssl_opts);
_mongoc_ssl_opts_cleanup (&pool->ssl_opts, true);
#endif

bson_free (pool);
Expand Down
32 changes: 26 additions & 6 deletions src/libmongoc/src/mongoc/mongoc-client.c
Expand Up @@ -975,17 +975,34 @@ mongoc_client_new (const char *uri_string)
*/

#ifdef MONGOC_ENABLE_SSL
/* Only called internally. Caller must ensure opts->internal is valid. */
void
_mongoc_client_set_internal_tls_opts (mongoc_client_t *client,
_mongoc_internal_tls_opts_t *internal)
{
if (!client->use_ssl) {
return;
}
client->ssl_opts.internal =
bson_malloc (sizeof (_mongoc_internal_tls_opts_t));
memcpy (client->ssl_opts.internal,
internal,
sizeof (_mongoc_internal_tls_opts_t));
}

void
mongoc_client_set_ssl_opts (mongoc_client_t *client,
const mongoc_ssl_opt_t *opts)
{
BSON_ASSERT (client);
BSON_ASSERT (opts);

_mongoc_ssl_opts_cleanup (&client->ssl_opts);
_mongoc_ssl_opts_cleanup (&client->ssl_opts,
false /* don't free internal opts */);

client->use_ssl = true;
_mongoc_ssl_opts_copy_to (opts, &client->ssl_opts);
_mongoc_ssl_opts_copy_to (
opts, &client->ssl_opts, false /* don't overwrite internal opts */);

if (client->topology->single_threaded) {
mongoc_topology_scanner_set_ssl_opts (client->topology->scanner,
Expand Down Expand Up @@ -1091,10 +1108,12 @@ _mongoc_client_new_from_uri (mongoc_topology_t *topology)
client->use_ssl = false;
if (mongoc_uri_get_tls (client->uri)) {
mongoc_ssl_opt_t ssl_opt = {0};
_mongoc_internal_tls_opts_t internal_tls_opts = {0};

_mongoc_ssl_opts_from_uri (&ssl_opt, client->uri);
_mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, client->uri);
/* sets use_ssl = true */
mongoc_client_set_ssl_opts (client, &ssl_opt);
_mongoc_client_set_internal_tls_opts (client, &internal_tls_opts);
}
#endif

Expand Down Expand Up @@ -1137,7 +1156,7 @@ mongoc_client_destroy (mongoc_client_t *client)
mongoc_set_destroy (client->client_sessions);

#ifdef MONGOC_ENABLE_SSL
_mongoc_ssl_opts_cleanup (&client->ssl_opts);
_mongoc_ssl_opts_cleanup (&client->ssl_opts, true);
#endif

bson_free (client);
Expand Down Expand Up @@ -1638,8 +1657,9 @@ _mongoc_client_retryable_write_command_with_stream (
retry_server_stream = mongoc_cluster_stream_for_writes (
&client->cluster, parts->assembled.session, NULL, &ignored_error);

if (retry_server_stream && retry_server_stream->sd->max_wire_version >=
WIRE_VERSION_RETRY_WRITES) {
if (retry_server_stream &&
retry_server_stream->sd->max_wire_version >=
WIRE_VERSION_RETRY_WRITES) {
parts->assembled.server_stream = retry_server_stream;
bson_destroy (reply);
GOTO (retry);
Expand Down
21 changes: 6 additions & 15 deletions src/libmongoc/src/mongoc/mongoc-secure-channel.c
Expand Up @@ -383,17 +383,8 @@ mongoc_secure_channel_setup_ca (
L"Root"); /* system store name. "My" or "Root" */

if (cert_store == NULL) {
cert_store = CertOpenStore (
CERT_STORE_PROV_SYSTEM, /* provider */
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, /* certificate encoding */
0, /* unused */
CERT_SYSTEM_STORE_CURRENT_USER, /* dwFlags */
L"My"); /* system store name. "My" or "Root" */

if (cert_store == NULL) {
MONGOC_ERROR ("Error opening certificate store");
return false;
}
MONGOC_ERROR ("Error opening certificate store");
return false;
}

if (CertAddCertificateContextToStore (
Expand Down Expand Up @@ -830,10 +821,10 @@ mongoc_secure_channel_handshake_step_2 (mongoc_stream_tls_t *tls,
"has expired");
break;
case CRYPT_E_NO_REVOCATION_CHECK:
/* This seems to be raised also when hostname doesn't match the
* certificate */
MONGOC_ERROR ("SSL Certification verification failed: failed "
"revocation/hostname check");
MONGOC_ERROR ("SSL Certification verification failed: certificate "
"does not include revocation check. Set "
"tlsDisableCertificateRevocationCheck to disable "
"revocation checking");
break;

case SEC_E_INSUFFICIENT_MEMORY:
Expand Down
22 changes: 19 additions & 3 deletions src/libmongoc/src/mongoc/mongoc-ssl-private.h
Expand Up @@ -25,16 +25,32 @@

BSON_BEGIN_DECLS

typedef struct {
bool tls_disable_certificate_revocation_check;
bool tls_disable_ocsp_endpoint_check;
} _mongoc_internal_tls_opts_t;

char *
mongoc_ssl_extract_subject (const char *filename, const char *passphrase);

void
_mongoc_ssl_opts_from_uri (mongoc_ssl_opt_t *ssl_opt, mongoc_uri_t *uri);
_mongoc_ssl_opts_from_uri (mongoc_ssl_opt_t *ssl_opt,
_mongoc_internal_tls_opts_t *internal,
mongoc_uri_t *uri);
void
_mongoc_ssl_opts_copy_to (const mongoc_ssl_opt_t *src, mongoc_ssl_opt_t *dst);
_mongoc_ssl_opts_copy_to (const mongoc_ssl_opt_t *src,
mongoc_ssl_opt_t *dst,
bool copy_internal);

bool
_mongoc_ssl_opts_disable_certificate_revocation_check (
const mongoc_ssl_opt_t *ssl_opt);

bool
_mongoc_ssl_opts_disable_ocsp_endpoint_check (const mongoc_ssl_opt_t *ssl_opt);

void
_mongoc_ssl_opts_cleanup (mongoc_ssl_opt_t *opt);
_mongoc_ssl_opts_cleanup (mongoc_ssl_opt_t *opt, bool free_internal);

BSON_END_DECLS

Expand Down

0 comments on commit 7f785ff

Please sign in to comment.