dotnet / SqlClient

Microsoft.Data.SqlClient provides database connectivity to SQL Server for .NET applications.
MIT License
836 stars 277 forks source link

Server principle name lookup does not include port number in the name #2394

Closed trexx closed 2 months ago

trexx commented 6 months ago

Describe the bug

Upon updating from 5.1.5 to 5.2.0, our applications running on Linux fail to connect to our databases using Integrated Security / Kerberos with an error: Microsoft.Data.SqlClient.SqlException (0x80131904): The target principal name is incorrect. Cannot generate SSPI context.

This is with a connection string such as: "Data Source=server.domain.local;Integrated Security=true"

server.domain.local here is a CNAME which resolves to server001.domain.local

In version 5.1.5 I can see it resolves the SPN in 2 different ways. It first resolves the SPN without the port number, and if that fails it retries with the port number in the SPN. 1st try -> MSSQLSvc/server001.domain.local@DOMAIN.LOCAL 2nd try -> MSSQLSvc/server001.domain.local:1433@DOMAIN.LOCAL < Lookup successful

In version 5.2.0, it only resolves the SPN without the port number, and then performs no more searches causing connectivity to fail. 1st try -> MSSQLSvc/server001.domain.local@DOMAIN.LOCAL

Our workaround has been to specify the port number in the connection string. "Data Source=server.domain.local,1433;Integrated Security=true"

Is this change of behaviour intentional or a result of a bug? We're not sure if this will be fixed in SqlClient, or if we should update our SPNs, or whether we should start including port numbers in all our connection strings.

Further technical details

Microsoft.Data.SqlClient version: 5.2.0 .NET target: 8.0 Operating system: Linux Container

JRahnama commented 6 months ago

@trexx We are aware of this issue in v5.2.0. Currently, we are investigating the code change that caused this behavior change. Could you please test with v5.2.0-preview5 and see if it works as you expect?

trexx commented 6 months ago

@JRahnama The behaviour and result is the same with v5.2.0-preview5; The SPN its searching for does not include the port number and it does not retry with the port number unlike 5.1.5. Connectivity fails with the same error message.

The target principal name is incorrect. Cannot generate SSPI from .NET exception. TGS request result: -1765328377/Server not found in Kerberos database from KRB5_TRACE logs.

David-Engel commented 6 months ago

@trexx To narrow it down even further, can you try the earlier previews? I suspect 5.2.0 preview 4 will start working for you, but if it doesn't it will be good to know which one contains the behavior change.

trexx commented 5 months ago

Hi @David-Engel I've been able to narrow it down to 5.2.0-preview2.23159.1 when the SPN behaviour is the same as 5.1.5. Preview versions after this fail.

JRahnama commented 5 months ago

@trexx :

  1. On the exception message, after The target principal name is incorrect. Cannot generate SSPI context. at the next line there should be another word indicating Status code of negotiation with server. Can you also provide that.
  2. Can you test the same application with net6 and see the outcome? The reason for this is going back to PR #2063
  3. In my testing I only was able to repro this when Kerberos ticket was expired or killed or not generated. When I regenerated a ticket (kinit) it started working.
trexx commented 5 months ago

@JRahnama

  1. Microsoft.Data.SqlClient.SqlException (0x80131904): The target principal name is incorrect. Cannot generate SSPI context.
    GenericFailure
  2. Yes. Building with net6 and SqlClient 5.2.0 results in a successful connection, and a return to the behaviour seen in version net8.0 & SqlClient 5.2.0-preview2.23159.1 and older.

  3. Our tickets are very much valid during the times we encounter this. I can re-produce errors and successes with certainty. I.e., there's no chance involved.

I suspect if you want to reproduce this on your end, you'll need to remove the default instance SPN for your SQL instance that doesn't have the port number listed and keep the SPN containing :1433. Such as the examples in the table here: https://learn.microsoft.com/en-us/sql/relational-databases/native-client/features/service-principal-name-spn-support-in-client-connections?view=sql-server-ver15#specifying-the-spn https://learn.microsoft.com/en-us/sql/connect/oledb/features/service-principal-name-spn-support-in-client-connections?view=sql-server-ver16#specifying-the-spn

This is likely because after 5.2.0-preview2.23159.1 its the only SPN that is searched for and contradicts the above documentation which explains:

MSSQLSvc/fqdn - The provider-generated, default SPN for a default instance when a protocol other than TCP is used.
MSSQLSvc/fqdn:port - The provider-generated, default SPN when TCP is used.

So we are puzzled as to whether this change in behaviour is intentional and requires changes to our SPNs here or if this is unexpected.


Doing a bit of digging, I can see a similar issue / PR which explains why we see behaviour in the previous versions. https://github.com/dotnet/SqlClient/pull/629 https://github.com/dotnet/SqlClient/pull/930

arellegue commented 4 months ago

@trexx, Could you please confirm if the Sql Server that you are connecting to has a defined Instance name or just default instance name.

kf-gonzalez2 commented 3 months ago

@trexx please try again after the 5.2.1 Hotfix is published and please let us know if you are still having an issue

JRahnama commented 3 months ago

Hotfix v5.2.1 is released. Can you try with that version please?

trexx commented 3 months ago

@arellegue Sorry for the late reply, it has a defined instance name (Listening on both a random port and 1433).

@kf-gonzalez2 @JRahnama I've just tested against 5.2.1 and I get the same error. Once adding 1433 to the connection string it connects fine, otherwise without it, it errors Server not found in Kerberos database

arellegue commented 3 months ago

If there is a defined instance, you may want to include the instance name in your connection string.

MSSQLSvc/ fqdn : InstanceName

Please try that and let us know.