-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does NegotiateStream support Kerberos Authentication on Linux and how? #26418
Comments
Can you specify what scenarios you think don't work? Are they HTTP scenarios (using HttpClient) or NegotiateStream scenarios (using NegotiateStream class). Or just SQL Client APIs? Can you post some sample code to demonstrate what APIs you're using? In general, we don't know of any known Kerberos issues with Linux as a client. Kerberos does requires interaction with a Kerberos server (i.e. Windows Active Directory) and the Linux client needs to be configured with Kerberos including setup against the Kerberos ticketing server, etc. |
we are using NegotiateStream; no HTTP scenarios; refer to #26293 for the sample code; karelz asked that I open a new issue; see my original post in #26293. Specifically we are writing a .NET Data Provider (similar in concept to the .NET Data Provider for SQL Server). The Data Provider must use Kerberos to authenticate and establish a connection to the Database server. This has been working on .NET Framework for years; now we are porting the Data Provider to .NET Core and it must run on Linux, macOS and Windows. |
Thx for the added info. What distro of Linux did you try this on? We'd like to set up the same environment to see if we can reproduce the problem you're seeing. Please include detail such as what packages (apt-get etc.) are installed into the distro. |
to answer some of your questions @CalArabshahi : At least for HTTP with 2.1 Negotiate stream does not use cache created with kinit - but creates in-memory ticket. |
BTW Credential Cache.DefaultNetworkCredentials may not work on Unix. You can look at unit tests under src/System.Net.Security/tests and use that as example. |
@wfurt I think you are stating that the following line of code from #26293 will not work on Linux authStream.AuthenticateAsClient(CredentialCache.DefaultNetworkCredentials, "HOST/ESROOT",
ProtectionLevel.EncryptAndSign,
impLevel); and that we must perform something like public static void GetDefaultKerberosCredentials(string username, string password)
{
// Fetch a Kerberos TGT which gets saved in the default cache
SafeGssCredHandle.Create(username, password, isNtlmOnly:false).Dispose();
} is this correct? |
As I stated on #26293: Kerberos support on Linux has likely rough edges. We tested it only on If you can help us debug through your scenario and tell us where things don't work as expected, we can likely help. |
I did some experimenting on Linux using a multi-machine setup (Windows w/ Active Directory machines and Linux client) that I am working on (eventually to be used as our 'Enterprise-Scenario' testing environment). I was able to get a Linux Debian-9 HttpClient to connect to a Windows IIS website using Kerberos (specified as Negotiate.Kerberos on IIS server) with both an explicit NetworkCredential and "default credentials" (CredentialCache.DefaultCredentials). In the "default credentials" case, the authentication did not work at first since I had no "kinit" done. But after doing a "kinit" with a credential from the Windows Active Directory domain, the .NET Core 2.1 app was able to use HttpClient with CredentialCache.DefaultCredentials. Code: var server = new Uri("http://corefx-net-iis.corefx-net.contoso.com/test/auth/kerberos/showidentity.ashx");
var handler = new HttpClientHandler();
// Use either explicit credential or default credentials
//handler.Credentials = new NetworkCredential("user1", "password", "COREFX-NET.CONTOSO.COM");
//handler.Credentials = CredentialCache.DefaultCredentials;
var client = new HttpClient(handler);
HttpResponseMessage response = await client.GetAsync(server); Explicit Network Credential (works)
Default Credentials test
Note: there is a separate bug here because the "Win32Exception" shouldn't be the top-level exception thrown by HttpClient. It should be an HttpRequestException as top-level exception. And then inside that it could the Win32Exception or perhaps something else like AuthenticationException and then Win32Exception inside that. Then do a "kinit" and Default Credentials (works)
I have not yet experimented with NegotiateStream class yet but plan to try that out over the coming days. |
I was able to test System.Net.Security.NegotiateStream between Windows and Linux using Kerberos. I setup the NegotiateStream server on a Windows machine (that is joined to the COREFX-NET domain). The client was on the Linux machine (also "joined" to the COREFX-NET domain). I used .NET Core 2.1 for everything. I made sure to run the NegotiateStream server application in the context of the machine account (NT AUTHORITY\SYSTEM) since all the default SPN's (such as HOST/COREFX-NET-IIS) on Windows are only registered against the machine account. I used the PsExec utility to run the server application under that machine context. I then used "kinit" to set up the "default credentials" for the Linux machine. I did a "kinit user2" which maps to COREFX\user2 user account on the domain. Here are the code snippets and results. As you can see, NegotiateStream worked and used Kerberos (and not NTLM). I have not yet tried the inverse of this test (i.e. a Linux NegotiateStream server and Windows NegotiateStream client). To do that, I will need to register some new SPN's against the Linux machine account. I'll try that at some point later. Code snippet (server) NegotiateStream authStream = new NegotiateStream(stream, false);
authStream.AuthenticateAsServer(
CredentialCache.DefaultNetworkCredentials,
ProtectionLevel.EncryptAndSign,
TokenImpersonationLevel.Identification); Code snippet (client) NegotiateStream authStream = new NegotiateStream(clientStream, false);
authStream.AuthenticateAsClient(
CredentialCache.DefaultNetworkCredentials,
"HOST/corefx-net-iis",
ProtectionLevel.EncryptAndSign,
TokenImpersonationLevel.Identification); Windows Server (NegotiateStream as server)
Linux Client (NegotiateStream as client)
|
cc: @stephentoub @rmkerr @Caesar1995 in case you're curious about Kerberos authentication in HttpClient and/or NegotiateStream classes. |
Based on the tests I've done with both HttpClient and NegotiateStream, I can say that .NET Core 2.1 supports Kerberos authentication from a Linux Client against a service (Windows server in the tests I ran). The key things I've noticed to make it work with Kerberos are:
Problems with any of the above configuration will result in NegotiateStream using NTLM instead of Kerberos. And in some cases, failing to authenticate at all and returning an error. |
Is not the need of SPN (must be registered, service run under machine account) too restrictive. Windows AD based servers can use UPN , e.g machine$@DOMAIN.COM, even Linux based servers that join AD can use it. GSSAPI supports that, if gss_import_name is called with GSS_C_NT_USER_NAME Currently UPN can be used as targetName in NegotiateStream.AuthenticateAsClient() on Windows, and I hope Linux could support it too, one day. |
Should we close this and open specific bug or feature request if something did not get answered? |
No. Don't close this. It is currently marked for 'documentation' and that is part of my work. I will close this when a corresponding documentation item is create for it. Not sure where that will be yet. |
This seems to be related to all your recent improvements @davidsh. Can we fix documentation for 5.0? |
Now tracking with dotnet/docs#14310 |
I stumbled on this as I was trying to work out how to convert a Kerberos ticket obtained with Kerberos.Net to an dotnet/aspnetcore#18576 (comment) I thought I'd ask in case anyone else had an idea as to how we could perform this leap from performing Kerberos authentication to SignalR: var client = new KerberosClient();
var kerbCred = new KerberosPasswordCredential("user@domain.com", "userP@ssw0rd!");
await client.Authenticate(kerbCred);
var ticket = await client.GetServiceTicket("http/yoursignalr.app.com");
var connection = new HubConnectionBuilder()
.WithUrl("https://our.server.com/hub/bub", options =>
{
options.Credentials = // somehow use ticket here?
})
.Build(); |
@karelz and @davidsh Would you please describe/state whether .NET Core 2.1 supports Kerberos Authentication from a Linux Client against a service? IMO, there are lots of confusing statements/issues around Kerberos Authentication on Linux and macOS and no clear statement as to what works and what does not work. Please clarify. For example how does ".NET Data Provider for SQL Server" support Kerberos authentication on Linux. Does it revert back to P-Invoke calls; if yes why? We are trying to create a roadmap for our product and hope to make it work on all platforms. I think Kerberos Authentication is fundamental and it has been tested on Linux (e.g. Red-Hat) already. I hope we are missing something fundamental (e.g. how to populate the cache with a Kerberos TGT for). Thanks in advance for clarification and help with Kerberos authentication on Linux and eventually macOS. I originally posted this question in #26293 .
The text was updated successfully, but these errors were encountered: