From c5cae48398de5804b7dee7b292fb577764135cce Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 17 Sep 2025 18:04:50 +0000 Subject: [PATCH 01/30] Switch to SCH_CREDENTIALS --- ...mongoc-stream-tls-secure-channel-private.h | 4 ++- .../mongoc/mongoc-stream-tls-secure-channel.c | 32 ++++++++++++------- 2 files changed, 24 insertions(+), 12 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 3550b7395c0..d667d4f9f57 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 @@ -26,8 +26,10 @@ /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 +#define SCHANNEL_USE_BLACKLISTS #include #include +#include BSON_BEGIN_DECLS @@ -52,7 +54,7 @@ typedef struct { // `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 + SCH_CREDENTIALS *cred; } mongoc_secure_channel_cred; typedef struct { 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 a242c242daf..0e7aefc96fe 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -74,9 +74,11 @@ #define SECURITY_WIN32 +#define SCHANNEL_USE_BLACKLISTS #include #include #include +#include /* mingw doesn't define these */ #ifndef SP_PROT_TLS1_1_CLIENT @@ -87,6 +89,9 @@ #define SP_PROT_TLS1_2_CLIENT 0x00000800 #endif +#ifndef SP_PROT_TLS1_3_CLIENT +#define SP_PROT_TLS1_3_CLIENT 0x00002000 +#endif static void _mongoc_stream_tls_secure_channel_destroy(mongoc_stream_t *stream) @@ -847,34 +852,34 @@ 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; + cred->cred->dwVersion = SCH_CREDENTIALS_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; + 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; + 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; + cred->cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; if (opt->weak_cert_validation) { - cred->cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + cred->cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; TRACE("%s", "disabled server certificate checks"); } else { - cred->cred.dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; + 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; + 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; + cred->cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; } if (opt->ca_file) { @@ -889,12 +894,17 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) cred->cert = mongoc_secure_channel_setup_certificate(opt); if (cred->cert) { - cred->cred.cCreds = 1; - cred->cred.paCred = &cred->cert; + cred->cred->cCreds = 1; + cred->cred->paCred = &cred->cert; } } - cred->cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + cred->cred->cTlsParameters = 1; + TLS_PARAMETERS tls_parameters = {0}; + cred->cred->pTlsParameters = &tls_parameters; + DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_3_CLIENT; + cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; + return cred; } From df6308cc68c5fc53839e12d3ff461f757ea5755f Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 17 Sep 2025 18:56:08 +0000 Subject: [PATCH 02/30] Move winternl.h above schannel.h --- .../src/mongoc/mongoc-stream-tls-secure-channel-private.h | 2 +- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 2 +- 2 files changed, 2 insertions(+), 2 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 d667d4f9f57..2d6f0c163a9 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 @@ -27,9 +27,9 @@ /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS +#include #include #include -#include BSON_BEGIN_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 0e7aefc96fe..067e139a803 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -75,10 +75,10 @@ #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS +#include #include #include #include -#include /* mingw doesn't define these */ #ifndef SP_PROT_TLS1_1_CLIENT From 0767a313e395c7a7cbf3de053b0728328186da50 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 17 Sep 2025 19:26:18 +0000 Subject: [PATCH 03/30] Fix test --- 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 80398273b35..8f81511543d 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -100,7 +100,7 @@ test_secure_channel_shared_creds_stream(void *unused) { 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. + cred->cred->dwVersion = 0; // Invalid version. capture_logs(true); mongoc_stream_t *stream = connect_with_secure_channel_cred(&ssl_opt, cred_ptr, &error); ASSERT(!stream); From 1a4c08bf43aed24c3cc5eca7600739e0d13e7f68 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 17 Sep 2025 20:06:05 +0000 Subject: [PATCH 04/30] Use subauth instead of winternl --- .../src/mongoc/mongoc-stream-tls-secure-channel-private.h | 2 +- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 2 +- 2 files changed, 2 insertions(+), 2 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 2d6f0c163a9..0d27af05d74 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 @@ -27,7 +27,7 @@ /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS -#include +#include #include #include 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 067e139a803..f1c58f96bad 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -75,10 +75,10 @@ #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS -#include #include #include #include +#include /* mingw doesn't define these */ #ifndef SP_PROT_TLS1_1_CLIENT From 68b306a346a6d0ac5dc82be23962b975d0175f71 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 18 Sep 2025 15:18:50 +0000 Subject: [PATCH 05/30] Enable TLS 1.3 for Windows Server 2022 and newer --- .../mongoc/mongoc-stream-tls-secure-channel-private.h | 3 ++- .../src/mongoc/mongoc-stream-tls-secure-channel.c | 11 +++++++++-- 2 files changed, 11 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 0d27af05d74..1b6595bda41 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 @@ -24,10 +24,11 @@ #include +#include + /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS -#include #include #include 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 f1c58f96bad..cb113e65b42 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -72,13 +72,14 @@ #undef MONGOC_LOG_DOMAIN #define MONGOC_LOG_DOMAIN "stream-tls-secure-channel" +#include #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS #include #include #include -#include + /* mingw doesn't define these */ #ifndef SP_PROT_TLS1_1_CLIENT @@ -902,7 +903,13 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) cred->cred->cTlsParameters = 1; TLS_PARAMETERS tls_parameters = {0}; cred->cred->pTlsParameters = &tls_parameters; - DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_3_CLIENT; + DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + + // TLS 1.3 is supported starting in Windows Server 2022 + if (_WIN32_WINNT >= 0x0A00) { + enabled_protocols |= SP_PROT_TLS1_3_CLIENT; + } + cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; return cred; From 9c62ea91e669dff40db21537d5eca786ca5195c0 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 18 Sep 2025 16:41:12 +0000 Subject: [PATCH 06/30] Remove erroneous & --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 cb113e65b42..016d46f7239 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -72,13 +72,12 @@ #undef MONGOC_LOG_DOMAIN #define MONGOC_LOG_DOMAIN "stream-tls-secure-channel" -#include - #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS #include #include #include +#include /* mingw doesn't define these */ @@ -896,7 +895,7 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) if (cred->cert) { cred->cred->cCreds = 1; - cred->cred->paCred = &cred->cert; + cred->cred->paCred = cred->cert; } } From 9f05bd3ce49b59fd523dc61641889d46081e367d Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 18 Sep 2025 16:56:41 +0000 Subject: [PATCH 07/30] Revert "Remove erroneous &" This reverts commit 9c62ea91e669dff40db21537d5eca786ca5195c0. --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 016d46f7239..cb113e65b42 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -72,12 +72,13 @@ #undef MONGOC_LOG_DOMAIN #define MONGOC_LOG_DOMAIN "stream-tls-secure-channel" +#include + #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS #include #include #include -#include /* mingw doesn't define these */ @@ -895,7 +896,7 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) if (cred->cert) { cred->cred->cCreds = 1; - cred->cred->paCred = cred->cert; + cred->cred->paCred = &cred->cert; } } From 05823c960f27505a6b305a0b872a108d20a4cef8 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 18 Sep 2025 17:52:00 +0000 Subject: [PATCH 08/30] Modify tls_params allocation --- .../src/mongoc/mongoc-stream-tls-secure-channel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 cb113e65b42..46d1732282c 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -900,16 +900,16 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) } } - cred->cred->cTlsParameters = 1; - TLS_PARAMETERS tls_parameters = {0}; - cred->cred->pTlsParameters = &tls_parameters; - DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + cred->cred->cTlsParameters = 1; + TLS_PARAMETERS tls_parameters; + cred->cred->pTlsParameters = &tls_parameters; // TLS 1.3 is supported starting in Windows Server 2022 + DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; if (_WIN32_WINNT >= 0x0A00) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; } - + cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; return cred; From d69e6303067a3209b4624a9e7e11cbae01ba6fb9 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 18 Sep 2025 20:21:46 +0000 Subject: [PATCH 09/30] Only use SCH_CREDENTIALS post-Windows Server 2019 --- ...mongoc-stream-tls-secure-channel-private.h | 6 +++++- .../mongoc/mongoc-stream-tls-secure-channel.c | 21 +++++++++++++------ 2 files changed, 20 insertions(+), 7 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 1b6595bda41..8bf09baf092 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 @@ -54,8 +54,12 @@ typedef struct { // `mongoc_secure_channel_cred` may be shared on multiple connections. typedef struct _mongoc_secure_channel_cred { - PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ + PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ +#if defined(SCH_CREDENTIALS) && (WORD)_WIN32_WINNT >= MAKEWORD(17763, 10) // Windows Server 2019 SCH_CREDENTIALS *cred; +#else + SCHANNEL_CRED *cred; +#endif } mongoc_secure_channel_cred; typedef struct { 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 46d1732282c..ae2cad86ce9 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -69,10 +69,11 @@ #include +#include + #undef MONGOC_LOG_DOMAIN #define MONGOC_LOG_DOMAIN "stream-tls-secure-channel" -#include #define SECURITY_WIN32 #define SCHANNEL_USE_BLACKLISTS @@ -853,7 +854,11 @@ 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)); +#if defined(SCH_CREDENTIALS) && (WORD)_WIN32_WINNT >= MAKEWORD(17763, 10) cred->cred->dwVersion = SCH_CREDENTIALS_VERSION; +#else + cred->cred->dwVersion = SCHANNEL_CRED_VERSION; +#endif /* SCHANNEL_CRED: * SCH_USE_STRONG_CRYPTO is not available in VS2010 @@ -900,17 +905,21 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) } } - cred->cred->cTlsParameters = 1; - TLS_PARAMETERS tls_parameters; - cred->cred->pTlsParameters = &tls_parameters; +#if defined(SCH_CREDENTIALS) && (WORD)_WIN32_WINNT >= MAKEWORD(17763, 10) + cred->cred->cTlsParameters = 1; + TLS_PARAMETERS tls_parameters; + cred->cred->pTlsParameters = &tls_parameters; - // TLS 1.3 is supported starting in Windows Server 2022 + // TLS 1.3 is supported starting with Windows Server 2022 DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; if (_WIN32_WINNT >= 0x0A00) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; } - + cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; +#else + cred->cred->grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; +#endif return cred; } From cb71275a5276b1d3e2d8556f91a3dfa430b9b000 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Fri, 19 Sep 2025 17:44:42 +0000 Subject: [PATCH 10/30] Simplify preprocessor statement --- .../src/mongoc/mongoc-stream-tls-secure-channel-private.h | 2 +- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 5 +++-- 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 8bf09baf092..bb1c2ab451d 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 @@ -55,7 +55,7 @@ typedef struct { // `mongoc_secure_channel_cred` may be shared on multiple connections. typedef struct _mongoc_secure_channel_cred { PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ -#if defined(SCH_CREDENTIALS) && (WORD)_WIN32_WINNT >= MAKEWORD(17763, 10) // Windows Server 2019 +#if defined(SCH_CREDENTIALS) SCH_CREDENTIALS *cred; #else SCHANNEL_CRED *cred; 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 ae2cad86ce9..e3a4b5d6323 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -854,7 +854,7 @@ 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)); -#if defined(SCH_CREDENTIALS) && (WORD)_WIN32_WINNT >= MAKEWORD(17763, 10) +#if defined(SCH_CREDENTIALS) cred->cred->dwVersion = SCH_CREDENTIALS_VERSION; #else cred->cred->dwVersion = SCHANNEL_CRED_VERSION; @@ -905,12 +905,13 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) } } -#if defined(SCH_CREDENTIALS) && (WORD)_WIN32_WINNT >= MAKEWORD(17763, 10) +#if defined(SCH_CREDENTIALS) cred->cred->cTlsParameters = 1; TLS_PARAMETERS tls_parameters; cred->cred->pTlsParameters = &tls_parameters; // TLS 1.3 is supported starting with Windows Server 2022 + // TODO - fix check, this enables on earlier versions too DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; if (_WIN32_WINNT >= 0x0A00) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; From 08e8cb520bc31d92f60fc06db870c56840d771e9 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Mon, 22 Sep 2025 14:28:36 +0000 Subject: [PATCH 11/30] More specific version check for 1.3 + introduce MONGOC_HAVE_SCH_CREDENTIALS --- src/libmongoc/CMakeLists.txt | 30 +++++++++++++++++ src/libmongoc/src/mongoc/mongoc-config.h.in | 9 +++++ ...mongoc-stream-tls-secure-channel-private.h | 4 +-- .../mongoc/mongoc-stream-tls-secure-channel.c | 33 +++++++++++++++---- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 6243b4b47db..f96b7e33a62 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -539,6 +539,36 @@ else () set (MONGOC_HAVE_BCRYPT_PBKDF2 0) endif () +# Check if SCH_CREDENTIALS is defined in schannel.h +if (WIN32 AND MONGOC_ENABLE_SSL_SECURE_CHANNEL) + + FILE (WRITE ${CMAKE_CURRENT_BINARY_DIR}/sch_credentials_test.c + " + #include + #include + #define SCHANNEL_USE_BLACKLISTS + #include + + int main(void) { + SCH_CREDENTIALS cred; + (void)cred; + return 0; + } + ") + + TRY_COMPILE (HAVE_SCH_CREDENTIALS ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/sch_credentials_test.c CMAKE_FLAGS + "-Werror -DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" OUTPUT_VARIABLE LOG2) + + if (HAVE_SCH_CREDENTIALS) + message(STATUS "SCH_CREDENTIALS symbol found.") + set (MONGOC_HAVE_SCH_CREDENTIALS 1) + else () + message(STATUS "SCH_CREDENTIALS symbol not found. Using SCHANNEL_CRED.") + set (MONGOC_HAVE_SCH_CREDENTIALS 0) + endif () +endif() + set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mcd-azure.c diff --git a/src/libmongoc/src/mongoc/mongoc-config.h.in b/src/libmongoc/src/mongoc/mongoc-config.h.in index a250d129689..49fae22192a 100644 --- a/src/libmongoc/src/mongoc/mongoc-config.h.in +++ b/src/libmongoc/src/mongoc/mongoc-config.h.in @@ -52,6 +52,15 @@ # undef MONGOC_ENABLE_SSL_SECURE_CHANNEL #endif +/* + * MONGOC_HAVE_SCH_CREDENTIALS is set from configure to determine if + * our Schannel Windows library supports SCH_CREDENTIALS + */ +#define MONGOC_HAVE_SCH_CREDENTIALS @MONGOC_HAVE_SCH_CREDENTIALS@ + +#if MONGOC_HAVE_SCH_CREDENTIALS != 1 +# undef MONGOC_HAVE_SCH_CREDENTIALS +#endif /* * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are 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 bb1c2ab451d..e7dc2c8ac1f 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 @@ -28,7 +28,7 @@ /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 -#define SCHANNEL_USE_BLACKLISTS +#define SCHANNEL_USE_BLACKLISTS 1 #include #include @@ -55,7 +55,7 @@ typedef struct { // `mongoc_secure_channel_cred` may be shared on multiple connections. typedef struct _mongoc_secure_channel_cred { PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ -#if defined(SCH_CREDENTIALS) +#ifdef MONGOC_HAVE_SCH_CREDENTIALS SCH_CREDENTIALS *cred; #else SCHANNEL_CRED *cred; 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 e3a4b5d6323..01a13dd2730 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -76,7 +76,7 @@ #define SECURITY_WIN32 -#define SCHANNEL_USE_BLACKLISTS +#define SCHANNEL_USE_BLACKLISTS 1 #include #include #include @@ -848,13 +848,36 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream) RETURN(mongoc_stream_should_retry(tls->base_stream)); } + // TLS 1.3 is supported starting with Windows Server 2022 + static bool +_mongoc_secure_channel_verify_tls_1_3_support () +{ + OSVERSIONINFOEX osvi; + int op=VER_GREATER_EQUAL; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwMajorVersion = 10; + osvi.dwMinorVersion = 0; + osvi.wProductType = VER_NT_SERVER; + osvi.dwBuildNumber = 20348; + + ULONGLONG dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); + + return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_PRODUCT_TYPE | VER_BUILDNUMBER, dwlConditionMask); +} + 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)); -#if defined(SCH_CREDENTIALS) +#ifdef MONGOC_HAVE_SCH_CREDENTIALS cred->cred->dwVersion = SCH_CREDENTIALS_VERSION; #else cred->cred->dwVersion = SCHANNEL_CRED_VERSION; @@ -905,15 +928,13 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) } } -#if defined(SCH_CREDENTIALS) +#ifdef MONGOC_HAVE_SCH_CREDENTIALS cred->cred->cTlsParameters = 1; TLS_PARAMETERS tls_parameters; cred->cred->pTlsParameters = &tls_parameters; - // TLS 1.3 is supported starting with Windows Server 2022 - // TODO - fix check, this enables on earlier versions too DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - if (_WIN32_WINNT >= 0x0A00) { + if (_mongoc_secure_channel_verify_tls_1_3_support()) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; } From c8e3d646cfd1be63f180985ecd6c9198dfff4579 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Mon, 22 Sep 2025 14:44:01 +0000 Subject: [PATCH 12/30] Fix scope of HAVE_SCH_CREDENTIALS check --- src/libmongoc/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index f96b7e33a62..60f234b47e4 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -559,16 +559,16 @@ if (WIN32 AND MONGOC_ENABLE_SSL_SECURE_CHANNEL) TRY_COMPILE (HAVE_SCH_CREDENTIALS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/sch_credentials_test.c CMAKE_FLAGS "-Werror -DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" OUTPUT_VARIABLE LOG2) - - if (HAVE_SCH_CREDENTIALS) - message(STATUS "SCH_CREDENTIALS symbol found.") - set (MONGOC_HAVE_SCH_CREDENTIALS 1) - else () - message(STATUS "SCH_CREDENTIALS symbol not found. Using SCHANNEL_CRED.") - set (MONGOC_HAVE_SCH_CREDENTIALS 0) - endif () endif() +if (HAVE_SCH_CREDENTIALS) + message(STATUS "SCH_CREDENTIALS symbol found.") + set (MONGOC_HAVE_SCH_CREDENTIALS 1) +else () + message(STATUS "SCH_CREDENTIALS symbol not found. Using SCHANNEL_CRED.") + set (MONGOC_HAVE_SCH_CREDENTIALS 0) +endif () + set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mcd-azure.c From f5cbb9973c7db1aba98a76c6690337162095b105 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Tue, 23 Sep 2025 13:11:40 +0000 Subject: [PATCH 13/30] Generic windows version function --- .../mongoc/mongoc-stream-tls-secure-channel.c | 31 +++-------- .../src/mongoc/mongoc-version-functions.c | 52 +++++++++++++++++++ .../src/mongoc/mongoc-version-functions.h | 4 ++ 3 files changed, 62 insertions(+), 25 deletions(-) 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 01a13dd2730..9b6802aefa3 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -80,6 +80,7 @@ #include #include #include +#include /* mingw doesn't define these */ @@ -848,29 +849,6 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream) RETURN(mongoc_stream_should_retry(tls->base_stream)); } - // TLS 1.3 is supported starting with Windows Server 2022 - static bool -_mongoc_secure_channel_verify_tls_1_3_support () -{ - OSVERSIONINFOEX osvi; - int op=VER_GREATER_EQUAL; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - osvi.dwMajorVersion = 10; - osvi.dwMinorVersion = 0; - osvi.wProductType = VER_NT_SERVER; - osvi.dwBuildNumber = 20348; - - ULONGLONG dwlConditionMask = 0; - VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_GREATER_EQUAL); - VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); - - return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_PRODUCT_TYPE | VER_BUILDNUMBER, dwlConditionMask); -} - mongoc_secure_channel_cred * mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) { @@ -934,10 +912,13 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) cred->cred->pTlsParameters = &tls_parameters; DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - if (_mongoc_secure_channel_verify_tls_1_3_support()) { + bool is_server = IsWindowsServer(); + + // TLS 1.3 is supported starting with Windows 11 and Windows Server 2022 + if ((is_server && _mongoc_verify_windows_version(10, 0, 19044, false)) || + (!is_server && _mongoc_verify_windows_version(10, 0, 22000, false))) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; } - cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; #else cred->cred->grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.c b/src/libmongoc/src/mongoc/mongoc-version-functions.c index db3badfade9..a465cfe66c1 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.c +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.c @@ -19,6 +19,13 @@ #include +#ifdef _WIN32 +#include +#include + +#include +#endif + /** * mongoc_get_major_version: * @@ -75,3 +82,48 @@ mongoc_check_version(int required_major, int required_minor, int required_micro) { return MONGOC_CHECK_VERSION(required_major, required_minor, required_micro); } + +#ifdef _WIN32 +/** + * _mongoc_verify_windows_version: + * + * True if the Windows version is greater than or equal to the required + * desktop or server version. + */ +bool +_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal) +{ + OSVERSIONINFOEX osvi; + bool matched; + int op = VER_GREATER_EQUAL; + + if (strictly_equal) { + op = VER_EQUAL; + } + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwMajorVersion = major_version; + osvi.dwMinorVersion = minor_version; + + ULONGLONG mask = 0; + mask = VER_SET_CONDITION(mask, VER_MAJORVERSION, op); + mask = VER_SET_CONDITION(mask, VER_MINORVERSION, op); + + matched = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask); + + // Compare build number separately if major and minor versions are equal + if (build_number && matched && _mongoc_verify_windows_version(major_version, minor_version, 0, true)) { + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwBuildNumber = build_number; + + mask = 0; + mask = VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); + + matched = VerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask); + } + + return matched; +} +#endif \ No newline at end of file diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.h b/src/libmongoc/src/mongoc/mongoc-version-functions.h index 3a08c181109..7dcabd6c920 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.h +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.h @@ -36,6 +36,10 @@ MONGOC_EXPORT(const char *) mongoc_get_version(void); MONGOC_EXPORT(bool) mongoc_check_version(int required_major, int required_minor, int required_micro); +#ifdef _WIN32 +MONGOC_EXPORT(bool) +_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal); +#endif BSON_END_DECLS From 757880bb1707128592c2d5cc559ebe3a2f4af8a1 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Tue, 23 Sep 2025 13:14:11 +0000 Subject: [PATCH 14/30] Newline at end of file --- src/libmongoc/src/mongoc/mongoc-version-functions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.c b/src/libmongoc/src/mongoc/mongoc-version-functions.c index a465cfe66c1..26a9675630d 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.c +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.c @@ -120,10 +120,10 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n mask = 0; mask = VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); - + matched = VerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask); } return matched; } -#endif \ No newline at end of file +#endif From 705c1f248d5525b64d93cba1b6692c978b780580 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Tue, 23 Sep 2025 13:44:12 +0000 Subject: [PATCH 15/30] Fix ver_set_condition call --- src/libmongoc/CMakeLists.txt | 2 -- .../src/mongoc/mongoc-stream-tls-secure-channel-private.h | 2 +- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 1 + src/libmongoc/src/mongoc/mongoc-version-functions.c | 6 +++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 60f234b47e4..6774844a9b4 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -562,10 +562,8 @@ if (WIN32 AND MONGOC_ENABLE_SSL_SECURE_CHANNEL) endif() if (HAVE_SCH_CREDENTIALS) - message(STATUS "SCH_CREDENTIALS symbol found.") set (MONGOC_HAVE_SCH_CREDENTIALS 1) else () - message(STATUS "SCH_CREDENTIALS symbol not found. Using SCHANNEL_CRED.") set (MONGOC_HAVE_SCH_CREDENTIALS 0) endif () 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 e7dc2c8ac1f..738606ed8a6 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 @@ -54,7 +54,7 @@ typedef struct { // `mongoc_secure_channel_cred` may be shared on multiple connections. typedef struct _mongoc_secure_channel_cred { - PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ + PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ #ifdef MONGOC_HAVE_SCH_CREDENTIALS SCH_CREDENTIALS *cred; #else 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 9b6802aefa3..b0ea749893e 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -918,6 +918,7 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) if ((is_server && _mongoc_verify_windows_version(10, 0, 19044, false)) || (!is_server && _mongoc_verify_windows_version(10, 0, 22000, false))) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; + printf("Enabling TLS 1.3 with Secure Channel \n"); } cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; #else diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.c b/src/libmongoc/src/mongoc/mongoc-version-functions.c index 26a9675630d..e07acf90a42 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.c +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.c @@ -107,8 +107,8 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n osvi.dwMinorVersion = minor_version; ULONGLONG mask = 0; - mask = VER_SET_CONDITION(mask, VER_MAJORVERSION, op); - mask = VER_SET_CONDITION(mask, VER_MINORVERSION, op); + VER_SET_CONDITION(mask, VER_MAJORVERSION, op); + VER_SET_CONDITION(mask, VER_MINORVERSION, op); matched = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask); @@ -119,7 +119,7 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n osvi.dwBuildNumber = build_number; mask = 0; - mask = VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); + VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); matched = VerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask); } From dab537d5cd477ee2ddf5c75c356c73eb267164d6 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Tue, 23 Sep 2025 14:26:46 +0000 Subject: [PATCH 16/30] Debug --- src/libmongoc/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 6774844a9b4..cca3602202c 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -563,8 +563,10 @@ endif() if (HAVE_SCH_CREDENTIALS) set (MONGOC_HAVE_SCH_CREDENTIALS 1) + message (STATUS "SCH_CREDENTIALS found") else () set (MONGOC_HAVE_SCH_CREDENTIALS 0) + message (STATUS "Using deprecated SCHANNEL_CREDS") endif () From 1dc7f700f007030c261e3923a56a10c81d5c1654 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Tue, 23 Sep 2025 19:02:41 +0000 Subject: [PATCH 17/30] Malloc cred->cred --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 3 +++ src/libmongoc/src/mongoc/mongoc-version-functions.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) 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 b0ea749893e..effc185bf10 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -856,8 +856,10 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) mongoc_secure_channel_cred *cred = bson_malloc0(sizeof(mongoc_secure_channel_cred)); #ifdef MONGOC_HAVE_SCH_CREDENTIALS + cred->cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); cred->cred->dwVersion = SCH_CREDENTIALS_VERSION; #else + cred->cred = bson_malloc0(sizeof(SCHANNEL_CRED)); cred->cred->dwVersion = SCHANNEL_CRED_VERSION; #endif @@ -936,6 +938,7 @@ mongoc_secure_channel_cred_deleter(void *cred_void) return; } CertFreeCertificateContext(cred->cert); + bson_free(cred->cred); bson_free(cred); } diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.h b/src/libmongoc/src/mongoc/mongoc-version-functions.h index 7dcabd6c920..9317bab0412 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.h +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.h @@ -38,7 +38,7 @@ MONGOC_EXPORT(bool) mongoc_check_version(int required_major, int required_minor, int required_micro); #ifdef _WIN32 MONGOC_EXPORT(bool) -_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal); +_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal); #endif BSON_END_DECLS From e667f6d7a9f8d9cf523462abb74cc0b2cc32ce58 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Tue, 23 Sep 2025 19:52:58 +0000 Subject: [PATCH 18/30] Remove & in acquire cred handle --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 effc185bf10..e03cb9f81f9 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -922,6 +922,7 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) enabled_protocols |= SP_PROT_TLS1_3_CLIENT; printf("Enabling TLS 1.3 with Secure Channel \n"); } + cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; #else cred->cred->grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; @@ -1015,7 +1016,7 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream, UNISP_NAME, /* security package */ SECPKG_CRED_OUTBOUND, /* we are preparing outbound connection */ NULL, /* Optional logon */ - &cred->cred, /* TLS "configuration", "auth data" */ + cred->cred, /* TLS "configuration", "auth data" */ NULL, /* unused */ NULL, /* unused */ &secure_channel->cred_handle->cred_handle, /* credential OUT param */ From c2ee9d57f79f0803bcf3c3097715fc5f20b1bc87 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 24 Sep 2025 18:04:02 +0000 Subject: [PATCH 19/30] Refactor setup logic --- ...mongoc-stream-tls-secure-channel-private.h | 13 +- .../mongoc/mongoc-stream-tls-secure-channel.c | 133 +++++++++++++----- .../tests/test-mongoc-secure-channel.c | 13 +- 3 files changed, 117 insertions(+), 42 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 738606ed8a6..0de9a392a48 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 @@ -46,6 +46,12 @@ typedef enum { ssl_connect_done } ssl_connect_state; +/* enum for underlying type cred field in mongoc_secure_channel_cred */ +typedef enum { + schannel_cred, + sch_credentials +} schannel_credential_type; + /* Structs to store Schannel handles */ typedef struct { CredHandle cred_handle; @@ -55,11 +61,8 @@ typedef struct { // `mongoc_secure_channel_cred` may be shared on multiple connections. typedef struct _mongoc_secure_channel_cred { PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ -#ifdef MONGOC_HAVE_SCH_CREDENTIALS - SCH_CREDENTIALS *cred; -#else - SCHANNEL_CRED *cred; -#endif + schannel_credential_type cred_type; + void *cred; /* Underlying type is specified by type. */ } mongoc_secure_channel_cred; typedef struct { 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 e03cb9f81f9..623f80cd25d 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -849,83 +849,143 @@ _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) +#ifdef MONGOC_HAVE_SCH_CREDENTIALS + +void * +_mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT cert, DWORD enabled_protocols) { - BSON_ASSERT_PARAM(opt); - mongoc_secure_channel_cred *cred = bson_malloc0(sizeof(mongoc_secure_channel_cred)); + SCH_CREDENTIALS *cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); -#ifdef MONGOC_HAVE_SCH_CREDENTIALS - cred->cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); - cred->cred->dwVersion = SCH_CREDENTIALS_VERSION; -#else - cred->cred = bson_malloc0(sizeof(SCHANNEL_CRED)); - cred->cred->dwVersion = SCHANNEL_CRED_VERSION; -#endif + // version + cred->dwVersion = SCH_CREDENTIALS_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; + 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; + 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; + cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; if (opt->weak_cert_validation) { - cred->cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; TRACE("%s", "disabled server certificate checks"); } else { - cred->cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; + cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; if (!_mongoc_ssl_opts_disable_certificate_revocation_check(opt)) { - cred->cred->dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + 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; + cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; } - if (opt->ca_file) { - mongoc_secure_channel_setup_ca(opt); + if (cert) { + cred->cCreds = 1; + cred->paCred = &cert; } - if (opt->crl_file) { - mongoc_secure_channel_setup_crl(opt); - } + TLS_PARAMETERS tls_parameters; + cred->cTlsParameters = 1; + cred->pTlsParameters = &tls_parameters; - if (opt->pem_file) { - cred->cert = mongoc_secure_channel_setup_certificate(opt); + // Blocked suites + CRYPTO_SETTINGS crypto_settings[1] = { { 0 } }; + cred->pTlsParameters->cDisabledCrypto = 0; + cred->pTlsParameters->pDisabledCrypto = crypto_settings; + + cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; - if (cred->cert) { - cred->cred->cCreds = 1; - cred->cred->paCred = &cred->cert; + return (void*)cred; +} + +#endif + +void * +_mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT cert, DWORD enabled_protocols) +{ + SCHANNEL_CRED *cred = bson_malloc0(sizeof(SCHANNEL_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->dwFlags = SCH_USE_STRONG_CRYPTO; +#endif + + /* By default, enable soft failing. + * A certificate with no revocation check is a soft failure. */ + cred->dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK; + /* An offline OCSP responder / CRL distribution list is a soft failure. */ + cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; + if (opt->weak_cert_validation) { + cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + TRACE("%s", "disabled server certificate checks"); + } else { + cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; + if (!_mongoc_ssl_opts_disable_certificate_revocation_check(opt)) { + cred->dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + TRACE("%s", "enabled server certificate revocation checks"); } + TRACE("%s", "enabled server certificate checks"); } -#ifdef MONGOC_HAVE_SCH_CREDENTIALS - cred->cred->cTlsParameters = 1; - TLS_PARAMETERS tls_parameters; - cred->cred->pTlsParameters = &tls_parameters; + if (opt->allow_invalid_hostname) { + cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + } + + if (cert) { + cred->cCreds = 1; + cred->paCred = &cert; + } + + cred->grbitEnabledProtocols = enabled_protocols; - DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + return (void*)cred; +} + +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)); + bool is_server = IsWindowsServer(); + DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - // TLS 1.3 is supported starting with Windows 11 and Windows Server 2022 + /* TLS 1.3 is supported starting with Windows 11 and Windows Server 2022. + * Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */ if ((is_server && _mongoc_verify_windows_version(10, 0, 19044, false)) || (!is_server && _mongoc_verify_windows_version(10, 0, 22000, false))) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; printf("Enabling TLS 1.3 with Secure Channel \n"); } - cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; + if (opt->pem_file) { + cred->cert = mongoc_secure_channel_setup_certificate(opt); + } + +#ifdef MONGOC_HAVE_SCH_CREDENTIALS + // SCH_CREDENTIALS is supported in Windows 10 1809 / Server 1809 and later + if (_mongoc_verify_windows_version(10, 0, 17763, false)) { + cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, cred->cert, enabled_protocols); + cred->cred_type = sch_credentials; + } else { + cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols); + cred->cred_type = schannel_cred; + } #else - cred->cred->grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols); + cred->cred_type = schannel_cred; #endif return cred; @@ -1026,6 +1086,7 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream, // Cast signed SECURITY_STATUS to unsigned DWORD. FormatMessage expects DWORD. char *msg = mongoc_winerr_to_string((DWORD)sspi_status); MONGOC_ERROR("Failed to initialize security context: %s", msg); + printf("Failed to initialize security context: %s\n", msg); bson_free(msg); // Detach the base stream so caller can free. tls->base_stream = NULL; diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 8f81511543d..eafb23110e3 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -100,7 +100,18 @@ test_secure_channel_shared_creds_stream(void *unused) { 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. +#ifdef MONGOC_HAVE_SCH_CREDENTIALS + if (cred->cred_type == sch_credentials) { + SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS*)cred->cred; + sch_cred->dwVersion = 0; // Invalid version. + } else { + SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED*)cred->cred; + sch_cred->dwVersion = 0; + } +#else + SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED*)cred->cred; + sch_cred->dwVersion = 0; +#endif capture_logs(true); mongoc_stream_t *stream = connect_with_secure_channel_cred(&ssl_opt, cred_ptr, &error); ASSERT(!stream); From 95b55841f2c015d9ee44292f8ad2c9d33abfb6f7 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 24 Sep 2025 18:35:39 +0000 Subject: [PATCH 20/30] Add accidentally deleted lines --- .../src/mongoc/mongoc-stream-tls-secure-channel.c | 11 +++++++++++ 1 file changed, 11 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 623f80cd25d..b4f943b2ff9 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -970,6 +970,14 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) printf("Enabling TLS 1.3 with Secure Channel \n"); } + 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); } @@ -979,13 +987,16 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) if (_mongoc_verify_windows_version(10, 0, 17763, false)) { cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, cred->cert, enabled_protocols); cred->cred_type = sch_credentials; + printf("Using SCH_CREDENTIALS\n"); } else { cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols); cred->cred_type = schannel_cred; + printf("Using SCHANNEL_CREDS\n"); } #else cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols); cred->cred_type = schannel_cred; + printf("Using SCHANNEL_CREDS\n"); #endif return cred; From 34e0b61ada38fb339572d1792c686012e7c56227 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 25 Sep 2025 14:04:50 +0000 Subject: [PATCH 21/30] Fix bug with paCred --- .../mongoc-stream-tls-secure-channel-private.h | 3 +-- .../mongoc/mongoc-stream-tls-secure-channel.c | 18 +++++++----------- 2 files changed, 8 insertions(+), 13 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 0de9a392a48..75dde3cf8cf 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 @@ -32,7 +32,6 @@ #include #include - BSON_BEGIN_DECLS @@ -62,7 +61,7 @@ typedef struct { typedef struct _mongoc_secure_channel_cred { PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ schannel_credential_type cred_type; - void *cred; /* Underlying type is specified by type. */ + void *cred; /* Underlying type is specified by schannel_credential_type. */ } mongoc_secure_channel_cred; typedef struct { 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 b4f943b2ff9..5b9a7fb61a8 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -852,7 +852,7 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream) #ifdef MONGOC_HAVE_SCH_CREDENTIALS void * -_mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT cert, DWORD enabled_protocols) +_mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT *cert, DWORD enabled_protocols) { SCH_CREDENTIALS *cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); @@ -889,7 +889,7 @@ _mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_C if (cert) { cred->cCreds = 1; - cred->paCred = &cert; + cred->paCred = cert; } TLS_PARAMETERS tls_parameters; @@ -909,7 +909,7 @@ _mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_C #endif void * -_mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT cert, DWORD enabled_protocols) +_mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT *cert, DWORD enabled_protocols) { SCHANNEL_CRED *cred = bson_malloc0(sizeof(SCHANNEL_CRED)); @@ -945,7 +945,7 @@ _mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CON if (cert) { cred->cCreds = 1; - cred->paCred = &cert; + cred->paCred = cert; } cred->grbitEnabledProtocols = enabled_protocols; @@ -985,18 +985,15 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) #ifdef MONGOC_HAVE_SCH_CREDENTIALS // SCH_CREDENTIALS is supported in Windows 10 1809 / Server 1809 and later if (_mongoc_verify_windows_version(10, 0, 17763, false)) { - cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, cred->cert, enabled_protocols); + cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, &cred->cert, enabled_protocols); cred->cred_type = sch_credentials; - printf("Using SCH_CREDENTIALS\n"); } else { - cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols); + cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, &cred->cert, enabled_protocols); cred->cred_type = schannel_cred; - printf("Using SCHANNEL_CREDS\n"); } #else - cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols); + cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, &cred->cert, enabled_protocols); cred->cred_type = schannel_cred; - printf("Using SCHANNEL_CREDS\n"); #endif return cred; @@ -1097,7 +1094,6 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream, // Cast signed SECURITY_STATUS to unsigned DWORD. FormatMessage expects DWORD. char *msg = mongoc_winerr_to_string((DWORD)sspi_status); MONGOC_ERROR("Failed to initialize security context: %s", msg); - printf("Failed to initialize security context: %s\n", msg); bson_free(msg); // Detach the base stream so caller can free. tls->base_stream = NULL; From a4b302dbdae4a6421e0926c179bf2f94ffab36fe Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 25 Sep 2025 14:58:13 +0000 Subject: [PATCH 22/30] Cleanup --- ...mongoc-stream-tls-secure-channel-private.h | 7 ++--- .../mongoc/mongoc-stream-tls-secure-channel.c | 31 +++++++++---------- .../tests/test-mongoc-secure-channel.c | 20 ++++++------ 3 files changed, 26 insertions(+), 32 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 75dde3cf8cf..f96b200b73b 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 @@ -46,10 +46,7 @@ typedef enum { } ssl_connect_state; /* enum for underlying type cred field in mongoc_secure_channel_cred */ -typedef enum { - schannel_cred, - sch_credentials -} schannel_credential_type; +typedef enum { schannel_cred, sch_credentials } schannel_credential_type; /* Structs to store Schannel handles */ typedef struct { @@ -61,7 +58,7 @@ typedef struct { typedef struct _mongoc_secure_channel_cred { PCCERT_CONTEXT cert; /* Owning. Optional client cert. */ schannel_credential_type cred_type; - void *cred; /* Underlying type is specified by schannel_credential_type. */ + void *cred; /* Underlying type is specified by schannel_credential_type. */ } mongoc_secure_channel_cred; typedef struct { 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 5b9a7fb61a8..a8defa0f5d0 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -856,7 +856,6 @@ _mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_C { SCH_CREDENTIALS *cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); - // version cred->dwVersion = SCH_CREDENTIALS_VERSION; /* SCHANNEL_CRED: @@ -892,18 +891,11 @@ _mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_C cred->paCred = cert; } - TLS_PARAMETERS tls_parameters; cred->cTlsParameters = 1; - cred->pTlsParameters = &tls_parameters; - - // Blocked suites - CRYPTO_SETTINGS crypto_settings[1] = { { 0 } }; - cred->pTlsParameters->cDisabledCrypto = 0; - cred->pTlsParameters->pDisabledCrypto = crypto_settings; - + cred->pTlsParameters = bson_malloc0(sizeof(TLS_PARAMETERS)); cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols; - return (void*)cred; + return (void *)cred; } #endif @@ -950,7 +942,7 @@ _mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CON cred->grbitEnabledProtocols = enabled_protocols; - return (void*)cred; + return (void *)cred; } mongoc_secure_channel_cred * @@ -958,16 +950,15 @@ 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)); - + bool is_server = IsWindowsServer(); - DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - /* TLS 1.3 is supported starting with Windows 11 and Windows Server 2022. + /* TLS 1.3 is supported on Windows 11 (or Windows Server 2022) and newer. * Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */ if ((is_server && _mongoc_verify_windows_version(10, 0, 19044, false)) || (!is_server && _mongoc_verify_windows_version(10, 0, 22000, false))) { enabled_protocols |= SP_PROT_TLS1_3_CLIENT; - printf("Enabling TLS 1.3 with Secure Channel \n"); } if (opt->ca_file) { @@ -984,7 +975,7 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) #ifdef MONGOC_HAVE_SCH_CREDENTIALS // SCH_CREDENTIALS is supported in Windows 10 1809 / Server 1809 and later - if (_mongoc_verify_windows_version(10, 0, 17763, false)) { + if (_mongoc_verify_windows_version(10, 0, 17763, false)) { cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, &cred->cert, enabled_protocols); cred->cred_type = sch_credentials; } else { @@ -1007,6 +998,12 @@ mongoc_secure_channel_cred_deleter(void *cred_void) return; } CertFreeCertificateContext(cred->cert); +#ifdef MONGOC_HAVE_SCH_CREDENTIALS + if (cred->cred_type == sch_credentials) { + SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS *)cred->cred; + bson_free(sch_cred->pTlsParameters); + } +#endif bson_free(cred->cred); bson_free(cred); } @@ -1084,7 +1081,7 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream, UNISP_NAME, /* security package */ SECPKG_CRED_OUTBOUND, /* we are preparing outbound connection */ NULL, /* Optional logon */ - cred->cred, /* TLS "configuration", "auth data" */ + cred->cred, /* TLS "configuration", "auth data" */ NULL, /* unused */ NULL, /* unused */ &secure_channel->cred_handle->cred_handle, /* credential OUT param */ diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index eafb23110e3..80fb76e1452 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -96,21 +96,21 @@ test_secure_channel_shared_creds_stream(void *unused) mongoc_shared_ptr_reset_null(&cred_ptr); } - // Test with bad SCHANNEL_CRED to exercise error path: + // Test with bad SCHANNEL CREDENTIALS 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); #ifdef MONGOC_HAVE_SCH_CREDENTIALS - if (cred->cred_type == sch_credentials) { - SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS*)cred->cred; - sch_cred->dwVersion = 0; // Invalid version. - } else { - SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED*)cred->cred; - sch_cred->dwVersion = 0; - } + if (cred->cred_type == sch_credentials) { + SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS *)cred->cred; + sch_cred->dwVersion = 0; // Invalid version. + } else { + SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED *)cred->cred; + sch_cred->dwVersion = 0; + } #else - SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED*)cred->cred; - sch_cred->dwVersion = 0; + SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED *)cred->cred; + sch_cred->dwVersion = 0; #endif capture_logs(true); mongoc_stream_t *stream = connect_with_secure_channel_cred(&ssl_opt, cred_ptr, &error); From 337329c8501627709532c59651aac104d4bd4726 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 25 Sep 2025 15:32:53 +0000 Subject: [PATCH 23/30] Remove cmake msgs --- src/libmongoc/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index cca3602202c..6774844a9b4 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -563,10 +563,8 @@ endif() if (HAVE_SCH_CREDENTIALS) set (MONGOC_HAVE_SCH_CREDENTIALS 1) - message (STATUS "SCH_CREDENTIALS found") else () set (MONGOC_HAVE_SCH_CREDENTIALS 0) - message (STATUS "Using deprecated SCHANNEL_CREDS") endif () From 475f08ab4e9fb767ae3ccd401dd7f0682578fdf5 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Thu, 25 Sep 2025 19:40:43 +0000 Subject: [PATCH 24/30] Fix pointer bug with cert --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 a8defa0f5d0..65d8d76c933 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -886,7 +886,7 @@ _mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_C cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; } - if (cert) { + if (*cert) { cred->cCreds = 1; cred->paCred = cert; } @@ -935,7 +935,7 @@ _mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CON cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; } - if (cert) { + if (*cert) { cred->cCreds = 1; cred->paCred = cert; } From 1e90324027de97c84d5fbe2d4f86ab4b22eaf5e5 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Fri, 26 Sep 2025 14:03:46 +0000 Subject: [PATCH 25/30] More accurate version checking using Rtl variant --- .../src/mongoc/mongoc-version-functions.c | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.c b/src/libmongoc/src/mongoc/mongoc-version-functions.c index e07acf90a42..855ce82a877 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.c +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.c @@ -84,6 +84,9 @@ mongoc_check_version(int required_major, int required_minor, int required_micro) } #ifdef _WIN32 + +typedef NTSTATUS (APIENTRY *RTLVERIFYVERSIONINFO_FN) (PRTL_OSVERSIONINFOEXW VersionInfo, ULONG TypeMask, ULONGLONG ConditionMask); + /** * _mongoc_verify_windows_version: * @@ -93,7 +96,8 @@ mongoc_check_version(int required_major, int required_minor, int required_micro) bool _mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal) { - OSVERSIONINFOEX osvi; + static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo; + OSVERSIONINFOEXW osvi; bool matched; int op = VER_GREATER_EQUAL; @@ -101,8 +105,16 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n op = VER_EQUAL; } - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + /* Windows version functions may not return the correct version for + later Windows versions unless the application is so manifested. Try + to use the more accurate kernel function RtlVerifyVersionInfo */ + HMODULE hDll = LoadLibrary(TEXT("Ntdll.dll")); + if (hDll) { + pRtlVerifyVersionInfo = (RTLVERIFYVERSIONINFO_FN)GetProcAddress(hDll, "RtlVerifyVersionInfo"); + } + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); osvi.dwMajorVersion = major_version; osvi.dwMinorVersion = minor_version; @@ -110,20 +122,30 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n VER_SET_CONDITION(mask, VER_MAJORVERSION, op); VER_SET_CONDITION(mask, VER_MINORVERSION, op); - matched = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask); + if (pRtlVerifyVersionInfo) { + matched = (pRtlVerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) == 0); + } else { + matched = (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0); + } // Compare build number separately if major and minor versions are equal if (build_number && matched && _mongoc_verify_windows_version(major_version, minor_version, 0, true)) { - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); osvi.dwBuildNumber = build_number; mask = 0; VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); - matched = VerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask); + if (pRtlVerifyVersionInfo) { + matched = (pRtlVerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask) == 0); + } + else { + matched = (VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, mask) != 0); + } } return matched; } + #endif From 807c5e44952851ca0af2b77134d936f68dc66235 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Fri, 26 Sep 2025 14:24:22 +0000 Subject: [PATCH 26/30] Format --- src/libmongoc/src/mongoc/mongoc-version-functions.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.c b/src/libmongoc/src/mongoc/mongoc-version-functions.c index 855ce82a877..d1b933d39f5 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.c +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.c @@ -85,7 +85,9 @@ mongoc_check_version(int required_major, int required_minor, int required_micro) #ifdef _WIN32 -typedef NTSTATUS (APIENTRY *RTLVERIFYVERSIONINFO_FN) (PRTL_OSVERSIONINFOEXW VersionInfo, ULONG TypeMask, ULONGLONG ConditionMask); +typedef NTSTATUS(APIENTRY *RTLVERIFYVERSIONINFO_FN)(PRTL_OSVERSIONINFOEXW VersionInfo, + ULONG TypeMask, + ULONGLONG ConditionMask); /** * _mongoc_verify_windows_version: @@ -106,7 +108,7 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n } /* Windows version functions may not return the correct version for - later Windows versions unless the application is so manifested. Try + later Windows versions unless the application is so manifested. Try to use the more accurate kernel function RtlVerifyVersionInfo */ HMODULE hDll = LoadLibrary(TEXT("Ntdll.dll")); if (hDll) { @@ -126,7 +128,7 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n matched = (pRtlVerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) == 0); } else { matched = (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0); - } + } // Compare build number separately if major and minor versions are equal if (build_number && matched && _mongoc_verify_windows_version(major_version, minor_version, 0, true)) { @@ -139,8 +141,7 @@ _mongoc_verify_windows_version(int major_version, int minor_version, int build_n if (pRtlVerifyVersionInfo) { matched = (pRtlVerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask) == 0); - } - else { + } else { matched = (VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, mask) != 0); } } From 62f84156e2e6843f0124a3028d99ae8b7c4f088d Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Mon, 29 Sep 2025 18:21:19 +0000 Subject: [PATCH 27/30] KA suggestions --- src/libmongoc/CMakeLists.txt | 29 ------- src/libmongoc/src/mongoc/mongoc-config.h.in | 10 --- .../mongoc/mongoc-stream-tls-secure-channel.c | 22 +++--- .../src/mongoc/mongoc-util-private.h | 7 ++ src/libmongoc/src/mongoc/mongoc-util.c | 66 ++++++++++++++++ .../src/mongoc/mongoc-version-functions.c | 75 ------------------- .../src/mongoc/mongoc-version-functions.h | 4 - .../tests/test-mongoc-secure-channel.c | 2 +- 8 files changed, 86 insertions(+), 129 deletions(-) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 6774844a9b4..2cf2cac14e4 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -539,35 +539,6 @@ else () set (MONGOC_HAVE_BCRYPT_PBKDF2 0) endif () -# Check if SCH_CREDENTIALS is defined in schannel.h -if (WIN32 AND MONGOC_ENABLE_SSL_SECURE_CHANNEL) - - FILE (WRITE ${CMAKE_CURRENT_BINARY_DIR}/sch_credentials_test.c - " - #include - #include - #define SCHANNEL_USE_BLACKLISTS - #include - - int main(void) { - SCH_CREDENTIALS cred; - (void)cred; - return 0; - } - ") - - TRY_COMPILE (HAVE_SCH_CREDENTIALS ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/sch_credentials_test.c CMAKE_FLAGS - "-Werror -DCMAKE_CXX_LINK_EXECUTABLE='echo not linking now...'" OUTPUT_VARIABLE LOG2) -endif() - -if (HAVE_SCH_CREDENTIALS) - set (MONGOC_HAVE_SCH_CREDENTIALS 1) -else () - set (MONGOC_HAVE_SCH_CREDENTIALS 0) -endif () - - set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mcd-azure.c ${PROJECT_SOURCE_DIR}/src/mongoc/mcd-nsinfo.c diff --git a/src/libmongoc/src/mongoc/mongoc-config.h.in b/src/libmongoc/src/mongoc/mongoc-config.h.in index 49fae22192a..88d8729357d 100644 --- a/src/libmongoc/src/mongoc/mongoc-config.h.in +++ b/src/libmongoc/src/mongoc/mongoc-config.h.in @@ -52,16 +52,6 @@ # undef MONGOC_ENABLE_SSL_SECURE_CHANNEL #endif -/* - * MONGOC_HAVE_SCH_CREDENTIALS is set from configure to determine if - * our Schannel Windows library supports SCH_CREDENTIALS - */ -#define MONGOC_HAVE_SCH_CREDENTIALS @MONGOC_HAVE_SCH_CREDENTIALS@ - -#if MONGOC_HAVE_SCH_CREDENTIALS != 1 -# undef MONGOC_HAVE_SCH_CREDENTIALS -#endif - /* * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are * compiled with Native Crypto support on Windows 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 65d8d76c933..8b7b44c75cb 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -80,8 +81,6 @@ #include #include #include -#include - /* mingw doesn't define these */ #ifndef SP_PROT_TLS1_1_CLIENT @@ -96,6 +95,10 @@ #define SP_PROT_TLS1_3_CLIENT 0x00002000 #endif +#ifdef SCH_CREDENTIALS_VERSION +#define HAVE_SCH_CREDENTIALS +#endif + static void _mongoc_stream_tls_secure_channel_destroy(mongoc_stream_t *stream) { @@ -849,7 +852,7 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream) RETURN(mongoc_stream_should_retry(tls->base_stream)); } -#ifdef MONGOC_HAVE_SCH_CREDENTIALS +#ifdef HAVE_SCH_CREDENTIALS void * _mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT *cert, DWORD enabled_protocols) @@ -951,14 +954,13 @@ 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)); - bool is_server = IsWindowsServer(); DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - /* TLS 1.3 is supported on Windows 11 (or Windows Server 2022) and newer. + /* TLS 1.3 is supported on Windows Server 2022 and newer. * Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */ - if ((is_server && _mongoc_verify_windows_version(10, 0, 19044, false)) || - (!is_server && _mongoc_verify_windows_version(10, 0, 22000, false))) { - enabled_protocols |= SP_PROT_TLS1_3_CLIENT; + if (_mongoc_verify_windows_version(10, 0, 20348, false)) { + // TODO - enable TLS 1.3 once renegotiation is supported. + // enabled_protocols |= SP_PROT_TLS1_3_CLIENT; } if (opt->ca_file) { @@ -973,7 +975,7 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) cred->cert = mongoc_secure_channel_setup_certificate(opt); } -#ifdef MONGOC_HAVE_SCH_CREDENTIALS +#ifdef HAVE_SCH_CREDENTIALS // SCH_CREDENTIALS is supported in Windows 10 1809 / Server 1809 and later if (_mongoc_verify_windows_version(10, 0, 17763, false)) { cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, &cred->cert, enabled_protocols); @@ -998,7 +1000,7 @@ mongoc_secure_channel_cred_deleter(void *cred_void) return; } CertFreeCertificateContext(cred->cert); -#ifdef MONGOC_HAVE_SCH_CREDENTIALS +#ifdef HAVE_SCH_CREDENTIALS if (cred->cred_type == sch_credentials) { SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS *)cred->cred; bson_free(sch_cred->pTlsParameters); diff --git a/src/libmongoc/src/mongoc/mongoc-util-private.h b/src/libmongoc/src/mongoc/mongoc-util-private.h index f897daa826e..193001de078 100644 --- a/src/libmongoc/src/mongoc/mongoc-util-private.h +++ b/src/libmongoc/src/mongoc/mongoc-util-private.h @@ -255,6 +255,13 @@ typedef struct { uint64_t value; } mcd_optional_u64_t; +/** + * Returns true if the Windows version is greater than or equal to the required + * desktop or server version. + */ +bool +_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal); + BSON_END_DECLS #endif /* MONGOC_UTIL_PRIVATE_H */ diff --git a/src/libmongoc/src/mongoc/mongoc-util.c b/src/libmongoc/src/mongoc/mongoc-util.c index b398117b318..00ffbdca979 100644 --- a/src/libmongoc/src/mongoc/mongoc-util.c +++ b/src/libmongoc/src/mongoc/mongoc-util.c @@ -39,6 +39,13 @@ #include #include +#ifdef _WIN32 +#include +#include + +#include +#endif + #include /** @@ -1025,3 +1032,62 @@ bin_to_hex(const uint8_t *bin, size_t bin_len) return out; } + +#ifdef _WIN32 + +typedef NTSTATUS(APIENTRY *RTLVERIFYVERSIONINFO_FN)(PRTL_OSVERSIONINFOEXW VersionInfo, + ULONG TypeMask, + ULONGLONG ConditionMask); + +bool +_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal) +{ + static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo; + OSVERSIONINFOEXW osvi; + bool matched; + int op = VER_GREATER_EQUAL; + + if (strictly_equal) { + op = VER_EQUAL; + } + + /* Windows version functions may not return the correct version for + later Windows versions unless the application is so manifested. Try + to use the more accurate kernel function RtlVerifyVersionInfo */ + pRtlVerifyVersionInfo = (RTLVERIFYVERSIONINFO_FN)GetProcAddress(GetModuleHandleA("ntdll"), "RtlVerifyVersionInfo"); + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + osvi.dwMajorVersion = major_version; + osvi.dwMinorVersion = minor_version; + + ULONGLONG mask = 0; + VER_SET_CONDITION(mask, VER_MAJORVERSION, op); + VER_SET_CONDITION(mask, VER_MINORVERSION, op); + + if (pRtlVerifyVersionInfo) { + matched = (pRtlVerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) == 0); + } else { + matched = (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0); + } + + // Compare build number separately if major and minor versions are equal + if (build_number && matched && _mongoc_verify_windows_version(major_version, minor_version, 0, true)) { + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + osvi.dwBuildNumber = build_number; + + mask = 0; + VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); + + if (pRtlVerifyVersionInfo) { + matched = (pRtlVerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask) == 0); + } else { + matched = (VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, mask) != 0); + } + } + + return matched; +} + +#endif diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.c b/src/libmongoc/src/mongoc/mongoc-version-functions.c index d1b933d39f5..db3badfade9 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.c +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.c @@ -19,13 +19,6 @@ #include -#ifdef _WIN32 -#include -#include - -#include -#endif - /** * mongoc_get_major_version: * @@ -82,71 +75,3 @@ mongoc_check_version(int required_major, int required_minor, int required_micro) { return MONGOC_CHECK_VERSION(required_major, required_minor, required_micro); } - -#ifdef _WIN32 - -typedef NTSTATUS(APIENTRY *RTLVERIFYVERSIONINFO_FN)(PRTL_OSVERSIONINFOEXW VersionInfo, - ULONG TypeMask, - ULONGLONG ConditionMask); - -/** - * _mongoc_verify_windows_version: - * - * True if the Windows version is greater than or equal to the required - * desktop or server version. - */ -bool -_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal) -{ - static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo; - OSVERSIONINFOEXW osvi; - bool matched; - int op = VER_GREATER_EQUAL; - - if (strictly_equal) { - op = VER_EQUAL; - } - - /* Windows version functions may not return the correct version for - later Windows versions unless the application is so manifested. Try - to use the more accurate kernel function RtlVerifyVersionInfo */ - HMODULE hDll = LoadLibrary(TEXT("Ntdll.dll")); - if (hDll) { - pRtlVerifyVersionInfo = (RTLVERIFYVERSIONINFO_FN)GetProcAddress(hDll, "RtlVerifyVersionInfo"); - } - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); - osvi.dwMajorVersion = major_version; - osvi.dwMinorVersion = minor_version; - - ULONGLONG mask = 0; - VER_SET_CONDITION(mask, VER_MAJORVERSION, op); - VER_SET_CONDITION(mask, VER_MINORVERSION, op); - - if (pRtlVerifyVersionInfo) { - matched = (pRtlVerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) == 0); - } else { - matched = (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0); - } - - // Compare build number separately if major and minor versions are equal - if (build_number && matched && _mongoc_verify_windows_version(major_version, minor_version, 0, true)) { - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); - osvi.dwBuildNumber = build_number; - - mask = 0; - VER_SET_CONDITION(mask, VER_BUILDNUMBER, op); - - if (pRtlVerifyVersionInfo) { - matched = (pRtlVerifyVersionInfo(&osvi, VER_BUILDNUMBER, mask) == 0); - } else { - matched = (VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, mask) != 0); - } - } - - return matched; -} - -#endif diff --git a/src/libmongoc/src/mongoc/mongoc-version-functions.h b/src/libmongoc/src/mongoc/mongoc-version-functions.h index 9317bab0412..3a08c181109 100644 --- a/src/libmongoc/src/mongoc/mongoc-version-functions.h +++ b/src/libmongoc/src/mongoc/mongoc-version-functions.h @@ -36,10 +36,6 @@ MONGOC_EXPORT(const char *) mongoc_get_version(void); MONGOC_EXPORT(bool) mongoc_check_version(int required_major, int required_minor, int required_micro); -#ifdef _WIN32 -MONGOC_EXPORT(bool) -_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal); -#endif BSON_END_DECLS diff --git a/src/libmongoc/tests/test-mongoc-secure-channel.c b/src/libmongoc/tests/test-mongoc-secure-channel.c index 80fb76e1452..0d84e1a90c5 100644 --- a/src/libmongoc/tests/test-mongoc-secure-channel.c +++ b/src/libmongoc/tests/test-mongoc-secure-channel.c @@ -100,7 +100,7 @@ test_secure_channel_shared_creds_stream(void *unused) { 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); -#ifdef MONGOC_HAVE_SCH_CREDENTIALS +#ifdef HAVE_SCH_CREDENTIALS if (cred->cred_type == sch_credentials) { SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS *)cred->cred; sch_cred->dwVersion = 0; // Invalid version. From ddf9c75b63456df868eb37a71d02f7c945f50a23 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Mon, 29 Sep 2025 18:49:15 +0000 Subject: [PATCH 28/30] Format --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 8b7b44c75cb..f874c137f69 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -959,8 +959,8 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt) /* TLS 1.3 is supported on Windows Server 2022 and newer. * Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */ if (_mongoc_verify_windows_version(10, 0, 20348, false)) { - // TODO - enable TLS 1.3 once renegotiation is supported. - // enabled_protocols |= SP_PROT_TLS1_3_CLIENT; + // TODO - enable TLS 1.3 once renegotiation is supported. + // enabled_protocols |= SP_PROT_TLS1_3_CLIENT; } if (opt->ca_file) { From 49e4095ca6324e4803cb627c1cdddcd2baf73e03 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 1 Oct 2025 15:00:14 +0000 Subject: [PATCH 29/30] Improvements --- src/libmongoc/CMakeLists.txt | 1 + src/libmongoc/src/mongoc/mongoc-config.h.in | 1 + ...mongoc-stream-tls-secure-channel-private.h | 8 +- .../mongoc/mongoc-stream-tls-secure-channel.c | 75 +++++++------------ .../src/mongoc/mongoc-util-private.h | 2 +- src/libmongoc/src/mongoc/mongoc-util.c | 4 +- 6 files changed, 37 insertions(+), 54 deletions(-) diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 2cf2cac14e4..6243b4b47db 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -539,6 +539,7 @@ else () set (MONGOC_HAVE_BCRYPT_PBKDF2 0) endif () + set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mcd-azure.c ${PROJECT_SOURCE_DIR}/src/mongoc/mcd-nsinfo.c diff --git a/src/libmongoc/src/mongoc/mongoc-config.h.in b/src/libmongoc/src/mongoc/mongoc-config.h.in index 88d8729357d..a250d129689 100644 --- a/src/libmongoc/src/mongoc/mongoc-config.h.in +++ b/src/libmongoc/src/mongoc/mongoc-config.h.in @@ -52,6 +52,7 @@ # undef MONGOC_ENABLE_SSL_SECURE_CHANNEL #endif + /* * MONGOC_ENABLE_CRYPTO_CNG is set from configure to determine if we are * compiled with Native Crypto support on Windows 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 f96b200b73b..bf22348ec1e 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 @@ -24,14 +24,18 @@ #include -#include +#include // For SCH_CREDENTIALS /* Its mandatory to indicate to Windows who is compiling the code */ #define SECURITY_WIN32 -#define SCHANNEL_USE_BLACKLISTS 1 +#define SCHANNEL_USE_BLACKLISTS 1 // For SCH_CREDENTIALS #include #include +#ifdef SCH_CREDENTIALS_VERSION +#define HAVE_SCH_CREDENTIALS +#endif + BSON_BEGIN_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 f874c137f69..9b21d8ff190 100644 --- a/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c +++ b/src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c @@ -95,10 +95,6 @@ #define SP_PROT_TLS1_3_CLIENT 0x00002000 #endif -#ifdef SCH_CREDENTIALS_VERSION -#define HAVE_SCH_CREDENTIALS -#endif - static void _mongoc_stream_tls_secure_channel_destroy(mongoc_stream_t *stream) { @@ -852,43 +848,51 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream) RETURN(mongoc_stream_should_retry(tls->base_stream)); } -#ifdef HAVE_SCH_CREDENTIALS - -void * -_mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT *cert, DWORD enabled_protocols) +static DWORD +get_cred_flags(const mongoc_ssl_opt_t *opt) { - SCH_CREDENTIALS *cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); + DWORD dwFlags; - cred->dwVersion = SCH_CREDENTIALS_VERSION; - -/* SCHANNEL_CRED: - * SCH_USE_STRONG_CRYPTO is not available in VS2010 - * https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */ + /* 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->dwFlags = SCH_USE_STRONG_CRYPTO; + dwFlags = SCH_USE_STRONG_CRYPTO; #endif /* By default, enable soft failing. * A certificate with no revocation check is a soft failure. */ - cred->dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK; + dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK; /* An offline OCSP responder / CRL distribution list is a soft failure. */ - cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; + dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; if (opt->weak_cert_validation) { - cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; + dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; TRACE("%s", "disabled server certificate checks"); } else { - cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; + dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; if (!_mongoc_ssl_opts_disable_certificate_revocation_check(opt)) { - cred->dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; + 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->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; } + return dwFlags; +} + +#ifdef HAVE_SCH_CREDENTIALS + +void * +_mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT *cert, DWORD enabled_protocols) +{ + SCH_CREDENTIALS *cred = bson_malloc0(sizeof(SCH_CREDENTIALS)); + + cred->dwVersion = SCH_CREDENTIALS_VERSION; + cred->dwFlags = get_cred_flags(opt); + if (*cert) { cred->cCreds = 1; cred->paCred = cert; @@ -909,34 +913,7 @@ _mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CON SCHANNEL_CRED *cred = bson_malloc0(sizeof(SCHANNEL_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->dwFlags = SCH_USE_STRONG_CRYPTO; -#endif - - /* By default, enable soft failing. - * A certificate with no revocation check is a soft failure. */ - cred->dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK; - /* An offline OCSP responder / CRL distribution list is a soft failure. */ - cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE; - if (opt->weak_cert_validation) { - cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; - TRACE("%s", "disabled server certificate checks"); - } else { - cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION; - if (!_mongoc_ssl_opts_disable_certificate_revocation_check(opt)) { - 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->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - } + cred->dwFlags = get_cred_flags(opt); if (*cert) { cred->cCreds = 1; diff --git a/src/libmongoc/src/mongoc/mongoc-util-private.h b/src/libmongoc/src/mongoc/mongoc-util-private.h index 193001de078..90a08b884c8 100644 --- a/src/libmongoc/src/mongoc/mongoc-util-private.h +++ b/src/libmongoc/src/mongoc/mongoc-util-private.h @@ -260,7 +260,7 @@ typedef struct { * desktop or server version. */ bool -_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal); +_mongoc_verify_windows_version(DWORD major_version, DWORD minor_version, DWORD build_number, bool strictly_equal); BSON_END_DECLS diff --git a/src/libmongoc/src/mongoc/mongoc-util.c b/src/libmongoc/src/mongoc/mongoc-util.c index 00ffbdca979..1d59df986f6 100644 --- a/src/libmongoc/src/mongoc/mongoc-util.c +++ b/src/libmongoc/src/mongoc/mongoc-util.c @@ -1040,12 +1040,12 @@ typedef NTSTATUS(APIENTRY *RTLVERIFYVERSIONINFO_FN)(PRTL_OSVERSIONINFOEXW Versio ULONGLONG ConditionMask); bool -_mongoc_verify_windows_version(int major_version, int minor_version, int build_number, bool strictly_equal) +_mongoc_verify_windows_version(DWORD major_version, DWORD minor_version, DWORD build_number, bool strictly_equal) { static RTLVERIFYVERSIONINFO_FN pRtlVerifyVersionInfo; OSVERSIONINFOEXW osvi; bool matched; - int op = VER_GREATER_EQUAL; + BYTE op = VER_GREATER_EQUAL; if (strictly_equal) { op = VER_EQUAL; From c88434e1bf9348a165da310b12d3ca276df25d89 Mon Sep 17 00:00:00 2001 From: Julia-Garland Date: Wed, 1 Oct 2025 15:11:19 +0000 Subject: [PATCH 30/30] Missing WIN32 check --- src/libmongoc/src/mongoc/mongoc-util-private.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libmongoc/src/mongoc/mongoc-util-private.h b/src/libmongoc/src/mongoc/mongoc-util-private.h index 90a08b884c8..60b19031ca6 100644 --- a/src/libmongoc/src/mongoc/mongoc-util-private.h +++ b/src/libmongoc/src/mongoc/mongoc-util-private.h @@ -255,6 +255,8 @@ typedef struct { uint64_t value; } mcd_optional_u64_t; +#ifdef _WIN32 + /** * Returns true if the Windows version is greater than or equal to the required * desktop or server version. @@ -262,6 +264,8 @@ typedef struct { bool _mongoc_verify_windows_version(DWORD major_version, DWORD minor_version, DWORD build_number, bool strictly_equal); +#endif + BSON_END_DECLS #endif /* MONGOC_UTIL_PRIVATE_H */