Bug 7258 - WebRequest.DefaultWebProxy with credentials fails
Summary: WebRequest.DefaultWebProxy with credentials fails
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll (show other bugs)
Version: 5.2
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Martin Baulig
URL:
Depends on:
Blocks:
 
Reported: 2012-09-18 11:20 UTC by Christian Gan
Modified: 2012-11-08 15:57 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Wireshark capture (3.36 KB, application/octet-stream)
2012-09-18 11:29 UTC, Christian Gan
Details
iOSProxyAuthTest application (25.49 KB, application/octet-stream)
2012-09-25 14:23 UTC, Christian Gan
Details
Wireshark capture from iOSProxyAuthTest application (12.86 KB, application/octet-stream)
2012-09-25 14:25 UTC, Christian Gan
Details
Proposed changes to WebConnection.cs (31.21 KB, text/plain)
2012-10-17 11:56 UTC, Christian Gan
Details
My C:\squid\etc\squid.conf (1.38 KB, application/octet-stream)
2012-10-17 12:59 UTC, Martin Baulig
Details
digest password file; the password is `monkey' (52 bytes, application/octet-stream)
2012-10-17 13:00 UTC, Martin Baulig
Details
Command-line test app (657 bytes, application/octet-stream)
2012-10-17 13:00 UTC, Martin Baulig
Details
Proposed changes to WebConnection.cs part 2 (33.06 KB, text/plain)
2012-10-19 11:25 UTC, Christian Gan
Details
Simple test app and proposed fixes (6.34 KB, application/octet-stream)
2012-10-22 15:17 UTC, Christian Gan
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Christian Gan 2012-09-18 11:20:24 UTC
Runtime:
	Mono 2.10.9 (tarball)
	GTK 2.24.10
	GTK# (2.12.0.0)
	Package version: 210090011
Apple Developer Tools:
	 Xcode 4.3.2 (1177)
	 Build 4E2002

We're using a Web Reference to consume services from several of our servers.  The issue is that when we attempt to use WebRequest.DefaultWebProxy.Credentials, the service calls fail to properly authenticate to our proxy server (Squid 2.7.STABLE8). 

A capture from Wireshark shows something like this: 

1. Request: CONNECT ourserver.com:443 HTTP 1.0 
2. Response: HTTP/1.1 407 Proxy Authentication Required (text/html) 
  Proxy-Authenticate: Digest realm... etc. 
  Connection: Close 
3. Request: CONNECT ourserver.com:443 HTTP 1.0 
  Proxy-Authorization: Digest username... etc. 

The issue is that in the response (2), the squid server requests the current TCP connection to be closed (and in fact, it also sends a FIN right after the 407), but the client sends the request with authentication (3) on the same TCP connection instead of initiating a new one (which gets eventually RST by the proxy server). 

Our .NET version of the same above code running on Windows works as expected. 

Anyone else seeing an issue with proxy authentication?  I've tested with both digest and NTLM authentication.
Comment 1 Christian Gan 2012-09-18 11:29:50 UTC
Created attachment 2567 [details]
Wireshark capture
Comment 2 Christian Gan 2012-09-18 15:50:09 UTC
I've just tried the same test with MonoTouch 5.4.1 and the issue still exists.
Comment 3 Christian Gan 2012-09-25 14:23:30 UTC
Created attachment 2613 [details]
iOSProxyAuthTest application

See AppDelegate.FinishedLaunching() for proxy code
Comment 4 Christian Gan 2012-09-25 14:25:48 UTC
Created attachment 2614 [details]
Wireshark capture from iOSProxyAuthTest application
Comment 5 Christian Gan 2012-09-25 14:28:31 UTC
After further investigation it seems this has something to do with using a proxy and authenticating the CONNECT request.

See iOSProxyAuthTest application (attachment #2613 [details]) and the corresponding wireshark capture (attachment #2614 [details]).

Using the same credentials for HTTP and HTTPS, the proxied HTTP POST request succeeds with authentication but the HTTPS CONNECT request fails.
Comment 6 Christian Gan 2012-10-09 16:48:00 UTC
After perusing the mono libraries I think the main culprit here is WebConnection.cs::CreateTunnel().  This method sends the CONNECT request for a proxied HTTPS request.

For NTLM:
- If you are creating a CONNECT tunnel using NTLM, you MUST include the "Proxy-Connection: Keep-Alive" header field in order for the connection to complete it's multipart handshake.

For Digest:
- If you look at the AuthenticationManager.Authenticate(challenge, request, creds) line, the request in question is the original request (e.g. POST, GET, etc) and not the CONNECT request.  Therefore in the when calculating the Digest response (see DigestClient.cs), the method and URI match the original request and not for the CONNECT.

I think the above explains things that I am seeing on our end.  BTW: we still haven't seen much activity on the bug we posted, has there been anyone assigned to this issue?

Also, if I wanted to test changes to the above files, what would be the easiest way I could modify monotouch (if at all)?
Comment 7 Rolf Bjarne Kvinge [MSFT] 2012-10-09 17:36:54 UTC
Martin, this looks like your area now, can you have a look?
Comment 8 Martin Baulig 2012-10-09 17:40:00 UTC
Yeah, sure.  I just finished my wsdl collections work and wanted to do some bug fixing anyways now ;-)
Comment 9 Christian Gan 2012-10-17 11:56:54 UTC
Created attachment 2756 [details]
Proposed changes to WebConnection.cs

I've made changes to WebConnection.cs (based on mono 2.10.9).  I've tested that this works on the WIN32 platform, but please look it over and test it yourselves just in case I've broken anything else.

Is there any way I can test this change on Monotouch so that I can verify that it works for our iOS application?
Comment 10 Martin Baulig 2012-10-17 12:57:38 UTC
Just tested this with a simple command line app and digest authentications and realised that there's a regression somewhere between Mono 2.10.10 and 2.11.2.
Comment 11 Martin Baulig 2012-10-17 12:59:29 UTC
Created attachment 2757 [details]
My C:\squid\etc\squid.conf
Comment 12 Martin Baulig 2012-10-17 13:00:17 UTC
Created attachment 2758 [details]
digest password file; the password is `monkey'
Comment 13 Martin Baulig 2012-10-17 13:00:43 UTC
Created attachment 2759 [details]
Command-line test app
Comment 14 Christian Gan 2012-10-17 13:16:10 UTC
@Martin: not sure what you mean by regression.  Did something else break between 2.10.10 and 2.11.2?  Because we're seeing issues in 2.10.9.
Comment 15 Martin Baulig 2012-10-17 13:18:19 UTC
I mean that digest authentication broke somewhere between 2.10.10 and 2.11.2 - and the breakage also found its way into monotouch.

