Skip to content

Commit c53a868

Browse files
committed
Adding TDS8 support to netcore
1 parent a6625b3 commit c53a868

25 files changed

+687
-160
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0"?>
2+
<docs>
3+
<members name="SqlConnectionEncryptionOption">
4+
<SqlConnectionEncryptionOption>
5+
<summary>
6+
Note that these settings cannot be used to bypass encryption and gain access to plaintext data. For details, see <see href="https://docs.microsoft.com/sql/relational-databases/security/encryption/always-encrypted-database-engine">Always Encrypted (Database Engine)</see>.
7+
</summary>
8+
<remarks>To be added.</remarks>
9+
</SqlConnectionEncryptionOption>
10+
<False>
11+
<summary>Specifies the connection does not use Always Encrypted. Should be used if no queries sent over the connection access encrypted columns.</summary>
12+
</False>
13+
<No>
14+
<summary>Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted.</summary>
15+
</No>
16+
<Optional>
17+
<summary>Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted.</summary>
18+
</Optional>
19+
<True>
20+
<summary>Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted.</summary>
21+
</True>
22+
<Mandatory>
23+
<summary>Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted.</summary>
24+
</Mandatory>
25+
<Strict>
26+
<summary>Enables Always Encrypted functionality for the connection. Query parameters that correspond to encrypted columns will be transparently encrypted and query results from encrypted columns will be transparently decrypted.</summary>
27+
</Strict>
28+
</members>
29+
</docs>

