public void Proxy_UseEnvironmentVariableToSetSystemProxy_RequestGoesThruProxy() { if (!UseSocketsHttpHandler) { throw new SkipTestException("Test needs SocketsHttpHandler"); } RemoteExecutor.Invoke(async(useSocketsHttpHandlerString, useHttp2String) => { 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(useSocketsHttpHandlerString, useHttp2String)) 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); } return(RemoteExecutor.SuccessExitCode); } }, UseSocketsHttpHandler.ToString(), UseHttp2.ToString()).Dispose(); }
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); } } }
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); } } }
public async Task UseCallback_HaveCredsAndUseAuthenticatedCustomProxyAndPostToSecureServer_Success() { 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); } } }
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 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); } } } }
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 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)) { StandardSocketsHttpHandler handler = CreateSocketsHttpHandler(); handler.SslOptions.RemoteCertificateValidationCallback = delegate { return(true); }; handler.Proxy = new WebProxy(proxyServer.Uri) { Credentials = new NetworkCredential("rightusername", "rightpassword") }; const string content = "This is a test"; using (var client = new HttpClient(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); } } }
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]); } } } }
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(); }
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); } } }
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); } } }
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); } } } }