Skip to content

Commit 74cdcba

Browse files
committed
Support mysql_clear_password auth switch. Fixes #268
For safety, sending the password in cleartext requires a secure connection.
1 parent fc5c777 commit 74cdcba

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

src/MySqlConnector/Serialization/ConnectionSettings.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ public ConnectionSettings(MySqlConnectionStringBuilder csb)
5959
UseCompression = csb.UseCompression;
6060
}
6161

62-
public ConnectionSettings WithUseCompression(bool useCompression) => new ConnectionSettings(this, useCompression);
62+
public ConnectionSettings WithSecureConnection(bool isSecureConnection) => new ConnectionSettings(this, isSecureConnection: isSecureConnection);
63+
public ConnectionSettings WithUseCompression(bool useCompression) => new ConnectionSettings(this, useCompression: useCompression);
6364

64-
private ConnectionSettings(ConnectionSettings other, bool? useCompression)
65+
private ConnectionSettings(ConnectionSettings other, bool? useCompression = null, bool? isSecureConnection = null)
6566
{
6667
// Base Options
6768
ConnectionString = other.ConnectionString;
@@ -77,6 +78,7 @@ private ConnectionSettings(ConnectionSettings other, bool? useCompression)
7778
SslMode = other.SslMode;
7879
CertificateFile = other.CertificateFile;
7980
CertificatePassword = other.CertificatePassword;
81+
IsSecureConnection = isSecureConnection ?? other.IsSecureConnection;
8082

8183
// Connection Pooling Options
8284
Pooling = other.Pooling;
@@ -115,6 +117,7 @@ private ConnectionSettings(ConnectionSettings other, bool? useCompression)
115117
internal readonly MySqlSslMode SslMode;
116118
internal readonly string CertificateFile;
117119
internal readonly string CertificatePassword;
120+
internal readonly bool IsSecureConnection;
118121

119122
// Connection Pooling Options
120123
internal readonly bool Pooling;

src/MySqlConnector/Serialization/MySqlSession.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ public async Task ConnectAsync(ConnectionSettings cs, IOBehavior ioBehavior, Can
231231
if (!serverSupportsSsl)
232232
throw new MySqlException("Server does not support SSL");
233233
await InitSslAsync(initialHandshake.ProtocolCapabilities, cs, ioBehavior, cancellationToken).ConfigureAwait(false);
234+
cs = cs.WithSecureConnection(true);
234235
}
235236

236237
var response = HandshakeResponse41Packet.Create(initialHandshake, cs);
@@ -286,12 +287,25 @@ private async Task SwitchAuthenticationAsync(PayloadData payload, ConnectionSett
286287
{
287288
// if the server didn't support the hashed password; rehash with the new challenge
288289
var switchRequest = AuthenticationMethodSwitchRequestPayload.Create(payload);
289-
if (switchRequest.Name != "mysql_native_password")
290+
switch (switchRequest.Name)
291+
{
292+
case "mysql_native_password":
293+
AuthPluginData = switchRequest.Data;
294+
var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, cs.Password);
295+
payload = new PayloadData(new ArraySegment<byte>(hashedPassword));
296+
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
297+
break;
298+
299+
case "mysql_clear_password":
300+
if (!cs.IsSecureConnection)
301+
throw new MySqlException("Authentication method '{0}' requires a secure connection.".FormatInvariant(switchRequest.Name));
302+
payload = new PayloadData(new ArraySegment<byte>(Encoding.UTF8.GetBytes(cs.Password)));
303+
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
304+
break;
305+
306+
default:
290307
throw new NotSupportedException("Authentication method '{0}' is not supported.".FormatInvariant(switchRequest.Name));
291-
AuthPluginData = switchRequest.Data;
292-
var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, cs.Password);
293-
payload = new PayloadData(new ArraySegment<byte>(hashedPassword));
294-
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
308+
}
295309
}
296310

297311
public async Task<bool> TryPingAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)

0 commit comments

Comments
 (0)