Exemplo n.º 1
0
        public async Task ClientOptions_TargetHostNull_OK()
        {
            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                {
                    var serverOptions = new SslServerAuthenticationOptions()
                    {
                        ServerCertificate = Configuration.Certificates.GetServerCertificate()
                    };
                    var clientOptions = new SslClientAuthenticationOptions()
                    {
                        RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
                    };

                    Assert.Null(clientOptions.TargetHost);

                    await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                        client.AuthenticateAsClientAsync(clientOptions),
                        server.AuthenticateAsServerAsync(serverOptions));

                    Assert.Equal(string.Empty, client.TargetHostName);
                    Assert.Equal(string.Empty, server.TargetHostName);
                }
        }
        public async Task ServerAsyncAuthenticate_NoCertificate_Throws(bool useAsync)
        {
            var serverOptions = new SslServerAuthenticationOptions();
            var clientOptions = new SslClientAuthenticationOptions()
            {
                TargetHost = _serverCertificate.GetNameInfo(X509NameType.SimpleName, false)
            };

            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                {
                    Task t1 = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None);
                    Task t2 = server.AuthenticateAsServerAsync(
                        (stream, clientHelloInfo, userState, cancellationToken) =>
                    {
                        if (useAsync)
                        {
                            return(new ValueTask <SslServerAuthenticationOptions>(serverOptions));
                        }

                        return(new ValueTask <SslServerAuthenticationOptions>(OptionsTask(serverOptions)));
                    },
                        null, CancellationToken.None);
                    await Assert.ThrowsAsync <System.NotSupportedException>(() => t2);
                }
        }
        public async Task ServerAsyncAuthenticate_SimpleSniOptions_Success()
        {
            var state         = new object();
            var serverOptions = new SslServerAuthenticationOptions()
            {
                ServerCertificate = _serverCertificate
            };
            var clientOptions = new SslClientAuthenticationOptions()
            {
                TargetHost = _serverCertificate.GetNameInfo(X509NameType.SimpleName, false)
            };

            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                {
                    Task t1 = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None);
                    Task t2 = server.AuthenticateAsServerAsync(
                        (stream, clientHelloInfo, userState, cancellationToken) =>
                    {
                        Assert.Equal(server, stream);
                        Assert.Equal(clientOptions.TargetHost, clientHelloInfo.ServerName);
                        Assert.True(object.ReferenceEquals(state, userState));
                        return(new ValueTask <SslServerAuthenticationOptions>(serverOptions));
                    },
                        state, CancellationToken.None);

                    await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2);
                }
        }
        public async Task ServerAsyncAuthenticate_SniSetVersion_Success(SslProtocols version)
        {
            var serverOptions = new SslServerAuthenticationOptions()
            {
                ServerCertificate = _serverCertificate, EnabledSslProtocols = version
            };
            var clientOptions = new SslClientAuthenticationOptions()
            {
                TargetHost = _serverCertificate.GetNameInfo(X509NameType.SimpleName, forIssuer: false)
            };

            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                {
                    Task t1 = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None);
                    Task t2 = server.AuthenticateAsServerAsync(
                        (stream, clientHelloInfo, userState, cancellationToken) =>
                    {
                        Assert.Equal(server, stream);
                        Assert.Equal(clientOptions.TargetHost, clientHelloInfo.ServerName);
                        return(new ValueTask <SslServerAuthenticationOptions>(serverOptions));
                    },
                        null, CancellationToken.None);

                    await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2);

                    // Verify that the SNI callback can impact version.
                    Assert.Equal(version, client.SslProtocol);
                }
        }
