public async Task ProxyTunnelRequest_OriginServerSendsProxyAuthChallenge_NoProxyAuthPerformed()
        {
            if (IsWinHttpHandler)
            {
                return;
            }

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
            {
                HttpClientHandler handler = CreateHttpClientHandler(allowAllCertificates: true);
                handler.Proxy = new WebProxy(proxyServer.Uri)
                {
                    Credentials = ConstructCredentials(new NetworkCredential("username", "password"), proxyServer.Uri, BasicAuth, true)
                };
                using (HttpClient client = CreateHttpClient(handler))
                {
                    var options = new LoopbackServer.Options {
                        UseSsl = true
                    };
                    await LoopbackServer.CreateServerAsync(async (server, uri) =>
                    {
                        Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri));

                        Task <HttpResponseMessage> clientTask = client.GetAsync(uri);
                        await server.AcceptConnectionSendResponseAndCloseAsync(statusCode: HttpStatusCode.ProxyAuthenticationRequired, additionalHeaders: "Proxy-Authenticate: Basic").WaitAsync(TestHelper.PassingTestTimeout);
                        using (var response = await clientTask.WaitAsync(TestHelper.PassingTestTimeout))
                        {
                            Assert.Equal(HttpStatusCode.ProxyAuthenticationRequired, response.StatusCode);
                        }
                    }, options).WaitAsync(TestHelper.PassingTestTimeout);
                }

                Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
            }
        }
        public async Task ProxyTunnelRequest_GetAsync_Success()
        {
            if (IsWinHttpHandler)
            {
                return;
            }

            const string Content = "Hello world";

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
            {
                HttpClientHandler handler = CreateHttpClientHandler(allowAllCertificates: true);
                handler.Proxy = new WebProxy(proxyServer.Uri);
                using (HttpClient client = CreateHttpClient(handler))
                {
                    var options = new LoopbackServer.Options {
                        UseSsl = true
                    };
                    await LoopbackServer.CreateServerAsync(async (server, uri) =>
                    {
                        Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri));

                        Task <HttpResponseMessage> clientTask = client.GetAsync(uri);
                        await server.AcceptConnectionSendResponseAndCloseAsync(content: Content);
                        using (var response = await clientTask)
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            Assert.Equal(Content, await response.Content.ReadAsStringAsync());
                        }
                    }, options);
                }

                Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
            }
        }
        public async Task AuthenticatedProxiedRequest_GetAsyncWithCreds_Success(NetworkCredential cred, bool wrapCredsInCache, bool connectionCloseAfter407)
        {
            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes   = cred != null ? AuthenticationSchemes.Basic : AuthenticationSchemes.None,
                ConnectionCloseAfter407 = connectionCloseAfter407
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
                using (HttpClientHandler handler = CreateHttpClientHandler())
                    using (HttpClient client = CreateHttpClient(handler))
                    {
                        handler.Proxy = new WebProxy(proxyServer.Uri)
                        {
                            Credentials = ConstructCredentials(cred, proxyServer.Uri, BasicAuth, wrapCredsInCache)
                        };

                        using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer))
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            TestHelper.VerifyResponseBody(
                                await response.Content.ReadAsStringAsync(),
                                response.Content.Headers.ContentMD5,
                                false,
                                null);

                            ValidateProxyBasicAuthentication(proxyServer, cred);
                        }
                    }
        }
        public async Task UseCallback_HaveNoCredsAndUseAuthenticatedCustomProxyAndPostToSecureServer_ProxyAuthenticationRequiredStatusCode()
        {
            if (!BackendSupportsCustomCertificateHandling)
            {
                return;
            }

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes   = AuthenticationSchemes.Basic,
                ConnectionCloseAfter407 = true
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Proxy = new WebProxy(proxyServer.Uri);
                handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                using (HttpClient client = CreateHttpClient(handler))
                    using (HttpResponseMessage response = await client.PostAsync(
                               Configuration.Http.SecureRemoteEchoServer,
                               new StringContent("This is a test")))
                    {
                        Assert.Equal(HttpStatusCode.ProxyAuthenticationRequired, response.StatusCode);
                    }
            }
        }
