Exemple #1
0
        public async Task Manual_CertificateSentMatchesCertificateReceived_Success(
            int numberOfRequests,
            bool reuseClient)                              // validate behavior with and without connection pooling, which impacts client cert usage
        {
            if (!BackendSupportsCustomCertificateHandling) // can't use [Conditional*] right now as it's evaluated at the wrong time for SocketsHttpHandler
            {
                _output.WriteLine($"Skipping {nameof(Manual_CertificateSentMatchesCertificateReceived_Success)}()");
                return;
            }

            var options = new LoopbackServer.Options {
                UseSsl = true
            };

            HttpClient CreateClient(X509Certificate2 cert)
            {
                HttpClientHandler handler = CreateHttpClientHandler();

                handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
                handler.ClientCertificates.Add(cert);
                Assert.True(handler.ClientCertificates.Contains(cert));
                return(CreateHttpClient(handler));
            }

            async Task MakeAndValidateRequest(HttpClient client, LoopbackServer server, Uri url, X509Certificate2 cert)
            {
                await TestHelper.WhenAllCompletedOrAnyFailed(
                    client.GetStringAsync(url),
                    server.AcceptConnectionAsync(async connection =>
                {
                    SslStream sslStream = Assert.IsType <SslStream>(connection.Stream);

                    // We can't do Assert.Equal(cert, sslStream.RemoteCertificate) because
                    // on .NET Framework sslStream.RemoteCertificate is always an X509Certificate
                    // object which is not equal to the X509Certificate2 object we use in the tests.
                    // So, we'll just compare a few properties to make sure it's the right certificate.
                    Assert.Equal(cert.Subject, sslStream.RemoteCertificate.Subject);
                    Assert.Equal(cert.Issuer, sslStream.RemoteCertificate.Issuer);

                    await connection.ReadRequestHeaderAndSendResponseAsync(additionalHeaders: "Connection: close\r\n");
                }));
            };

            await LoopbackServer.CreateServerAsync(async (server, url) =>
            {
                using (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate())
                {
                    if (reuseClient)
                    {
                        using (HttpClient client = CreateClient(cert))
                        {
                            for (int i = 0; i < numberOfRequests; i++)
                            {
                                await MakeAndValidateRequest(client, server, url, cert);

                                GC.Collect();
                                GC.WaitForPendingFinalizers();
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < numberOfRequests; i++)
                        {
                            using (HttpClient client = CreateClient(cert))
                            {
                                await MakeAndValidateRequest(client, server, url, cert);
                            }

                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                        }
                    }
                }
            }, options);
        }
Exemple #2
0
        public async Task Manual_CertificateSentMatchesCertificateReceived_Success(
            int numberOfRequests,
            bool reuseClient)                              // validate behavior with and without connection pooling, which impacts client cert usage
        {
            if (!BackendSupportsCustomCertificateHandling) // can't use [Conditional*] right now as it's evaluated at the wrong time for SocketsHttpHandler
            {
                _output.WriteLine($"Skipping {nameof(Manual_CertificateSentMatchesCertificateReceived_Success)}()");
                return;
            }

            var options = new LoopbackServer.Options {
                UseSsl = true
            };

            Func <X509Certificate2, HttpClient> createClient = (cert) =>
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.ServerCertificateCustomValidationCallback = delegate { return(true); };
                handler.ClientCertificates.Add(cert);
                return(new HttpClient(handler));
            };

            Func <HttpClient, LoopbackServer, Uri, X509Certificate2, Task> makeAndValidateRequest = async(client, server, url, cert) =>
            {
                await TestHelper.WhenAllCompletedOrAnyFailed(
                    client.GetStringAsync(url),
                    server.AcceptConnectionAsync(async connection =>
                {
                    SslStream sslStream = Assert.IsType <SslStream>(connection.Stream);
                    Assert.Equal(cert, sslStream.RemoteCertificate);
                    await connection.ReadRequestHeaderAndSendResponseAsync();
                }));
            };

            await LoopbackServer.CreateServerAsync(async (server, url) =>
            {
                if (reuseClient)
                {
                    using (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate())
                    {
                        using (HttpClient client = createClient(cert))
                        {
                            for (int i = 0; i < numberOfRequests; i++)
                            {
                                await makeAndValidateRequest(client, server, url, cert);

                                GC.Collect();
                                GC.WaitForPendingFinalizers();
                            }
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < numberOfRequests; i++)
                    {
                        using (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate())
                        {
                            using (HttpClient client = createClient(cert))
                            {
                                await makeAndValidateRequest(client, server, url, cert);
                            }
                        }

                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                    }
                }
            }, options);
        }
        public async Task Manual_CertificateSentMatchesCertificateReceived_Success(
            int numberOfRequests,
            bool reuseClient) // validate behavior with and without connection pooling, which impacts client cert usage
        {
            var options = new LoopbackServer.Options {
                UseSsl = true
            };

            using (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate())
            {
                Func <HttpClient> createClient = () =>
                {
                    var handler = new HttpClientHandler()
                    {
                        ServerCertificateCustomValidationCallback = delegate { return(true); }
                    };
                    handler.ClientCertificates.Add(cert);
                    return(new HttpClient(handler));
                };

                Func <HttpClient, Socket, Uri, Task> makeAndValidateRequest = async(client, server, url) =>
                {
                    await TestHelper.WhenAllCompletedOrAnyFailed(
                        client.GetStringAsync(url),
                        LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        SslStream sslStream = Assert.IsType <SslStream>(stream);
                        Assert.Equal(cert, sslStream.RemoteCertificate);
                        await LoopbackServer.ReadWriteAcceptedAsync(socket, reader, writer);
                    }, options));
                };

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    if (reuseClient)
                    {
                        using (HttpClient client = createClient())
                        {
                            for (int i = 0; i < numberOfRequests; i++)
                            {
                                await makeAndValidateRequest(client, server, url);

                                GC.Collect();
                                GC.WaitForPendingFinalizers();
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < numberOfRequests; i++)
                        {
                            using (HttpClient client = createClient())
                            {
                                await makeAndValidateRequest(client, server, url);
                            }

                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                        }
                    }
                }, options);
            }
        }
Exemple #4
0
        public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(bool useProxy)
        {
            const string ExpectedUsername = "******";
            const string ExpectedPassword = "******";

            LoopbackServer.Options options = new LoopbackServer.Options {
                IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword
            };

            await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(() =>
            {
                var psi = new ProcessStartInfo();
                psi.Environment.Add("http_proxy", $"http://{uri.Host}:{uri.Port}");

                RemoteExecutor.Invoke(async(useProxyString, useVersionString, uriString) =>
                {
                    using (HttpClientHandler handler = CreateHttpClientHandler(useVersionString))
                        using (HttpClient client = CreateHttpClient(handler, useVersionString))
                        {
                            var creds = new NetworkCredential(ExpectedUsername, ExpectedPassword);
                            handler.DefaultProxyCredentials = creds;
                            handler.UseProxy = bool.Parse(useProxyString);

                            HttpResponseMessage response = await client.GetAsync(uriString);
                            // Correctness of user and password is done in server part.
                            Assert.True(response.StatusCode == HttpStatusCode.OK);
                        };
                }, useProxy.ToString(), UseVersion.ToString(),
                                      // If proxy is used , the url does not matter. We set it to be different to avoid confusion.
                                      useProxy ? Configuration.Http.RemoteEchoServer.ToString() : uri.ToString(),
                                      new RemoteInvokeOptions {
                    StartInfo = psi
                }).Dispose();
            }),
                                                            server => server.AcceptConnectionAsync(async connection =>
            {
                const string headerName = "Proxy-Authorization";
                List <string> lines     = await connection.ReadRequestHeaderAsync().ConfigureAwait(false);

                // First request should not have proxy credentials in either case.
                for (int i = 1; i < lines.Count; i++)
                {
                    Assert.False(lines[i].StartsWith(headerName));
                }

                if (useProxy)
                {
                    // Reject request and wait for authenticated one.
                    await connection.SendResponseAsync(HttpStatusCode.ProxyAuthenticationRequired, "Proxy-Authenticate: Basic realm=\"NetCore\"\r\n").ConfigureAwait(false);

                    lines      = await connection.ReadRequestHeaderAsync().ConfigureAwait(false);
                    bool valid = false;
                    for (int i = 1; i < lines.Count; i++)
                    {
                        if (lines[i].StartsWith(headerName))
                        {
                            valid = LoopbackServer.IsBasicAuthTokenValid(lines[i], options);
                        }
                    }

                    Assert.True(valid);
                }

                await connection.SendResponseAsync(HttpStatusCode.OK).ConfigureAwait(false);
            }));
        }