Skip to content

Commit

Permalink
Fix SSL CA validation. Fixes #1462
Browse files Browse the repository at this point in the history
Build a chain from the last certificate in the certificate chain presented by the remote server.

If we have an untrusted root, verify that the root certificate in the chain is one of the certificates specified by MySqlConnectionStringBuilder.SslCa.
  • Loading branch information
bgrainger committed Mar 17, 2024
1 parent d9e59c7 commit e855216
Showing 1 changed file with 17 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/MySqlConnector/Core/ServerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1389,18 +1389,30 @@ private async Task InitSslAsync(ProtocolCapabilities serverCapabilities, Connect

bool ValidateRemoteCertificate(object rcbSender, X509Certificate? rcbCertificate, X509Chain? rcbChain, SslPolicyErrors rcbPolicyErrors)
{
// if no CA verification is required, then we trust any remote certificate
if (cs.SslMode is MySqlSslMode.Preferred or MySqlSslMode.Required)
return true;

// if there are errors, then try to build a path to a root certificate from the certificates presented by the remote host
if ((rcbPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0 &&
rcbCertificate is not null &&
rcbChain is not null &&
caCertificateChain is not null &&
caCertificateChain.Build((X509Certificate2) rcbCertificate) &&
caCertificateChain.Build(rcbChain.ChainElements[^1].Certificate) &&
caCertificateChain.ChainStatus.Length > 0)
{
var chainStatus = caCertificateChain.ChainStatus[0].Status & ~X509ChainStatusFlags.UntrustedRoot;
if (chainStatus == X509ChainStatusFlags.NoError)
rcbPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
// if the only error is an Untrusted Root Certificate, then check all provided SSL CA certificates to see if one is the root
if (caCertificateChain.ChainStatus[0].Status == X509ChainStatusFlags.UntrustedRoot)
{
var rootCertificate = caCertificateChain.ChainElements[^1].Certificate;
foreach (var sslCaCertificate in caCertificateChain.ChainPolicy.ExtraStore)
{
if (rootCertificate.RawData.AsSpan().SequenceEqual(sslCaCertificate.RawData))
{
rcbPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
break;
}
}
}
}

if (cs.SslMode == MySqlSslMode.VerifyCA)
Expand Down

0 comments on commit e855216

Please sign in to comment.