Exemple #5
0
        public async Task AuthenticatedProxyTunnelRequest_PostAsyncWithNoCreds_Throws()
        {
            if (IsWinHttpHandler)
            {
                return;
            }

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes = AuthenticationSchemes.Basic,
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Proxy = new WebProxy(proxyServer.Uri);
                handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                using (HttpClient client = CreateHttpClient(handler))
                {
                    HttpRequestException e = await Assert.ThrowsAnyAsync <HttpRequestException>(async() => await client.PostAsync("https://nosuchhost.invalid", new StringContent(content)));

                    Assert.Contains("407", e.Message);
                }
            }
        }
Exemple #6
0
        public async Task ProxyTunnelRequest_MaxConnectionsSetButDoesNotApplyToProxyConnect_Success()
        {
            if (IsWinHttpHandler)
            {
                return;
            }

            const string Content = "Hello world";

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Proxy = new WebProxy(proxyServer.Uri);
                handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                handler.MaxConnectionsPerServer = 1;
                using (HttpClient client = CreateHttpClient(handler))
                {
                    var options = new LoopbackServer.Options {
                        UseSsl = true
                    };
                    await LoopbackServer.CreateServerAsync(async (server1, uri1) =>
                    {
                        await LoopbackServer.CreateServerAsync(async(server2, uri2) =>
                        {
                            Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri1));
                            Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri2));

                            Task <HttpResponseMessage> clientTask1 = client.GetAsync(uri1);
                            Task <HttpResponseMessage> clientTask2 = client.GetAsync(uri2);
                            await server1.AcceptConnectionAsync(async connection1 =>
                            {
                                await server2.AcceptConnectionAsync(async connection2 =>
                                {
                                    await connection1.HandleRequestAsync(content: Content);
                                    await connection2.HandleRequestAsync(content: Content);
                                });
                            });

                            using (var response1 = await clientTask1)
                            {
                                Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
                                Assert.Equal(Content, await response1.Content.ReadAsStringAsync());
                            }

                            using (var response2 = await clientTask2)
                            {
                                Assert.Equal(HttpStatusCode.OK, response2.StatusCode);
                                Assert.Equal(Content, await response2.Content.ReadAsStringAsync());
                            }
                        }, options);
                    }, options);
                }

                Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
                Assert.Contains("CONNECT", proxyServer.Requests[1].RequestLine);
            }
        }
Exemple #7
0
        public async Task Proxy_BypassFalse_GetRequestGoesThroughCustomProxy(ICredentials creds, bool wrapCredsInCache)
        {
            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes = creds != null ? AuthenticationSchemes.Basic : AuthenticationSchemes.None
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                const string BasicAuth = "Basic";
                if (wrapCredsInCache)
                {
                    Assert.IsAssignableFrom <NetworkCredential>(creds);
                    var cache = new CredentialCache();
                    cache.Add(proxyServer.Uri, BasicAuth, (NetworkCredential)creds);
                    creds = cache;
                }

                using (HttpClientHandler handler = CreateHttpClientHandler())
                    using (var client = new HttpClient(handler))
                    {
                        handler.Proxy = new WebProxy(proxyServer.Uri)
                        {
                            Credentials = creds
                        };

                        using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer))
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            TestHelper.VerifyResponseBody(
                                await response.Content.ReadAsStringAsync(),
                                response.Content.Headers.ContentMD5,
                                false,
                                null);

                            if (options.AuthenticationSchemes != AuthenticationSchemes.None)
                            {
                                NetworkCredential nc = creds?.GetCredential(proxyServer.Uri, BasicAuth);
                                Assert.NotNull(nc);
                                string expectedAuth =
                                    string.IsNullOrEmpty(nc.Domain) ? $"{nc.UserName}:{nc.Password}" :
                                    $"{nc.Domain}\\{nc.UserName}:{nc.Password}";
                                _output.WriteLine($"expectedAuth={expectedAuth}");
                                string expectedAuthHash = Convert.ToBase64String(Encoding.UTF8.GetBytes(expectedAuth));

                                // Check last request to proxy server. CurlHandler will use pre-auth for Basic proxy auth,
                                // so there might only be 1 request received by the proxy server. Other handlers won't use
                                // pre-auth for proxy so there would be 2 requests.
                                int requestCount = proxyServer.Requests.Count;
                                _output.WriteLine($"proxyServer.Requests.Count={requestCount}");
                                Assert.Equal(BasicAuth, proxyServer.Requests[requestCount - 1].AuthorizationHeaderValueScheme);
                                Assert.Equal(expectedAuthHash, proxyServer.Requests[requestCount - 1].AuthorizationHeaderValueToken);
                            }
                        }
                    }
            }
        }
        public static LoopbackProxyServer Create(Options options = null)
        {
            options = options ?? new Options();

            var server = new LoopbackProxyServer(options);

            server.Start();

            return(server);
        }
