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

Fix | Fix certificate validation #2439

Draft
wants to merge 55 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
95c67b1
Initial merge from certValidation and certTest branch from David-Enge…
arellegue Feb 5, 2024
ed691c5
Initial merge from certValidation and certTest branch from David-Enge…
arellegue Feb 5, 2024
5452a9c
Merge branch 'main' into FixCertificateValidation
arellegue Feb 5, 2024
fa54829
Added unit test in Manual Tests.
arellegue Mar 25, 2024
e8d3e54
Merged latest project files from upstream.
arellegue Mar 25, 2024
67f2091
Merge branch 'main' into FixCertificateValidation
arellegue Mar 25, 2024
cf5739c
Fixed project files.
arellegue Mar 25, 2024
267acdd
Fix script for linux to install openssl first.
arellegue Mar 27, 2024
af9a1ff
Add force installation of openssl from PSGallery.
arellegue Mar 27, 2024
3c682cc
Removed OpenSsl installation.
arellegue Mar 27, 2024
45ad5f8
Add 1 second delay for the certificate to be created.
arellegue Mar 27, 2024
3522200
Add debug to display certificate location.
arellegue Mar 27, 2024
78f75e4
Add print working directory to script.
arellegue Mar 27, 2024
9d417da
Add cat to display content of result.txt.
arellegue Mar 27, 2024
60768f0
Add parameter for the location of certificate.
arellegue Mar 27, 2024
7136a33
Fix script parameters.
arellegue Mar 28, 2024
d7423ed
Fix script so that if FQDN is over 64 characters then don't use it as…
arellegue Apr 1, 2024
07a2332
Without specifiying CN, the openssl command becomes interactive. Thu…
arellegue Apr 1, 2024
aa13fb1
Fix string length test to -gt 64.
arellegue Apr 1, 2024
4369b9e
Add the installation of openssl for linux.
arellegue Apr 1, 2024
1c39823
Clean-up unwanted comments from scripts and unit test.
arellegue Apr 1, 2024
aa0dfc2
Removed unnecessary using.
arellegue Apr 1, 2024
2a4d831
Added byte array comparer function.
arellegue Apr 2, 2024
e7c1e48
Change tests expected results.
arellegue Apr 2, 2024
d1a1bab
Use AsSpan().SequenceEqual in ByteArrayCompare function.
arellegue Apr 2, 2024
7f1806a
Drop ByteArrayCompare function and use inline .AsSpan().SequenceEqual…
arellegue Apr 2, 2024
523b921
Merged upstream MDS solution file.
arellegue Apr 3, 2024
131450e
Bring back TrySNIEventScope.Create inside ValidateServerCertificate i…
arellegue Apr 3, 2024
2c5b5fd
Merge netfx MDS project file.
arellegue Apr 3, 2024
1b6371a
Removed one second delay to wait for the creation of certificate to c…
arellegue Apr 3, 2024
d1a9880
Added license information to new class files.
arellegue Apr 3, 2024
6f198e7
Re-merge Manual Tests project file.
arellegue Apr 3, 2024
cb7cc8e
Change parameter names. Added more set of parameters.
arellegue Apr 8, 2024
c065a90
Fix some wrong expecated result in the set of parameters.
arellegue Apr 8, 2024
0f1d82f
Ammend makepfxcert.ps1 desciption.
arellegue Apr 8, 2024
dfbc847
Applied suggested change in the comment at line 141 of SNICommon.cs.
arellegue Apr 18, 2024
9d8c7d9
Added extra line as suggested.
arellegue Apr 18, 2024
9095e71
Merged from upstream main.
arellegue Apr 18, 2024
f301515
Applied suggested changes.
arellegue Apr 19, 2024
e413d9c
No change just trigerring pipeline run for this PR.
arellegue Apr 19, 2024
db6656d
Revert Nuget.config changes.
arellegue Apr 24, 2024
8821999
Merge branch 'main' into FixCertificateValidation
arellegue Apr 24, 2024
804473f
Merge branch 'main' into FixCertificateValidation
arellegue Apr 25, 2024
3341d76
Change default Tds Server encryption to not supported in Functional T…
arellegue Apr 29, 2024
5e8bd99
Restore original TestTdsServer.cs in Functional Test.
arellegue Apr 29, 2024
7ee63c2
Changed TdsServer default encryption to None in Manual Tests.
arellegue Apr 29, 2024
b5539d1
Actually, make the test TdsServer default Encryption to NotSupported …
arellegue Apr 29, 2024
2dd6fb1
Removed blank line from TestTdsServer.cs.
arellegue Apr 29, 2024
b6770d3
Make Windows and Linux certificate key length to be 4096.
arellegue Apr 30, 2024
43b940b
Commenbt out dpkg-reconfigure in the certificate maker script.
arellegue May 1, 2024
df87444
Update script that creates certificate.
arellegue May 2, 2024
e485ce4
Merge branch 'main' into FixCertificateValidation
arellegue May 2, 2024
81b5a09
Added unit test wrapper for Windows and Unix. MaxOS will be excluded.
arellegue May 2, 2024
faf2b14
Updated script so that the dpkg-reconfigure is noninteractive.
arellegue May 2, 2024
e9adb82
Add comment that possible value for certificate includes a mismatched…
arellegue May 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view