Exemplo n.º 5
0
        public async Task SslStream_SecondNegotiateClientCertificateAsync_Throws(bool sendClientCertificate)
        {
            using CancellationTokenSource cts = new CancellationTokenSource();
            cts.CancelAfter(TestConfiguration.PassingTestTimeout);

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                    using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate())
                        using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate())
                        {
                            SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions()
                            {
                                TargetHost          = Guid.NewGuid().ToString("N"),
                                EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12,
                            };
                            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
                            clientOptions.LocalCertificateSelectionCallback   = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>
                            {
                                return(sendClientCertificate ? clientCertificate : null);
                            };

                            SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions()
                            {
                                ServerCertificate = serverCertificate
                            };
                            serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                            await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                                client.AuthenticateAsClientAsync(clientOptions, cts.Token),
                                server.AuthenticateAsServerAsync(serverOptions, cts.Token));

                            await TestHelper.PingPong(client, server, cts.Token);

                            Assert.Null(server.RemoteCertificate);

                            // Client needs to be reading for renegotiation to happen.
                            byte[]          buffer = new byte[TestHelper.s_ping.Length];
                            ValueTask <int> t      = client.ReadAsync(buffer, cts.Token);

                            await server.NegotiateClientCertificateAsync(cts.Token);

                            if (sendClientCertificate)
                            {
                                Assert.NotNull(server.RemoteCertificate);
                            }
                            else
                            {
                                Assert.Null(server.RemoteCertificate);
                            }
                            // Finish the client's read
                            await server.WriteAsync(TestHelper.s_ping, cts.Token);

                            await t;

                            await Assert.ThrowsAsync <InvalidOperationException>(() => server.NegotiateClientCertificateAsync());
                        }
        }
Exemplo n.º 6
0
        private async Task ClientAsyncSslHelper(
            EncryptionPolicy encryptionPolicy,
            SslProtocols clientSslProtocols,
            SslProtocols serverSslProtocols,
            RemoteCertificateValidationCallback certificateCallback = null)
        {
            _log.WriteLine("Server: " + serverSslProtocols + "; Client: " + clientSslProtocols);

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();

            using (client)
                using (server)
                {
                    // Use a different SNI for each connection to prevent TLS 1.3 renegotiation issue: https://github.com/dotnet/runtime/issues/47378
                    string serverName = TestHelper.GetTestSNIName(nameof(ClientAsyncSslHelper), clientSslProtocols, serverSslProtocols);

                    Task serverTask = default;
                    try
                    {
                        Task clientTask = client.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
                        {
                            EnabledSslProtocols = clientSslProtocols,
                            RemoteCertificateValidationCallback = AllowAnyServerCertificate,
                            TargetHost = serverName
                        });
                        serverTask = server.AuthenticateAsServerAsync(new SslServerAuthenticationOptions
                        {
                            EncryptionPolicy               = encryptionPolicy,
                            EnabledSslProtocols            = serverSslProtocols,
                            ServerCertificate              = TestConfiguration.ServerCertificate,
                            CertificateRevocationCheckMode = X509RevocationMode.NoCheck
                        });

                        await clientTask.WaitAsync(TestConfiguration.PassingTestTimeout);

                        _log.WriteLine("Client authenticated to server with encryption cipher: {0} {1}-bit strength",
                                       client.CipherAlgorithm, client.CipherStrength);
                        Assert.True(client.CipherAlgorithm != CipherAlgorithmType.Null, "Cipher algorithm should not be NULL");
                        Assert.True(client.CipherStrength > 0, "Cipher strength should be greater than 0");
                    }
                    finally
                    {
                        // make sure we signal server in case of client failures
                        client.Close();
                        try
                        {
                            await serverTask;
                        }
                        catch (Exception ex)
                        {
                            // We generally don't care about server but can log exception to help diagnose test failures
                            _log.WriteLine(ex.ToString());
                        }
                    }
                }
        }
