Skip to content

Commit 2a3c83f

Browse files
committed
Add explicit handling of SNI-layer SSL protocols
This guards against future changes to the SslProtocols enum
1 parent 1e195f6 commit 2a3c83f

File tree

11 files changed

+102
-21
lines changed

11 files changed

+102
-21
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,9 @@
928928
<Compile Include="$(CommonSourceRoot)\Interop\Windows\Sni\SniNativeWrapper.cs">
929929
<Link>Interop\Windows\Sni\SniNativeWrapper.cs</Link>
930930
</Compile>
931+
<Compile Include="$(CommonSourceRoot)\Interop\Windows\Sni\SniSslProtocols.cs">
932+
<Link>Interop\Windows\Sni\SniSslProtocols.cs</Link>
933+
</Compile>
931934
<Compile Include="$(CommonSourceRoot)\Interop\Windows\Sni\TransparentNetworkResolutionMode.cs">
932935
<Link>Interop\Windows\Sni\TransparentNetworkResolutionMode.cs</Link>
933936
</Compile>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@
219219
<Compile Include="$(CommonSourceRoot)\Interop\Windows\Sni\SqlDependencyProcessDispatcherStorage.netfx.cs">
220220
<Link>Interop\Windows\Sni\SqlDependencyProcessDispatcherStorage.netfx.cs</Link>
221221
</Compile>
222+
<Compile Include="$(CommonSourceRoot)\Interop\Windows\Sni\SniSslProtocols.cs">
223+
<Link>Interop\Windows\Sni\SniSslProtocols.cs</Link>
224+
</Compile>
222225
<Compile Include="$(CommonSourceRoot)\Interop\Windows\Sni\TransparentNetworkResolutionMode.cs">
223226
<Link>Interop\Windows\Sni\TransparentNetworkResolutionMode.cs</Link>
224227
</Compile>

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/ISniNativeMethods.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ unsafe uint SniSecGenClientContextWrapper(
9292

9393
uint SniTerminate();
9494

95-
uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out uint pProtocolVersion);
95+
uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out SniSslProtocols pProtocolVersion);
9696

9797
uint SniWriteAsyncWrapper(SNIHandle pConn, SNIPacket pPacket);
9898

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeMethods.netcore.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public uint SniSetInfo(SNIHandle pConn, QueryType queryType, ref uint pbQueryInf
148148
public uint SniTerminate() =>
149149
SNITerminate();
150150

151-
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out uint pProtocolVersion) =>
151+
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out SniSslProtocols pProtocolVersion) =>
152152
SNIWaitForSSLHandshakeToCompleteWrapper(pConn, dwMilliseconds, out pProtocolVersion);
153153

154154
public uint SniWriteAsyncWrapper(SNIHandle pConn, SNIPacket pPacket) =>
@@ -299,7 +299,7 @@ private static extern int SNIServerEnumReadWrapper(
299299
private static extern uint SNIWaitForSSLHandshakeToCompleteWrapper(
300300
[In] SNIHandle pConn,
301301
int dwMilliseconds,
302-
out uint pProtocolVersion);
302+
out SniSslProtocols pProtocolVersion);
303303

304304
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
305305
private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacket pPacket);

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeMethodsArm64.netfx.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public uint SniSetInfo(SNIHandle pConn, QueryType queryType, ref uint pbQueryInf
148148
public uint SniTerminate() =>
149149
SNITerminate();
150150

151-
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out uint pProtocolVersion) =>
151+
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out SniSslProtocols pProtocolVersion) =>
152152
SNIWaitForSSLHandshakeToCompleteWrapper(pConn, dwMilliseconds, out pProtocolVersion);
153153

154154
public uint SniWriteAsyncWrapper(SNIHandle pConn, SNIPacket pPacket) =>
@@ -299,7 +299,7 @@ private static extern int SNIServerEnumReadWrapper(
299299
private static extern uint SNIWaitForSSLHandshakeToCompleteWrapper(
300300
[In] SNIHandle pConn,
301301
int dwMilliseconds,
302-
out uint pProtocolVersion);
302+
out SniSslProtocols pProtocolVersion);
303303

304304
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
305305
private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacket pPacket);

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeMethodsNotSupported.netfx.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public uint SniSetInfo(SNIHandle pConn, QueryType queryType, ref uint pbQueryInf
142142
public uint SniTerminate() =>
143143
throw ADP.SNIPlatformNotSupported(_architecture);
144144

145-
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out uint pProtocolVersion) =>
145+
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out SniSslProtocols pProtocolVersion) =>
146146
throw ADP.SNIPlatformNotSupported(_architecture);
147147

148148
public uint SniWriteAsyncWrapper(SNIHandle pConn, SNIPacket pPacket) =>

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeMethodsX64.netfx.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public uint SniSetInfo(SNIHandle pConn, QueryType queryType, ref uint pbQueryInf
148148
public uint SniTerminate() =>
149149
SNITerminate();
150150

151-
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out uint pProtocolVersion) =>
151+
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out SniSslProtocols pProtocolVersion) =>
152152
SNIWaitForSSLHandshakeToCompleteWrapper(pConn, dwMilliseconds, out pProtocolVersion);
153153

154154
public uint SniWriteAsyncWrapper(SNIHandle pConn, SNIPacket pPacket) =>
@@ -299,7 +299,7 @@ private static extern int SNIServerEnumReadWrapper(
299299
private static extern uint SNIWaitForSSLHandshakeToCompleteWrapper(
300300
[In] SNIHandle pConn,
301301
int dwMilliseconds,
302-
out uint pProtocolVersion);
302+
out SniSslProtocols pProtocolVersion);
303303

304304
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
305305
private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacket pPacket);

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeMethodsX86.netfx.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public uint SniSetInfo(SNIHandle pConn, QueryType queryType, ref uint pbQueryInf
148148
public uint SniTerminate() =>
149149
SNITerminate();
150150

151-
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out uint pProtocolVersion) =>
151+
public uint SniWaitForSslHandshakeToComplete(SNIHandle pConn, int dwMilliseconds, out SniSslProtocols pProtocolVersion) =>
152152
SNIWaitForSSLHandshakeToCompleteWrapper(pConn, dwMilliseconds, out pProtocolVersion);
153153

154154
public uint SniWriteAsyncWrapper(SNIHandle pConn, SNIPacket pPacket) =>
@@ -299,7 +299,7 @@ private static extern int SNIServerEnumReadWrapper(
299299
private static extern uint SNIWaitForSSLHandshakeToCompleteWrapper(
300300
[In] SNIHandle pConn,
301301
int dwMilliseconds,
302-
out uint pProtocolVersion);
302+
out SniSslProtocols pProtocolVersion);
303303

304304
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
305305
private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacket pPacket);

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeWrapper.cs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,19 +376,67 @@ internal static uint SniSetInfo(SNIHandle pConn, QueryType qType, ref uint pbQIn
376376

377377
internal static uint SniTerminate() =>
378378
s_nativeMethods.SniTerminate();
379-
379+
380380
internal static uint SniWaitForSslHandshakeToComplete(
381381
SNIHandle pConn,
382382
int dwMilliseconds,
383-
out uint pProtocolVersion) =>
384-
s_nativeMethods.SniWaitForSslHandshakeToComplete(pConn, dwMilliseconds, out pProtocolVersion);
383+
out System.Security.Authentication.SslProtocols pProtocolVersion)
384+
{
385+
uint returnValue = s_nativeMethods.SniWaitForSslHandshakeToComplete(pConn, dwMilliseconds, out SniSslProtocols nativeProtocolVersion);
386+
387+
#pragma warning disable CA5398 // Avoid hardcoded SslProtocols values
388+
if ((nativeProtocolVersion & SniSslProtocols.SP_PROT_TLS1_2) != 0)
389+
{
390+
pProtocolVersion = System.Security.Authentication.SslProtocols.Tls12;
391+
}
392+
else if ((nativeProtocolVersion & SniSslProtocols.SP_PROT_TLS1_3) != 0)
393+
{
394+
#if NET
395+
pProtocolVersion = System.Security.Authentication.SslProtocols.Tls13;
396+
#else
397+
// Only .NET Core supports SslProtocols.Tls13
398+
pProtocolVersion = (System.Security.Authentication.SslProtocols)0x3000;
399+
#endif
400+
}
401+
else if ((nativeProtocolVersion & SniSslProtocols.SP_PROT_TLS1_1) != 0)
402+
{
403+
#if NET8_0_OR_GREATER
404+
#pragma warning disable SYSLIB0039 // Type or member is obsolete: TLS 1.0 & 1.1 are deprecated
405+
#endif
406+
pProtocolVersion = System.Security.Authentication.SslProtocols.Tls11;
407+
}
408+
else if ((nativeProtocolVersion & SniSslProtocols.SP_PROT_TLS1_0) != 0)
409+
{
410+
pProtocolVersion = System.Security.Authentication.SslProtocols.Tls;
411+
#if NET8_0_OR_GREATER
412+
#pragma warning restore SYSLIB0039 // Type or member is obsolete: SSL and TLS 1.0 & 1.1 is deprecated
413+
#endif
414+
}
415+
else if ((nativeProtocolVersion & SniSslProtocols.SP_PROT_SSL3) != 0)
416+
{
417+
// SSL 2.0 and 3.0 are only referenced to log a warning, not explicitly used for connections
418+
#pragma warning disable CS0618, CA5397
419+
pProtocolVersion = System.Security.Authentication.SslProtocols.Ssl3;
420+
}
421+
else if ((nativeProtocolVersion & SniSslProtocols.SP_PROT_SSL2) != 0)
422+
{
423+
pProtocolVersion = System.Security.Authentication.SslProtocols.Ssl2;
424+
#pragma warning restore CS0618, CA5397
425+
}
426+
else
427+
{
428+
pProtocolVersion = System.Security.Authentication.SslProtocols.None;
429+
}
430+
#pragma warning restore CA5398 // Avoid hardcoded SslProtocols values
431+
return returnValue;
432+
}
385433

386434
internal static uint SniWritePacket(SNIHandle pConn, SNIPacket packet, bool sync) =>
387435
sync
388436
? s_nativeMethods.SniWriteSyncOverAsync(pConn, packet)
389437
: s_nativeMethods.SniWriteAsyncWrapper(pConn, packet);
390438

391-
#endregion
439+
#endregion
392440

393441
#region Private Methods
394442

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace Interop.Windows.Sni
6+
{
7+
internal enum SniSslProtocols : uint
8+
{
9+
// Protocol versions from native SNI
10+
SP_PROT_SSL2_SERVER = 0x00000004,
11+
SP_PROT_SSL2_CLIENT = 0x00000008,
12+
SP_PROT_SSL3_SERVER = 0x00000010,
13+
SP_PROT_SSL3_CLIENT = 0x00000020,
14+
SP_PROT_TLS1_0_SERVER = 0x00000040,
15+
SP_PROT_TLS1_0_CLIENT = 0x00000080,
16+
SP_PROT_TLS1_1_SERVER = 0x00000100,
17+
SP_PROT_TLS1_1_CLIENT = 0x00000200,
18+
SP_PROT_TLS1_2_SERVER = 0x00000400,
19+
SP_PROT_TLS1_2_CLIENT = 0x00000800,
20+
SP_PROT_TLS1_3_SERVER = 0x00001000,
21+
SP_PROT_TLS1_3_CLIENT = 0x00002000,
22+
SP_PROT_NONE = 0x0,
23+
24+
// Combinations for easier use when mapping to SslProtocols
25+
SP_PROT_SSL2 = SP_PROT_SSL2_SERVER | SP_PROT_SSL2_CLIENT,
26+
SP_PROT_SSL3 = SP_PROT_SSL3_SERVER | SP_PROT_SSL3_CLIENT,
27+
SP_PROT_TLS1_0 = SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_0_CLIENT,
28+
SP_PROT_TLS1_1 = SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT,
29+
SP_PROT_TLS1_2 = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_CLIENT,
30+
SP_PROT_TLS1_3 = SP_PROT_TLS1_3_SERVER | SP_PROT_TLS1_3_CLIENT,
31+
}
32+
}

0 commit comments

Comments
 (0)