What's more important to you: digest auth or ntlm ?
Comment 16 Christian Gan 2012-10-17 13:20:27 UTC
Ah, of course I'm going to say they're both important ;), but let's start with digest as that would probably be more common.
Comment 17 Martin Baulig 2012-10-17 13:50:44 UTC
Ok, found the first problem :-)

The server returns this:

===
Proxy-Authenticate: Digest realm="Provcon-Faust", nonce="le1+UCAk1gLAdQAA", qop="auth", stale=false
===

HttpWebRequest.CheckAuthorization() calls 'response.Headers.GetValues ("Proxy-Authenticate")' which splits this on the commas, returning 4 headers instead of just 1.
Comment 18 Martin Baulig 2012-10-18 00:00:47 UTC
Update:

Digest authentication is now working with and without SSL with master, 2.10 and monotouch.

Spent the last couple of hours trying to get NTLM working on Windows, then finally found this article:
http://social.technet.microsoft.com/Forums/en/windowsserver2008r2general/thread/6249b318-2aed-4923-a3d8-44ef8c9b6c71

The
Network security: LAN Manager authentication level - Send LM & NTLM - use NTLMv2 if negotiated
really helped.

Now I have NTLM auth working in a command-line version on Windows and with mono without SSL.
Comment 19 Christian Gan 2012-10-18 10:12:47 UTC
Funny, I had to fight the same problem and found the same solution when we needed to get NTLM working on Windows about a month ago...

