Skip to content

Commit

Permalink
Persist the fallback TLS version only on success. Fixes #1349
Browse files Browse the repository at this point in the history
If an exception happens during TLS negotiation, we only want to set the fallback TLS version on the connection pool if connecting succeeded. Otherwise, we could get into a permanent state of trying to connect with a TLS version that will fail.

Signed-off-by: Bradley Grainger <bgrainger@gmail.com>
  • Loading branch information
bgrainger committed Jul 21, 2023
1 parent 5a7c78c commit 5284e88
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions src/MySqlConnector/Core/ServerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -424,14 +424,15 @@ public async Task DisposeAsync(IOBehavior ioBehavior, CancellationToken cancella
// (which is SslProtocols.None; see https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls),
// then fall back to SslProtocols.Tls11 if that fails and it's possible that the cause is a yaSSL server.
bool shouldRetrySsl;
var shouldUpdatePoolSslProtocols = false;
var sslProtocols = Pool?.SslProtocols ?? cs.TlsVersions;
PayloadData payload;
InitialHandshakePayload initialHandshake;
do
{
bool tls11or10Supported = (sslProtocols & (SslProtocols.Tls | SslProtocols.Tls11)) != SslProtocols.None;
bool tls12Supported = (sslProtocols & SslProtocols.Tls12) == SslProtocols.Tls12;
shouldRetrySsl = (sslProtocols == SslProtocols.None || (tls12Supported && tls11or10Supported)) && Utility.IsWindows();
var isTls11or10Supported = (sslProtocols & (SslProtocols.Tls | SslProtocols.Tls11)) != SslProtocols.None;
var isTls12Supported = (sslProtocols & SslProtocols.Tls12) == SslProtocols.Tls12;
shouldRetrySsl = (sslProtocols == SslProtocols.None || (isTls12Supported && isTls11or10Supported)) && Utility.IsWindows();

var connected = false;
if (cs.ConnectionProtocol == MySqlConnectionProtocol.Sockets)
Expand Down Expand Up @@ -538,19 +539,20 @@ public async Task DisposeAsync(IOBehavior ioBehavior, CancellationToken cancella
{
await InitSslAsync(initialHandshake.ProtocolCapabilities, cs, connection, sslProtocols, ioBehavior, cancellationToken).ConfigureAwait(false);
shouldRetrySsl = false;
if (shouldUpdatePoolSslProtocols && Pool is not null)
Pool.SslProtocols = sslProtocols;
}
catch (ArgumentException ex) when (ex.ParamName == "sslProtocolType" && sslProtocols == SslProtocols.None)
{
Log.Debug(ex, "Session{0} doesn't support SslProtocols.None; falling back to explicitly specifying SslProtocols", m_logArguments);
sslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
}
catch (Exception ex) when (shouldRetrySsl && ((ex is MySqlException && ex.InnerException is IOException) || ex is IOException))
catch (Exception ex) when (shouldRetrySsl && ((ex is MySqlException && ex.InnerException is AuthenticationException or IOException) || ex is AuthenticationException or IOException))
{
// negotiating TLS 1.2 with a yaSSL-based server throws an exception on Windows, see comment at top of method
Log.Debug(ex, "Session{0} failed negotiating TLS; falling back to TLS 1.1", m_logArguments);
Log.Warn(ex, "Session{0} failed negotiating TLS; falling back to TLS 1.1", m_logArguments);
sslProtocols = sslProtocols == SslProtocols.None ? SslProtocols.Tls | SslProtocols.Tls11 : (SslProtocols.Tls | SslProtocols.Tls11) & sslProtocols;
if (Pool is not null)
Pool.SslProtocols = sslProtocols;
shouldUpdatePoolSslProtocols = true;
}
}
else
Expand Down

0 comments on commit 5284e88

Please sign in to comment.