0

I just upgraded my C# project from .NET 6 to .NET 8. I started getting

Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The target principal name is incorrect.)

So digging through StackOverflow and lots of googling led me to upgrading SQL Server from 2017 to 2022 and upgrading Windows Server from 2012 to 2022. This was because I had no luck installing my wildcard SSL cert on SQL 2017. Nor would the self-signed cert work. That one gave me

A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.) I have tried using the wildcard cert, which it accepted, but got the same errors above. I tried changing the server name via:

SELECT @@SERVERNAME
EXEC sp_dropserver 'SERVER';
GO
EXEC sp_addserver 'FQDN SERVER NAME', local;
GO

(Removed server names for privacy. e.g. server.domain.com) Then restarted the server. Same errors. Since my valid SSL wildcard cert wasn't working, even when adding the server name to the username, I tried reissuing the self cert via PowerShell:

New-SelfSignedCertificate -Type SSLServerAuthentication -Subject "CN=FQDN Server" -FriendlyName "SQL Server Test self-signed" -DnsName "FQDN Server",'localhost.'  -KeyAlgorithm RSA -KeyLength 2048 -Hash 'SHA256' -TextExtension '2.5.29.37={text}1.3.6.1.5.5.7.3.1' -NotAfter (Get-Date).AddMonths(24) -KeySpec KeyExchange -Provider "Microsoft RSA SChannel Cryptographic Provider"-CertStoreLocation "Cert:\LocalMachine\My"

Reset the cert in SQL Manager and restarted the server. Same errors.

Finally, I broke down and bought a new SSL cert just for this server using MMC to create the request then installed it as above. Restarted the service. Same errors.

I've tried multiple connection strings from Trusted_Connection=True; to variations of Encrypt=false; TrustServerCertificate=true; changing those to true and false in all combinations. I've changed the server names back and forth and run through all the connection string combinations again and got the same errors.

I tried changing the properties for SQL Server Network Configuration forcing encryption on and off. My other apps connect just fine with it off, but nothing connects with it on. I expect this since there seems to be a problem with how it interacts with the SSL cert.

Looking at the certs in MMC, all say they are fine. All have the private key.

I have no idea what else to try, so I come to you all as a last hope. Can someone please tell me what I am missing? It shouldn't be this hard.

UPDATE: I wrote a test routine within the app to connect using the same connections string as in the appsettings.json file. It connects to the database and grabs a record from it. No errors! Now I am completely confused! How can this code work within the same project that says it fails to connect, using the same connection string?

 private async static Task<bool> TestSQL()
    {
        var connectionString = "Server=server.domain.com;Database=myDb;Persist Security Info=True;User ID=MyUser;Password=MyPass;MultipleActiveResultSets=true;Encrypt=true;TrustServerCertificate=true;";
        using (var connection = new SqlConnection(connectionString))
        {
            try
            {
                await connection.OpenAsync();
                Console.WriteLine("Connected successfully!");

                // Retrieve one record from the "Customers" table
                var sqlQuery = "SELECT TOP 1 * FROM Customers";
                using (var command = new SqlCommand(sqlQuery, connection))
                {
                    using (var reader = await command.ExecuteReaderAsync())
                    {
                        if (await reader.ReadAsync())
                        {
                            // Assuming "Customers" table has a column called "CustName"
                            var custName = reader["CustName"].ToString();
                            Console.WriteLine($"Customer Name: {custName}");
                        }
                        else
                        {
                            Console.WriteLine("No records found in the 'Customers' table.");
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error connecting to SQL server: " + ex.Message);
                return false;
            }
        }
    }

Is this a bug with Entity Framework? .NET?

JayTee
  • 437
  • 4
  • 10
  • How are you installing the certificate? Are you using SQL Server Configuration Manager, or are you inserting the thumbprint directly into the registry? What is your connection string to the server, is it `server.domain.com` or just `server`? – Charlieface Jul 28 '23 at 18:05
  • 2 ways: 1) a couple times when installed via MMC it showed up in the dropdown for SQL Manager. 2) After installing via MMC I went through the export process to PFX then used the import from SQL Manager. In all cases, the certs are going into Local Machine -> Personal -> Certificates folder. – JayTee Jul 28 '23 at 20:03
  • 1
    Ignoring the `Trust Server Certificate=1/true/yes` option for now... whether it's a CA cert or a self-signed cert the connecting clients need to know that they can trust the cert and they usually do that by looking at the Issuer of the cert and confirming that the Issuer is in the Trusted Publishers certificate store of their machine (or their personal account). In the normal case of CA certs this means that the public key of either the Intermediate CA or the Root CA is in the store. For self-signed certs it means the public key of the self-signed cert itself must be there. – AlwaysLearning Jul 28 '23 at 23:59
  • As far as connecting clients go, that also includes the SQL Server instance on which you're trying to `EXEC sp_addserver 'FQDN SERVER NAME'` – AlwaysLearning Jul 29 '23 at 00:01
  • OK and how are you connecting, are you using the full FQDN or just the machine name? – Charlieface Jul 29 '23 at 22:14
  • I have been connecting 'server=MyServer'. I haven't changed this to 'server=MyServer.Domain.com' as this would be a breaking change to a dozen apps that connect to the SQL server if this is now a requirement. If this is now a requirement in .NET 8, that adds problems that is probably out of the realm of this topic. – JayTee Jul 31 '23 at 17:21
  • I wanted to take .NET out of the loop, so based on the comments above I used the SQL Manager to `Force Encryption=Yes` and tried connecting with SSMS. Using `MyServer`, it failed. When I used the FQDN `MyServer.domain.com` I was able to connect just fine! Thinking I had a win, I went back to the .NET app and changed it to the FQDN. Unfortunately I still got the `Error: A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The target principal name is incorrect.)` – JayTee Jul 31 '23 at 17:36
  • I tried the simplest form for my connection string `Server=MyServer.domain.com;Database=MyDb;Trusted_Connection=True;` which failed with the same error. I tried a different connection string `Server=MyServer.domain.com;Database=MyDb;Persist Security Info=True; User ID=MyUser; Password=MyPassword;MultipleActiveResultSets=true; Encrypt=true; TrustServerCertificate=true;` which also failed with the same error. – JayTee Jul 31 '23 at 17:41
  • Trusted_Connection=Yes;Encrypt=Optional works for me. – Cetin Basoz Jul 31 '23 at 19:59

1 Answers1

0

First, thank you to everyone who made comments above. They were the actual solution. (Using the FQDN in the connection string instead of just the server name as it had been previously.)

The problem that I was facing and why the connection string worked in the test stub but not in the code was because someone had changed one of the connection strings in the appsettings.Development.json that overrode my changes to the main file. It just happened to be the one connection I was testing. I found that out after changing the hard-coded connection string to:

var connectionString = ctx.Database.GetConnectionString();

in order to find out exactly what the context thought it was connecting to.

JayTee
  • 437
  • 4
  • 10