Anyways, looks like you're close to a solution here Martin.  To get NTLM working with SSL on mono (via CONNECT), take a look at what I did in WebConnection.cs (which is very similar to what happens in HttpWebRequest.cs).
Comment 20 Christian Gan 2012-10-18 10:29:25 UTC
There are some key things I had to do get the CONNECT request to authenticate with NTLM, hopefully it helps you:

- The NTLMSSP_NEGOTIATE and NTLMSSP_AUTH responses have to come on the same TCP connection, so needed to add "Proxy-Connection: keep-alive" to the CONNECT NTLM responses.  Otherwise squid will complain and break the connection on the NTLMSSP_NEGOTIATE.
- Because of the above, you must flush the server's entire NTLMSSP_CHALLENGE response (headers and contents) from the stream so that you can read the next server response from the same stream.
- In WebConnection.CreateTunnel, don't throw the SecureChannelFailure exception until the entire multipart NTLM auth has completed or failed.
Comment 21 Martin Baulig 2012-10-18 17:45:58 UTC
Thanks, I must admit, I have no idea how NTLM works.

However, I just tested your WebConnection.cs and it's working fine in Mono master :-)

Now testing with Monotouch.
Comment 22 Christian Gan 2012-10-18 18:12:11 UTC
Sweet
Comment 23 Martin Baulig 2012-10-18 18:42:41 UTC
Unfortunately, it seems like I just broke digest authentication :-(
Comment 24 Martin Baulig 2012-10-18 18:58:57 UTC
Ok, the problem is the following:

The server supports both Digest and NTLM authentication, both have different usernames (mono/monkey for Digest and test/monkey for NTLM in my case).

On the first request, the server replies

{Server: squid/2.7.STABLE8
 Date: Thu, 18 Oct 2012 22:51:01 GMT
 Content-Type: text/html
 Content-Length: 1324
 X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
 Proxy-Authenticate: Digest realm="Provcon-Faust", nonce="1YeAUCA8iwPkdAAA", qop="auth", stale=false,NTLM
 X-Cache: MISS from Provcon-Faust
 X-Cache-Lookup: NONE from Provcon-Faust:3128
 Via: 1.0 Provcon-Faust:3128 (squid/2.7.STABLE8)
 Connection: close
 
 }

I set the NTLM credentials and we reply with

{CONNECT www.google.com:443 HTTP/1.0
 Host: www.google.com
 Proxy-Authorization: Digest username="test", realm="Provcon-Faust", nonce="1YeAUCA8iwPkdAAA", uri="/", response="21b349cc5255e9098ea27660b81b1ae6", qop="auth", nc=00000001, cnonce="ZftmT7WhUXn0WmSVGsxc"
 Proxy-Authorization: NTLM TlRMTVNTUAABAAAAA5IAAA0ADQAgAAAAAAAAACAAAABQUk9WQ09OLUZBVVNU
 Proxy-Connection: keep-alive
 
 }

The server then replies with another 407

{Server: squid/2.7.STABLE8
 Date: Thu, 18 Oct 2012 22:52:43 GMT
 Content-Type: text/html
 Content-Length: 1324
 X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
 Proxy-Authenticate: Digest realm="Provcon-Faust", nonce="O4iAUJA8iwOaeQAA", qop="auth", stale=false
 X-Cache: MISS from Provcon-Faust
 X-Cache-Lookup: NONE from Provcon-Faust:3128
 Via: 1.0 Provcon-Faust:3128 (squid/2.7.STABLE8)
 Connection: close
 
 }

which will then of course fail because I set the NTLM credentials and not the Digest ones.

Any idea why the server is rejecting the NTLM Authorization ?

It works fine if I swap NTLM and Digest in my squid.conf, making NTLM come first.
Comment 25 Martin Baulig 2012-10-18 22:27:51 UTC
Nevermind, I figured it out - all done now :-)

I also tested this with your original test case in Monotouch and it's now working fine !
Comment 27 Christian Gan 2012-10-19 10:47:15 UTC
Dang, I'm running into my original issue noted in comment #0 (attachment #2567 [details]).  This seems to only happen for me in monotouch (not on my Win32 mono) and only occasionally happens (~1/5 times).

