mysql-net / MySqlConnector

MySQL Connector for .NET
https://mysqlconnector.net
MIT License
1.39k stars 333 forks source link

SSL Authentication Error after upgrading to .NET 6 when connecting to MySQL database with TLS 1.1 #1315

Closed janarthanansf3463 closed 11 months ago

janarthanansf3463 commented 1 year ago

Software versions MySqlConnector version: 2.2.5 Server type (MySQL, MariaDB, Aurora, etc.) and version: MySQL 5.7.19 .NET version: 6.0

Describe the bug I have a MySQL database with version 5.7.19 and TLS version 1.1. I'm trying to establish a connection in my .NET Core 3.1 application. This code works fine, but after upgrading to .NET 6, it throws exceptions.

Exception MySqlConnector.MySqlException(0x80004005): SSL Authentication Error\ r\ n-- - > System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.\r\ n-- - > System.ComponentModel.Win32Exception(0x8009030E): No credentials are available in the security package at System.Net.SSPIWrapper.AcquireCredentialsHandle(ISSPIInterface secModule, String package, CredentialUse intent, SCH_CREDENTIALS scc) at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCH_CREDENTIALS secureCredential) at System.Net.Security.SslStreamPal.AcquireCredentialsHandleSchCredentials(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) -- - End of inner exception stack trace-- - at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[] & thumbPrint) at System.Net.Security.SecureChannel.GenerateToken(ReadOnlySpan1 inputBuffer, Byte[] & output) at System.Net.Security.SecureChannel.NextMessage(ReadOnlySpan 1 incomingBuffer) at System.Net.Security.SslStream.ProcessBlob(Int32 frameSize) at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter) at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm) at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions) at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ServerSession.cs: line 1539 at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ServerSession.cs: line 1569 at MySqlConnector.Core.ServerSession.ConnectAsync(ConnectionSettings cs, MySqlConnection connection, Int32 startTickCount, ILoadBalancer loadBalancer, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ServerSession.cs: line 539 at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, String logMessage, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ConnectionPool.cs: line 403 at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, String logMessage, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ConnectionPool.cs: line 408 at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ConnectionPool.cs: line 98 at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / Core / ConnectionPool.cs: line 128 at MySqlConnector.MySqlConnection.CreateSessionAsync(ConnectionPool pool, Int32 startTickCount, Activity activity, Nullable1 ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / MySqlConnection.cs: line 929 at MySqlConnector.MySqlConnection.OpenAsync(Nullable 1 ioBehavior, CancellationToken cancellationToken) in / / src / MySqlConnector / MySqlConnection.cs: line 423 at MySqlConnector.MySqlConnection.Open() in / / src / MySqlConnector / MySqlConnection.cs: line 382 at WebApplication1.Program.Main(String[] args) in D: \WebApplication1\ WebApplication1\ Program.cs: line 24

Code sample

string connStr = "server=Myserver;user id=myuser;password=my password;database=db;SslMode=Required;SslCa=D:\\server-ca.pem;SslCert=D:\\client-cert.pem;SslKey=D:\\client-key.pem;";
try {
  using(MySqlConnection connection = new MySqlConnection(connStr)) {
    connection.Open();
    connection.Close();
  }
} catch (Exception ex) 
{
 // handle the exception
}

Additional context Note: This Same Code Works fine in the .Net 3.1, but i am facing issue in .Net core 6.0 version

bgrainger commented 1 year ago

I assume you're on Windows? Which version of Windows?

Have you tried adding ;TlsVersion = Tls 1.1 to your connection string?

bgrainger commented 1 year ago

Based on https://github.com/mysql-net/MySqlConnector/commit/bf06ea96c1bbaf7b17baf15960321619607bc334 it may also help to add ;Tls Cipher Suites=TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256.

You may have to play around with those different options to see if you can find something that works.

JANARTHANAN1907 commented 1 year ago

I assume you're on Windows? Which version of Windows? -- Yes, I am using Windows 10 pro Have you tried adding ;TlsVersion = Tls 1.1 to your connection string? I tried the suggested option still I am getting the same Exception.

JANARTHANAN1907 commented 1 year ago

Based on bf06ea9 it may also help to add ;Tls Cipher Suites=TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256. You may have to play around with those different options to see if you can find something that works.

I tried the above suggestion, but I am facing the issue 'CipherSuitesPolicy is not supported on this platform'.

Connectionstring: string connStr = "server=Myserver;user id=myuser;password=my password;database=db;SslMode=Required;SslCa=D:\\server-ca.pem;SslCert=D:\\client-cert.pem;SslKey=D:\\client-key.pem;TlsVersion = Tls 1.1;Tls Cipher Suites=TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA;";

bgrainger commented 1 year ago

Sorry; my mistake: as per the documentation, that option is only supported for Linux.

bgrainger commented 1 year ago

Do you have a minimal repro (e.g., perhaps using mysql:5.7.19 in Docker for Windows) that shows the problem?

janarthanansf3463 commented 1 year ago

Do you have a minimal repro (e.g., perhaps using mysql:5.7.19 in Docker for Windows) that shows the problem?

We have configured MySQL 5.7.19 on a Google Cloud resource with TLS 1.1. To replicate the procedure, follow these steps:

  1. Create an ASP.NET Core 3.1 web application.
  2. Create a sample program as shown below:
string connStr = "server=Myserver;user id=myuser;password=my password;database=db;SslMode=Required;SslCa=D:\\server-ca.pem;SslCert=D:\\client-cert.pem;SslKey=D:\\client-key.pem;";
try {
  using(MySqlConnection connection = new MySqlConnection(connStr)) {
    connection.Open();
    connection.Close();
  }
} catch (Exception ex) 
{
 // handle the exception
}
  1. credential is working fine in .NET Core 3.1.
  2. Upgrade to .NET Core 6.0. 5.We are facing an SSL authentication error in .NET Core 6.0."
bgrainger commented 1 year ago

I created a new Google Cloud SQL instance, which defaulted to MySQL 5.7.40. I wasn't able to reproduce a connectivity bug with it (using net6.0 on Windows 10 as the client):

[INFO]  ConnectionPool  Pool1 creating new connection pool for ConnectionString: Server=34.83.90.253;User ID=root;SSL Mode=Required;SSL Cert=C:\Temp\client-cert.pem;SSL Key=C:\Temp\client-key.pem;SSL CA=C:\Temp\server-ca.pem;TLS Version="TLS 1.1"
[TRACE] ConnectionPool  Pool1 waiting for an available session
[TRACE] ServerSession   Session1.1 created new session
[DEBUG] ConnectionPool  Pool1 no pooled session available; created new Session1.1
[TRACE] ServerSession   Session1.1 connecting to IpAddress 34.83.90.253 (1 of 1) for HostName '34.83.90.253' (1 of 1)
[TRACE] ServerSession   Session1.1 connected to IpAddress 34.83.90.253 for HostName '34.83.90.253' with local Port 50342
[TRACE] ServerSession   Session1.1 server sent AuthPluginName=mysql_native_password
[DEBUG] ServerSession   Session1.1 made connection; ServerVersion=5.7.40-google-log; ConnectionId=70; Compression=False; Attributes=True; DeprecateEof=True; Ssl=True; SessionTrack=True; Pipelining=True; QueryAttributes=False
[TRACE] ServerSession   Session1.1 initializing TLS connection
[TRACE] ServerSession   Session1.1 loading CA certificate(s) from CertificateFile 'C:\Temp\server-ca.pem'
[TRACE] ServerSession   Session1.1 loading certificate at Index 0 in the CA certificate file.
[TRACE] ServerSession   Session1.1 loaded certificates from CertificateFile 'C:\Temp\server-ca.pem'; CertificateCount: 1
[DEBUG] ServerSession   Session1.1 connected TLS with SslProtocol=Tls11, NegotiatedCipherSuite=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[TRACE] ServerSession   Session1.1 creating connection attributes
[TRACE] ConnectionPool  Pool1 returning new Session1.1 to caller; LeasedSessionsCount=1
[TRACE] ServerSession   Session1.1 returning to Pool1
[TRACE] ConnectionPool  Pool1 receiving Session1.1 back
[INFO]  ConnectionPool  Pool1 clearing connection pool
[TRACE] ConnectionPool  Pool1 recovered no sessions
[DEBUG] ConnectionPool  Pool1 found Session1.1 to clean up
[TRACE] ServerSession   Session1.1 sending QUIT command
[DEBUG] ServerSession   Session1.1 closing stream/socket
bgrainger commented 1 year ago

I also couldn't repro with mysql:5.7.19 running locally (and configured with SSL) in a Docker container:

[INFO]  ConnectionPool  Pool1 creating new connection pool for ConnectionString: Server=localhost;Port=3306;User ID=root;SSL Mode=Required;Certificate File=F:\Code\Projects\MySqlConnector\.ci\server\certs\ssl-client.pfx;Allow Public Key Retrieval=True
[TRACE] ConnectionPool  Pool1 waiting for an available session
[TRACE] ServerSession   Session1.1 created new session
[DEBUG] ConnectionPool  Pool1 no pooled session available; created new Session1.1
[TRACE] ServerSession   Session1.1 connecting to IpAddress 127.0.0.1 (1 of 2) for HostName 'localhost' (1 of 1)
[TRACE] ServerSession   Session1.1 connected to IpAddress 127.0.0.1 for HostName 'localhost' with local Port 51313
[TRACE] ServerSession   Session1.1 server sent AuthPluginName=mysql_native_password
[DEBUG] ServerSession   Session1.1 made connection; ServerVersion=5.7.19; ConnectionId=8; Compression=False; Attributes=True; DeprecateEof=True; Ssl=True; SessionTrack=True; Pipelining=True; QueryAttributes=False
[TRACE] ServerSession   Session1.1 initializing TLS connection
[ERROR] ServerSession   Session1.1 couldn't initialize TLS connection
System.IO.IOException: Cannot determine the frame size or a corrupted frame was received.
   at System.Net.Security.SslStream.GetFrameSize(ReadOnlySpan`1 buffer)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
   at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in F:\Code\Projects\MySqlConnector\src\MySqlConnector\Core\ServerSession.cs:line 1541
[DEBUG] ServerSession   Session1.1 closing stream/socket
[DEBUG] ServerSession   Session1.1 failed negotiating TLS; falling back to TLS 1.1
MySqlConnector.MySqlException (0x80004005): MySQL Server rejected client certificate
 ---> System.IO.IOException: Cannot determine the frame size or a corrupted frame was received.
   at System.Net.Security.SslStream.GetFrameSize(ReadOnlySpan`1 buffer)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
   at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in F:\Code\Projects\MySqlConnector\src\MySqlConnector\Core\ServerSession.cs:line 1541
   at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in F:\Code\Projects\MySqlConnector\src\MySqlConnector\Core\ServerSession.cs:line 1573
   at MySqlConnector.Core.ServerSession.ConnectAsync(ConnectionSettings cs, MySqlConnection connection, Int32 startTickCount, ILoadBalancer loadBalancer, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in F:\Code\Projects\MySqlConnector\src\MySqlConnector\Core\ServerSession.cs:line 539
[TRACE] ServerSession   Session1.1 connecting to IpAddress 127.0.0.1 (1 of 2) for HostName 'localhost' (1 of 1)
[TRACE] ServerSession   Session1.1 connected to IpAddress 127.0.0.1 for HostName 'localhost' with local Port 51314
[TRACE] ServerSession   Session1.1 server sent AuthPluginName=mysql_native_password
[DEBUG] ServerSession   Session1.1 made connection; ServerVersion=5.7.19; ConnectionId=9; Compression=False; Attributes=True; DeprecateEof=True; Ssl=True; SessionTrack=True; Pipelining=True; QueryAttributes=False
[TRACE] ServerSession   Session1.1 initializing TLS connection
[DEBUG] ServerSession   Session1.1 connected TLS with SslProtocol=Tls11, NegotiatedCipherSuite=TLS_RSA_WITH_AES_256_CBC_SHA
[TRACE] ServerSession   Session1.1 creating connection attributes
[TRACE] ConnectionPool  Pool1 returning new Session1.1 to caller; LeasedSessionsCount=1
[TRACE] ServerSession   Session1.1 returning to Pool1
[TRACE] ConnectionPool  Pool1 receiving Session1.1 back
[INFO]  ConnectionPool  Pool1 clearing connection pool
[TRACE] ConnectionPool  Pool1 recovered no sessions
[DEBUG] ConnectionPool  Pool1 found Session1.1 to clean up
[TRACE] ServerSession   Session1.1 sending QUIT command
[DEBUG] ServerSession   Session1.1 closing stream/socket
bgrainger commented 1 year ago

Can you provide the full logs (with Trace level enabled) for a failing connection?

janarthanansf3463 commented 1 year ago

Can you provide the full logs (with Trace level enabled) for a failing connection?

Exception: MyTraceSource Error: 0 : MySqlConnector.MySqlException (0x80004005): SSL Authentication Error ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> System.ComponentModel.Win32Exception (0x8009030E): No credentials are available in the security package at System.Net.SSPIWrapper.AcquireCredentialsHandle(ISSPIInterface secModule, String package, CredentialUse intent, SCH_CREDENTIALS scc) at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCH_CREDENTIALS secureCredential) at System.Net.Security.SslStreamPal.AcquireCredentialsHandleSchCredentials(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) --- End of inner exception stack trace --- at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint) at System.Net.Security.SecureChannel.GenerateToken(ReadOnlySpan1 inputBuffer, Byte[]& output) at System.Net.Security.SecureChannel.NextMessage(ReadOnlySpan1 incomingBuffer) at System.Net.Security.SslStream.ProcessBlob(Int32 frameSize) at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter) at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm) at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions) at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ServerSession.cs:line 1539 at MySqlConnector.Core.ServerSession.InitSslAsync(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, MySqlConnection connection, SslProtocols sslProtocols, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ServerSession.cs:line 1569 at MySqlConnector.Core.ServerSession.ConnectAsync(ConnectionSettings cs, MySqlConnection connection, Int32 startTickCount, ILoadBalancer loadBalancer, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ServerSession.cs:line 539 at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, String logMessage, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ConnectionPool.cs:line 403 at MySqlConnector.Core.ConnectionPool.ConnectSessionAsync(MySqlConnection connection, String logMessage, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ConnectionPool.cs:line 408 at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ConnectionPool.cs:line 98 at MySqlConnector.Core.ConnectionPool.GetSessionAsync(MySqlConnection connection, Int32 startTickCount, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/Core/ConnectionPool.cs:line 128 at MySqlConnector.MySqlConnection.CreateSessionAsync(ConnectionPool pool, Int32 startTickCount, Activity activity, Nullable`1 ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/MySqlConnection.cs:line 929 at MySqlConnector.MySqlConnection.OpenAsync(Nullable`1 ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/MySqlConnection.cs:line 423 at MySqlConnector.MySqlConnection.Open() in //src/MySqlConnector/MySqlConnection.cs:line 382 at WebApplication1.Program.Main(String[] args) in D:\WebApplication1\WebApplication1\Program.cs:line 25

janarthanansf3463 commented 1 year ago

We followed the link below to configure MySQL using Google Cloud for your reference. https://support.google.com/appsheet/answer/10107301?hl=en

bgrainger commented 1 year ago

I already did that, as I posted above: https://github.com/mysql-net/MySqlConnector/issues/1315#issuecomment-1535121673.

janarthanansf3463 commented 1 year ago

Hi team,

https://www.nuget.org/packages/MySqlConnector/2.2.6?_src=template

In the latest version of MySqlConnector (2.2.6), I did not experience that issue. I would like to know if you have fixed that issue in MySQLConnector 2.2.6

bgrainger commented 1 year ago

There were no known fixes/improvements to TLS in v2.2.6.

bgrainger commented 11 months ago

There was a TLS fix in 2.2.7 although that shouldn't have addressed this problem (it was a bug that caused a permanent fallback to TLS 1.1 on servers that didn't support it): https://github.com/mysql-net/MySqlConnector/issues/1349.