Exemple #9
0
 public async Task Proxy_SendSecureRequestThruProxy_ConnectTunnelUsed()
 {
     using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
     {
         HttpClientHandler handler = CreateHttpClientHandler();
         handler.Proxy = new WebProxy(proxyServer.Uri);
         using (HttpClient client = CreateHttpClient(handler))
             using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.SecureRemoteEchoServer))
             {
                 Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                 _output.WriteLine($"Proxy request line: {proxyServer.Requests[0].RequestLine}");
                 Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
             }
     }
 }
        public async Task AuthProxy__ValidCreds_ProxySendsRequestToServer(
            AuthenticationSchemes proxyAuthScheme,
            bool secureServer,
            bool proxyClosesConnectionAfterFirst407Response)
        {
            if (PlatformDetection.IsWindowsNanoServer && IsWinHttpHandler && proxyAuthScheme == AuthenticationSchemes.Digest)
            {
                // WinHTTP doesn't support Digest very well and is disabled on Nano.
                return;
            }

            if (!PlatformDetection.IsWindows &&
                (proxyAuthScheme == AuthenticationSchemes.Negotiate || proxyAuthScheme == AuthenticationSchemes.Ntlm))
            {
                // CI machines don't have GSSAPI module installed and will fail with error from
                // System.Net.Security.NegotiateStreamPal.AcquireCredentialsHandle():
                //        "GSSAPI operation failed with error - An invalid status code was supplied
                //         Configuration file does not specify default realm)."
                return;
            }

            Uri serverUri = secureServer ? Configuration.Http.SecureRemoteEchoServer : Configuration.Http.RemoteEchoServer;

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes   = proxyAuthScheme,
                ConnectionCloseAfter407 = proxyClosesConnectionAfterFirst407Response
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                using (HttpClientHandler handler = CreateHttpClientHandler())
                    using (HttpClient client = CreateHttpClient(handler))
                    {
                        handler.Proxy             = new WebProxy(proxyServer.Uri);
                        handler.Proxy.Credentials = new NetworkCredential("username", "password");
                        using (HttpResponseMessage response = await client.GetAsync(serverUri))
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            TestHelper.VerifyResponseBody(
                                await response.Content.ReadAsStringAsync(),
                                response.Content.Headers.ContentMD5,
                                false,
                                null);
                        }
                    }
            }
        }
Exemple #11
0
        public async Task UseCallback_HaveCredsAndUseAuthenticatedCustomProxyAndPostToSecureServer_Success()
        {
            if (!BackendSupportsCustomCertificateHandling)
            {
                return;
            }

            if (IsWinHttpHandler && PlatformDetection.IsWindows7)
            {
                // Issue #27612
                return;
            }

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes   = AuthenticationSchemes.Basic,
                ConnectionCloseAfter407 = true
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                handler.Proxy = new WebProxy(proxyServer.Uri)
                {
                    Credentials = new NetworkCredential("rightusername", "rightpassword")
                };

                const string content = "This is a test";

                using (HttpClient client = CreateHttpClient(handler))
                    using (HttpResponseMessage response = await client.PostAsync(
                               Configuration.Http.SecureRemoteEchoServer,
                               new StringContent(content)))
                    {
                        string responseContent = await response.Content.ReadAsStringAsync();

                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        TestHelper.VerifyResponseBody(
                            responseContent,
                            response.Content.Headers.ContentMD5,
                            false,
                            content);
                    }
            }
        }
