diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md
index cc9a60e538..1ebb710197 100644
--- a/BUILDGUIDE.md
+++ b/BUILDGUIDE.md
@@ -257,6 +257,12 @@ To use this feature, you must enable the following AppContext switch at applicat
**"Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior"**
+## Enabling OS secure protocols preference
+
+TLS 1.3 has been excluded due to the fact that the driver lacks full support. To enable OS preferences as before, enable the following AppContext switch on application startup:
+
+**"Switch.Microsoft.Data.SqlClient.EnableSecureProtocolsByOS"**
+
## Debugging SqlClient on Linux from Windows
For enhanced developer experience, we support debugging SqlClient on Linux from Windows, using the project "**Microsoft.Data.SqlClient.DockerLinuxTest**" that requires "Container Tools" to be enabled in Visual Studio. You may import configuration: [VS19Components.vsconfig](./tools/vsconfig/VS19Components.vsconfig) if not enabled already.
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs
index 20159ca382..7f1b3e17ea 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs
@@ -264,7 +264,7 @@ internal struct SNI_Error
private static extern uint SNIGetInfoWrapper([In] SNIHandle pConn, SNINativeMethodWrapper.QTypes QType, out ProviderEnum provNum);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
- private static extern uint SNIInitialize([In] IntPtr pmo);
+ private static extern uint SNIInitialize([In] bool useSystemDefaultSecureProtocols, [In] IntPtr pmo);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
private static extern uint SNIOpenSyncExWrapper(ref SNI_CLIENT_CONSUMER_INFO pClientConsumerInfo, out IntPtr ppConn);
@@ -340,7 +340,7 @@ internal static uint SniGetConnectionIPString(SNIHandle pConn, ref string connIP
internal static uint SNIInitialize()
{
- return SNIInitialize(IntPtr.Zero);
+ return SNIInitialize(LocalAppContextSwitches.UseSystemDefaultSecureProtocols, IntPtr.Zero);
}
internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHandle parent, ref IntPtr pConn, bool fSync, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs
index bd3facd5fc..dbee403f41 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Security.Authentication;
namespace Microsoft.Data.SqlClient.SNI
{
@@ -11,6 +12,16 @@ namespace Microsoft.Data.SqlClient.SNI
///
internal abstract class SNIHandle
{
+ ///
+ /// Exclude TLS 1.3 (not fully supported).
+ ///
+ protected readonly SslProtocols SupportedProtocols = LocalAppContextSwitches.UseSystemDefaultSecureProtocols ? SslProtocols.None : SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
+ //protected readonly SslProtocols SupportedProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
+#pragma warning disable CS0618 // Type or member is obsolete
+ | SslProtocols.Ssl2 | SslProtocols.Ssl3
+#pragma warning restore CS0618 // Type or member is obsolete
+ ;
+
///
/// Dispose class
///
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs
index a11779870b..c0758f3ab5 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs
@@ -355,8 +355,7 @@ public override uint EnableSsl(uint options)
_validateCert = (options & TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE) != 0;
try
{
-
- _sslStream.AuthenticateAsClient(_targetServer);
+ _sslStream.AuthenticateAsClient(_targetServer, null, SupportedProtocols, true);
_sslOverTdsStream.FinishHandshake();
}
catch (AuthenticationException aue)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
index 0ee3e91291..a38ff3207e 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
@@ -587,7 +587,7 @@ public override uint EnableSsl(uint options)
try
{
- _sslStream.AuthenticateAsClient(_targetServer);
+ _sslStream.AuthenticateAsClient(_targetServer, null, SupportedProtocols, true);
_sslOverTdsStream.FinishHandshake();
}
catch (AuthenticationException aue)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs
index ecb6e0bb43..89df41b417 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs
@@ -421,14 +421,10 @@ internal override uint WaitForSSLHandShakeToComplete(out int protocolVersion)
protocolVersion = (int)SslProtocols.Ssl2;
#pragma warning restore CS0618 // Type or member is obsolete : SSL is depricated
}
- else if (nativeProtocol.HasFlag(NativeProtocols.SP_PROT_NONE))
+ else //if (nativeProtocol.HasFlag(NativeProtocols.SP_PROT_NONE))
{
protocolVersion = (int)SslProtocols.None;
}
- else
- {
- throw new ArgumentException(StringsHelper.Format(StringsHelper.net_invalid_enum, nameof(NativeProtocols)), nameof(NativeProtocols));
- }
return returnValue;
}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs
index b28c736977..abbfda7ede 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs
@@ -89,7 +89,7 @@ internal static class SNINativeManagedWrapperX64
internal static extern uint SNIGetInfoWrapper([In] SNIHandle pConn, SNINativeMethodWrapper.QTypes QType, out ProviderEnum provNum);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIInitialize")]
- internal static extern uint SNIInitialize([In] IntPtr pmo);
+ internal static extern uint SNIInitialize([In] bool useSystemDefaultSecureProtocols, [In] IntPtr pmo);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
internal static extern uint SNIOpenSyncExWrapper(ref SNI_CLIENT_CONSUMER_INFO pClientConsumerInfo, out IntPtr ppConn);
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs
index 2dc215ad36..b700e4b108 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs
@@ -89,7 +89,7 @@ internal static class SNINativeManagedWrapperX86
internal static extern uint SNIGetInfoWrapper([In] SNIHandle pConn, SNINativeMethodWrapper.QTypes QType, out ProviderEnum provNum);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIInitialize")]
- internal static extern uint SNIInitialize([In] IntPtr pmo);
+ internal static extern uint SNIInitialize([In] bool useSystemDefaultSecureProtocols, [In] IntPtr pmo);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
internal static extern uint SNIOpenSyncExWrapper(ref SNI_CLIENT_CONSUMER_INFO pClientConsumerInfo, out IntPtr ppConn);
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs
index 19dd12587a..d1fb0ad3e5 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs
@@ -585,11 +585,11 @@ private static uint SNIGetInfoWrapper([In] SNIHandle pConn, SNINativeMethodWrapp
SNINativeManagedWrapperX86.SNIGetInfoWrapper(pConn, QType, out provNum);
}
- private static uint SNIInitialize([In] IntPtr pmo)
+ private static uint SNIInitialize([In] bool useSystemDefaultSecureProtocols, [In] IntPtr pmo)
{
return s_is64bitProcess ?
- SNINativeManagedWrapperX64.SNIInitialize(pmo) :
- SNINativeManagedWrapperX86.SNIInitialize(pmo);
+ SNINativeManagedWrapperX64.SNIInitialize(useSystemDefaultSecureProtocols, pmo) :
+ SNINativeManagedWrapperX86.SNIInitialize(useSystemDefaultSecureProtocols, pmo);
}
private static uint SNIOpenSyncExWrapper(ref SNI_CLIENT_CONSUMER_INFO pClientConsumerInfo, out IntPtr ppConn)
@@ -757,7 +757,7 @@ internal static uint SniGetConnectionIPString(SNIHandle pConn, ref string connIP
internal static uint SNIInitialize()
{
- return SNIInitialize(IntPtr.Zero);
+ return SNIInitialize(LocalAppContextSwitches.UseSystemDefaultSecureProtocols, IntPtr.Zero);
}
internal static unsafe uint SNIOpenMarsSession(ConsumerInfo consumerInfo, SNIHandle parent, ref IntPtr pConn, bool fSync, SqlConnectionIPAddressPreference ipPreference, SQLDNSInfo cachedDNSInfo)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
index 9d2111ac24..c0947e5854 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs
@@ -13,11 +13,13 @@ internal static partial class LocalAppContextSwitches
private const string TypeName = nameof(LocalAppContextSwitches);
internal const string MakeReadAsyncBlockingString = @"Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking";
internal const string LegacyRowVersionNullString = @"Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior";
+ internal const string UseSystemDefaultSecureProtocolsString = @"Switch.Microsoft.Data.SqlClient.UseSystemDefaultSecureProtocols";
// safety switch
internal const string EnableRetryLogicSwitch = "Switch.Microsoft.Data.SqlClient.EnableRetryLogic";
private static bool _makeReadAsyncBlocking;
private static bool? s_LegacyRowVersionNullBehavior;
+ private static bool? s_UseSystemDefaultSecureProtocols;
private static bool? s_isRetryEnabled = null;
#if !NETFRAMEWORK
@@ -70,15 +72,29 @@ public static bool LegacyRowVersionNullBehavior
{
if (s_LegacyRowVersionNullBehavior is null)
{
- bool value = false;
- if (AppContext.TryGetSwitch(LegacyRowVersionNullString, out bool providedValue))
- {
- value = providedValue;
- }
- s_LegacyRowVersionNullBehavior = value;
+ bool result;
+ result = AppContext.TryGetSwitch(LegacyRowVersionNullString, out result) ? result : false;
+ s_LegacyRowVersionNullBehavior = result;
}
return s_LegacyRowVersionNullBehavior.Value;
}
}
+
+ ///
+ /// For backward compatibility, this switch can be on to jump back on OS preferences.
+ ///
+ public static bool UseSystemDefaultSecureProtocols
+ {
+ get
+ {
+ if (s_UseSystemDefaultSecureProtocols is null)
+ {
+ bool result;
+ result = AppContext.TryGetSwitch(UseSystemDefaultSecureProtocolsString, out result) ? result : false;
+ s_UseSystemDefaultSecureProtocols = result;
+ }
+ return s_UseSystemDefaultSecureProtocols.Value;
+ }
+ }
}
}