a3245b33f41da2cd6ce80a77860e0fb125959ae7
[platform/upstream/dotnet/runtime.git] /
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Net.Test.Common;
8 using System.Runtime.InteropServices;
9 using System.Text;
10 using System.Threading.Tasks;
11 using Microsoft.DotNet.RemoteExecutor;
12 using Xunit;
13 using Xunit.Abstractions;
14
15 namespace System.Net.Http.Functional.Tests
16 {
17     using Configuration = System.Net.Test.Common.Configuration;
18
19     public abstract class HttpClientHandler_DefaultProxyCredentials_Test : HttpClientHandlerTestBase
20     {
21         public HttpClientHandler_DefaultProxyCredentials_Test(ITestOutputHelper output) : base(output) { }
22
23         [Fact]
24         public void Default_Get_Null()
25         {
26             using (HttpClientHandler handler = CreateHttpClientHandler())
27             {
28                 Assert.Null(handler.DefaultProxyCredentials);
29             }
30         }
31
32         [Fact]
33         public void SetGet_Roundtrips()
34         {
35             using (HttpClientHandler handler = CreateHttpClientHandler())
36             {
37                 var creds = new NetworkCredential("username", "password", "domain");
38
39                 handler.DefaultProxyCredentials = null;
40                 Assert.Null(handler.DefaultProxyCredentials);
41
42                 handler.DefaultProxyCredentials = creds;
43                 Assert.Same(creds, handler.DefaultProxyCredentials);
44
45                 handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
46                 Assert.Same(CredentialCache.DefaultCredentials, handler.DefaultProxyCredentials);
47             }
48         }
49
50         [Fact]
51         public async Task ProxyExplicitlyProvided_DefaultCredentials_Ignored()
52         {
53             var explicitProxyCreds = new NetworkCredential("rightusername", "rightpassword");
54             var defaultSystemProxyCreds = new NetworkCredential("wrongusername", "wrongpassword");
55             string expectCreds = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{explicitProxyCreds.UserName}:{explicitProxyCreds.Password}"));
56
57             await LoopbackServer.CreateClientAndServerAsync(async proxyUrl =>
58             {
59                 using (HttpClientHandler handler = CreateHttpClientHandler())
60                 using (HttpClient client = CreateHttpClient(handler))
61                 {
62                     handler.Proxy = new UseSpecifiedUriWebProxy(proxyUrl, explicitProxyCreds);
63                     handler.DefaultProxyCredentials = defaultSystemProxyCreds;
64                     using (HttpResponseMessage response = await client.GetAsync("http://notatrealserver.com/")) // URL does not matter
65                     {
66                         Assert.Equal(HttpStatusCode.OK, response.StatusCode);
67                     }
68                 }
69             }, async server =>
70             {
71                 if (!IsCurlHandler) // libcurl sends Basic auth preemptively when only basic creds are provided; other handlers wait for 407.
72                 {
73                     await server.AcceptConnectionSendResponseAndCloseAsync(
74                         HttpStatusCode.ProxyAuthenticationRequired, "Proxy-Authenticate: Basic\r\n");
75                 }
76
77                 List<string> headers = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.OK);
78                 Assert.Equal(expectCreds, LoopbackServer.GetRequestHeaderValue(headers, "Proxy-Authorization"));
79             });
80         }
81
82         [OuterLoop("Uses external server")]
83         [PlatformSpecific(TestPlatforms.AnyUnix)] // The default proxy is resolved via WinINet on Windows.
84         [Theory]
85         [InlineData(false)]
86         [InlineData(true)]
87         public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(bool useProxy)
88         {
89             const string ExpectedUsername = "rightusername";
90             const string ExpectedPassword = "rightpassword";
91             LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword };
92
93             await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUri) =>
94             {
95                 // libcurl will read a default proxy from the http_proxy environment variable.  Ensure that when it does,
96                 // our default proxy credentials are used.  To avoid messing up anything else in this process, we run the
97                 // test in another process.
98                 var psi = new ProcessStartInfo();
99                 Task<List<string>> proxyTask = null;
100
101                 if (useProxy)
102                 {
103                     proxyTask = proxyServer.AcceptConnectionPerformAuthenticationAndCloseAsync("Proxy-Authenticate: Basic realm=\"NetCore\"\r\n");
104                     psi.Environment.Add("http_proxy", $"http://{proxyUri.Host}:{proxyUri.Port}");
105                 }
106
107                 RemoteExecutor.Invoke(async (useProxyString, useSocketsHttpHandlerString, useHttp2String) =>
108                 {
109                     using (HttpClientHandler handler = CreateHttpClientHandler(useSocketsHttpHandlerString, useHttp2String))
110                     using (HttpClient client = CreateHttpClient(handler, useHttp2String))
111                     {
112                         var creds = new NetworkCredential(ExpectedUsername, ExpectedPassword);
113                         handler.DefaultProxyCredentials = creds;
114                         handler.UseProxy = bool.Parse(useProxyString);
115
116                         HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer);
117                         // Correctness of user and password is done in server part.
118                         Assert.True(response.StatusCode == HttpStatusCode.OK);
119                     }
120                 }, useProxy.ToString(), UseSocketsHttpHandler.ToString(), UseHttp2.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose();
121                 if (useProxy)
122                 {
123                     await proxyTask;
124                 }
125             }, options);
126         }
127
128         // The purpose of this test is mainly to validate the .NET Framework OOB System.Net.Http implementation
129         // since it has an underlying dependency to WebRequest. While .NET Core implementations of System.Net.Http
130         // are not using any WebRequest code, the test is still useful to validate correctness.
131         [OuterLoop("Uses external server")]
132         [Fact]
133         public async Task ProxyNotExplicitlyProvided_DefaultCredentialsSet_DefaultWebProxySetToNull_Success()
134         {
135             WebRequest.DefaultWebProxy = null;
136
137             using (HttpClientHandler handler = CreateHttpClientHandler())
138             using (HttpClient client = CreateHttpClient(handler))
139             {
140                 handler.DefaultProxyCredentials = new NetworkCredential("UsernameNotUsed", "PasswordNotUsed");
141                 HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer);
142
143                 Assert.Equal(HttpStatusCode.OK, response.StatusCode);
144             }
145         }
146     }
147 }