From 12389aa14fc1c6b48c0ad45a05ded81503c0ea49 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 30 Jun 2025 19:15:46 -0400 Subject: [PATCH 01/16] add `const` to `mongoc_ssl_opt_t` params --- src/libmongoc/src/mongoc/mongoc-secure-channel-private.h | 6 +++--- src/libmongoc/src/mongoc/mongoc-secure-channel.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h b/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h index 673e2543da..2a7f71d934 100644 --- a/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h +++ b/src/libmongoc/src/mongoc/mongoc-secure-channel-private.h @@ -33,10 +33,10 @@ BSON_BEGIN_DECLS bool -mongoc_secure_channel_setup_ca (mongoc_ssl_opt_t *opt); +mongoc_secure_channel_setup_ca (const mongoc_ssl_opt_t *opt); bool -mongoc_secure_channel_setup_crl (mongoc_ssl_opt_t *opt); +mongoc_secure_channel_setup_crl (const mongoc_ssl_opt_t *opt); // mongoc_secure_channel_load_crl is used in tests. PCCRL_CONTEXT @@ -49,7 +49,7 @@ ssize_t mongoc_secure_channel_write (mongoc_stream_tls_t *tls, const void *data, size_t data_length); PCCERT_CONTEXT -mongoc_secure_channel_setup_certificate (mongoc_ssl_opt_t *opt); +mongoc_secure_channel_setup_certificate (const mongoc_ssl_opt_t *opt); /* it may require 16k + some overhead to hold one decryptable block of data - do diff --git a/src/libmongoc/src/mongoc/mongoc-secure-channel.c b/src/libmongoc/src/mongoc/mongoc-secure-channel.c index 688da5d9f4..bd6b19cc8a 100644 --- a/src/libmongoc/src/mongoc/mongoc-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-secure-channel.c @@ -379,14 +379,14 @@ mongoc_secure_channel_setup_certificate_from_file (const char *filename) } PCCERT_CONTEXT -mongoc_secure_channel_setup_certificate (mongoc_ssl_opt_t *opt) +mongoc_secure_channel_setup_certificate (const mongoc_ssl_opt_t *opt) { return mongoc_secure_channel_setup_certificate_from_file (opt->pem_file); } bool -mongoc_secure_channel_setup_ca (mongoc_ssl_opt_t *opt) +mongoc_secure_channel_setup_ca (const mongoc_ssl_opt_t *opt) { bool ok = false; char *pem = NULL; @@ -496,7 +496,7 @@ mongoc_secure_channel_load_crl (const char *crl_file) } bool -mongoc_secure_channel_setup_crl (mongoc_ssl_opt_t *opt) +mongoc_secure_channel_setup_crl (const mongoc_ssl_opt_t *opt) { HCERTSTORE cert_store = NULL; bool ok = false; From 188aa51dec3c070942aff49e84f85d52976103d8 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 30 Jun 2025 19:25:37 -0400 Subject: [PATCH 02/16] rename `mongoc_secure_channel_cred` to `mongoc_secure_channel_cred_handle` --- .../src/mongoc/mongoc-stream-tls-secure-channel-private.h | 4 ++-- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h index 730c842aec..6c53b1a558 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h @@ -45,7 +45,7 @@ typedef struct { CredHandle cred_handle; TimeStamp time_stamp; PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ -} mongoc_secure_channel_cred; +} mongoc_secure_channel_cred_handle; typedef struct { CtxtHandle ctxt_handle; @@ -59,7 +59,7 @@ typedef struct { */ typedef struct { ssl_connect_state connecting_state; - mongoc_secure_channel_cred *cred; + mongoc_secure_channel_cred_handle *cred; mongoc_secure_channel_ctxt *ctxt; SecPkgContext_StreamSizes stream_sizes; size_t encdata_length, decdata_length; diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c index 8c5c9f8241..d9834ae792 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -937,7 +937,8 @@ mongoc_stream_tls_secure_channel_new (mongoc_stream_t *base_stream, const char * schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - secure_channel->cred = (mongoc_secure_channel_cred *) bson_malloc0 (sizeof (mongoc_secure_channel_cred)); + secure_channel->cred = + (mongoc_secure_channel_cred_handle *) bson_malloc0 (sizeof (mongoc_secure_channel_cred_handle)); if (cert) { // Store client cert to free later. secure_channel->cred->cert = cert; From 08ad1289a0b3a5b7af23bf91e1a1bd17ba8e5a1b Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 30 Jun 2025 19:31:32 -0400 Subject: [PATCH 03/16] share `SCHANNEL_CRED` Share `SCHANNEL_CRED` on all client/pool connections. This is intended to simplify future fix for CDRIVER-5998. As an added benefit, this reduces the repeated reading of PEM files for each connection. --- src/libmongoc/CMakeLists.txt | 1 + src/libmongoc/src/mongoc/mongoc-client-pool.c | 13 + .../src/mongoc/mongoc-client-private.h | 2 + src/libmongoc/src/mongoc/mongoc-client.c | 24 +- .../src/mongoc/mongoc-secure-channel.c | 30 +- .../src/mongoc/mongoc-server-monitor.c | 6 + .../src/mongoc/mongoc-stream-tls-private.h | 9 + ...mongoc-stream-tls-secure-channel-private.h | 27 +- .../mongoc/mongoc-stream-tls-secure-channel.c | 159 ++++++----- src/libmongoc/src/mongoc/mongoc-stream-tls.c | 16 +- .../mongoc/mongoc-topology-scanner-private.h | 3 + .../src/mongoc/mongoc-topology-scanner.c | 15 + src/libmongoc/tests/test-libmongoc-main.c | 1 + .../tests/test-mongoc-secure-channel.c | 262 ++++++++++++++++++ 14 files changed, 483 insertions(+), 85 deletions(-) create mode 100644 src/libmongoc/tests/test-mongoc-secure-channel.c diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 1a0a833328..56581bf1bf 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -1075,6 +1075,7 @@ set (test-libmongoc-sources ${PROJECT_SOURCE_DIR}/tests/test-mongoc-scram.c ${PROJECT_SOURCE_DIR}/tests/test-mongoc-sdam-monitoring.c ${PROJECT_SOURCE_DIR}/tests/test-mongoc-sdam.c + ${PROJECT_SOURCE_DIR}/tests/test-mongoc-secure-channel.c ${PROJECT_SOURCE_DIR}/tests/test-mongoc-server-description.c ${PROJECT_SOURCE_DIR}/tests/test-mongoc-server-selection-errors.c ${PROJECT_SOURCE_DIR}/tests/test-mongoc-server-selection.c diff --git a/src/libmongoc/src/mongoc/mongoc-client-pool.c b/src/libmongoc/src/mongoc/mongoc-client-pool.c index acc0653799..1a7c0755e2 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-pool.c +++ b/src/libmongoc/src/mongoc/mongoc-client-pool.c @@ -39,6 +39,10 @@ #include #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +#include +#endif + struct _mongoc_client_pool_t { bson_mutex_t mutex; mongoc_cond_t cond; @@ -84,6 +88,15 @@ mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool, const mongoc_ssl_op SSL_CTX_free (pool->topology->scanner->openssl_ctx); pool->topology->scanner->openssl_ctx = _mongoc_openssl_ctx_new (&pool->ssl_opts); #endif + +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + // Access to secure_channel_cred_ptr does not need the thread-safe `mongoc_atomic_*` functions. + // secure_channel_cred_ptr is not expected to be modified by multiple threads. + // mongoc_client_pool_set_ssl_opts documentation prohibits calling after threads start. + mongoc_shared_ptr_reset (&pool->topology->scanner->secure_channel_cred_ptr, + mongoc_secure_channel_cred_new (&pool->ssl_opts), + mongoc_secure_channel_cred_deleter); +#endif } mongoc_topology_scanner_set_ssl_opts (pool->topology->scanner, &pool->ssl_opts); diff --git a/src/libmongoc/src/mongoc/mongoc-client-private.h b/src/libmongoc/src/mongoc/mongoc-client-private.h index 81920e8c74..9a420c7f1a 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-private.h +++ b/src/libmongoc/src/mongoc/mongoc-client-private.h @@ -38,6 +38,7 @@ #include #include #include +#include BSON_BEGIN_DECLS @@ -212,6 +213,7 @@ mongoc_client_connect (bool buffered, const mongoc_uri_t *uri, const mongoc_host_list_t *host, void *openssl_ctx_void, + mongoc_shared_ptr secure_channel_cred_ptr, bson_error_t *error); diff --git a/src/libmongoc/src/mongoc/mongoc-client.c b/src/libmongoc/src/mongoc/mongoc-client.c index a663744dbb..bcd053fbc5 100644 --- a/src/libmongoc/src/mongoc/mongoc-client.c +++ b/src/libmongoc/src/mongoc/mongoc-client.c @@ -70,6 +70,11 @@ #include #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +#include +#include +#endif + #include #include @@ -756,6 +761,7 @@ mongoc_client_connect (bool buffered, const mongoc_uri_t *uri, const mongoc_host_list_t *host, void *openssl_ctx_void, + mongoc_shared_ptr secure_channel_cred_ptr, bson_error_t *error) { mongoc_stream_t *base_stream = NULL; @@ -765,6 +771,7 @@ mongoc_client_connect (bool buffered, BSON_ASSERT (host); BSON_UNUSED (openssl_ctx_void); + BSON_UNUSED (secure_channel_cred_ptr); #ifndef MONGOC_ENABLE_SSL if (ssl_opts_void || mongoc_uri_get_tls (uri)) { @@ -814,6 +821,9 @@ mongoc_client_connect (bool buffered, // Use shared OpenSSL context. base_stream = mongoc_stream_tls_new_with_hostname_and_openssl_context ( base_stream, host->host, ssl_opts, true, (SSL_CTX *) openssl_ctx_void); +#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + // Use shared Secure Channel credentials. + base_stream = mongoc_stream_tls_new_with_secure_channel_cred (base_stream, ssl_opts, secure_channel_cred_ptr); #else base_stream = mongoc_stream_tls_new_with_hostname (base_stream, host->host, ssl_opts, true); #endif @@ -881,9 +891,13 @@ mongoc_client_default_stream_initiator (const mongoc_uri_t *uri, #if defined(MONGOC_ENABLE_SSL_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L SSL_CTX *ssl_ctx = client->topology->scanner->openssl_ctx; - return mongoc_client_connect (true, use_ssl, ssl_opts_void, uri, host, (void *) ssl_ctx, error); + return mongoc_client_connect ( + true, use_ssl, ssl_opts_void, uri, host, (void *) ssl_ctx, MONGOC_SHARED_PTR_NULL, error); +#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + mongoc_shared_ptr cred_ptr = client->topology->scanner->secure_channel_cred_ptr; + return mongoc_client_connect (true, use_ssl, ssl_opts_void, uri, host, NULL, cred_ptr, error); #else - return mongoc_client_connect (true, use_ssl, ssl_opts_void, uri, host, NULL, error); + return mongoc_client_connect (true, use_ssl, ssl_opts_void, uri, host, NULL, MONGOC_SHARED_PTR_NULL, error); #endif } @@ -1028,6 +1042,12 @@ _mongoc_client_set_ssl_opts_for_single_or_pooled (mongoc_client_t *client, const SSL_CTX_free (client->topology->scanner->openssl_ctx); client->topology->scanner->openssl_ctx = _mongoc_openssl_ctx_new (&client->ssl_opts); #endif + +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + mongoc_shared_ptr_reset (&client->topology->scanner->secure_channel_cred_ptr, + mongoc_secure_channel_cred_new (&client->ssl_opts), + mongoc_secure_channel_cred_deleter); +#endif } } #endif // MONGOC_ENABLE_SSL diff --git a/src/libmongoc/src/mongoc/mongoc-secure-channel.c b/src/libmongoc/src/mongoc/mongoc-secure-channel.c index bd6b19cc8a..48145ee1a6 100644 --- a/src/libmongoc/src/mongoc/mongoc-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-secure-channel.c @@ -671,18 +671,18 @@ mongoc_secure_channel_handshake_step_1 (mongoc_stream_tls_t *tls, char *hostname secure_channel->ctxt = (mongoc_secure_channel_ctxt *) bson_malloc0 (sizeof (mongoc_secure_channel_ctxt)); /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ - sspi_status = InitializeSecurityContext (&secure_channel->cred->cred_handle, /* phCredential */ - NULL, /* phContext */ - hostname, /* pszTargetName */ - secure_channel->req_flags, /* fContextReq */ - 0, /* Reserved1, must be 0 */ - 0, /* TargetDataRep, unused */ - NULL, /* pInput */ - 0, /* Reserved2, must be 0 */ - &secure_channel->ctxt->ctxt_handle, /* phNewContext OUT param */ - &outbuf_desc, /* pOutput OUT param */ - &secure_channel->ret_flags, /* pfContextAttr OUT param */ - &secure_channel->ctxt->time_stamp /* ptsExpiry OUT param */ + sspi_status = InitializeSecurityContext (&secure_channel->cred_handle->cred_handle, /* phCredential */ + NULL, /* phContext */ + hostname, /* pszTargetName */ + secure_channel->req_flags, /* fContextReq */ + 0, /* Reserved1, must be 0 */ + 0, /* TargetDataRep, unused */ + NULL, /* pInput */ + 0, /* Reserved2, must be 0 */ + &secure_channel->ctxt->ctxt_handle, /* phNewContext OUT param */ + &outbuf_desc, /* pOutput OUT param */ + &secure_channel->ret_flags, /* pfContextAttr OUT param */ + &secure_channel->ctxt->time_stamp /* ptsExpiry OUT param */ ); if (sspi_status != SEC_I_CONTINUE_NEEDED) { // Cast signed SECURITY_STATUS to unsigned DWORD. FormatMessage expects DWORD. @@ -739,7 +739,7 @@ mongoc_secure_channel_handshake_step_2 (mongoc_stream_tls_t *tls, char *hostname TRACE ("%s", "SSL/TLS connection with endpoint (step 2/3)"); - if (!secure_channel->cred || !secure_channel->ctxt) { + if (!secure_channel->cred_handle || !secure_channel->ctxt) { MONGOC_LOG_AND_SET_ERROR ( error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "required TLS credentials or context not provided"); @@ -809,7 +809,7 @@ mongoc_secure_channel_handshake_step_2 (mongoc_stream_tls_t *tls, char *hostname /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ - sspi_status = InitializeSecurityContext (&secure_channel->cred->cred_handle, + sspi_status = InitializeSecurityContext (&secure_channel->cred_handle->cred_handle, &secure_channel->ctxt->ctxt_handle, hostname, secure_channel->req_flags, @@ -989,7 +989,7 @@ mongoc_secure_channel_handshake_step_3 (mongoc_stream_tls_t *tls, char *hostname TRACE ("SSL/TLS connection with %s (step 3/3)", hostname); - if (!secure_channel->cred) { + if (!secure_channel->cred_handle) { MONGOC_LOG_AND_SET_ERROR ( error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "required TLS credentials not provided"); return false; diff --git a/src/libmongoc/src/mongoc/mongoc-server-monitor.c b/src/libmongoc/src/mongoc/mongoc-server-monitor.c index 2c85d78ff0..11204d6550 100644 --- a/src/libmongoc/src/mongoc/mongoc-server-monitor.c +++ b/src/libmongoc/src/mongoc/mongoc-server-monitor.c @@ -933,6 +933,7 @@ _server_monitor_setup_connection (mongoc_server_monitor_t *server_monitor, } else { void *ssl_opts_void = NULL; void *openssl_ctx_void = NULL; + mongoc_shared_ptr secure_channel_cred_ptr = MONGOC_SHARED_PTR_NULL; #ifdef MONGOC_ENABLE_SSL ssl_opts_void = server_monitor->ssl_opts; @@ -942,12 +943,17 @@ _server_monitor_setup_connection (mongoc_server_monitor_t *server_monitor, openssl_ctx_void = server_monitor->topology->scanner->openssl_ctx; #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + secure_channel_cred_ptr = server_monitor->topology->scanner->secure_channel_cred_ptr; +#endif + server_monitor->stream = mongoc_client_connect (false, ssl_opts_void != NULL, ssl_opts_void, server_monitor->uri, &server_monitor->description->host, openssl_ctx_void, + secure_channel_cred_ptr, error); } diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h b/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h index ad2907fdb0..87fb52befa 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h @@ -28,6 +28,8 @@ #include #endif +#include + BSON_BEGIN_DECLS /** @@ -55,6 +57,13 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context (mongoc_stream_t *base_s SSL_CTX *ssl_ctx) BSON_GNUC_WARN_UNUSED_RESULT; #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +mongoc_stream_t * +mongoc_stream_tls_new_with_secure_channel_cred (mongoc_stream_t *base_stream, + mongoc_ssl_opt_t *opt, + mongoc_shared_ptr secure_channel_cred_ptr) BSON_GNUC_WARN_UNUSED_RESULT; +#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL + BSON_END_DECLS #endif /* MONGOC_STREAM_TLS_PRIVATE_H */ diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h index 6c53b1a558..147eff1374 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h @@ -22,9 +22,12 @@ #ifdef MONGOC_ENABLE_SSL_SECURE_CHANNEL #include +#include + /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 #include +#include BSON_BEGIN_DECLS @@ -44,9 +47,14 @@ typedef enum { typedef struct { CredHandle cred_handle; TimeStamp time_stamp; - PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ } mongoc_secure_channel_cred_handle; +// `mongoc_secure_channel_cred` may be shared on multiple connections. +typedef struct _mongoc_secure_channel_cred { + PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ + SCHANNEL_CRED cred; // TODO: switch to SCH_CREDENTIALS to support TLS v1.3 +} mongoc_secure_channel_cred; + typedef struct { CtxtHandle ctxt_handle; TimeStamp time_stamp; @@ -59,7 +67,8 @@ typedef struct { */ typedef struct { ssl_connect_state connecting_state; - mongoc_secure_channel_cred_handle *cred; + mongoc_shared_ptr cred_ptr; // Manages a mongoc_secure_channel_cred. + mongoc_secure_channel_cred_handle *cred_handle; mongoc_secure_channel_ctxt *ctxt; SecPkgContext_StreamSizes stream_sizes; size_t encdata_length, decdata_length; @@ -72,6 +81,20 @@ typedef struct { bool recv_connection_closed; /* true if connection closed, regardless how */ } mongoc_stream_tls_secure_channel_t; +struct _mongoc_ssl_opt_t; // Forward declare. Defined in mongoc-ssl.h. +struct _mongoc_stream_t; // Forward declare. Defined in mongoc-stream.h. + +mongoc_secure_channel_cred * +mongoc_secure_channel_cred_new (const struct _mongoc_ssl_opt_t *opt); + +// mongoc_secure_channel_cred_deleter is useful as a deleter for mongoc_shared_t. +void +mongoc_secure_channel_cred_deleter (void *cred_void); + +struct _mongoc_stream_t * +mongoc_stream_tls_secure_channel_new_with_creds (struct _mongoc_stream_t *base_stream, + struct _mongoc_ssl_opt_t *opt, + mongoc_shared_ptr cred_ptr /* optional */); BSON_END_DECLS diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c index d9834ae792..c025cbb01a 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -103,7 +103,7 @@ _mongoc_stream_tls_secure_channel_destroy (mongoc_stream_t *stream) TRACE ("%s", "shutting down SSL/TLS connection"); - if (secure_channel->cred && secure_channel->ctxt) { + if (secure_channel->cred_handle && secure_channel->ctxt) { SecBufferDesc BuffDesc; SecBuffer Buffer; SECURITY_STATUS sspi_status; @@ -124,7 +124,7 @@ _mongoc_stream_tls_secure_channel_destroy (mongoc_stream_t *stream) _mongoc_secure_channel_init_sec_buffer (&outbuf, SECBUFFER_EMPTY, NULL, 0); _mongoc_secure_channel_init_sec_buffer_desc (&outbuf_desc, &outbuf, 1); - sspi_status = InitializeSecurityContext (&secure_channel->cred->cred_handle, + sspi_status = InitializeSecurityContext (&secure_channel->cred_handle->cred_handle, &secure_channel->ctxt->ctxt_handle, /*tls->hostname*/ NULL, secure_channel->req_flags, @@ -157,15 +157,16 @@ _mongoc_stream_tls_secure_channel_destroy (mongoc_stream_t *stream) } /* free SSPI Schannel API credential handle */ - if (secure_channel->cred) { + if (secure_channel->cred_handle) { /* decrement the reference counter of the credential/session handle */ /* if the handle was not cached and the refcount is zero */ TRACE ("%s", "clear credential handle"); - FreeCredentialsHandle (&secure_channel->cred->cred_handle); - CertFreeCertificateContext (secure_channel->cred->cert); - bson_free (secure_channel->cred); + FreeCredentialsHandle (&secure_channel->cred_handle->cred_handle); + bson_free (secure_channel->cred_handle); } + mongoc_shared_ptr_reset_null (&secure_channel->cred_ptr); + /* free internal buffer for received encrypted data */ if (secure_channel->encdata_buffer != NULL) { bson_free (secure_channel->encdata_buffer); @@ -840,21 +841,94 @@ _mongoc_stream_tls_secure_channel_should_retry (mongoc_stream_t *stream) RETURN (mongoc_stream_should_retry (tls->base_stream)); } +mongoc_secure_channel_cred * +mongoc_secure_channel_cred_new (const mongoc_ssl_opt_t *opt) +{ + BSON_ASSERT_PARAM (opt); + mongoc_secure_channel_cred *cred = bson_malloc0 (sizeof (mongoc_secure_channel_cred)); + + cred->cred.dwVersion = SCHANNEL_CRED_VERSION; + +/* SCHANNEL_CRED: + * SCH_USE_STRONG_CRYPTO is not available in VS2010 + * https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */ +#ifdef SCH_USE_STRONG_CRYPTO + cred->cred.dwFlags = SCH_USE_STRONG_CRYPTO; +#endif + + /* By default, enable soft failing. + * A certificate with no revocation check is a soft failure. */ + cred->cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK; + /* An offline OCSP responder / CRL distribution list is a soft failure. */ + cred->cred.dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; + if (opt->weak_cert_validation) { + cred->cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + TRACE ("%s", "disabled server certificate checks"); + } else { + cred->cred.dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; + if (!_mongoc_ssl_opts_disable_certificate_revocation_check (opt)) { + cred->cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + TRACE ("%s", "enabled server certificate revocation checks"); + } + TRACE ("%s", "enabled server certificate checks"); + } + + if (opt->allow_invalid_hostname) { + cred->cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + } + + if (opt->ca_file) { + mongoc_secure_channel_setup_ca (opt); + } + + if (opt->crl_file) { + mongoc_secure_channel_setup_crl (opt); + } + + if (opt->pem_file) { + cred->cert = mongoc_secure_channel_setup_certificate (opt); + + if (cred->cert) { + cred->cred.cCreds = 1; + cred->cred.paCred = &cred->cert; + } + } + + cred->cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + return cred; +} + +void +mongoc_secure_channel_cred_deleter (void *cred_void) +{ + mongoc_secure_channel_cred *cred = cred_void; + if (!cred) { + return; + } + CertFreeCertificateContext (cred->cert); + bson_free (cred); +} + mongoc_stream_t * mongoc_stream_tls_secure_channel_new (mongoc_stream_t *base_stream, const char *host, mongoc_ssl_opt_t *opt, int client) { BSON_UNUSED (host); BSON_UNUSED (client); + return mongoc_stream_tls_secure_channel_new_with_creds (base_stream, opt, MONGOC_SHARED_PTR_NULL); +} +mongoc_stream_t * +mongoc_stream_tls_secure_channel_new_with_creds (mongoc_stream_t *base_stream, + mongoc_ssl_opt_t *opt, + mongoc_shared_ptr cred_ptr) +{ SECURITY_STATUS sspi_status = SEC_E_OK; - SCHANNEL_CRED schannel_cred; mongoc_stream_tls_t *tls; mongoc_stream_tls_secure_channel_t *secure_channel; - PCCERT_CONTEXT cert = NULL; ENTRY; - BSON_ASSERT (base_stream); - BSON_ASSERT (opt); + BSON_ASSERT_PARAM (base_stream); + BSON_ASSERT_PARAM (opt); secure_channel = (mongoc_stream_tls_secure_channel_t *) bson_malloc0 (sizeof *secure_channel); @@ -886,63 +960,18 @@ mongoc_stream_tls_secure_channel_new (mongoc_stream_t *base_stream, const char * TRACE ("%s", "SSL/TLS connection with endpoint AcquireCredentialsHandle"); /* setup Schannel API options */ - memset (&schannel_cred, 0, sizeof (schannel_cred)); - schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; - -/* SCHANNEL_CRED: - * SCH_USE_STRONG_CRYPTO is not available in VS2010 - * https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */ -#ifdef SCH_USE_STRONG_CRYPTO - schannel_cred.dwFlags = SCH_USE_STRONG_CRYPTO; -#endif - - /* By default, enable soft failing. - * A certificate with no revocation check is a soft failure. */ - schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK; - /* An offline OCSP responder / CRL distribution list is a soft failure. */ - schannel_cred.dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; - if (opt->weak_cert_validation) { - schannel_cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; - TRACE ("%s", "disabled server certificate checks"); + if (mongoc_shared_ptr_is_null (cred_ptr)) { + // Shared credentials were not passed. Create credentials for this stream: + mongoc_shared_ptr_reset ( + &secure_channel->cred_ptr, mongoc_secure_channel_cred_new (opt), mongoc_secure_channel_cred_deleter); } else { - schannel_cred.dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; - if (!_mongoc_ssl_opts_disable_certificate_revocation_check (opt)) { - schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - TRACE ("%s", "enabled server certificate revocation checks"); - } - TRACE ("%s", "enabled server certificate checks"); - } - - if (opt->allow_invalid_hostname) { - schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - } - - if (opt->ca_file) { - mongoc_secure_channel_setup_ca (opt); - } - - if (opt->crl_file) { - mongoc_secure_channel_setup_crl (opt); - } - - if (opt->pem_file) { - cert = mongoc_secure_channel_setup_certificate (opt); - - if (cert) { - schannel_cred.cCreds = 1; - schannel_cred.paCred = &cert; - } + mongoc_shared_ptr_assign (&secure_channel->cred_ptr, cred_ptr); // Increase reference count. } + mongoc_secure_channel_cred *cred = secure_channel->cred_ptr.ptr; - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - - secure_channel->cred = + secure_channel->cred_handle = (mongoc_secure_channel_cred_handle *) bson_malloc0 (sizeof (mongoc_secure_channel_cred_handle)); - if (cert) { - // Store client cert to free later. - secure_channel->cred->cert = cert; - } /* Example: * https://msdn.microsoft.com/en-us/library/windows/desktop/aa375454%28v=vs.85%29.aspx @@ -953,11 +982,11 @@ mongoc_stream_tls_secure_channel_new (mongoc_stream_t *base_stream, const char * UNISP_NAME, /* security package */ SECPKG_CRED_OUTBOUND, /* we are preparing outbound connection */ NULL, /* Optional logon */ - &schannel_cred, /* TLS "configuration", "auth data" */ + &cred->cred, /* TLS "configuration", "auth data" */ NULL, /* unused */ NULL, /* unused */ - &secure_channel->cred->cred_handle, /* credential OUT param */ - &secure_channel->cred->time_stamp); /* certificate expiration time */ + &secure_channel->cred_handle->cred_handle, /* credential OUT param */ + &secure_channel->cred_handle->time_stamp); /* certificate expiration time */ if (sspi_status != SEC_E_OK) { // Cast signed SECURITY_STATUS to unsigned DWORD. FormatMessage expects DWORD. diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls.c b/src/libmongoc/src/mongoc/mongoc-stream-tls.c index 2e28061ed4..7332072f6e 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls.c @@ -143,7 +143,7 @@ mongoc_stream_tls_handshake_block (mongoc_stream_t *stream, const char *host, in * NULL on failure, otherwise a mongoc_stream_t. * * Side effects: - * None. + * May set opt->allow_invalid_hostname to true. * *-------------------------------------------------------------------------- */ @@ -227,4 +227,18 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context ( } #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +mongoc_stream_t * +mongoc_stream_tls_new_with_secure_channel_cred (mongoc_stream_t *base_stream, + mongoc_ssl_opt_t *opt, + mongoc_shared_ptr secure_channel_cred_ptr) +{ + if (opt->weak_cert_validation) { + // For compatibility with `mongoc_stream_tls_new_with_hostname`, modify `opt` directly: + opt->allow_invalid_hostname = true; + } + return mongoc_stream_tls_secure_channel_new_with_creds (base_stream, opt, secure_channel_cred_ptr); +} +#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL + #endif diff --git a/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h b/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h index a8fc135501..1441414c26 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h +++ b/src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h @@ -35,6 +35,7 @@ #include #include #include +#include BSON_BEGIN_DECLS @@ -133,6 +134,8 @@ typedef struct mongoc_topology_scanner { #if defined(MONGOC_ENABLE_SSL_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L SSL_CTX *openssl_ctx; +#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + mongoc_shared_ptr secure_channel_cred_ptr; // Manages a mongoc_secure_channel_cred. #endif int64_t dns_cache_timeout_ms; diff --git a/src/libmongoc/src/mongoc/mongoc-topology-scanner.c b/src/libmongoc/src/mongoc/mongoc-topology-scanner.c index 425037d396..a6e5bacb38 100644 --- a/src/libmongoc/src/mongoc/mongoc-topology-scanner.c +++ b/src/libmongoc/src/mongoc/mongoc-topology-scanner.c @@ -35,6 +35,11 @@ #include #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +#include +#include +#endif + #include #include #include @@ -429,6 +434,9 @@ mongoc_topology_scanner_new (const mongoc_uri_t *uri, /* may be overridden for testing. */ ts->dns_cache_timeout_ms = DNS_CACHE_TIMEOUT_MS; bson_mutex_init (&ts->handshake_cmd_mtx); +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + ts->secure_channel_cred_ptr = MONGOC_SHARED_PTR_NULL; +#endif _init_hello (ts); @@ -475,6 +483,10 @@ mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts) ts->openssl_ctx = NULL; #endif +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + mongoc_shared_ptr_reset_null (&ts->secure_channel_cred_ptr); +#endif + /* This field can be set by a mongoc_client */ bson_free ((char *) ts->appname); @@ -800,6 +812,9 @@ _mongoc_topology_scanner_node_setup_stream_for_tls (mongoc_topology_scanner_node #if defined(MONGOC_ENABLE_SSL_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L tls_stream = mongoc_stream_tls_new_with_hostname_and_openssl_context ( stream, node->host.host, node->ts->ssl_opts, 1, node->ts->openssl_ctx); +#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) + tls_stream = + mongoc_stream_tls_new_with_secure_channel_cred (stream, node->ts->ssl_opts, node->ts->secure_channel_cred_ptr); #else tls_stream = mongoc_stream_tls_new_with_hostname (stream, node->host.host, node->ts->ssl_opts, 1); #endif diff --git a/src/libmongoc/tests/test-libmongoc-main.c b/src/libmongoc/tests/test-libmongoc-main.c index a6f6696948..80b968611c 100644 --- a/src/libmongoc/tests/test-libmongoc-main.c +++ b/src/libmongoc/tests/test-libmongoc-main.c @@ -161,6 +161,7 @@ main (int argc, char *argv[]) TEST_INSTALL (test_mcd_nsinfo_install); TEST_INSTALL (test_bulkwrite_install); TEST_INSTALL (test_mongoc_oidc_callback_install); + TEST_INSTALL (test_secure_channel_install); const int ret = TestSuite_Run (&suite); diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c new file mode 100644 index 0000000000..3730b3e3cf --- /dev/null +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -0,0 +1,262 @@ +#include + +#include "TestSuite.h" +#include "test-libmongoc.h" + +#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +#include +#include // _mongoc_host_list_from_string_with_err +#include // mongoc_client_connect_tcp +#include // _mongoc_log_get_handler +#include + + +static bool +connect_with_secure_channel_cred (mongoc_ssl_opt_t *ssl_opt, mongoc_shared_ptr cred_ptr, bson_error_t *error) +{ + mongoc_host_list_t host; + const int32_t connect_timout_ms = 10000; + + *error = (bson_error_t) {0}; + + if (!_mongoc_host_list_from_string_with_err (&host, "localhost:27017", error)) { + return false; + } + mongoc_stream_t *tcp_stream = mongoc_client_connect_tcp (connect_timout_ms, &host, error); + if (!tcp_stream) { + return false; + } + + mongoc_stream_t *tls_stream = mongoc_stream_tls_secure_channel_new_with_creds (tcp_stream, ssl_opt, cred_ptr); + if (!tls_stream) { + mongoc_stream_destroy (tcp_stream); + return false; + } + + if (!mongoc_stream_tls_handshake_block (tls_stream, host.host, connect_timout_ms, error)) { + mongoc_stream_destroy (tls_stream); + return false; + } + + mongoc_stream_destroy (tls_stream); + return true; +} + +// Test a TLS stream can be create with shared Secure Channel credentials. +static void +test_secure_channel_shared_creds_stream (void *unused) +{ + BSON_UNUSED (unused); + + bool ok; + bson_error_t error; + mongoc_ssl_opt_t ssl_opt = {.ca_file = CERT_TEST_DIR "/ca.pem", .pem_file = CERT_TEST_DIR "/client.pem"}; + // Test with no sharing: + { + ok = connect_with_secure_channel_cred (&ssl_opt, MONGOC_SHARED_PTR_NULL, &error); + ASSERT_OR_PRINT (ok, error); + } + + // Test with sharing: + { + mongoc_shared_ptr cred_ptr = + mongoc_shared_ptr_create (mongoc_secure_channel_cred_new (&ssl_opt), mongoc_secure_channel_cred_deleter); + ok = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); + ASSERT_OR_PRINT (ok, error); + // Use again. + ok = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); + ASSERT_OR_PRINT (ok, error); + mongoc_shared_ptr_reset_null (&cred_ptr); + } +} + +typedef struct { + size_t failures; + size_t failures2; +} cert_failures; + +void +count_cert_failures (mongoc_log_level_t log_level, const char *log_domain, const char *message, void *user_data) +{ + cert_failures *cf = user_data; + if (strstr (message, "Failed to open file: 'does-not-exist.pem'")) { + cf->failures++; + } + if (strstr (message, "Failed to open file: 'does-not-exist-2.pem'")) { + cf->failures2++; + } +} + +static bool +try_ping (mongoc_client_t *client, bson_error_t *error) +{ + return mongoc_client_command_simple (client, "admin", tmp_bson (BSON_STR ({"ping" : 1})), NULL, NULL, error); +} + +static bool +try_ping_with_reconnect (mongoc_client_t *client, bson_error_t *error) +{ + // Force a connection error with a failpoint: + if (!mongoc_client_command_simple (client, + "admin", + tmp_bson (BSON_STR ({ + "configureFailPoint" : "failCommand", + "mode" : {"times" : 1}, + "data" : {"closeConnection" : true, "failCommands" : ["ping"]} + })), + NULL, + NULL, + error)) { + return false; + } + + // Expect first ping to fail: + if (try_ping (client, error)) { + bson_set_error (error, 0, 0, "unexpected: ping succeeded, but expected to fail"); + return false; + } + + // Ping again: + return try_ping (client, error); +} + +static void +test_secure_channel_shared_creds_client (void *unused) +{ + BSON_UNUSED (unused); + + bson_error_t error; + + // Save log function: + mongoc_log_func_t saved_log_func; + void *saved_log_data; + _mongoc_log_get_handler (&saved_log_func, &saved_log_data); + + // Set log function to count failed attempts to load client cert: + cert_failures cf = {0}; + mongoc_log_set_handler (count_cert_failures, &cf); + + // Test client: + { + mongoc_client_t *client = test_framework_new_default_client (); + + // Set client cert to a bad path: + { + mongoc_ssl_opt_t ssl_opt = *test_framework_get_ssl_opts (); + ssl_opt.pem_file = "does-not-exist.pem"; + mongoc_client_set_ssl_opts (client, &ssl_opt); + } + + // Expect insert OK. Cert fails to load, but server configured with --tlsAllowConnectionsWithoutCertificates: + { + bool ok = try_ping (client, &error); + ASSERT_OR_PRINT (ok, error); + } + + // Expect exactly one attempt to load the client cert: + ASSERT_CMPSIZE_T (1, ==, cf.failures); + } + + cf = (cert_failures) {0}; + + // Test pool: + { + mongoc_client_pool_t *pool = test_framework_new_default_client_pool (); + + // Set client cert to a bad path: + { + mongoc_ssl_opt_t ssl_opt = *test_framework_get_ssl_opts (); + ssl_opt.pem_file = "does-not-exist.pem"; + mongoc_client_pool_set_ssl_opts (pool, &ssl_opt); + } + + mongoc_client_t *client = mongoc_client_pool_pop (pool); + + // Expect insert OK. Cert fails to load, but server configured with --tlsAllowConnectionsWithoutCertificates: + { + bool ok = try_ping (client, &error); + ASSERT_OR_PRINT (ok, error); + } + + mongoc_client_pool_push (pool, client); + + // Expect exactly one attempt to load the client cert: + ASSERT_CMPSIZE_T (1, ==, cf.failures); + + mongoc_client_pool_destroy (pool); + } + + cf = (cert_failures) {0}; + + // Test client changing TLS options after connecting: + { + // Changing TLS options after connecting is prohibited on a client pool, but not on a single-threaded client. + // It is not a documented feature, but is tested for OpenSSL. + mongoc_client_t *client = test_framework_new_default_client (); + + // Set client cert to a bad path: + { + mongoc_ssl_opt_t ssl_opt = *test_framework_get_ssl_opts (); + ssl_opt.pem_file = "does-not-exist.pem"; + mongoc_client_set_ssl_opts (client, &ssl_opt); + } + + // Expect insert OK. Cert fails to load, but server configured with --tlsAllowConnectionsWithoutCertificates: + { + bool ok = try_ping (client, &error); + ASSERT_OR_PRINT (ok, error); + } + + // Expect exactly one attempt to load the client cert: + ASSERT_CMPSIZE_T (1, ==, cf.failures); + ASSERT_CMPSIZE_T (0, ==, cf.failures2); + + // Change the client cert: + { + mongoc_ssl_opt_t ssl_opt = *test_framework_get_ssl_opts (); + ssl_opt.pem_file = "does-not-exist-2.pem"; + mongoc_client_set_ssl_opts (client, &ssl_opt); + } + + // Force a reconnect. + { + bool ok = try_ping_with_reconnect (client, &error); + ASSERT_OR_PRINT (ok, error); + } + + // Expect an attempt to load the new cert: + ASSERT_CMPSIZE_T (1, ==, cf.failures); // Unchanged. + ASSERT_CMPSIZE_T (1, ==, cf.failures2); + + mongoc_client_destroy (client); + } + + // Restore log handler: + mongoc_log_set_handler (saved_log_func, saved_log_data); +} + +void +test_secure_channel_install (TestSuite *suite) +{ + TestSuite_AddFull (suite, + "/secure_channel/shared_creds/stream", + test_secure_channel_shared_creds_stream, + NULL, + NULL, + test_framework_skip_if_no_server_ssl); + + TestSuite_AddFull (suite, + "/secure_channel/shared_creds/client", + test_secure_channel_shared_creds_client, + NULL, + NULL, + test_framework_skip_if_no_server_ssl); +} + +#else // MONGOC_ENABLE_SSL_SECURE_CHANNEL +void +test_secure_channel_install (TestSuite *suite) +{ + BSON_UNUSED (suite); +} +#endif // MONGOC_ENABLE_SSL_SECURE_CHANNEL From 61f17ad26a1363afe39f2000d6f6cb0a28d215ea Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Mon, 30 Jun 2025 19:33:07 -0400 Subject: [PATCH 04/16] fix X509 test Capture logs earlier to account for secure channel loading the PEM file when SSL options are set. This revealed the OpenSSL implementation also logs. --- src/libmongoc/tests/test-mongoc-x509.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libmongoc/tests/test-mongoc-x509.c b/src/libmongoc/tests/test-mongoc-x509.c index 1fb58bb55d..ac0023b98c 100644 --- a/src/libmongoc/tests/test-mongoc-x509.c +++ b/src/libmongoc/tests/test-mongoc-x509.c @@ -346,15 +346,13 @@ test_x509_auth (void *unused) bson_error_t error = {0}; bool ok; { - mongoc_client_t *client = test_framework_client_new_from_uri (uri, NULL); capture_logs (true); + mongoc_client_t *client = test_framework_client_new_from_uri (uri, NULL); ok = try_insert (client, &error); -#if defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT) +#if defined(MONGOC_ENABLE_SSL_SECURE_TRANSPORT) || defined(MONGOC_ENABLE_SSL_OPENSSL) ASSERT_CAPTURED_LOG ("tls", MONGOC_LOG_LEVEL_ERROR, "Cannot find certificate"); #elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) ASSERT_CAPTURED_LOG ("tls", MONGOC_LOG_LEVEL_ERROR, "Failed to open file"); -#elif defined(MONGOC_ENABLE_SSL_OPENSSL) - ASSERT_NO_CAPTURED_LOGS ("tls"); #endif mongoc_client_destroy (client); } From 1269427bf160c1df6384903643f7a2f615983fb3 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Tue, 1 Jul 2025 09:22:39 -0400 Subject: [PATCH 05/16] fix test leak --- src/libmongoc/tests/test-mongoc-secure-channel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 3730b3e3cf..2b76d14e4e 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -155,6 +155,7 @@ test_secure_channel_shared_creds_client (void *unused) // Expect exactly one attempt to load the client cert: ASSERT_CMPSIZE_T (1, ==, cf.failures); + mongoc_client_destroy (client); } cf = (cert_failures) {0}; From 4def631ac8599eac495d10d97140adfed5be9ef9 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Wed, 2 Jul 2025 13:45:09 -0400 Subject: [PATCH 06/16] use mlib asserts --- src/libmongoc/tests/test-mongoc-secure-channel.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 2b76d14e4e..303f94d8be 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -9,7 +9,7 @@ #include // mongoc_client_connect_tcp #include // _mongoc_log_get_handler #include - +#include static bool connect_with_secure_channel_cred (mongoc_ssl_opt_t *ssl_opt, mongoc_shared_ptr cred_ptr, bson_error_t *error) @@ -154,7 +154,7 @@ test_secure_channel_shared_creds_client (void *unused) } // Expect exactly one attempt to load the client cert: - ASSERT_CMPSIZE_T (1, ==, cf.failures); + mlib_check (1, eq, cf.failures); mongoc_client_destroy (client); } @@ -182,7 +182,7 @@ test_secure_channel_shared_creds_client (void *unused) mongoc_client_pool_push (pool, client); // Expect exactly one attempt to load the client cert: - ASSERT_CMPSIZE_T (1, ==, cf.failures); + mlib_check (1, eq, cf.failures); mongoc_client_pool_destroy (pool); } @@ -209,8 +209,8 @@ test_secure_channel_shared_creds_client (void *unused) } // Expect exactly one attempt to load the client cert: - ASSERT_CMPSIZE_T (1, ==, cf.failures); - ASSERT_CMPSIZE_T (0, ==, cf.failures2); + mlib_check (1, eq, cf.failures); + mlib_check (0, eq, cf.failures2); // Change the client cert: { @@ -226,8 +226,8 @@ test_secure_channel_shared_creds_client (void *unused) } // Expect an attempt to load the new cert: - ASSERT_CMPSIZE_T (1, ==, cf.failures); // Unchanged. - ASSERT_CMPSIZE_T (1, ==, cf.failures2); + mlib_check (1, eq, cf.failures); // Unchanged. + mlib_check (1, eq, cf.failures2); mongoc_client_destroy (client); } From 3eaed346d52d25369d6236c48ee596dd6451cff0 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 08:03:53 -0400 Subject: [PATCH 07/16] add missing `static` --- src/libmongoc/tests/test-mongoc-secure-channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 303f94d8be..4e1e50489d 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -75,7 +75,7 @@ typedef struct { size_t failures2; } cert_failures; -void +static void count_cert_failures (mongoc_log_level_t log_level, const char *log_domain, const char *message, void *user_data) { cert_failures *cf = user_data; From 9b28df2b4fac9e8f51611e3a1804842611459fdc Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 08:04:31 -0400 Subject: [PATCH 08/16] use `BSON_UNUSED` --- src/libmongoc/tests/test-mongoc-secure-channel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 4e1e50489d..e081a501b8 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -78,6 +78,8 @@ typedef struct { static void count_cert_failures (mongoc_log_level_t log_level, const char *log_domain, const char *message, void *user_data) { + BSON_UNUSED (log_level); + BSON_UNUSED (log_domain); cert_failures *cf = user_data; if (strstr (message, "Failed to open file: 'does-not-exist.pem'")) { cf->failures++; From cd31b46021e429bc12477bcc7b7f3b001da8558c Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 08:05:06 -0400 Subject: [PATCH 09/16] use `elif` for consistency --- src/libmongoc/src/mongoc/mongoc-client-pool.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-client-pool.c b/src/libmongoc/src/mongoc/mongoc-client-pool.c index 1a7c0755e2..3d4ca15137 100644 --- a/src/libmongoc/src/mongoc/mongoc-client-pool.c +++ b/src/libmongoc/src/mongoc/mongoc-client-pool.c @@ -87,9 +87,7 @@ mongoc_client_pool_set_ssl_opts (mongoc_client_pool_t *pool, const mongoc_ssl_op #if defined(MONGOC_ENABLE_SSL_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L SSL_CTX_free (pool->topology->scanner->openssl_ctx); pool->topology->scanner->openssl_ctx = _mongoc_openssl_ctx_new (&pool->ssl_opts); -#endif - -#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) // Access to secure_channel_cred_ptr does not need the thread-safe `mongoc_atomic_*` functions. // secure_channel_cred_ptr is not expected to be modified by multiple threads. // mongoc_client_pool_set_ssl_opts documentation prohibits calling after threads start. From 98b30a06db1c696542ca81396407690158636561 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 08:06:53 -0400 Subject: [PATCH 10/16] use more `elif` --- src/libmongoc/src/mongoc/mongoc-stream-tls-private.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h b/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h index 87fb52befa..ef6d3c8848 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-private.h @@ -55,9 +55,7 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context (mongoc_stream_t *base_s mongoc_ssl_opt_t *opt, int client, SSL_CTX *ssl_ctx) BSON_GNUC_WARN_UNUSED_RESULT; -#endif - -#if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +#elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) mongoc_stream_t * mongoc_stream_tls_new_with_secure_channel_cred (mongoc_stream_t *base_stream, mongoc_ssl_opt_t *opt, From e5cc6ea319ea00bc019adef1fd62ec7e1b66ae61 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 09:19:54 -0400 Subject: [PATCH 11/16] revise block comments and add arg asserts --- src/libmongoc/src/mongoc/mongoc-stream-tls.c | 99 +++++++++----------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls.c b/src/libmongoc/src/mongoc/mongoc-stream-tls.c index 7332072f6e..940c4e98dd 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls.c @@ -121,37 +121,22 @@ mongoc_stream_tls_handshake_block (mongoc_stream_t *stream, const char *host, in return false; } - -/* - *-------------------------------------------------------------------------- - * - * mongoc_stream_tls_new_with_hostname -- - * - * Creates a new mongoc_stream_tls_t to communicate with a remote - * server using a TLS stream. - * - * @host the hostname we are connected to and to verify the - * server certificate against - * - * @base_stream should be a stream that will become owned by the - * resulting tls stream. It will be used for raw I/O. - * - * @trust_store_dir should be a path to the SSL cert db to use for - * verifying trust of the remote server. - * - * Returns: - * NULL on failure, otherwise a mongoc_stream_t. - * - * Side effects: - * May set opt->allow_invalid_hostname to true. - * - *-------------------------------------------------------------------------- - */ - +// mongoc_stream_tls_new_with_hostname creates a TLS stream. +// +// base_stream: underlying data stream. Ownership is transferred to the returned stream on success. +// host: hostname used to verify the the server certificate. +// opt: TLS options. +// client: indicates a client or server stream. Secure Channel implementation does not support server streams. +// +// Side effect: May set opt->allow_invalid_hostname to true. +// +// Returns a new stream on success. Returns `NULL` on failure. mongoc_stream_t * mongoc_stream_tls_new_with_hostname (mongoc_stream_t *base_stream, const char *host, mongoc_ssl_opt_t *opt, int client) { - BSON_ASSERT (base_stream); + BSON_ASSERT_PARAM (base_stream); + BSON_OPTIONAL_PARAM (host); + BSON_ASSERT_PARAM (opt); /* !client is only used for testing, * when the streams are pretending to be the server */ @@ -178,37 +163,27 @@ mongoc_stream_tls_new_with_hostname (mongoc_stream_t *base_stream, const char *h } #if defined(MONGOC_ENABLE_SSL_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L -/* - *-------------------------------------------------------------------------- - * - * mongoc_stream_tls_new_with_hostname_and_openssl_context -- - * - * Creates a new mongoc_stream_tls_t to communicate with a remote - * server using a TLS stream, using an existing OpenSSL context. - * - * @ssl_ctx is the global OpenSSL context for the mongoc_client_t - * associated with this function call. - * - * @host the hostname we are connected to and to verify the - * server certificate against - * - * @base_stream should be a stream that will become owned by the - * resulting tls stream. It will be used for raw I/O. - * - * Returns: - * NULL on failure, otherwise a mongoc_stream_t. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ - +// Create an OpenSSL TLS stream with a shared context. +// +// This is an internal extension to mongoc_stream_tls_new_with_hostname. +// +// base_stream: underlying data stream. Ownership is transferred to the returned stream on success. +// host: hostname used to verify the the server certificate. +// opt: TLS options. +// client: indicates a client or server stream. +// ssl_ctx: shared context. +// +// Side effect: May set opt->allow_invalid_hostname to true for compatibility with mongoc_stream_tls_new_with_hostname. +// +// Returns a new stream on success. Returns `NULL` on failure. mongoc_stream_t * mongoc_stream_tls_new_with_hostname_and_openssl_context ( mongoc_stream_t *base_stream, const char *host, mongoc_ssl_opt_t *opt, int client, SSL_CTX *ssl_ctx) { - BSON_ASSERT (base_stream); + BSON_ASSERT_PARAM (base_stream); + BSON_OPTIONAL_PARAM (host); + BSON_ASSERT_PARAM (opt); + BSON_OPTIONAL_PARAM (ssl_ctx); /* !client is only used for testing, * when the streams are pretending to be the server */ @@ -228,11 +203,25 @@ mongoc_stream_tls_new_with_hostname_and_openssl_context ( #endif #if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) +// Create a Secure Channel TLS stream with shared credentials. +// +// This is an internal extension to mongoc_stream_tls_new_with_hostname. +// +// base_stream: underlying data stream. Ownership is transferred to the returned stream on success. +// opt: TLS options. +// secure_channel_cred_ptr: optional shared credentials. May be MONGOC_SHARED_PTR_NULL. +// +// Side effect: May set opt->allow_invalid_hostname to true for compatibility with mongoc_stream_tls_new_with_hostname. +// +// Returns a new stream on success. Returns `NULL` on failure. mongoc_stream_t * mongoc_stream_tls_new_with_secure_channel_cred (mongoc_stream_t *base_stream, mongoc_ssl_opt_t *opt, mongoc_shared_ptr secure_channel_cred_ptr) { + BSON_ASSERT_PARAM (base_stream); + BSON_ASSERT_PARAM (opt); + if (opt->weak_cert_validation) { // For compatibility with `mongoc_stream_tls_new_with_hostname`, modify `opt` directly: opt->allow_invalid_hostname = true; From 1dd9a6b92a3b324eaee1cb27cee694df17855a39 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 09:33:39 -0400 Subject: [PATCH 12/16] fix memory leak --- .../src/mongoc/mongoc-stream-tls-secure-channel.c | 3 +++ src/libmongoc/tests/test-mongoc-secure-channel.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c index c025cbb01a..c46e651728 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -993,6 +993,9 @@ mongoc_stream_tls_secure_channel_new_with_creds (mongoc_stream_t *base_stream, char *msg = mongoc_winerr_to_string ((DWORD) sspi_status); MONGOC_ERROR ("Failed to initialize security context: %s", msg); bson_free (msg); + // Detach the base stream so caller can free. + tls->base_stream = NULL; + mongoc_stream_destroy ((mongoc_stream_t *) tls); RETURN (NULL); } diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index e081a501b8..8034f2fdce 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -68,6 +68,18 @@ test_secure_channel_shared_creds_stream (void *unused) ASSERT_OR_PRINT (ok, error); mongoc_shared_ptr_reset_null (&cred_ptr); } + + // Test with bad SCHANNEL_CRED to exercise error path: + { + mongoc_secure_channel_cred *cred = mongoc_secure_channel_cred_new (&ssl_opt); + mongoc_shared_ptr cred_ptr = mongoc_shared_ptr_create (cred, mongoc_secure_channel_cred_deleter); + cred->cred.dwVersion = 0; // Invalid version. + capture_logs (true); + ok = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); + ASSERT (!ok); + ASSERT_CAPTURED_LOG ("schannel", MONGOC_LOG_LEVEL_ERROR, "Failed to initialize security context"); + mongoc_shared_ptr_reset_null (&cred_ptr); + } } typedef struct { From c71518c0dff4a9005aa72391b7b39c38221c3f53 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 09:44:36 -0400 Subject: [PATCH 13/16] avoid single-use variable --- src/libmongoc/src/mongoc/mongoc-client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-client.c b/src/libmongoc/src/mongoc/mongoc-client.c index bcd053fbc5..2946a2ea80 100644 --- a/src/libmongoc/src/mongoc/mongoc-client.c +++ b/src/libmongoc/src/mongoc/mongoc-client.c @@ -894,8 +894,8 @@ mongoc_client_default_stream_initiator (const mongoc_uri_t *uri, return mongoc_client_connect ( true, use_ssl, ssl_opts_void, uri, host, (void *) ssl_ctx, MONGOC_SHARED_PTR_NULL, error); #elif defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) - mongoc_shared_ptr cred_ptr = client->topology->scanner->secure_channel_cred_ptr; - return mongoc_client_connect (true, use_ssl, ssl_opts_void, uri, host, NULL, cred_ptr, error); + return mongoc_client_connect ( + true, use_ssl, ssl_opts_void, uri, host, NULL, client->topology->scanner->secure_channel_cred_ptr, error); #else return mongoc_client_connect (true, use_ssl, ssl_opts_void, uri, host, NULL, MONGOC_SHARED_PTR_NULL, error); #endif From ff947ee53d85dc72e5fd2dbce6697f85c9916a5f Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 10:09:57 -0400 Subject: [PATCH 14/16] check shared credentials pointer and ref count in test --- .../tests/test-mongoc-secure-channel.c | 59 ++++++++++++++----- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 8034f2fdce..0003f197e2 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -5,13 +5,14 @@ #if defined(MONGOC_ENABLE_SSL_SECURE_CHANNEL) #include -#include // _mongoc_host_list_from_string_with_err -#include // mongoc_client_connect_tcp -#include // _mongoc_log_get_handler +#include // _mongoc_host_list_from_string_with_err +#include // mongoc_client_connect_tcp +#include // _mongoc_log_get_handler +#include // _mongoc_stream_tls_t #include #include -static bool +static mongoc_stream_t * connect_with_secure_channel_cred (mongoc_ssl_opt_t *ssl_opt, mongoc_shared_ptr cred_ptr, bson_error_t *error) { mongoc_host_list_t host; @@ -38,8 +39,7 @@ connect_with_secure_channel_cred (mongoc_ssl_opt_t *ssl_opt, mongoc_shared_ptr c return false; } - mongoc_stream_destroy (tls_stream); - return true; + return tls_stream; } // Test a TLS stream can be create with shared Secure Channel credentials. @@ -48,24 +48,51 @@ test_secure_channel_shared_creds_stream (void *unused) { BSON_UNUSED (unused); - bool ok; + mongoc_stream_t *stream; + mongoc_stream_tls_secure_channel_t *schannel_stream_view; bson_error_t error; mongoc_ssl_opt_t ssl_opt = {.ca_file = CERT_TEST_DIR "/ca.pem", .pem_file = CERT_TEST_DIR "/client.pem"}; // Test with no sharing: { - ok = connect_with_secure_channel_cred (&ssl_opt, MONGOC_SHARED_PTR_NULL, &error); - ASSERT_OR_PRINT (ok, error); + mongoc_stream_t *stream = connect_with_secure_channel_cred (&ssl_opt, MONGOC_SHARED_PTR_NULL, &error); + ASSERT_OR_PRINT (stream, error); + mongoc_stream_destroy (stream); } // Test with sharing: { mongoc_shared_ptr cred_ptr = mongoc_shared_ptr_create (mongoc_secure_channel_cred_new (&ssl_opt), mongoc_secure_channel_cred_deleter); - ok = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); - ASSERT_OR_PRINT (ok, error); - // Use again. - ok = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); - ASSERT_OR_PRINT (ok, error); + { + mongoc_stream_t *stream = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); + ASSERT_OR_PRINT (stream, error); + // Check same credentials are stored on stream: + { + mongoc_stream_tls_t *tls_stream = (mongoc_stream_tls_t *) stream; + mongoc_stream_tls_secure_channel_t *schannel = tls_stream->ctx; + ASSERT_CMPVOID (schannel->cred_ptr.ptr, ==, cred_ptr.ptr); + } + + ASSERT_CMPINT (mongoc_shared_ptr_use_count (cred_ptr), ==, 2); + mongoc_stream_destroy (stream); + ASSERT_CMPINT (mongoc_shared_ptr_use_count (cred_ptr), ==, 1); + } + + // Use again: + { + mongoc_stream_t *stream = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); + ASSERT_OR_PRINT (stream, error); + // Check same credentials are stored on stream: + { + mongoc_stream_tls_t *tls_stream = (mongoc_stream_tls_t *) stream; + mongoc_stream_tls_secure_channel_t *schannel = tls_stream->ctx; + ASSERT_CMPVOID (schannel->cred_ptr.ptr, ==, cred_ptr.ptr); + } + + ASSERT_CMPINT (mongoc_shared_ptr_use_count (cred_ptr), ==, 2); + mongoc_stream_destroy (stream); + ASSERT_CMPINT (mongoc_shared_ptr_use_count (cred_ptr), ==, 1); + } mongoc_shared_ptr_reset_null (&cred_ptr); } @@ -75,8 +102,8 @@ test_secure_channel_shared_creds_stream (void *unused) mongoc_shared_ptr cred_ptr = mongoc_shared_ptr_create (cred, mongoc_secure_channel_cred_deleter); cred->cred.dwVersion = 0; // Invalid version. capture_logs (true); - ok = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); - ASSERT (!ok); + mongoc_stream_t *stream = connect_with_secure_channel_cred (&ssl_opt, cred_ptr, &error); + ASSERT (!stream); ASSERT_CAPTURED_LOG ("schannel", MONGOC_LOG_LEVEL_ERROR, "Failed to initialize security context"); mongoc_shared_ptr_reset_null (&cred_ptr); } From a293192f5e1600951b5306aa67ca7f65f91629da Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 14:48:51 -0400 Subject: [PATCH 15/16] remove stray declaration --- src/libmongoc/tests/test-mongoc-secure-channel.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 0003f197e2..ea29c6215e 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -49,7 +49,6 @@ test_secure_channel_shared_creds_stream (void *unused) BSON_UNUSED (unused); mongoc_stream_t *stream; - mongoc_stream_tls_secure_channel_t *schannel_stream_view; bson_error_t error; mongoc_ssl_opt_t ssl_opt = {.ca_file = CERT_TEST_DIR "/ca.pem", .pem_file = CERT_TEST_DIR "/client.pem"}; // Test with no sharing: From b69782c61694a617facef1212f222cb7b27a39df Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Thu, 3 Jul 2025 14:54:24 -0400 Subject: [PATCH 16/16] use more `const` --- .../src/mongoc/mongoc-stream-tls-secure-channel-private.h | 2 +- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 2 +- src/libmongoc/tests/test-mongoc-secure-channel.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h index 147eff1374..1c7d014a4f 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h @@ -93,7 +93,7 @@ mongoc_secure_channel_cred_deleter (void *cred_void); struct _mongoc_stream_t * mongoc_stream_tls_secure_channel_new_with_creds (struct _mongoc_stream_t *base_stream, - struct _mongoc_ssl_opt_t *opt, + const struct _mongoc_ssl_opt_t *opt, mongoc_shared_ptr cred_ptr /* optional */); BSON_END_DECLS diff --git a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c index c46e651728..708cd326de 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -919,7 +919,7 @@ mongoc_stream_tls_secure_channel_new (mongoc_stream_t *base_stream, const char * mongoc_stream_t * mongoc_stream_tls_secure_channel_new_with_creds (mongoc_stream_t *base_stream, - mongoc_ssl_opt_t *opt, + const mongoc_ssl_opt_t *opt, mongoc_shared_ptr cred_ptr) { SECURITY_STATUS sspi_status = SEC_E_OK; diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index ea29c6215e..11985118da 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -13,7 +13,7 @@ #include static mongoc_stream_t * -connect_with_secure_channel_cred (mongoc_ssl_opt_t *ssl_opt, mongoc_shared_ptr cred_ptr, bson_error_t *error) +connect_with_secure_channel_cred (const mongoc_ssl_opt_t *ssl_opt, mongoc_shared_ptr cred_ptr, bson_error_t *error) { mongoc_host_list_t host; const int32_t connect_timout_ms = 10000; @@ -50,7 +50,7 @@ test_secure_channel_shared_creds_stream (void *unused) mongoc_stream_t *stream; bson_error_t error; - mongoc_ssl_opt_t ssl_opt = {.ca_file = CERT_TEST_DIR "/ca.pem", .pem_file = CERT_TEST_DIR "/client.pem"}; + const mongoc_ssl_opt_t ssl_opt = {.ca_file = CERT_TEST_DIR "/ca.pem", .pem_file = CERT_TEST_DIR "/client.pem"}; // Test with no sharing: { mongoc_stream_t *stream = connect_with_secure_channel_cred (&ssl_opt, MONGOC_SHARED_PTR_NULL, &error);