Skip to content
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

WebClient / WebRequest can't use Negotiate (Kerberos) authentication #129

Open
IncubusRK opened this issue Dec 14, 2021 · 15 comments
Open

Comments

@IncubusRK
Copy link

When try next simple test, I get data on Windows, and WebException under wine-mono.

var request = (HttpWebRequest)WebRequest.Create("KERBEROS_TEST_URL");
request.Credentials = CredentialCache.DefaultCredentials;
request.UseDefaultCredentials = true;
using (var response = (HttpWebResponse)request.GetResponse())
using (var responseStream = new StreamReader(response.GetResponseStream()))
    Console.WriteLine("Response first line: {0}", responseStream.ReadLine());

I check negotiate auth in wine by install windows version of Firefox, it's work correct.

@IncubusRK
Copy link
Author

IncubusRK commented Dec 14, 2021

I also install dotnet 4.6.1 by using "winetricks dotnet461", and negotiate sample from first post also works fine.

sample-source.zip

@IncubusRK
Copy link
Author

Maybe importing System.Net.Security namespace from corefx can fix this.
NegotiateStream.cs from mono is only throwing NotImplementedException.

@madewokherd
Copy link
Owner

madewokherd commented Jan 4, 2022

The corefx version of this doesn't seem to be complete. It references a method called InitializeStreamPart that I can't find.

Edit: Never mind, it's in InternalNegotiateStream.cs, guess I'll keep trying.

@madewokherd
Copy link
Owner

Looks like this will require implementations of the AssociatedName, Spn, IsNTLM, IsMutualAuthFlag, IsConfidentialityFlag, IsIntegrityFlag, IsDelegationFlag, Encrypt, and Decrypt members of the NTAuthentication class in Mono.

@madewokherd
Copy link
Owner

OK, turns out Mono doesn't have an implementation of that either, I was just confused by their modification of the one in referencesource. So we can import that from corefx too.

Surprisingly, with a few imports from corefx, it builds, but I don't have a way to test it. I'll make a PR with the changes.

@IncubusRK
Copy link
Author

IncubusRK commented Jan 5, 2022

I make quick test, importing NegotiateStream is not enough.
I try to make detailed test on next week. Maybe another part of System.Net.Security also required...

@IncubusRK
Copy link
Author

Calling HttpWebRequest.GetResponse() in dotnet automatically add "Authorization: Negotiate ..." to HttpWebRequest.Headers. Wine-mono don't do that even after import NegotiateStream from corefx.

@madewokherd
Copy link
Owner

It could be that there's some special treatment elsewhere in corefx that we need to port to the Mono class libraries.

@madewokherd
Copy link
Owner

I'm having trouble figuring out how the Authorization header is supposed to get set, in either Mono classlibs or corefx.

@madewokherd
Copy link
Owner

So, if I'm understanding this correctly, Negotiate is a wire protocol for authentication, and by itself is not based on HTTP. NegotiateStream implements the wire protocol and none of the HTTP parts. For this to work in HTTP requests we still need something to connect the HTTP bits to the lower level implementation in NegotiateStream.

@madewokherd
Copy link
Owner

On corefx's HttpWebRequest, this appears to work based on winhttp.dll and not use NegotiateStream at all. I don't think switching over to this implementation is feasible, last time I tried to do something similar (to try to get crypt32-based certificate management) I found too many interdepedencies.

On Mono's HttpWebRequest, this works based on the AuthenticationManager class, for which Mono has registered builtin IAuthenticationModule classes for Basic, Digest, and NTLM authentication.

So, I think we need an IAuthenticationModule class for Negotiate, and such a thing doesn't exist yet. NegotiateStream may help, if it actually works (I don't currently have a way to test it, and I'm still suspicious of it). I don't understand how Negotiate works, so I don't know how hard that is, but for now it doesn't seem worth it for me to work on this, sorry.

@IncubusRK
Copy link
Author

I believe that the mechanism should be similar to the one in tests NegotiateStreamKerberosTest.cs
Unfortunately in practice ClientStream turns out to be closed before calling AuthenticateAsClientasync

@madewokherd
Copy link
Owner

Based on https://www.ietf.org/rfc/rfc4559.txt it seems like this communicates through repeated HTTP requests with different headers. NegoiateStream seems to use GSS-SPNEGO? Anyway, I don't think it's even helpful for this.

@madewokherd
Copy link
Owner

Hm, or maybe there needs to be a translation between HTTP header data and stream data? I still don't really get this.

madewokherd pushed a commit to madewokherd/mono that referenced this issue Jan 31, 2022
@IncubusRK
Copy link
Author

IncubusRK commented Aug 22, 2022

On corefx's HttpWebRequest, this appears to work based on winhttp.dll and not use NegotiateStream at all.

I try to run samples with WINEDEBUG=+kerberos,secur32,schannel,wininet,winhttp and I do not see the any calls of functions from these libraries...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants