This is Xamarin's bug tracking system. For product support, please use the support links listed in your Xamarin Account.
Bug 19594 - WebException.Response is null when https request needs proxy authentication
Summary: WebException.Response is null when https request needs proxy authentication
Status: VERIFIED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System (show other bugs)
Version: 3.4.0
Hardware: PC All
: High normal
Target Milestone: ---
Assignee: Marek Safar
URL:
Depends on:
Blocks: 44978
  Show dependency tree
 
Reported: 2014-05-07 09:38 UTC by Matt Ward
Modified: 2016-10-03 14:22 UTC (History)
3 users (show)

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


Attachments
Unit tests for proxy authentication (1.54 KB, application/octet-stream)
2014-05-07 09:38 UTC, Matt Ward
Details

Description Matt Ward 2014-05-07 09:38:57 UTC
Created attachment 6750 [details]
Unit tests for proxy authentication

When a machine has a system wide proxy that requires authentication for all https requests, requesting a secure url such as https://www.nuget.org/api/v2 the WebException thrown contains a null Response. Making a request to a non-secure url does include a non-null Response object.

With the following console code:

public static void Main (string[] args)
{
	string url = "https://www.nuget.org/api/v2";

	var request = WebRequest.Create(url) as HttpWebRequest;
	
	// Mirroring NuGet's behaviour with the proxy and default 
	// credentials for the proxy.
	// If the proxy and the default credentials are not set
	// then a different error ConnectFailure occurs.
	var systemProxy = WebRequest.GetSystemWebProxy ();
	request.Proxy = systemProxy;
	request.Proxy.Credentials = CredentialCache.DefaultCredentials;

	WebException webEx = null;
	try {
		request.GetResponse ();
	} catch (WebException ex) {
		webEx = ex;
	}

	var response = webEx.Response as HttpWebResponse;
	Console.WriteLine("WebException.Status: {0}", webEx.Status);
	if (response != null) {
		Console.WriteLine ("Response.StatusCode: {0}", response.StatusCode);
	}

	Console.WriteLine (webEx);
}

The expected result is:

WebException.Response != null.
WebException.Status == ProtocolError.
WebException.Response.StatusCode == ProxyAuthenticationRequired

Actual result is:

WebException.Response == null.
WebException.Status != ProtocolError.


On the Mac with Mono 3.4.0:
===========================

WebException.Status: SecureChannelFailure
System.Net.WebException: Error getting response stream (The remote server returned a 407 status code.): SecureChannelFailure ---> System.Exception:
    at System.Net.WebConnection.HandleError(WebExceptionStatus st, System.Exception e, System.String where)
    at System.Net.WebConnection.CreateTunnel(System.Net.HttpWebRequest request, System.Uri connectUri, System.IO.Stream stream, System.Byte[] ByRef buffer)
    at System.Net.WebConnection.CreateStream(System.Net.HttpWebRequest request)
    at System.Net.WebConnection.InitConnection(System.Object state)    at System.Net.WebConnection.<WebConnection>m__0(System.Object state)
   at System.Net.WebConnection.HandleError (WebExceptionStatus st, System.Exception e, System.String where) [0x0003a] in /Volumes/build-root-ramdisk/mono-3.4.0/mcs/class/System/System.Net/WebConnection.cs:488    --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x0005e] in /Volumes/build-root-ramdisk/mono-3.4.0/mcs/class/System/System.Net/HttpWebRequest.cs:987
    at System.Net.HttpWebRequest.GetResponse () [0x0000e] in /Volumes/build-root-ramdisk/mono-3.4.0/mcs/class/System/System.Net/HttpWebRequest.cs:1003


On Windows using Mono 3.2.3:
============================