src/Microsoft.Data.SqlClient.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient",
120120
..\doc\snippets\Microsoft.Data.SqlClient\SqlConnection.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnection.xml
121121
..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml
122122
..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml
123+
SqlConnectionEncryptionOption.xml = SqlConnectionEncryptionOption.xml
123124
..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml
124125
..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml
125126
..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml
@@ -204,6 +205,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4F3CD363-B1E
204205
EndProject
205206
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlServer.Server", "Microsoft.SqlServer.Server\Microsoft.SqlServer.Server.csproj", "{A314812A-7820-4565-A2A8-ABBE391C11E4}"
206207
EndProject
208+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestTDSS", "..\TestTDSS\TestTDSS.csproj", "{78129850-6C89-471C-884A-CEDB48A1B15F}"
209+
EndProject
207210
Global
208211
GlobalSection(SolutionConfigurationPlatforms) = preSolution
209212
Debug|Any CPU = Debug|Any CPU
@@ -488,6 +491,18 @@ Global
488491
{A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x64.Build.0 = Release|Any CPU
489492
{A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x86.ActiveCfg = Release|Any CPU
490493
{A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x86.Build.0 = Release|Any CPU
494+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
495+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Debug|Any CPU.Build.0 = Debug|Any CPU
496+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Debug|x64.ActiveCfg = Debug|Any CPU
497+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Debug|x64.Build.0 = Debug|Any CPU
498+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Debug|x86.ActiveCfg = Debug|Any CPU
499+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Debug|x86.Build.0 = Debug|Any CPU
500+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Release|Any CPU.ActiveCfg = Release|Any CPU
501+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Release|Any CPU.Build.0 = Release|Any CPU
502+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Release|x64.ActiveCfg = Release|Any CPU
503+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Release|x64.Build.0 = Release|Any CPU
504+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Release|x86.ActiveCfg = Release|Any CPU
505+
{78129850-6C89-471C-884A-CEDB48A1B15F}.Release|x86.Build.0 = Release|Any CPU
491506
EndGlobalSection
492507
GlobalSection(SolutionProperties) = preSolution
493508
HideSolutionNode = FALSE

src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ public void Remove(SqlBulkCopyColumnOrderHint columnOrderHint) { }
383383
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyColumnOrderHintCollection.xml' path='docs/members[@name="SqlBulkCopyColumnOrderHintCollection"]/RemoveAt/*'/>
384384
public new void RemoveAt(int index) { }
385385
}
386+
387+
386388
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlBulkCopyOptions.xml' path='docs/members[@name="SqlBulkCopyOptions"]/SqlBulkCopyOptions/*'/>
387389
[System.FlagsAttribute]
388390
public enum SqlBulkCopyOptions
@@ -500,6 +502,17 @@ public enum SqlConnectionIPAddressPreference
500502
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionIPAddressPreference.xml' path='docs/members[@name="SqlConnectionIPAddressPreference"]/UsePlatformDefault/*' />
501503
UsePlatformDefault = 2
502504
}
505+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/SqlConnectionEncryptionOption/*'/>
506+
public enum SqlConnectionEncryptionOption
507+
{
508+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/Optional/*' />
509+
Optional = 0,
510+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/Mandatory/*' />
511+
Mandatory = 1,
512+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/Strict/*' />
513+
Strict =2
514+
}
515+
503516
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlColumnEncryptionCertificateStoreProvider.xml' path='docs/members[@name="SqlColumnEncryptionCertificateStoreProvider"]/SqlColumnEncryptionCertificateStoreProvider/*'/>
504517
public partial class SqlColumnEncryptionCertificateStoreProvider : Microsoft.Data.SqlClient.SqlColumnEncryptionKeyStoreProvider
505518
{
@@ -994,7 +1007,15 @@ public SqlConnectionStringBuilder(string connectionString) { }
9941007
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/Encrypt/*'/>
9951008
[System.ComponentModel.DisplayNameAttribute("Encrypt")]
9961009
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
997-
public bool Encrypt { get { throw null; } set { } }
1010+
public SqlConnectionEncryptionOption Encrypt { get { throw null; } set { } }
1011+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/IsTDS8/*'/>
1012+
[System.ComponentModel.DisplayNameAttribute("IsTDS8")]
1013+
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
1014+
public bool IsTDS8 { get { throw null; } set { } }
1015+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/HostNameInCertificate/*'/>
1016+
[System.ComponentModel.DisplayNameAttribute("Host Name In Certificate")]
1017+
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]
1018+
public string HostNameInCertificate { get { throw null; } set { } }
9981019
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/Enlist/*'/>
9991020
[System.ComponentModel.DisplayNameAttribute("Enlist")]
10001021
[System.ComponentModel.RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties.All)]

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Collections.Generic;
67
using System.ComponentModel;
78
using System.IO;
89
using System.IO.Pipes;
@@ -22,7 +23,9 @@ internal sealed class SNINpHandle : SNIPhysicalHandle
2223
// private const int MAX_PIPE_INSTANCES = 255; // TODO: Investigate pipe instance limit.
2324

2425
private readonly string _targetServer;
26+
private readonly string _serverNameIndication;
2527
private readonly object _sendSync;
28+
private readonly bool _isTDS8;
2629

2730
private Stream _stream;
2831
private NamedPipeClientStream _pipeStream;
@@ -37,14 +40,16 @@ internal sealed class SNINpHandle : SNIPhysicalHandle
3740
private int _bufferSize = TdsEnums.DEFAULT_LOGIN_PACKET_SIZE;
3841
private readonly Guid _connectionId = Guid.NewGuid();
3942

40-
public SNINpHandle(string serverName, string pipeName, long timerExpire)
43+
public SNINpHandle(string serverName, string pipeName, long timerExpire, bool isTDS8, string serverNameIndication)
4144
{
4245
using (TrySNIEventScope.Create(nameof(SNINpHandle)))
4346
{
4447
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Setting server name = {1}, pipe name = {2}", args0: _connectionId, args1: serverName, args2: pipeName);
4548

4649
_sendSync = new object();
4750
_targetServer = serverName;
51+
_isTDS8 = isTDS8;
52+
_serverNameIndication = serverNameIndication;
4853

4954
try
5055
{
@@ -90,8 +95,14 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire)
9095
return;
9196
}
9297

93-
_sslOverTdsStream = new SslOverTdsStream(_pipeStream, _connectionId);
94-
_sslStream = new SNISslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate));
98+
Stream stream = _pipeStream;
99+
100+
if (!_isTDS8)
101+
{
102+
_sslOverTdsStream = new SslOverTdsStream(_pipeStream, _connectionId);
103+
stream = _sslOverTdsStream;
104+
}
105+
_sslStream = new SNISslStream(stream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate));
95106

96107
_stream = _pipeStream;
97108
_status = TdsEnums.SNI_SUCCESS;
@@ -312,8 +323,29 @@ public override uint EnableSsl(uint options)
312323
_validateCert = (options & TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE) != 0;
313324
try
314325
{
315-
_sslStream.AuthenticateAsClient(_targetServer, null, SupportedProtocols, false);
316-
_sslOverTdsStream.FinishHandshake();
326+
if (_isTDS8)
327+
{
328+
#if NETCOREAPP
329+
SslApplicationProtocol TDS8 = new("tds/8.0");
330+
331+
SslClientAuthenticationOptions sslClientOptions = new()
332+
{
333+
TargetHost = _serverNameIndication,
334+
ApplicationProtocols = new List<SslApplicationProtocol>() { TDS8 },
335+
EnabledSslProtocols = SupportedProtocols,
336+
ClientCertificates = null,
337+
};
338+
_sslStream.AuthenticateAsClientAsync(sslClientOptions).Wait();
339+
#endif
340+
}
341+
else
342+
{
343+
_sslStream.AuthenticateAsClient(_targetServer, null, SupportedProtocols, false);
344+
}
345+
if (_sslOverTdsStream is not null)
346+
{
347+
_sslOverTdsStream.FinishHandshake();
348+
}
317349
}
318350
catch (AuthenticationException aue)
319351
{
@@ -334,8 +366,11 @@ public override void DisableSsl()
334366
{
335367
_sslStream.Dispose();
336368
_sslStream = null;
337-
_sslOverTdsStream.Dispose();
338-
_sslOverTdsStream = null;
369+
if (_sslOverTdsStream is not null)
370+
{
371+
_sslOverTdsStream.Dispose();
372+
_sslOverTdsStream = null;
373+
}
339374

340375
_stream = _pipeStream;
341376
}

0 commit comments

Comments
 (0)