Skip to content

Commit c2ee9d5

Browse files
committed
Refactor setup logic
1 parent e667f6d commit c2ee9d5

File tree

3 files changed

+117
-42
lines changed

3 files changed

+117
-42
lines changed

src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel-private.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ typedef enum {
4646
ssl_connect_done
4747
} ssl_connect_state;
4848

49+
/* enum for underlying type cred field in mongoc_secure_channel_cred */
50+
typedef enum {
51+
schannel_cred,
52+
sch_credentials
53+
} schannel_credential_type;
54+
4955
/* Structs to store Schannel handles */
5056
typedef struct {
5157
CredHandle cred_handle;
@@ -55,11 +61,8 @@ typedef struct {
5561
// `mongoc_secure_channel_cred` may be shared on multiple connections.
5662
typedef struct _mongoc_secure_channel_cred {
5763
PCCERT_CONTEXT cert; /* Owning. Optional client cert. */
58-
#ifdef MONGOC_HAVE_SCH_CREDENTIALS
59-
SCH_CREDENTIALS *cred;
60-
#else
61-
SCHANNEL_CRED *cred;
62-
#endif
64+
schannel_credential_type cred_type;
65+
void *cred; /* Underlying type is specified by type. */
6366
} mongoc_secure_channel_cred;
6467

6568
typedef struct {

src/libmongoc/src/mongoc/mongoc-stream-tls-secure-channel.c

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -849,83 +849,143 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream)
849849
RETURN(mongoc_stream_should_retry(tls->base_stream));
850850
}
851851

852-
mongoc_secure_channel_cred *
853-
mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt)
852+
#ifdef MONGOC_HAVE_SCH_CREDENTIALS
853+
854+
void *
855+
_mongoc_secure_channel_sch_credentials_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT cert, DWORD enabled_protocols)
854856
{
855-
BSON_ASSERT_PARAM(opt);
856-
mongoc_secure_channel_cred *cred = bson_malloc0(sizeof(mongoc_secure_channel_cred));
857+
SCH_CREDENTIALS *cred = bson_malloc0(sizeof(SCH_CREDENTIALS));
857858

858-
#ifdef MONGOC_HAVE_SCH_CREDENTIALS
859-
cred->cred = bson_malloc0(sizeof(SCH_CREDENTIALS));
860-
cred->cred->dwVersion = SCH_CREDENTIALS_VERSION;
861-
#else
862-
cred->cred = bson_malloc0(sizeof(SCHANNEL_CRED));
863-
cred->cred->dwVersion = SCHANNEL_CRED_VERSION;
864-
#endif
859+
// version
860+
cred->dwVersion = SCH_CREDENTIALS_VERSION;
865861

866862
/* SCHANNEL_CRED:
867863
* SCH_USE_STRONG_CRYPTO is not available in VS2010
868864
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */
869865
#ifdef SCH_USE_STRONG_CRYPTO
870-
cred->cred->dwFlags = SCH_USE_STRONG_CRYPTO;
866+
cred->dwFlags = SCH_USE_STRONG_CRYPTO;
871867
#endif
872868

873869
/* By default, enable soft failing.
874870
* A certificate with no revocation check is a soft failure. */
875-
cred->cred->dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK;
871+
cred->dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK;
876872
/* An offline OCSP responder / CRL distribution list is a soft failure. */
877-
cred->cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE;
873+
cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE;
878874
if (opt->weak_cert_validation) {
879-
cred->cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
875+
cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
880876
TRACE("%s", "disabled server certificate checks");
881877
} else {
882-
cred->cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION;
878+
cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION;
883879
if (!_mongoc_ssl_opts_disable_certificate_revocation_check(opt)) {
884-
cred->cred->dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
880+
cred->dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
885881
TRACE("%s", "enabled server certificate revocation checks");
886882
}
887883
TRACE("%s", "enabled server certificate checks");
888884
}
889885

890886
if (opt->allow_invalid_hostname) {
891-
cred->cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
887+
cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
892888
}
893889

894-
if (opt->ca_file) {
895-
mongoc_secure_channel_setup_ca(opt);
890+
if (cert) {
891+
cred->cCreds = 1;
892+
cred->paCred = &cert;
896893
}
897894

898-
if (opt->crl_file) {
899-
mongoc_secure_channel_setup_crl(opt);
900-
}
895+
TLS_PARAMETERS tls_parameters;
896+
cred->cTlsParameters = 1;
897+
cred->pTlsParameters = &tls_parameters;
901898

902-
if (opt->pem_file) {
903-
cred->cert = mongoc_secure_channel_setup_certificate(opt);
899+
// Blocked suites
900+
CRYPTO_SETTINGS crypto_settings[1] = { { 0 } };
901+
cred->pTlsParameters->cDisabledCrypto = 0;
902+
cred->pTlsParameters->pDisabledCrypto = crypto_settings;
903+
904+
cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols;
904905

905-
if (cred->cert) {
906-
cred->cred->cCreds = 1;
907-
cred->cred->paCred = &cred->cert;
906+
return (void*)cred;
907+
}
908+
909+
#endif
910+
911+
void *
912+
_mongoc_secure_channel_schannel_cred_new(const mongoc_ssl_opt_t *opt, PCCERT_CONTEXT cert, DWORD enabled_protocols)
913+
{
914+
SCHANNEL_CRED *cred = bson_malloc0(sizeof(SCHANNEL_CRED));
915+
916+
cred->dwVersion = SCHANNEL_CRED_VERSION;
917+
918+
/* SCHANNEL_CRED:
919+
* SCH_USE_STRONG_CRYPTO is not available in VS2010
920+
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */
921+
#ifdef SCH_USE_STRONG_CRYPTO
922+
cred->dwFlags = SCH_USE_STRONG_CRYPTO;
923+
#endif
924+
925+
/* By default, enable soft failing.
926+
* A certificate with no revocation check is a soft failure. */
927+
cred->dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK;
928+
/* An offline OCSP responder / CRL distribution list is a soft failure. */
929+
cred->dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE;
930+
if (opt->weak_cert_validation) {
931+
cred->dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
932+
TRACE("%s", "disabled server certificate checks");
933+
} else {
934+
cred->dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION;
935+
if (!_mongoc_ssl_opts_disable_certificate_revocation_check(opt)) {
936+
cred->dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
937+
TRACE("%s", "enabled server certificate revocation checks");
908938
}
939+
TRACE("%s", "enabled server certificate checks");
909940
}
910941

911-
#ifdef MONGOC_HAVE_SCH_CREDENTIALS
912-
cred->cred->cTlsParameters = 1;
913-
TLS_PARAMETERS tls_parameters;
914-
cred->cred->pTlsParameters = &tls_parameters;
942+
if (opt->allow_invalid_hostname) {
943+
cred->dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
944+
}
945+
946+
if (cert) {
947+
cred->cCreds = 1;
948+
cred->paCred = &cert;
949+
}
950+
951+
cred->grbitEnabledProtocols = enabled_protocols;
915952

916-
DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
953+
return (void*)cred;
954+
}
955+
956+
mongoc_secure_channel_cred *
957+
mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt)
958+
{
959+
BSON_ASSERT_PARAM(opt);
960+
mongoc_secure_channel_cred *cred = bson_malloc0(sizeof(mongoc_secure_channel_cred));
961+
917962
bool is_server = IsWindowsServer();
963+
DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
918964

919-
// TLS 1.3 is supported starting with Windows 11 and Windows Server 2022
965+
/* TLS 1.3 is supported starting with Windows 11 and Windows Server 2022.
966+
* Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */
920967
if ((is_server && _mongoc_verify_windows_version(10, 0, 19044, false)) ||
921968
(!is_server && _mongoc_verify_windows_version(10, 0, 22000, false))) {
922969
enabled_protocols |= SP_PROT_TLS1_3_CLIENT;
923970
printf("Enabling TLS 1.3 with Secure Channel \n");
924971
}
925972

926-
cred->cred->pTlsParameters->grbitDisabledProtocols = (DWORD)~enabled_protocols;
973+
if (opt->pem_file) {
974+
cred->cert = mongoc_secure_channel_setup_certificate(opt);
975+
}
976+
977+
#ifdef MONGOC_HAVE_SCH_CREDENTIALS
978+
// SCH_CREDENTIALS is supported in Windows 10 1809 / Server 1809 and later
979+
if (_mongoc_verify_windows_version(10, 0, 17763, false)) {
980+
cred->cred = _mongoc_secure_channel_sch_credentials_new(opt, cred->cert, enabled_protocols);
981+
cred->cred_type = sch_credentials;
982+
} else {
983+
cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols);
984+
cred->cred_type = schannel_cred;
985+
}
927986
#else
928-
cred->cred->grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
987+
cred->cred = _mongoc_secure_channel_schannel_cred_new(opt, cred->cert, enabled_protocols);
988+
cred->cred_type = schannel_cred;
929989
#endif
930990

931991
return cred;
@@ -1026,6 +1086,7 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
10261086
// Cast signed SECURITY_STATUS to unsigned DWORD. FormatMessage expects DWORD.
10271087
char *msg = mongoc_winerr_to_string((DWORD)sspi_status);
10281088
MONGOC_ERROR("Failed to initialize security context: %s", msg);
1089+
printf("Failed to initialize security context: %s\n", msg);
10291090
bson_free(msg);
10301091
// Detach the base stream so caller can free.
10311092
tls->base_stream = NULL;

src/libmongoc/tests/test-mongoc-secure-channel.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,18 @@ test_secure_channel_shared_creds_stream(void *unused)
100100
{
101101
mongoc_secure_channel_cred *cred = mongoc_secure_channel_cred_new(&ssl_opt);
102102
mongoc_shared_ptr cred_ptr = mongoc_shared_ptr_create(cred, mongoc_secure_channel_cred_deleter);
103-
cred->cred->dwVersion = 0; // Invalid version.
103+
#ifdef MONGOC_HAVE_SCH_CREDENTIALS
104+
if (cred->cred_type == sch_credentials) {
105+
SCH_CREDENTIALS *sch_cred = (SCH_CREDENTIALS*)cred->cred;
106+
sch_cred->dwVersion = 0; // Invalid version.
107+
} else {
108+
SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED*)cred->cred;
109+
sch_cred->dwVersion = 0;
110+
}
111+
#else
112+
SCHANNEL_CRED *sch_cred = (SCHANNEL_CRED*)cred->cred;
113+
sch_cred->dwVersion = 0;
114+
#endif
104115
capture_logs(true);
105116
mongoc_stream_t *stream = connect_with_secure_channel_cred(&ssl_opt, cred_ptr, &error);
106117
ASSERT(!stream);

0 commit comments

Comments
 (0)