62
62
#include <mongoc/mongoc-stream-tls-private.h>
63
63
#include <mongoc/mongoc-stream-tls-secure-channel-private.h>
64
64
#include <mongoc/mongoc-trace-private.h>
65
+ #include <mongoc/mongoc-util-private.h>
65
66
66
67
#include <mongoc/mongoc-log.h>
67
68
#include <mongoc/mongoc-ssl.h>
68
69
#include <mongoc/mongoc-stream-tls.h>
69
70
70
71
#include <bson/bson.h>
71
72
73
+ #include <subauth.h>
74
+
72
75
#undef MONGOC_LOG_DOMAIN
73
76
#define MONGOC_LOG_DOMAIN "stream-tls-secure-channel"
74
77
75
78
76
79
#define SECURITY_WIN32
80
+ #define SCHANNEL_USE_BLACKLISTS 1
77
81
#include <schannel.h>
78
82
#include <schnlsp.h>
79
83
#include <security.h>
87
91
#define SP_PROT_TLS1_2_CLIENT 0x00000800
88
92
#endif
89
93
94
+ #ifndef SP_PROT_TLS1_3_CLIENT
95
+ #define SP_PROT_TLS1_3_CLIENT 0x00002000
96
+ #endif
90
97
91
98
static void
92
99
_mongoc_stream_tls_secure_channel_destroy (mongoc_stream_t * stream )
@@ -841,40 +848,96 @@ _mongoc_stream_tls_secure_channel_should_retry(mongoc_stream_t *stream)
841
848
RETURN (mongoc_stream_should_retry (tls -> base_stream ));
842
849
}
843
850
844
- mongoc_secure_channel_cred *
845
- mongoc_secure_channel_cred_new (const mongoc_ssl_opt_t * opt )
851
+ static DWORD
852
+ get_cred_flags (const mongoc_ssl_opt_t * opt )
846
853
{
847
- BSON_ASSERT_PARAM (opt );
848
- mongoc_secure_channel_cred * cred = bson_malloc0 (sizeof (mongoc_secure_channel_cred ));
854
+ DWORD dwFlags ;
849
855
850
- cred -> cred .dwVersion = SCHANNEL_CRED_VERSION ;
851
-
852
- /* SCHANNEL_CRED:
853
- * SCH_USE_STRONG_CRYPTO is not available in VS2010
854
- * https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */
856
+ /* SCH_USE_STRONG_CRYPTO is not available in VS2010
857
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/aa379810.aspx */
855
858
#ifdef SCH_USE_STRONG_CRYPTO
856
- cred -> cred . dwFlags = SCH_USE_STRONG_CRYPTO ;
859
+ dwFlags = SCH_USE_STRONG_CRYPTO ;
857
860
#endif
858
861
859
862
/* By default, enable soft failing.
860
863
* A certificate with no revocation check is a soft failure. */
861
- cred -> cred . dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK ;
864
+ dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK ;
862
865
/* An offline OCSP responder / CRL distribution list is a soft failure. */
863
- cred -> cred . dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE ;
866
+ dwFlags |= SCH_CRED_IGNORE_REVOCATION_OFFLINE ;
864
867
if (opt -> weak_cert_validation ) {
865
- cred -> cred . dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION ;
868
+ dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION ;
866
869
TRACE ("%s" , "disabled server certificate checks" );
867
870
} else {
868
- cred -> cred . dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION ;
871
+ dwFlags |= SCH_CRED_AUTO_CRED_VALIDATION ;
869
872
if (!_mongoc_ssl_opts_disable_certificate_revocation_check (opt )) {
870
- cred -> cred . dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN ;
873
+ dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN ;
871
874
TRACE ("%s" , "enabled server certificate revocation checks" );
872
875
}
873
876
TRACE ("%s" , "enabled server certificate checks" );
874
877
}
875
878
876
879
if (opt -> allow_invalid_hostname ) {
877
- cred -> cred .dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK ;
880
+ dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK ;
881
+ }
882
+
883
+ return dwFlags ;
884
+ }
885
+
886
+ #ifdef HAVE_SCH_CREDENTIALS
887
+
888
+ void *
889
+ _mongoc_secure_channel_sch_credentials_new (const mongoc_ssl_opt_t * opt , PCCERT_CONTEXT * cert , DWORD enabled_protocols )
890
+ {
891
+ SCH_CREDENTIALS * cred = bson_malloc0 (sizeof (SCH_CREDENTIALS ));
892
+
893
+ cred -> dwVersion = SCH_CREDENTIALS_VERSION ;
894
+ cred -> dwFlags = get_cred_flags (opt );
895
+
896
+ if (* cert ) {
897
+ cred -> cCreds = 1 ;
898
+ cred -> paCred = cert ;
899
+ }
900
+
901
+ cred -> cTlsParameters = 1 ;
902
+ cred -> pTlsParameters = bson_malloc0 (sizeof (TLS_PARAMETERS ));
903
+ cred -> pTlsParameters -> grbitDisabledProtocols = (DWORD )~enabled_protocols ;
904
+
905
+ return (void * )cred ;
906
+ }
907
+
908
+ #endif
909
+
910
+ void *
911
+ _mongoc_secure_channel_schannel_cred_new (const mongoc_ssl_opt_t * opt , PCCERT_CONTEXT * cert , DWORD enabled_protocols )
912
+ {
913
+ SCHANNEL_CRED * cred = bson_malloc0 (sizeof (SCHANNEL_CRED ));
914
+
915
+ cred -> dwVersion = SCHANNEL_CRED_VERSION ;
916
+ cred -> dwFlags = get_cred_flags (opt );
917
+
918
+ if (* cert ) {
919
+ cred -> cCreds = 1 ;
920
+ cred -> paCred = cert ;
921
+ }
922
+
923
+ cred -> grbitEnabledProtocols = enabled_protocols ;
924
+
925
+ return (void * )cred ;
926
+ }
927
+
928
+ mongoc_secure_channel_cred *
929
+ mongoc_secure_channel_cred_new (const mongoc_ssl_opt_t * opt )
930
+ {
931
+ BSON_ASSERT_PARAM (opt );
932
+ mongoc_secure_channel_cred * cred = bson_malloc0 (sizeof (mongoc_secure_channel_cred ));
933
+
934
+ DWORD enabled_protocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT ;
935
+
936
+ /* TLS 1.3 is supported on Windows Server 2022 and newer.
937
+ * Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */
938
+ if (_mongoc_verify_windows_version (10 , 0 , 20348 , false)) {
939
+ // TODO - enable TLS 1.3 once renegotiation is supported.
940
+ // enabled_protocols |= SP_PROT_TLS1_3_CLIENT;
878
941
}
879
942
880
943
if (opt -> ca_file ) {
@@ -887,14 +950,22 @@ mongoc_secure_channel_cred_new(const mongoc_ssl_opt_t *opt)
887
950
888
951
if (opt -> pem_file ) {
889
952
cred -> cert = mongoc_secure_channel_setup_certificate (opt );
953
+ }
890
954
891
- if (cred -> cert ) {
892
- cred -> cred .cCreds = 1 ;
893
- cred -> cred .paCred = & cred -> cert ;
894
- }
955
+ #ifdef HAVE_SCH_CREDENTIALS
956
+ // SCH_CREDENTIALS is supported in Windows 10 1809 / Server 1809 and later
957
+ if (_mongoc_verify_windows_version (10 , 0 , 17763 , false)) {
958
+ cred -> cred = _mongoc_secure_channel_sch_credentials_new (opt , & cred -> cert , enabled_protocols );
959
+ cred -> cred_type = sch_credentials ;
960
+ } else {
961
+ cred -> cred = _mongoc_secure_channel_schannel_cred_new (opt , & cred -> cert , enabled_protocols );
962
+ cred -> cred_type = schannel_cred ;
895
963
}
964
+ #else
965
+ cred -> cred = _mongoc_secure_channel_schannel_cred_new (opt , & cred -> cert , enabled_protocols );
966
+ cred -> cred_type = schannel_cred ;
967
+ #endif
896
968
897
- cred -> cred .grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT ;
898
969
return cred ;
899
970
}
900
971
@@ -906,6 +977,13 @@ mongoc_secure_channel_cred_deleter(void *cred_void)
906
977
return ;
907
978
}
908
979
CertFreeCertificateContext (cred -> cert );
980
+ #ifdef HAVE_SCH_CREDENTIALS
981
+ if (cred -> cred_type == sch_credentials ) {
982
+ SCH_CREDENTIALS * sch_cred = (SCH_CREDENTIALS * )cred -> cred ;
983
+ bson_free (sch_cred -> pTlsParameters );
984
+ }
985
+ #endif
986
+ bson_free (cred -> cred );
909
987
bson_free (cred );
910
988
}
911
989
@@ -982,7 +1060,7 @@ mongoc_stream_tls_secure_channel_new_with_creds(mongoc_stream_t *base_stream,
982
1060
UNISP_NAME , /* security package */
983
1061
SECPKG_CRED_OUTBOUND , /* we are preparing outbound connection */
984
1062
NULL , /* Optional logon */
985
- & cred -> cred , /* TLS "configuration", "auth data" */
1063
+ cred -> cred , /* TLS "configuration", "auth data" */
986
1064
NULL , /* unused */
987
1065
NULL , /* unused */
988
1066
& secure_channel -> cred_handle -> cred_handle , /* credential OUT param */
0 commit comments