Exemple #12
0
        public async Task Proxy_HaveNoCredsAndUseAuthenticatedCustomProxy_ProxyAuthenticationRequiredStatusCode()
        {
            var options = new LoopbackProxyServer.Options {
                AuthenticationSchemes = AuthenticationSchemes.Basic
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Proxy = new WebProxy(proxyServer.Uri);
                using (var client = new HttpClient(handler))
                    using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer))
                    {
                        Assert.Equal(HttpStatusCode.ProxyAuthenticationRequired, response.StatusCode);
                    }
            }
        }
        public async Task Proxy_DomainJoinedProxyServerUsesKerberos_Success(Uri server)
        {
            // We skip the test unless it is running on a Windows client machine. That is because only Windows
            // automatically registers an SPN for HTTP/<hostname> of the machine. This will enable Kerberos to properly
            // work with the loopback proxy server.
            if (!PlatformDetection.IsWindows || !PlatformDetection.IsNotWindowsNanoServer)
            {
                throw new SkipTestException("Test can only run on domain joined Windows client machine");
            }

            var options = new LoopbackProxyServer.Options {
                AuthenticationSchemes = AuthenticationSchemes.Negotiate
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                using (HttpClientHandler handler = CreateHttpClientHandler())
                    using (HttpClient client = CreateHttpClient(handler))
                    {
                        // Use 'localhost' DNS name for loopback proxy server (instead of IP address) so that the SPN will
                        // get calculated properly to use Kerberos.
                        _output.WriteLine(proxyServer.Uri.AbsoluteUri.ToString());
                        handler.Proxy = new WebProxy("localhost", proxyServer.Uri.Port)
                        {
                            Credentials = DomainCredential
                        };

                        using (HttpResponseMessage response = await client.GetAsync(server))
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                            int requestCount = proxyServer.Requests.Count;

                            // We expect 2 requests to the proxy server. One without the 'Proxy-Authorization' header and
                            // one with the header.
                            Assert.Equal(2, requestCount);
                            Assert.Equal("Negotiate", proxyServer.Requests[requestCount - 1].AuthorizationHeaderValueScheme);

                            // Base64 tokens that use SPNEGO protocol start with 'Y'. NTLM tokens start with 'T'.
                            Assert.Equal('Y', proxyServer.Requests[requestCount - 1].AuthorizationHeaderValueToken[0]);
                        }
                    }
            }
        }
Exemple #14
0
        private void ValidateProxyBasicAuthentication(LoopbackProxyServer proxyServer, NetworkCredential cred)
        {
            if (cred != null)
            {
                string expectedAuth =
                    string.IsNullOrEmpty(cred.Domain) ?
                    $"{cred.UserName}:{cred.Password}" :
                    $"{cred.Domain}\\{cred.UserName}:{cred.Password}";
                _output.WriteLine($"expectedAuth={expectedAuth}");
                string expectedAuthHash = Convert.ToBase64String(Encoding.UTF8.GetBytes(expectedAuth));

                // Check last request to proxy server. Handlers that don't use
                // pre-auth for proxy will make 2 requests.
                int requestCount = proxyServer.Requests.Count;
                _output.WriteLine($"proxyServer.Requests.Count={requestCount}");
                Assert.Equal(BasicAuth, proxyServer.Requests[requestCount - 1].AuthorizationHeaderValueScheme);
                Assert.Equal(expectedAuthHash, proxyServer.Requests[requestCount - 1].AuthorizationHeaderValueToken);
            }
        }
Exemple #15
0
        public void Proxy_UseEnvironmentVariableToSetSystemProxy_RequestGoesThruProxy()
        {
            RemoteExecutor.Invoke(async(useVersionString) =>
            {
                var options = new LoopbackProxyServer.Options {
                    AddViaRequestHeader = true
                };
                using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
                {
                    Environment.SetEnvironmentVariable("http_proxy", proxyServer.Uri.AbsoluteUri.ToString());

                    using (HttpClient client = CreateHttpClient(useVersionString))
                        using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer))
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            string body = await response.Content.ReadAsStringAsync();
                            Assert.Contains(proxyServer.ViaHeader, body);
                        }
                }
            }, UseVersion.ToString()).Dispose();
        }
Exemple #16
0
        public async Task Proxy_SendSecureRequestThruProxy_ConnectTunnelUsed()
        {
            if (PlatformDetection.IsFedora && IsCurlHandler)
            {
                // CurlHandler seems unstable on Fedora26 and returns error
                // "System.Net.Http.CurlException : Failure when receiving data from the peer".
                return;
            }

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Proxy = new WebProxy(proxyServer.Uri);
                using (var client = new HttpClient(handler))
                    using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.SecureRemoteEchoServer))
                    {
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        _output.WriteLine($"Proxy request line: {proxyServer.Requests[0].RequestLine}");
                        Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
                    }
            }
        }
Exemple #17
0
        public async Task AuthenticatedProxyTunnelRequest_PostAsyncWithCreds_Success(NetworkCredential cred, bool wrapCredsInCache, bool connectionCloseAfter407)
        {
            if (IsWinHttpHandler)
            {
                return;
            }

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes   = cred != null ? AuthenticationSchemes.Basic : AuthenticationSchemes.None,
                ConnectionCloseAfter407 = connectionCloseAfter407
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
                using (HttpClientHandler handler = CreateHttpClientHandler())
                    using (HttpClient client = CreateHttpClient(handler))
                    {
                        handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                        handler.Proxy = new WebProxy(proxyServer.Uri)
                        {
                            Credentials = ConstructCredentials(cred, proxyServer.Uri, BasicAuth, wrapCredsInCache)
                        };

                        using (HttpResponseMessage response = await client.PostAsync(Configuration.Http.SecureRemoteEchoServer, new StringContent(content)))
                        {
                            string responseContent = await response.Content.ReadAsStringAsync();

                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            TestHelper.VerifyResponseBody(
                                responseContent,
                                response.Content.Headers.ContentMD5,
                                false,
                                content);

                            ValidateProxyBasicAuthentication(proxyServer, cred);
                        }
                    }
        }
Exemple #18
0
        public async Task AuthenticatedProxyTunnelRequest_PostAsyncWithNoCreds_ProxyAuthenticationRequiredStatusCode()
        {
            if (IsWinHttpHandler)
            {
                return;
            }

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes = AuthenticationSchemes.Basic,
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Proxy = new WebProxy(proxyServer.Uri);
                handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                using (HttpClient client = CreateHttpClient(handler))
                    using (HttpResponseMessage response = await client.PostAsync(Configuration.Http.SecureRemoteEchoServer, new StringContent(content)))
                    {
                        Assert.Equal(HttpStatusCode.ProxyAuthenticationRequired, response.StatusCode);
                    }
            }
        }
