wine-mono
                                
                                 wine-mono copied to clipboard
                                
                                    wine-mono copied to clipboard
                            
                            
                            
                        WebClient / WebRequest can't use Negotiate (Kerberos) authentication
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.
I also install dotnet 4.6.1 by using "winetricks dotnet461", and negotiate sample from first post also works fine.
Maybe importing System.Net.Security namespace from corefx can fix this. NegotiateStream.cs from mono is only throwing NotImplementedException.
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.
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.
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.
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...
Calling HttpWebRequest.GetResponse() in dotnet automatically add "Authorization: Negotiate ..." to HttpWebRequest.Headers. Wine-mono don't do that even after import NegotiateStream from corefx.
It could be that there's some special treatment elsewhere in corefx that we need to port to the Mono class libraries.
I'm having trouble figuring out how the Authorization header is supposed to get set, in either Mono classlibs or corefx.
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.
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.
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
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.
Hm, or maybe there needs to be a translation between HTTP header data and stream data? I still don't really get this.
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...