Skip to content

Commit abee0c7

Browse files
committed
Add logging for provisional TLS connection and failure reasons.
Signed-off-by: Bradley Grainger <[email protected]>
1 parent 34524ef commit abee0c7

File tree

3 files changed

+65
-15
lines changed

3 files changed

+65
-15
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -528,26 +528,43 @@ public async Task DisposeAsync(IOBehavior ioBehavior, CancellationToken cancella
528528
}
529529

530530
var ok = OkPayload.Create(payload.Span, this);
531+
531532
if (m_sslPolicyErrors != SslPolicyErrors.None)
532533
{
533-
// SSL would normally have thrown error, so connector need to ensure server certificates
534+
// SSL would normally have thrown error, but this was suppressed in ValidateRemoteCertificate; now we need to verify the server certificate
534535
// pass only if :
535536
// * connection method is MitM-proof (e.g. unix socket)
536537
// * auth plugin is MitM-proof and check SHA2(user's hashed password, scramble, certificate fingerprint)
537-
if (cs.ConnectionProtocol != MySqlConnectionProtocol.UnixSocket)
538+
// see https://mariadb.org/mission-impossible-zero-configuration-ssl/
539+
var ignoreCertificateError = false;
540+
541+
if (cs.ConnectionProtocol == MySqlConnectionProtocol.UnixSocket)
538542
{
539-
if (string.IsNullOrEmpty(password) || !ValidateFingerprint(ok.StatusInfo, initialHandshake.AuthPluginData.AsSpan(0, 20), password!))
540-
{
541-
ShutdownSocket();
542-
HostName = "";
543-
lock (m_lock)
544-
m_state = State.Failed;
543+
Log.CertificateErrorUnixSocket(m_logger, Id, m_sslPolicyErrors);
544+
ignoreCertificateError = true;
545+
}
546+
else if (string.IsNullOrEmpty(password))
547+
{
548+
// there is no shared secret that can be used to validate the certificate
549+
Log.CertificateErrorNoPassword(m_logger, Id, m_sslPolicyErrors);
550+
}
551+
else if (ValidateFingerprint(ok.StatusInfo, initialHandshake.AuthPluginData.AsSpan(0, 20), password))
552+
{
553+
Log.CertificateErrorValidThumbprint(m_logger, Id, m_sslPolicyErrors);
554+
ignoreCertificateError = true;
555+
}
545556

546-
// throw a MySqlException with an AuthenticationException InnerException to mimic what would have happened if ValidateRemoteCertificate returned false
547-
var innerException = new AuthenticationException($"The remote certificate was rejected due to the following error: {m_sslPolicyErrors}");
548-
Log.CouldNotInitializeTlsConnection(m_logger, innerException, Id);
549-
throw new MySqlException(MySqlErrorCode.UnableToConnectToHost, "SSL Authentication Error", innerException);
550-
}
557+
if (!ignoreCertificateError)
558+
{
559+
ShutdownSocket();
560+
HostName = "";
561+
lock (m_lock)
562+
m_state = State.Failed;
563+
564+
// throw a MySqlException with an AuthenticationException InnerException to mimic what would have happened if ValidateRemoteCertificate returned false
565+
var innerException = new AuthenticationException($"The remote certificate was rejected due to the following error: {m_sslPolicyErrors}");
566+
Log.CouldNotInitializeTlsConnection(m_logger, innerException, Id);
567+
throw new MySqlException(MySqlErrorCode.UnableToConnectToHost, "SSL Authentication Error", innerException);
551568
}
552569
}
553570

