Skip to content

Commit

Permalink
Fix down-level SSL/TLS version warnings (#3126)
Browse files Browse the repository at this point in the history
* Added test for downlevel connectivity warning

* Correctly test bit flags for legacy SSL protocol warning

* Corrected warning disablement/restore.

(cherry picked from commit 198b906)
  • Loading branch information
edwardneal authored and benrr101 committed Jan 21, 2025
1 parent 955ac52 commit d92016b
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -768,30 +768,30 @@ private static string ToFriendlyName(this SslProtocols protocol)
name = "TLS 1.3";
}*/
#pragma warning disable CA5398 // Avoid hardcoded SslProtocols values
if ((protocol & SslProtocols.Tls12) == SslProtocols.Tls12)
if ((protocol & SslProtocols.Tls12) != SslProtocols.None)
{
name = "TLS 1.2";
}
#if NET
#pragma warning disable SYSLIB0039 // Type or member is obsolete: TLS 1.0 & 1.1 are deprecated
#endif
else if ((protocol & SslProtocols.Tls11) == SslProtocols.Tls11)
else if ((protocol & SslProtocols.Tls11) != SslProtocols.None)
{
name = "TLS 1.1";
}
else if ((protocol & SslProtocols.Tls) == SslProtocols.Tls)
else if ((protocol & SslProtocols.Tls) != SslProtocols.None)
{
name = "TLS 1.0";
}
#if NET
#pragma warning restore SYSLIB0039 // Type or member is obsolete: SSL and TLS 1.0 & 1.1 is deprecated
#endif
#pragma warning disable CS0618 // Type or member is obsolete: SSL is deprecated
else if ((protocol & SslProtocols.Ssl3) == SslProtocols.Ssl3)
else if ((protocol & SslProtocols.Ssl3) != SslProtocols.None)
{
name = "SSL 3.0";
}
else if ((protocol & SslProtocols.Ssl2) == SslProtocols.Ssl2)
else if ((protocol & SslProtocols.Ssl2) != SslProtocols.None)
#pragma warning restore CS0618 // Type or member is obsolete: SSL and TLS 1.0 & 1.1 is deprecated
{
name = "SSL 2.0";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SqlServer.TDS.PreLogin;
Expand All @@ -26,15 +27,21 @@ public class ConnectionTestParameters
public string HostNameInCertificate => _hnic;
public bool TestResult => _result;
public TDSPreLoginTokenEncryptionType TdsEncryptionType => _encryptionType;
public SslProtocols EncryptionProtocols { get; }

public ConnectionTestParameters(TDSPreLoginTokenEncryptionType tdsEncryptionType, SqlConnectionEncryptOption encryptOption, bool trustServerCert, string cert, string hnic, bool result)
: this(tdsEncryptionType, encryptOption, trustServerCert, cert, hnic, SslProtocols.Tls12, result)
{ }

public ConnectionTestParameters(TDSPreLoginTokenEncryptionType tdsEncryptionType, SqlConnectionEncryptOption encryptOption, bool trustServerCert, string cert, string hnic, SslProtocols sslProtocols, bool result)
{
_encryptionOption = encryptOption;
_trustServerCert = trustServerCert;
_cert = cert;
_hnic = hnic;
_result = result;
_encryptionType = tdsEncryptionType;
EncryptionProtocols = sslProtocols;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

using System.Collections.Generic;
using System.IO;
using System.Security.Authentication;
using Microsoft.SqlServer.TDS.PreLogin;

namespace Microsoft.Data.SqlClient.ManualTesting.Tests.DataCommon
{
public class ConnectionTestParametersData
{
private const int CASES = 30;
private string _empty = string.Empty;
// It was advised to store the client certificate in its own folder.
private static readonly string s_fullPathToCer = Path.Combine(Directory.GetCurrentDirectory(), "clientcert", "localhostcert.cer");
Expand All @@ -22,7 +22,7 @@ public class ConnectionTestParametersData

public static IEnumerable<object[]> GetConnectionTestParameters()
{
for (int i = 0; i < CASES; i++)
for (int i = 0; i < Data.ConnectionTestParametersList.Count; i++)
{
yield return new object[] { Data.ConnectionTestParametersList[i] };
}
Expand All @@ -33,11 +33,11 @@ public ConnectionTestParametersData()
// Test cases possible field values for connection parameters:
// These combinations are based on the possible values of Encrypt, TrustServerCertificate, Certificate, HostNameInCertificate
/*
* TDSEncryption | Encrypt | TrustServerCertificate | Certificate | HNIC | TestResults
* ----------------------------------------------------------------------------------------------
* Off | Optional | true | valid | valid name | true
* On | Mandatory | false | mismatched | empty | false
* Required | | x | ChainError? | wrong name? |
* TDSEncryption | Encrypt | TrustServerCertificate | Certificate | HNIC | SSL Protocols | TestResults
* ---------------------------------------------------------------------------------------------------------------
* Off | Optional | true | valid | valid name | TLS 1.2 | true
* On | Mandatory | false | mismatched | empty | TLS 1.0, TLS 1.1 | false
* Required | | x | ChainError? | wrong name? | |
*/
ConnectionTestParametersList = new List<ConnectionTestParameters>
{
Expand Down Expand Up @@ -79,6 +79,21 @@ public ConnectionTestParametersData()
new(TDSPreLoginTokenEncryptionType.On, SqlConnectionEncryptOption.Mandatory, true, s_mismatchedcert, _empty, true),
new(TDSPreLoginTokenEncryptionType.Required, SqlConnectionEncryptOption.Mandatory, false, s_mismatchedcert, _empty, false),
new(TDSPreLoginTokenEncryptionType.Required, SqlConnectionEncryptOption.Mandatory, true, s_mismatchedcert, _empty, true),

// Multiple SSL protocols test
#pragma warning disable CA5397 // Do not use deprecated SslProtocols values
#pragma warning disable CA5398 // Avoid hardcoded SslProtocols values
#if NET
#pragma warning disable SYSLIB0039 // Type or member is obsolete: TLS 1.0 & 1.1 are deprecated
#endif
new(TDSPreLoginTokenEncryptionType.Off, SqlConnectionEncryptOption.Mandatory, false, s_fullPathToCer, _empty, SslProtocols.Tls | SslProtocols.Tls11, true),
new(TDSPreLoginTokenEncryptionType.On, SqlConnectionEncryptOption.Mandatory, false, s_fullPathToCer, _empty, SslProtocols.Tls | SslProtocols.Tls11, true),
new(TDSPreLoginTokenEncryptionType.Required, SqlConnectionEncryptOption.Mandatory, false, s_fullPathToCer, _empty, SslProtocols.Tls | SslProtocols.Tls11, true),
#if NET
#pragma warning restore SYSLIB0039 // Type or member is obsolete: TLS 1.0 & 1.1 are deprecated
#endif
#pragma warning restore CA5397 // Do not use deprecated SslProtocols values
#pragma warning restore CA5398 // Avoid hardcoded SslProtocols values
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ private void ConnectionTest(ConnectionTestParameters connectionTestParameters)
#else
new X509Certificate2(s_fullPathToPfx, "nopassword", X509KeyStorageFlags.UserKeySet),
#endif
encryptionProtocols: connectionTestParameters.EncryptionProtocols,
encryptionType: connectionTestParameters.TdsEncryptionType);

builder = new(server.ConnectionString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using Microsoft.SqlServer.TDS.EndPoint;
using Microsoft.SqlServer.TDS.PreLogin;
Expand All @@ -31,7 +32,7 @@ public TestTdsServer(QueryEngine engine, TDSServerArguments args) : base(args)

public static TestTdsServer StartServerWithQueryEngine(QueryEngine engine, bool enableFedAuth = false, bool enableLog = false,
int connectionTimeout = DefaultConnectionTimeout, [CallerMemberName] string methodName = "",
X509Certificate2 encryptionCertificate = null, TDSPreLoginTokenEncryptionType encryptionType = TDSPreLoginTokenEncryptionType.NotSupported)
X509Certificate2 encryptionCertificate = null, SslProtocols encryptionProtocols = SslProtocols.Tls12, TDSPreLoginTokenEncryptionType encryptionType = TDSPreLoginTokenEncryptionType.NotSupported)
{
TDSServerArguments args = new TDSServerArguments()
{
Expand All @@ -48,6 +49,7 @@ public static TestTdsServer StartServerWithQueryEngine(QueryEngine engine, bool
args.EncryptionCertificate = encryptionCertificate;
}

args.EncryptionProtocols = encryptionProtocols;
args.Encryption = encryptionType;

TestTdsServer server = engine == null ? new TestTdsServer(args) : new TestTdsServer(engine, args);
Expand Down Expand Up @@ -83,9 +85,9 @@ public static TestTdsServer StartServerWithQueryEngine(QueryEngine engine, bool

public static TestTdsServer StartTestServer(bool enableFedAuth = false, bool enableLog = false,
int connectionTimeout = DefaultConnectionTimeout, [CallerMemberName] string methodName = "",
X509Certificate2 encryptionCertificate = null, TDSPreLoginTokenEncryptionType encryptionType = TDSPreLoginTokenEncryptionType.NotSupported)
X509Certificate2 encryptionCertificate = null, SslProtocols encryptionProtocols = SslProtocols.Tls12, TDSPreLoginTokenEncryptionType encryptionType = TDSPreLoginTokenEncryptionType.NotSupported)
{
return StartServerWithQueryEngine(null, enableFedAuth, enableLog, connectionTimeout, methodName, encryptionCertificate, encryptionType);
return StartServerWithQueryEngine(null, enableFedAuth, enableLog, connectionTimeout, methodName, encryptionCertificate, encryptionProtocols, encryptionType);
}

public void Dispose() => _endpoint?.Stop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using Microsoft.SqlServer.TDS.EndPoint.SSPI;

Expand Down Expand Up @@ -68,6 +69,11 @@ public interface ITDSServerSession
/// </summary>
X509Certificate EncryptionCertificate { get; }

/// <summary>
/// SSL/TLS protocols to use for transport encryption
/// </summary>
SslProtocols EncryptionProtocols { get; }

/// <summary>
/// Counter of connection reset requests for this session
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ public class TDSParser
/// </summary>
public TextWriter EventLog { get; set; }

/// <summary>
/// Encryption protocol for server to use with AuthenticateAsServer
/// </summary>
public static SslProtocols ServerSslProtocol { get; set; }

/// <summary>
/// Protocol stream between the client and the server
/// </summary>
Expand All @@ -43,8 +38,6 @@ public TDSParser(Stream transport)
// Save original transport
_originalTransport = transport;

ServerSslProtocol = SslProtocols.Tls12;

// Wrap transport layer with TDS
Transport = new TDSStream(transport, false);
}
Expand All @@ -57,14 +50,6 @@ public void SetTDSStreamPreWriteCallback(Func<byte[], int, int, ushort> funcTDSS
Transport.PreWriteCallBack = funcTDSStreamPreWriteCallBack;
}

/// <summary>
/// Resets the targeted encryption protocol for the server.
/// </summary>
public static void ResetTargetProtocol()
{
ServerSslProtocol = SslProtocols.Tls12;
}

/// <summary>
/// Enable transport encryption
/// </summary>
Expand Down Expand Up @@ -105,7 +90,7 @@ protected void EnableClientTransportEncryption(string server)
/// <summary>
/// Enable transport encryption
/// </summary>
protected void EnableServerTransportEncryption(X509Certificate certificate)
protected void EnableServerTransportEncryption(X509Certificate certificate, SslProtocols encryptionProtocols)
{
// Check if transport encryption is applied
if (Transport.InnerStream is SslStream)
Expand All @@ -128,7 +113,7 @@ protected void EnableServerTransportEncryption(X509Certificate certificate)
SslStream ssl = new SslStream(multiplexer, true);

// Secure the channel
ssl.AuthenticateAsServer(certificate, false, ServerSslProtocol, false);
ssl.AuthenticateAsServer(certificate, false, encryptionProtocols, false);

// Replace TDS stream with raw transport stream in multiplexer
multiplexer.InnerStream = Transport.InnerStream;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public void Run()
if (Session.Encryption == TDSEncryptionType.LoginOnly || Session.Encryption == TDSEncryptionType.Full)
{
// Enable server side encryption
EnableServerTransportEncryption(Session.EncryptionCertificate);
EnableServerTransportEncryption(Session.EncryptionCertificate, Session.EncryptionProtocols);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ public virtual ITDSServerSession OpenSession()
// Create a new session
GenericTDSServerSession session = new GenericTDSServerSession(this, (uint)_sessionCount);

// Use configured encryption certificate
// Use configured encryption certificate and protocols
session.EncryptionCertificate = Arguments.EncryptionCertificate;
session.EncryptionProtocols = Arguments.EncryptionProtocols;

return session;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Generic;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using Microsoft.SqlServer.TDS.EndPoint;
using Microsoft.SqlServer.TDS.EndPoint.SSPI;
Expand Down Expand Up @@ -78,6 +79,11 @@ public class GenericTDSServerSession : ITDSServerSession
/// </summary>
public X509Certificate EncryptionCertificate { get; set; }

/// <summary>
/// SSL/TLS protocols to use for transport encryption
/// </summary>
public SslProtocols EncryptionProtocols { get; set; }

/// <summary>
/// Nonce option sent by client
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.IO;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using Microsoft.SqlServer.TDS.PreLogin;

Expand Down Expand Up @@ -69,6 +70,11 @@ public class TDSServerArguments
/// </summary>
public X509Certificate EncryptionCertificate { get; set; }

/// <summary>
/// SSL/TLS protocols to use for transport encryption
/// </summary>
public SslProtocols EncryptionProtocols { get; set; }

/// <summary>
/// Initialization constructor
/// </summary>
Expand All @@ -88,6 +94,7 @@ public TDSServerArguments()
FedAuthRequiredPreLoginOption = TdsPreLoginFedAuthRequiredOption.FedAuthNotRequired;

EncryptionCertificate = new X509Certificate2("TdsServerCertificate.pfx", "SecretPassword123456");
EncryptionProtocols = SslProtocols.Tls12;

ServerPrincipalName = AzureADServicePrincipalName;
StsUrl = AzureADProductionTokenEndpoint;
Expand Down

0 comments on commit d92016b

Please sign in to comment.