Exemple #19
0
        public async Task MultiProxy_PAC_Failover_Succeeds()
        {
            if (IsWinHttpHandler)
            {
                // PAC-based failover is only supported on Windows/SocketsHttpHandler
                return;
            }

            // Create our failing proxy server.
            // Bind a port to reserve it, but don't start listening yet. The first Connect() should fail and cause a fail-over.
            using Socket failingProxyServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            failingProxyServer.Bind(new IPEndPoint(IPAddress.Loopback, 0));
            var failingEndPoint = (IPEndPoint)failingProxyServer.LocalEndPoint;

            using LoopbackProxyServer succeedingProxyServer = LoopbackProxyServer.Create();
            string proxyConfigString = $"{failingEndPoint.Address}:{failingEndPoint.Port} {succeedingProxyServer.Uri.Host}:{succeedingProxyServer.Uri.Port}";

            // Create a WinInetProxyHelper and override its values with our own.
            object winInetProxyHelper = Activator.CreateInstance(typeof(HttpClient).Assembly.GetType("System.Net.Http.WinInetProxyHelper", true), true);

            winInetProxyHelper.GetType().GetField("_autoConfigUrl", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(winInetProxyHelper, null);
            winInetProxyHelper.GetType().GetField("_autoDetect", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(winInetProxyHelper, false);
            winInetProxyHelper.GetType().GetField("_proxy", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(winInetProxyHelper, proxyConfigString);
            winInetProxyHelper.GetType().GetField("_proxyBypass", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(winInetProxyHelper, null);

            // Create a HttpWindowsProxy with our custom WinInetProxyHelper.
            IWebProxy httpWindowsProxy = (IWebProxy)Activator.CreateInstance(typeof(HttpClient).Assembly.GetType("System.Net.Http.HttpWindowsProxy", true), Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance, null, new[] { winInetProxyHelper, null }, null);

            Task <bool> nextFailedConnection = null;

            // Run a request with that proxy.
            Task requestTask = LoopbackServerFactory.CreateClientAndServerAsync(
                async uri =>
            {
                using HttpClientHandler handler = CreateHttpClientHandler();
                using HttpClient client         = CreateHttpClient(handler);
                handler.Proxy = httpWindowsProxy;

                // First request is expected to hit the failing proxy server, then failover to the succeeding proxy server.
                Assert.Equal("foo", await client.GetStringAsync(uri));

                // Second request should start directly at the succeeding proxy server.
                // So, start listening on our failing proxy server to catch if it tries to connect.
                failingProxyServer.Listen(1);
                nextFailedConnection = WaitForNextFailedConnection();
                Assert.Equal("bar", await client.GetStringAsync(uri));
            },
                async server =>
            {
                await server.HandleRequestAsync(statusCode: HttpStatusCode.OK, content: "foo");
                await server.HandleRequestAsync(statusCode: HttpStatusCode.OK, content: "bar");
            });

            // Wait for request to finish.
            await requestTask;

            // Triggers WaitForNextFailedConnection to stop, and then check
            // to ensure we haven't got any further requests against it.
            failingProxyServer.Dispose();
            Assert.False(await nextFailedConnection);

            Assert.Equal(2, succeedingProxyServer.Requests.Count);

            async Task <bool> WaitForNextFailedConnection()
            {
                try
                {
                    (await failingProxyServer.AcceptAsync()).Dispose();
                    return(true);
                }
                catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted)
                {
                    // Dispose() of the loopback server will cause AcceptAsync() in EstablishConnectionAsync() to abort.
                    return(false);
                }
            }
        }
Exemple #20
0
        public async Task AuthProxy__ValidCreds_ProxySendsRequestToServer(
            AuthenticationSchemes proxyAuthScheme,
            bool secureServer,
            bool proxyClosesConnectionAfterFirst407Response)
        {
            if (PlatformDetection.IsFedora && IsCurlHandler)
            {
                // CurlHandler seems unstable on Fedora26 and returns error
                // "System.Net.Http.CurlException : Failure when receiving data from the peer".
                return;
            }

            if (PlatformDetection.IsWindowsNanoServer && IsWinHttpHandler && proxyAuthScheme == AuthenticationSchemes.Digest)
            {
                // WinHTTP doesn't support Digest very well and is disabled on Nano.
                return;
            }

            if (PlatformDetection.IsFullFramework &&
                (proxyAuthScheme == AuthenticationSchemes.Negotiate || proxyAuthScheme == AuthenticationSchemes.Ntlm))
            {
                // Skip due to bug in .NET Framework with Windows auth and proxy tunneling.
                return;
            }

            if (!PlatformDetection.IsWindows &&
                (proxyAuthScheme == AuthenticationSchemes.Negotiate || proxyAuthScheme == AuthenticationSchemes.Ntlm))
            {
                // CI machines don't have GSSAPI module installed and will fail with error from
                // System.Net.Security.NegotiateStreamPal.AcquireCredentialsHandle():
                //        "GSSAPI operation failed with error - An invalid status code was supplied
                //         Configuration file does not specify default realm)."
                return;
            }

            if (IsCurlHandler && proxyAuthScheme != AuthenticationSchemes.Basic)
            {
                // Issue #27870 curl HttpHandler can only do basic auth to proxy.
                return;
            }

            Uri serverUri = secureServer ? Configuration.Http.SecureRemoteEchoServer : Configuration.Http.RemoteEchoServer;

            var options = new LoopbackProxyServer.Options
            {
                AuthenticationSchemes   = proxyAuthScheme,
                ConnectionCloseAfter407 = proxyClosesConnectionAfterFirst407Response
            };

            using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options))
            {
                using (StandardSocketsHttpHandler handler = CreateSocketsHttpHandler())
                    using (var client = new HttpClient(handler))
                    {
                        handler.Proxy             = new WebProxy(proxyServer.Uri);
                        handler.Proxy.Credentials = new NetworkCredential("username", "password");
                        using (HttpResponseMessage response = await client.GetAsync(serverUri))
                        {
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            TestHelper.VerifyResponseBody(
                                await response.Content.ReadAsStringAsync(),
                                response.Content.Headers.ContentMD5,
                                false,
                                null);
                        }
                    }
            }
        }