Exemplo n.º 7
0
        public async Task SslStream_StreamToStream_Alpn_NonMatchingProtocols_Fail()
        {
            (SslStream clientStream, SslStream serverStream) = TestHelper.GetConnectedSslStreams();

            using (serverStream)
                using (clientStream)
                    using (X509Certificate2 certificate = Configuration.Certificates.GetServerCertificate())
                    {
                        SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions
                        {
                            ApplicationProtocols = new List <SslApplicationProtocol> {
                                SslApplicationProtocol.Http2
                            },
                            ServerCertificate = certificate,
                        };
                        SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions
                        {
                            ApplicationProtocols = new List <SslApplicationProtocol> {
                                SslApplicationProtocol.Http11
                            },
                            RemoteCertificateValidationCallback = AllowAnyServerCertificate,
                            TargetHost = certificate.GetNameInfo(X509NameType.SimpleName, false),
                        };

                        // Test ALPN failure only on platforms that supports ALPN.
                        if (BackendSupportsAlpn)
                        {
                            Task t1 = Assert.ThrowsAsync <AuthenticationException>(() => clientStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions));

                            await Assert.ThrowsAsync <AuthenticationException>(() => serverStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions));

                            serverStream.Dispose();

                            await t1.WaitAsync(TestConfiguration.PassingTestTimeout);
                        }
                        else
                        {
                            Task t1 = clientStream.AuthenticateAsClientAsync(TestAuthenticateAsync, clientOptions);
                            Task t2 = serverStream.AuthenticateAsServerAsync(TestAuthenticateAsync, serverOptions);

                            await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2);

                            Assert.Equal(default(SslApplicationProtocol), clientStream.NegotiatedApplicationProtocol);
                            Assert.Equal(default(SslApplicationProtocol), serverStream.NegotiatedApplicationProtocol);
                        }
                    }
        }
        private async Task <string[]> ConnectAndGatherAcceptableIssuers(SslCertificateTrust trust)
        {
            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                    using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate())
                        using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate())
                        {
                            SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions
                            {
                                ServerCertificate                   = serverCertificate,
                                ClientCertificateRequired           = true,
                                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true,
                                ServerCertificateContext            = SslStreamCertificateContext.Create(serverCertificate, null, false, trust)
                            };

                            string[] acceptableIssuers = Array.Empty <string>();
                            SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions
                            {
                                TargetHost = "localhost",
                                // Force Tls 1.2 to avoid issues with certain OpenSSL versions and Tls 1.3
                                // https://github.com/openssl/openssl/issues/7384
                                EnabledSslProtocols = SslProtocols.Tls12,
                                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true,
                                LocalCertificateSelectionCallback   = (sender, targetHost, localCertificates, remoteCertificate, issuers) =>
                                {
                                    if (remoteCertificate == null)
                                    {
                                        // ignore the first call that is called before handshake
                                        return(null);
                                    }

                                    acceptableIssuers = issuers;
                                    return(clientCertificate);
                                },
                            };

                            await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                                client.AuthenticateAsClientAsync(clientOptions),
                                server.AuthenticateAsServerAsync(serverOptions));

                            return(acceptableIssuers);
                        }
        }
Exemplo n.º 9
0
        public async Task SslStream_NegotiateClientCertificateAsyncConcurrentIO_Throws(bool doRead)
        {
            using CancellationTokenSource cts = new CancellationTokenSource();
            cts.CancelAfter(TestConfiguration.PassingTestTimeout);

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                    using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate())
                        using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate())
                        {
                            SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions()
                            {
                                TargetHost         = Guid.NewGuid().ToString("N"),
                                ClientCertificates = new X509CertificateCollection(new X509Certificate2[] { clientCertificate })
                            };
                            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                            SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions()
                            {
                                ServerCertificate = serverCertificate
                            };
                            serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                            await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                                client.AuthenticateAsClientAsync(clientOptions, cts.Token),
                                server.AuthenticateAsServerAsync(serverOptions, cts.Token));

                            await TestHelper.PingPong(client, server, cts.Token);

                            Assert.Null(server.RemoteCertificate);

                            Task t = server.NegotiateClientCertificateAsync(cts.Token);
                            if (doRead)
                            {
                                byte[] buffer = new byte[TestHelper.s_ping.Length];
                                await Assert.ThrowsAsync <NotSupportedException>(() => server.ReadAsync(buffer).AsTask());
                            }
                            else
                            {
                                await Assert.ThrowsAsync <NotSupportedException>(() => server.WriteAsync(TestHelper.s_ping).AsTask());
                            }
                        }
        }