To re-iterate (see attachment #2567 [details]):
1. Request: CONNECT ourserver.com:443 HTTP 1.0 
2. Response: HTTP/1.1 407 Proxy Authentication Required (text/html) 
  Proxy-Authenticate: Digest realm... etc. 
  Connection: Close 
3. Request: CONNECT ourserver.com:443 HTTP 1.0 
  Proxy-Authorization: Digest username... etc. 

The issue is that in the response (2), the squid server requests the current
TCP connection to be closed (and in fact, it also sends a FIN right after the
407), but the client sends the request with authentication (3) on the same TCP
connection instead of initiating a new one (which gets eventually RST by the
proxy server).
Comment 28 Christian Gan 2012-10-19 10:48:30 UTC
BTW: the issue noted in comment #27 happens for both NTLM and Digest.
Comment 29 Christian Gan 2012-10-19 11:25:22 UTC
Created attachment 2766 [details]
Proposed changes to WebConnection.cs part 2
Comment 30 Christian Gan 2012-10-19 11:30:25 UTC
See attachment #2766 [details].

Since I can't recompile monotouch, this is a bit of a shot in the dark to fix the issue I'm seeing in comment #27.  Basically, if the 407 response from the server contains a "Connection: close" header field, we should close the current socket and not re-use it.

That being said, WebConnection.CanReuse should be able to detect that the socket has been closed remotely?  Maybe it's just timing? I'm not sure why this only sometimes affects monotouch.

I've tested that the above fix does not adversely affect the mono Win32 version (2.10.9).
Comment 31 Martin Baulig 2012-10-21 12:46:50 UTC
I think it is timing, depending on whether or not the client already received the FIN from the server.

I'm also seeing this with a simple command-line test:
https://github.com/baulig/Provcon-Faust/blob/839f050b1d9f312e1fe073007d1c507a87538d79/TestProxyAuth/Main.cs

The CreateTunnel() part of your patch fixes this for me.

Which means there's a decent chance now that I can finish all three of the current WebConnection.cs bugs: this one, #7599 and #6329 :-)
Comment 32 Martin Baulig 2012-10-21 15:36:40 UTC
Should be fixed now; mono master c399f10, 2-10 5e29582, mobile-master e52cc69.
Comment 33 Martin Baulig 2012-10-21 15:39:42 UTC
Christian, I mailed you an updated System.dll and the WebConnection.cs containing the fix for both this bug and #7599, which is related (reusing existing connection to proxy server where it shouldn't).
Comment 34 Christian Gan 2012-10-22 15:17:23 UTC
Created attachment 2773 [details]
Simple test app and proposed fixes
Comment 35 Christian Gan 2012-10-22 15:33:08 UTC
Layers upon layers Martin... layers upon layers.  I think we've fixed the issues due to the SSL connect failing through the proxy, but it seems there are still problems in the non-SSL connections :(.

See attachment #2773 [details] for a simple test app to replicate this problem along with proposed fixes.

Both failures occur on the second attempt to create a request and will occur for NTLM and Digest for different reasons:

- Digest: It seems in DigestClient.cs the digest session is hashed using the request's address and credentials.  But it fails to take into consideration the server's nonce value.  If the server's nonce value changes shouldn't there be a new digest session created?  I've changed DigestClient.cs to add the server's nonce to the hash.

- NTLM: A null reference exception occurs in WebConnectionGroup.PrepareSharingNtlm because this method assumes the NTLM auth was performed using the request.Credentials instead of request.Proxy.Credentials.  I think this guy was running into the issue a while ago: http://mono.1490590.n4.nabble.com/Problem-when-HttpWebRequest-GetRequestStream-called-td3585594.html.  Anyways, I've put in extra checks so that the exception doesn't occur.
Comment 36 Martin Baulig 2012-10-23 17:22:12 UTC
Ok, I'll have a look at these now.
Comment 37 Martin Baulig 2012-10-23 19:29:59 UTC
Thanks a lot for your patch, it fixed the problem for me :-)
Comment 38 Christian Gan 2012-10-25 09:49:51 UTC
Good news Martin, looks like this last update is a winner!
Comment 39 Sebastien Pouliot 2012-11-08 13:08:33 UTC
Martin, any reason to keep this bug report open ?
Comment 40 Martin Baulig 2012-11-08 15:57:40 UTC
No, let's close it.