Large diffs are not rendered by default.

Expand Up @@ -24,6 +24,8 @@ internal sealed class SNINpHandle : SNIPhysicalHandle

private readonly string _targetServer;
private readonly object _sendSync;
private readonly string _hostNameInCertificate;
private readonly string _serverCertificateFilename;
private readonly bool _tlsFirst;
private Stream _stream;
private NamedPipeClientStream _pipeStream;
Expand All @@ -38,7 +40,7 @@ internal sealed class SNINpHandle : SNIPhysicalHandle
private int _bufferSize = TdsEnums.DEFAULT_LOGIN_PACKET_SIZE;
private readonly Guid _connectionId = Guid.NewGuid();

public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, bool tlsFirst)
public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, bool tlsFirst, string hostNameInCertificate, string serverCertificateFilename)
{
using (TrySNIEventScope.Create(nameof(SNINpHandle)))
{
Expand All @@ -47,6 +49,8 @@ public SNINpHandle(string serverName, string pipeName, TimeoutTimer timeout, boo
_sendSync = new object();
_targetServer = serverName;
_tlsFirst = tlsFirst;
_hostNameInCertificate = hostNameInCertificate;
_serverCertificateFilename = serverCertificateFilename;
try
{
_pipeStream = new NamedPipeClientStream(
Expand Down Expand Up @@ -369,23 +373,23 @@ public override void DisableSsl()
/// Validate server certificate
/// </summary>
/// <param name="sender">Sender object</param>
/// <param name="cert">X.509 certificate</param>
/// <param name="serverCertificate">X.509 certificate</param>
/// <param name="chain">X.509 chain</param>
/// <param name="policyErrors">Policy errors</param>
/// <returns>true if valid</returns>
private bool ValidateServerCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
private bool ValidateServerCertificate(object sender, X509Certificate serverCertificate, X509Chain chain, SslPolicyErrors policyErrors)
{
using (TrySNIEventScope.Create(nameof(SNINpHandle)))
arellegue marked this conversation as resolved.
Show resolved Hide resolved
{
{
if (!_validateCert)
{
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Certificate validation not requested.", args0: ConnectionId);
return true;
}

SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Proceeding to SSL certificate validation.", args0: ConnectionId);
return SNICommon.ValidateSslServerCertificate(_targetServer, cert, policyErrors);
}
return SNICommon.ValidateSslServerCertificate(_connectionId, _targetServer, _hostNameInCertificate, serverCertificate, _serverCertificateFilename, policyErrors);
}
}

/// <summary>
Expand Down
Expand Up @@ -191,7 +191,7 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode)
tlsFirst, hostNameInCertificate, serverCertificateFilename);
break;
case DataSource.Protocol.NP:
sniHandle = CreateNpHandle(details, timeout, parallel, tlsFirst);
sniHandle = CreateNpHandle(details, timeout, parallel, tlsFirst, hostNameInCertificate, serverCertificateFilename);
break;
default:
Debug.Fail($"Unexpected connection protocol: {details._connectionProtocol}");
Expand Down Expand Up @@ -347,16 +347,18 @@ private static byte[][] GetSqlServerSPNs(string hostNameOrAddress, string portOr
/// <param name="timeout">Timer expiration</param>
/// <param name="parallel">Should MultiSubnetFailover be used. Only returns an error for named pipes.</param>
/// <param name="tlsFirst"></param>
/// <param name="hostNameInCertificate">Host name in certificate</param>
/// <param name="serverCertificateFilename">Used for the path to the Server Certificate</param>
/// <returns>SNINpHandle</returns>
private static SNINpHandle CreateNpHandle(DataSource details, TimeoutTimer timeout, bool parallel, bool tlsFirst)
private static SNINpHandle CreateNpHandle(DataSource details, TimeoutTimer timeout, bool parallel, bool tlsFirst, string hostNameInCertificate, string serverCertificateFilename)
{
if (parallel)
{
// Connecting to a SQL Server instance using the MultiSubnetFailover connection option is only supported when using the TCP protocol
SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, Strings.SNI_ERROR_49);
return null;
}
return new SNINpHandle(details.PipeHostName, details.PipeName, timeout, tlsFirst);
return new SNINpHandle(details.PipeHostName, details.PipeName, timeout, tlsFirst, hostNameInCertificate, serverCertificateFilename);
}

/// <summary>
Expand Down
Expand Up @@ -644,7 +644,6 @@ public override uint EnableSsl(uint options)
}
else
{
// TODO: Resolve whether to send _serverNameIndication or _targetServer. _serverNameIndication currently results in error. Why?
_sslStream.AuthenticateAsClient(_targetServer, null, s_supportedProtocols, false);
}
if (_sslOverTdsStream is not null)
Expand Down Expand Up @@ -698,33 +697,8 @@ private bool ValidateServerCertificate(object sender, X509Certificate serverCert
return true;
}

string serverNameToValidate;
if (!string.IsNullOrEmpty(_hostNameInCertificate))
{
serverNameToValidate = _hostNameInCertificate;
}
else
{
serverNameToValidate = _targetServer;
}

if (!string.IsNullOrEmpty(_serverCertificateFilename))
{
X509Certificate clientCertificate = null;
try
{
clientCertificate = new X509Certificate(_serverCertificateFilename);
return SNICommon.ValidateSslServerCertificate(clientCertificate, serverCertificate, policyErrors);
}
catch (Exception e)
{
// if this fails, then fall back to the HostNameInCertificate or TargetServer validation.
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, IOException occurred: {1}", args0: _connectionId, args1: e.Message);
}
}

SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Certificate will be validated for Target Server name", args0: _connectionId);
return SNICommon.ValidateSslServerCertificate(serverNameToValidate, serverCertificate, policyErrors);
return SNICommon.ValidateSslServerCertificate(_connectionId, _targetServer, _hostNameInCertificate, serverCertificate, _serverCertificateFilename, policyErrors);
}

/// <summary>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Microsoft.Data.SqlClient/src/Resources/Strings.resx
Expand Up @@ -4740,4 +4740,7 @@
<data name="SQL_RemoteCertificateNotAvailable" xml:space="preserve">
<value>Certificate not available while validating the certificate.</value>
</data>
<data name="SQL_RemoteCertificateDoesNotMatchServerCertificate" xml:space="preserve">
<value>The certificate provided by the server does not match the certificate provided by the ServerCertificate option.</value>
</data>
</root>
Expand Up @@ -12,6 +12,7 @@
using System.Security;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlServer.TDS.PreLogin;
using Microsoft.SqlServer.TDS.Servers;
using Xunit;

Expand Down Expand Up @@ -49,7 +50,7 @@ public async Task PreLoginEncryptionExcludedTest()
using TestTdsServer server = TestTdsServer.StartTestServer(false, false, 5, excludeEncryption: true);
SqlConnectionStringBuilder builder = new(server.ConnectionString)
{
IntegratedSecurity = true
IntegratedSecurity = true,
};

using SqlConnection connection = new(builder.ConnectionString);
Expand Down
Expand Up @@ -65,6 +65,5 @@ public static TestTdsServer StartTestServer(bool enableFedAuth = false, bool ena
public void Dispose() => _endpoint?.Stop();

public string ConnectionString { get; private set; }

}
}
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SqlServer.TDS.PreLogin;

namespace Microsoft.Data.SqlClient.ManualTesting.Tests.DataCommon
{
public class ConnectionTestParameters
{
public SqlConnectionEncryptOption Encrypt { get; set; }
public bool TrustServerCertificate { get; set; }
public string Certificate { get; set; }
public string HostNameInCertificate { get; set; }
public bool TestResult { get; set; }
public TDSPreLoginTokenEncryptionType TdsEncryptionType { get; set; }
}
}