Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge recent updates to the PR in TDS8 #2

Merged
merged 4 commits into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
<members name="SqlConnectionEncryptionOption">
<SqlConnectionEncryptionOption>
<summary>

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>.
These options are used to control encryption behavior of the communication between the server and the client.</see>.
</summary>
<remarks>To be added.</remarks>
</SqlConnectionEncryptionOption>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Data.SqlClient.SNI
{
Expand All @@ -15,13 +20,29 @@ internal abstract class SNIHandle
/// <summary>
/// Exclude TLS 1.3 (not fully supported).
/// </summary>
protected readonly SslProtocols SupportedProtocols = LocalAppContextSwitches.UseSystemDefaultSecureProtocols ? SslProtocols.None : SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
protected static readonly SslProtocols s_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
;

#if !NETSTANDARD2_0
protected static readonly List<SslApplicationProtocol> s_tdsProtocols = new List<SslApplicationProtocol>(7) { new(TdsEnums.TDS8_Protocol) };

protected static async Task AuthenticateClientAsync(SslStream sslStream, string serverNameIndication, X509CertificateCollection certificate)
{
SslClientAuthenticationOptions sslClientOptions = new()
{
TargetHost = serverNameIndication,
ApplicationProtocols = s_tdsProtocols,
EnabledSslProtocols = s_supportedProtocols,
ClientCertificates = certificate
};
await sslStream.AuthenticateAsClientAsync(sslClientOptions, CancellationToken.None);
}
#endif

/// <summary>
/// Dispose class
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Pipes;
Expand Down Expand Up @@ -324,22 +323,13 @@ public override uint EnableSsl(uint options)
{
if (_isTDS8)
{
#if NETCOREAPP
SslApplicationProtocol TDS8 = new("tds/8.0");

SslClientAuthenticationOptions sslClientOptions = new()
{
TargetHost = _serverNameIndication,
ApplicationProtocols = new List<SslApplicationProtocol>() { TDS8 },
EnabledSslProtocols = SupportedProtocols,
ClientCertificates = null,
};
_sslStream.AuthenticateAsClientAsync(sslClientOptions).Wait();
#if !NETSTANDARD2_0
AuthenticateClientAsync(_sslStream, _serverNameIndication, null);
#endif
}
else
{
_sslStream.AuthenticateAsClient(_targetServer, null, SupportedProtocols, false);
_sslStream.AuthenticateAsClient(_targetServer, null, s_supportedProtocols, false);
}
if (_sslOverTdsStream is not null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Microsoft.Data.SqlClient.SNI
internal abstract class SNIPhysicalHandle : SNIHandle
{
protected const int DefaultPoolSize = 4;

#if DEBUG
private static int s_packetId;
#endif
Expand Down Expand Up @@ -84,7 +85,7 @@ private string GetStackParts()
{
return string.Join(Environment.NewLine,
Environment.StackTrace
.Split(new string[] { Environment.NewLine },StringSplitOptions.None)
.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)
.Skip(3) // trims off the common parts at the top of the stack so you can see what the actual caller was
.Take(7) // trims off most of the bottom of the stack because when running under xunit there's a lot of spam
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ internal class SNIProxy
{
private const int DefaultSqlServerPort = 1433;
private const int DefaultSqlServerDacPort = 1434;
private const int DefaultSqlServerTDS8Port = 4433;
private const string SqlServerSpnHeader = "MSSQLSvc";
private const string TDS8SNIServerKey = "Server";
private const string TDS8SNIInstanceKey = "Instance";
Expand Down Expand Up @@ -336,7 +335,7 @@ private static SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire
}
else
{
port = isAdminConnection ? DefaultSqlServerDacPort : (isTDS8 ? DefaultSqlServerTDS8Port : DefaultSqlServerPort);
port = isAdminConnection ? DefaultSqlServerDacPort : DefaultSqlServerPort;
}

return new SNITCPHandle(hostName, port, timerExpire, parallel, ipPreference, cachedFQDN, ref pendingDNSInfo, isTDS8, hostNameInCertificate, serverNameIndication);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ internal sealed class SNITCPHandle : SNIPhysicalHandle
private readonly Socket _socket;
private NetworkStream _tcpStream;
private readonly string _hostNameInCertificate;
private readonly bool _isTDSS;
private readonly string _serverIndicationName;
private readonly bool _isTDS8;
private readonly string _serverNameIndication;

private Stream _stream;
private SslStream _sslStream;
Expand Down Expand Up @@ -121,19 +121,19 @@ public override int ProtocolVersion
/// <param name="ipPreference">IP address preference</param>
/// <param name="cachedFQDN">Key for DNS Cache</param>
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
/// <param name="isTDSS">Support TDS8.0</param>
/// <param name="isTDS8">Support TDS8.0</param>
/// <param name="hostNameInCertificate">Host Name in Certoficate</param>
/// <param name="serverNameIndication"></param>
public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isTDSS, string hostNameInCertificate, string serverNameIndication)
public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isTDS8, string hostNameInCertificate, string serverNameIndication)
{
using (TrySNIEventScope.Create(nameof(SNITCPHandle)))
{
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Setting server name = {1}", args0: _connectionId, args1: serverName);

_targetServer = serverName;
_isTDSS = isTDSS;
_isTDS8 = isTDS8;
_hostNameInCertificate = hostNameInCertificate;
_serverIndicationName = serverNameIndication;
_serverNameIndication = serverNameIndication;
_sendSync = new object();

SQLDNSInfo cachedDNSInfo;
Expand Down Expand Up @@ -259,7 +259,7 @@ public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel
_tcpStream = new SNINetworkStream(_socket, true);

Stream stream = _tcpStream;
if (!_isTDSS)
if (!_isTDS8)
{
_sslOverTdsStream = new SslOverTdsStream(_tcpStream, _connectionId);
stream = _sslOverTdsStream;
Expand Down Expand Up @@ -598,23 +598,15 @@ public override uint EnableSsl(uint options)

try
{
if (_isTDSS)
if (_isTDS8)
{
#if NETCOREAPP

SslClientAuthenticationOptions sslClientOptions = new()
{
TargetHost = _serverIndicationName,
ApplicationProtocols = new List<SslApplicationProtocol>() { new(TdsEnums.TDS8) },
EnabledSslProtocols = SupportedProtocols,
ClientCertificates = null,
};
_sslStream.AuthenticateAsClientAsync(sslClientOptions).Wait();
#if !NETSTANDARD2_0
AuthenticateClientAsync(_sslStream, _serverNameIndication, null).Wait();
#endif
}
else
{
_sslStream.AuthenticateAsClient(_serverIndicationName, null, SupportedProtocols, false);
_sslStream.AuthenticateAsClient(_serverNameIndication, null, s_supportedProtocols, false);
}
if (_sslOverTdsStream is not null)
{
Expand Down Expand Up @@ -676,7 +668,7 @@ private bool ValidateServerCertificate(object sender, X509Certificate cert, X509
}
else
{
serverNameToValidate = _hostNameInCertificate;
serverNameToValidate = _targetServer;
}

SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Certificate will be validated for Target Server name", args0: _connectionId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ internal void Connect(
SqlClientEventSource.Log.TryTraceEvent("TdsParser.Connect | SEC | SSPI or Active Directory Authentication Library loaded for SQL Server based integrated authentication");
}

// if Strict encryotion is chosen TDS8 should be used and trust server certificate should be false.
// if Strict encryption is chosen TDS8 should be used and trust server certificate should be false.
if (encrypt == SqlConnectionEncryptionOption.Strict)
{
isTDS8 = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ internal void Connect(ServerInfo serverInfo,

// UNDONE - send "" for instance now, need to fix later
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> Sending prelogin handshake");
SendPreLoginHandshake(instanceName, encrypt, isTDS8!, string.IsNullOrEmpty(certificate), useOriginalAddressInfo);
SendPreLoginHandshake(instanceName, encrypt, isTDS8, !string.IsNullOrEmpty(certificate), useOriginalAddressInfo);

_connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);
_connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
Expand Down Expand Up @@ -1257,7 +1257,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake(SqlAuthenticationMethod
// NOT_SUP: No encryption.
break;

case (EncryptionOptions.Strict):
case (EncryptionOptions.STRICT):
if ((serverOption & EncryptionOptions.OPTIONS_MASK) == EncryptionOptions.REQ)
{
_physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByClient(), "", 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ internal enum EncryptionOptions
NOT_SUP,
REQ,
LOGIN,
Strict, //TDS8
STRICT, //TDS8
OPTIONS_MASK = 0x3f,
CTAIP = 0x40,
CLIENT_CERT = 0x80,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ public enum ActiveDirectoryWorkflow : byte
public const int SQL2005_MAJOR = 0x72; // the high-byte is sufficient to distinguish later versions
public const int SQL2008_MAJOR = 0x73;
public const int SQL2012_MAJOR = 0x74;
public const string TDS8 = "tds/8.0"; //TDS8
public const string TDS8_Protocol = "tds/8.0"; //TDS8

// Increments:
public const int SQL2000SP1_INCREMENT = 0x00;
Expand Down Expand Up @@ -1121,7 +1121,7 @@ public enum SqlConnectionAttestationProtocol
public enum SqlConnectionEncryptionOption
{
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/Optional/*' />
Optional =0,
Optional = 0,
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/Mandatory/*' />
Mandatory = 1,
/// <include file='../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptionOption.xml' path='docs/members[@name="SqlConnectionEncryptionOption"]/Strict/*' />
Expand Down