@@ -1664,11 +1681,22 @@ await sslStream.AuthenticateAsClientAsync(clientAuthenticationOptions.TargetHost
16641681
m_payloadHandler!.ByteHandler = sslByteHandler;
16651682
m_isSecureConnection = true;
16661683
m_sslStream = sslStream;
1684+
if (m_sslPolicyErrors != SslPolicyErrors.None)
1685+
{
1686+
#if NETCOREAPP3_0_OR_GREATER
1687+
Log.ConnectedTlsBasicPreliminary(m_logger, Id, m_sslPolicyErrors, sslStream.SslProtocol, sslStream.NegotiatedCipherSuite);
1688+
#else
1689+
Log.ConnectedTlsDetailedPreliminary(m_logger, Id, m_sslPolicyErrors, sslStream.SslProtocol, sslStream.CipherAlgorithm, sslStream.HashAlgorithm, sslStream.KeyExchangeAlgorithm, sslStream.KeyExchangeStrength);
1690+
#endif
1691+
}
1692+
else
1693+
{
16671694
#if NETCOREAPP3_0_OR_GREATER
1668-
Log.ConnectedTlsBasic(m_logger, Id, sslStream.SslProtocol, sslStream.NegotiatedCipherSuite);
1695+
Log.ConnectedTlsBasic(m_logger, Id, sslStream.SslProtocol, sslStream.NegotiatedCipherSuite);
16691696
#else
1670-
Log.ConnectedTlsDetailed(m_logger, Id, sslStream.SslProtocol, sslStream.CipherAlgorithm, sslStream.HashAlgorithm, sslStream.KeyExchangeAlgorithm, sslStream.KeyExchangeStrength);
1697+
Log.ConnectedTlsDetailed(m_logger, Id, sslStream.SslProtocol, sslStream.CipherAlgorithm, sslStream.HashAlgorithm, sslStream.KeyExchangeAlgorithm, sslStream.KeyExchangeStrength);
16711698
#endif
1699+
}
16721700
}
16731701
catch (Exception ex)
16741702
{

src/MySqlConnector/Logging/EventIds.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ internal static class EventIds
8181
public const int CreatingConnectionAttributes = 2153;
8282
public const int ObtainingPasswordViaProvidePasswordCallback = 2154;
8383
public const int FailedToObtainPassword = 2155;
84+
public const int ConnectedTlsBasicPreliminary = 2156;
85+
public const int ConnectedTlsDetailedPreliminary = 2157;
86+
public const int CertificateErrorUnixSocket = 2158;
87+
public const int CertificateErrorNoPassword = 2159;
88+
public const int CertificateErrorValidThumbprint = 2160;
8489

8590
// Command execution events, 2200-2299
8691
public const int CannotExecuteNewCommandInState = 2200;

src/MySqlConnector/Logging/Log.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,23 @@ internal static partial class Log
201201
[LoggerMessage(EventIds.FailedToObtainPassword, LogLevel.Error, "Session {SessionId} failed to obtain password via ProvidePasswordCallback: {ExceptionMessage}")]
202202
public static partial void FailedToObtainPassword(ILogger logger, Exception exception, string sessionId, string exceptionMessage);
203203

204+
#if NETCOREAPP3_0_OR_GREATER
205+
[LoggerMessage(EventIds.ConnectedTlsBasicPreliminary, LogLevel.Debug, "Session {SessionId} provisionally connected TLS with error {SslPolicyErrors} using {SslProtocol} and {NegotiatedCipherSuite}")]
206+
public static partial void ConnectedTlsBasicPreliminary(ILogger logger, string sessionId, SslPolicyErrors sslPolicyErrors, SslProtocols sslProtocol, TlsCipherSuite negotiatedCipherSuite);
207+
#endif
208+
209+
[LoggerMessage(EventIds.ConnectedTlsDetailedPreliminary, LogLevel.Debug, "Session {SessionId} provisionally connected TLS with error {SslPolicyErrors} using {SslProtocol}, {CipherAlgorithm}, {HashAlgorithm}, {KeyExchangeAlgorithm}, {KeyExchangeStrength}")]
210+
public static partial void ConnectedTlsDetailedPreliminary(ILogger logger, string sessionId, SslPolicyErrors sslPolicyErrors, SslProtocols sslProtocol, CipherAlgorithmType cipherAlgorithm, HashAlgorithmType hashAlgorithm, ExchangeAlgorithmType keyExchangeAlgorithm, int keyExchangeStrength);
211+
212+
[LoggerMessage(EventIds.CertificateErrorUnixSocket, LogLevel.Trace, "Session {SessionId} ignoring remote certificate error {SslPolicyErrors} due to Unix socket connection")]
213+
public static partial void CertificateErrorUnixSocket(ILogger logger, string sessionId, SslPolicyErrors sslPolicyErrors);
214+
215+
[LoggerMessage(EventIds.CertificateErrorNoPassword, LogLevel.Trace, "Session {SessionId} acknowledging remote certificate error {SslPolicyErrors} due to passwordless connection")]
216+
public static partial void CertificateErrorNoPassword(ILogger logger, string sessionId, SslPolicyErrors sslPolicyErrors);
217+
218+
[LoggerMessage(EventIds.CertificateErrorValidThumbprint, LogLevel.Trace, "Session {SessionId} ignoring remote certificate error {SslPolicyErrors} due to valid signature in OK packet")]
219+
public static partial void CertificateErrorValidThumbprint(ILogger logger, string sessionId, SslPolicyErrors sslPolicyErrors);
220+
204221
[LoggerMessage(EventIds.IgnoringCancellationForCommand, LogLevel.Trace, "Ignoring cancellation for closed connection or invalid command {CommandId}")]
205222
public static partial void IgnoringCancellationForCommand(ILogger logger, int commandId);
206223

0 commit comments

Comments
 (0)