WebException.Status: SecureChannelFailure
System.Net.WebException: Error getting response stream (The remote server returned a 407 status code.): SecureChannelFailure ---> System.Exception:    at System
.Net.WebConnection.HandleError(WebExceptionStatus st, System.Exception e, System.String where)
   at System.Net.WebConnection.CreateTunnel(System.Net.HttpWebRequest request, System.Uri connectUri, System.IO.Stream stream, System.Byte[] ByRef buffer)
   at System.Net.WebConnection.CreateStream(System.Net.HttpWebRequest request)
   at System.Net.WebConnection.InitConnection(System.Object state)
   at System.Net.WebConnection.<WebConnection>m__20(System.Object state)
  at System.Net.WebConnection.HandleError (WebExceptionStatus st, System.Exception e, System.String where) [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0



On Windows using .NET Framework:
================================

WebException.Status: ProtocolError
Response.StatusCode: ProxyAuthenticationRequired
System.Net.WebException: The remote server returned an error: (407) Proxy Authentication Required.
   at System.Net.HttpWebRequest.GetResponse()



Proxy configuration
===================

To test this I used Fiddler installed on Windows and using it as a reverse proxy for the Mac.
http://www.telerik.com/fiddler

To enable the reverse proxy:
http://docs.telerik.com/fiddler/configure-fiddler/tasks/usefiddlerasreverseproxy

To enable proxy authentication in Fiddler:
Select Rules menu, then select Require Proxy Authentication.

To setup the Mac to use a proxy:
================================

System Preferences - Network - Advanced - Proxies.
Tick both:
"Web Proxy (HTTP)"
"Secure Web Proxy (HTTPS)"

Enter the IP address of your Windows machine and the Fiddler port 8888.
Click OK.
Click Apply.
Comment 1 Martin Baulig 2014-05-12 10:49:17 UTC
Why do you need this?  If it's just cosmetic, ie. no customer complained / uses this in their code, then please set priority to enhancement.  Error handling is suboptimal at other places as well.
Comment 4 Martin Baulig 2014-05-12 11:38:53 UTC
You are the "customer" who has a real problem with this, so let's keep priority at normal :-)

I just couldn't think of any real-world situation where this could be a problem until you told me about NuGet.
Comment 6 Matt Ward 2014-05-14 06:37:21 UTC
I have added a change to NuGet to handle the 407 response over a HTTPS connection on Mono. So changing the Importance of this issue down to Low.
Comment 7 Miguel de Icaza [MSFT] 2016-06-23 20:33:14 UTC
Marek, do you mind taking a look at this?
Comment 8 Marek Safar 2016-08-16 20:31:54 UTC
Fixed in master
Comment 9 Matt Ward 2016-09-28 14:22:31 UTC
I have tried a recent build from master: 4.9.0 (master/94cc2de) and also Mono 4.8.0 and proxy auth still seems to not work with a https url.

The WebException.Response is still null when proxy authentication is required for a http request.

I can see that now there is a WebException added as the InnerException to the WebException. NuGet uses the status code from the parent exception so NuGet still fails to recognise that a proxy authentication response has been returned.

The workaround added to NuGet no longer works with Mono 4.6 or above.

The unit tests attached to the bug report are still failing for me for the https request.
Comment 10 Marek Safar 2016-09-30 22:13:29 UTC
Fixed in master and Mono 4.8
Comment 11 Matt Ward 2016-10-03 10:23:42 UTC
This fix looks good with NuGet v2.

Tested a recent build of Mono 4.8.0 with Xamarin Studio 6.0.2 and I see a proxy auth dialog for both http and https package sources.

4.8.0 (mono-4.8.0-branch/a1b9700 Sun Oct  2 18:50:48 EDT 2016)
4.8.0.158

Trying an older Mono 4.8.0.53 without the fix and Xamarin Studio 6.0.2 fails to show a proxy auth dialog.

NuGet v3 in Xamarin Studio 6.1 is not working with a https package source. NuGet 3 is using different code when detecting proxy authentication being required. I will look into this and open a separate bug with some code that reproduces the problem.
Comment 12 Matt Ward 2016-10-03 14:22:55 UTC
Opened a separate bug #44978 for the HttpClientHandler problem affecting NuGet v3.

Note You need to log in before you can comment on or make changes to this bug.