SqlClient: A connection was successfully established with the server, but then an error occurred during the pre-login handshake.
Describe the bug
After I update the Microsoft.Data.SqlClient from 3.0.1 to 4.0.1 when I try to access the database I’m getting
Exception message:
Stack trace:
Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 - An internal exception was caught)
---> System.Security.Authentication.AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.
at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
at Microsoft.Data.SqlClient.SNI.SNITCPHandle.EnableSsl(UInt32 options)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass18_0.<Exists>b__0(DateTime giveUp)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0`2.<Execute>b__0(DbContext c, TState s)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation, Func`2 verifySucceeded)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists(Boolean retryOnNotExists)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists()
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:51a7429a-eee3-4ee4-802e-be6c50c1129b
Error Number:-2146893019,State:0,Class:20
Expected behavior
Connect to database
Further technical details
Microsoft.Data.SqlClient version: 4.0.1 .NET target: .NET 6.0 on MacOS SQL Server version: Microsoft SQL Server 2019 (RTM-CU14) (KB5007182) - 15.0.4188.2 (X64) Developer Edition (64-bit) on Linux (Ubuntu 20.04.3 LTS) <X64> Operating system: Docker Linux
Additional context I’m running EF Core 6.0.1 migrations
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 31 (4 by maintainers)
Links to this issue
Commits related to this issue
- test-3 for sqlserver added possible fix to connectionString as suggested by https://github.com/dotnet/SqlClient/issues/1479 — committed to D76X/AZ-400-Demo-01 by D76XPH a year ago
Have you tried to set
TrustServerCertificate=Truein your connection string ?@lillo42 have your tried adding
Encrypt=falseto your connection string? or as mentioned aboveTrustServerCertificate=True@JRahnama and @alaincroisetiere when I add
TrustServerCertificate=TrueorEncrypt=falseworks, why I need to added it now?We are experiencing the same problem trying to access a SQL Server from a .NET 5 microservice deployed on OpenShift. The version of the Microsoft.Data.SqlClient is 4.1.0.
We solved this by adding the following parameters in the connection string:
TrustServerCertificate=True;MultiSubnetFailover=TrueThis connection string works for me
"Data Source=localhost; TrustServerCertificate=True; MultiSubnetFailover=True; Initial Catalog=YourDB; User ID='sa'; Password='YourPass';"Thanks, I added TrustServerCertificate=True; to the connection string and it worked
@stijnherreman for development and localhost you can use
Encrypt=falsein your connection string.I was runned in this issue for both System.Data.SqlClient Microsoft.Data.SqlClient on Android 11.0 - API 30. Encrypt, TrustServerCertificate and MultiSubnetFailover flags set to true are not helped for me. On Windows work as expected.
server version: Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) Sep 24 2019 13:48:23 Copyright © 2019 Microsoft Corporation Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: ) (Hypervisor)
Here is my exception message: A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 - An internal exception was caught)
System.Data.SqlClient is in servicing mode and is not updating on regular basis, but for addressing security issues and important updates. We suggest using Microsoft.Data.SqlClient as active ADO.NET library which gets updated and implements new features.
By changing this behavior, two issues has been addressed :
Default Encrypt to True. This is for security. Similar to http/https, if the client starts with allowing non-encrypted connections, it will always be susceptible to MITM attacks. Even if the server is configured to require encryption, there can be a MITM altering the server’s response to say it doesn’t require encryption. The MITM can then proxy the connection. client <-plain text-> MITM <-encrypted-> server = the connection is compromised.
Security has been encouraging us for years to change the default behavior of client drivers to be secure by default and we have resisted, knowing that it is a breaking change for most users. It’s easy enough for developers to add Encrypt = false to all their connection strings, if they need to. We just want to make sure they understand the choice they are making and they are making it deliberately. With cloud computing becoming more and more common, it’s not safe to leave the default value of Encrypt equal to false.
The less-breaking, but still important, fix here is to ensure connections fail if the client does not have any encryption libraries available and either Encrypt = true or the server requires encryption. SqlClient + native SNI is the only MS driver we’ve found that will successfully connect in that scenario.
This worked for me. Thanks!
@alaincroisetiere Thanks, I haven’t saw the breaking changes parts
You can read the breaking changes https://github.com/dotnet/SqlClient/blob/main/release-notes/4.0/4.0.0.md#breaking-changes
I had the same issue, as a workaround I suggest switching to System.Data.SqlClient, it works as expected