dbcli / mssql-cli

A command-line client for SQL Server with auto-completion and syntax highlighting
BSD 3-Clause "New" or "Revised" License
1.35k stars 191 forks source link

Use GSS_C_NT_HOSTBASED_SERVICE, not GSS_KRB5_NT_PRINCIPAL_NAME #474

Open nicowilliams opened 4 years ago

nicowilliams commented 4 years ago

Using GSS_KRB5_NT_PRINCIPAL_NAME, and setting the realm to anything other than the empty realm, is a recipe for failure in multi-realm environments.

For example, today I had to debug a case involving three realms, let's call them AD.FOO.EXAMPLE, FOO.EXAMPLE, and N.FOO.EXAMPLE, where on a Linux system [libdefaults] default_realm = N.FOO.EXAMPLE, and the SQL Server's principal really is MSSQLSvc/someserver.ad.foo.example@AD.FOO.EXAMPLE, but mssql-cli constructed a raw Kerberos principal name of the form MSSQLSvc/someserver.ad.foo.example@<default_realm>, i.e., MSSQLSvc/someserver.ad.foo.example@N.FOO.EXAMPLE. The client credentials we for user@AD.FOO.EXAMPLE...

What happened then was that the client fetched a cross-realm TGT, krbtgt/N.FOO.EXAMPLE@FOO.EXAMPLE then asked a KDC for N.FOO.EXAMPLE for a service ticket for MSSQLSvc/someserver.ad.foo.example@N.FOO.EXAMPLE, which yielded a referral to FOO.EXAMPLE, which then rejected the request because it would mean doubling back to AD.FOO.EXAMPLE, which would be a loop.

Constructing an alternate krb5.conf with [libdefaults] default_realm = AD.FOO.EXAMPLE and using it by setting the KRB5_CONFIG environment variable worked around the problem by causing mssql-cli to construct the correct service principal name, MSSQLSvc/someserver.ad.foo.example@AD.FOO.EXAMPLE.

If mssql-cli had either use GSS_C_NT_HOSTBASED_SERVICE and MSSQLSvc@someserver.ad.foo.example, or GSS_KRB5_NT_PRINCIPAL_NAME and MSSQLSvc/someserver.ad.foo.example@ (note the "empty" realm), then it would have worked without us having to work around it.

nicowilliams commented 4 years ago

See https://github.com/FreeTDS/freetds/issues/338.

nicowilliams commented 4 years ago

MIT Kerberos and Heimdal nowadays support :<port> in service principal names, too. FYI.

nicowilliams commented 4 years ago

Hmm, where in this codebase might a fix go? I couldn't find anything about initiation of GSS security contexts. There are large binary artifacts in the repo, which is where I imagine the code is.

nicowilliams commented 4 years ago

https://krbdev.mit.edu/rt/Ticket/Display.html?id=8903

detule commented 4 years ago

I looked into this once (how does their service construct principal names).

I believe it's somewhere in here:

https://github.com/dotnet/corefx/blob/release/2.2/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs#L344

Good luck.