Exemplo n.º 10
0
        public async Task NegotiateClientCertificateAsync_PendingData_Throws()
        {
            using CancellationTokenSource cts = new CancellationTokenSource();
            cts.CancelAfter(TestConfiguration.PassingTestTimeout);

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                    using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate())
                        using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate())
                        {
                            SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions()
                            {
                                TargetHost         = Guid.NewGuid().ToString("N"),
                                ClientCertificates = new X509CertificateCollection(new X509Certificate2[] { clientCertificate })
                            };
                            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                            SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions()
                            {
                                ServerCertificate = serverCertificate
                            };
                            serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                            await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                                client.AuthenticateAsClientAsync(clientOptions, cts.Token),
                                server.AuthenticateAsServerAsync(serverOptions, cts.Token));

                            await TestHelper.PingPong(client, server, cts.Token);

                            Assert.Null(server.RemoteCertificate);

                            // This should go out in single TLS frame
                            await client.WriteAsync(new byte[200], cts.Token);

                            byte[] readBuffer = new byte[10];
                            // when we read part of the frame, remaining part should left decrypted
                            await server.ReadAsync(readBuffer, cts.Token);

                            await Assert.ThrowsAsync <InvalidOperationException>(() => server.NegotiateClientCertificateAsync(cts.Token));
                        }
        }
        public async Task CertificateSelectionCallback_DelayedCertificate_OK(bool delayCertificate, bool sendClientCertificate)
        {
            X509Certificate?remoteCertificate = null;

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                {
                    int count = 0;
                    SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions();
                    clientOptions.TargetHost = "localhost";
                    // Force Tls 1.2 to avoid issues with certain OpenSSL versions and Tls 1.3
                    // https://github.com/openssl/openssl/issues/7384
                    clientOptions.EnabledSslProtocols = SslProtocols.Tls12;
                    clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
                    clientOptions.LocalCertificateSelectionCallback   = (sender, targetHost, localCertificates, certificate, acceptableIssuers) =>
                    {
                        count++;
                        remoteCertificate = certificate;
                        if (delayCertificate && count == 1)
                        {
                            // wait until we get remote certificate from peer e.g. handshake started.
                            return(null);
                        }

                        return(sendClientCertificate ? _clientCertificate : null);
                    };

                    SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions();
                    serverOptions.ServerCertificate                   = _serverCertificate;
                    serverOptions.ClientCertificateRequired           = true;
                    serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                    {
                        if (sendClientCertificate)
                        {
                            Assert.NotNull(certificate);
                            // The client chain may be incomplete.
                            Assert.True(sslPolicyErrors == SslPolicyErrors.None || sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors);
                        }
                        else
                        {
                            Assert.Equal(SslPolicyErrors.RemoteCertificateNotAvailable, sslPolicyErrors);
                        }

                        return(true);
                    };


                    await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                        client.AuthenticateAsClientAsync(clientOptions),
                        server.AuthenticateAsServerAsync(serverOptions));

                    // verify that the session is usable with or without client's certificate
                    await TestHelper.PingPong(client, server);

                    await TestHelper.PingPong(server, client);

                    if (delayCertificate)
                    {
                        // LocalCertificateSelectionCallback should be called with real remote certificate.
                        Assert.NotNull(remoteCertificate);
                    }
                }
        }
Exemplo n.º 12
0
        public async Task SslStream_NegotiateClientCertificateAsyncTls13_Succeeds(bool sendClientCertificate)
        {
            bool negotiateClientCertificateCalled = false;

            using CancellationTokenSource cts = new CancellationTokenSource();
            cts.CancelAfter(TestConfiguration.PassingTestTimeout);

            (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams();
            using (client)
                using (server)
                    using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate())
                        using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate())
                        {
                            SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions()
                            {
                                TargetHost          = Guid.NewGuid().ToString("N"),
                                EnabledSslProtocols = SslProtocols.Tls13,
                            };
                            clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
                            clientOptions.LocalCertificateSelectionCallback   = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>
                            {
                                return(sendClientCertificate ? clientCertificate : null);
                            };

                            SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions()
                            {
                                ServerCertificate = serverCertificate
                            };
                            serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                            {
                                if (negotiateClientCertificateCalled && sendClientCertificate)
                                {
                                    Assert.Equal(clientCertificate.GetCertHash(), certificate?.GetCertHash());
                                }
                                else
                                {
                                    Assert.Null(certificate);
                                }

                                return(true);
                            };

                            await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
                                client.AuthenticateAsClientAsync(clientOptions, cts.Token),
                                server.AuthenticateAsServerAsync(serverOptions, cts.Token));

                            // need this to complete TLS 1.3 handshake
                            await TestHelper.PingPong(client, server);

                            Assert.Null(server.RemoteCertificate);

                            // Client needs to be reading for renegotiation to happen.
                            byte[]          buffer = new byte[TestHelper.s_ping.Length];
                            ValueTask <int> t      = client.ReadAsync(buffer, cts.Token);

                            negotiateClientCertificateCalled = true;
                            await server.NegotiateClientCertificateAsync(cts.Token);

                            if (sendClientCertificate)
                            {
                                Assert.NotNull(server.RemoteCertificate);
                            }
                            else
                            {
                                Assert.Null(server.RemoteCertificate);
                            }
                            // Finish the client's read
                            await server.WriteAsync(TestHelper.s_ping, cts.Token);

                            await t;
                            // verify that the session is usable with or without client's certificate
                            await TestHelper.PingPong(client, server, cts.Token);

                            await TestHelper.PingPong(server, client, cts.Token);
                        }
        }