public void TestAcceptOnlySelfSignedCertMode()
        {
            _listener = CreateListener();
            _listener.TlsIdentity.Should()
            .NotBeNull("because otherwise the TLS identity was not created for the listener");
            _listener.TlsIdentity.Certs.Should().HaveCount(1,
                                                           "because otherwise bogus certs were used");

            DisableDefaultServerCertPinning = true;

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,
                false,//accept only self signed server cert
                null,
                //TODO: Need to handle Linux throwing different error TLSCertUntrusted (5008)
                (int)CouchbaseLiteError.TLSCertUnknownRoot,
                CouchbaseLiteErrorType.CouchbaseLite
                );

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,
                true, //accept only self signed server cert
                null,
                0,
                0
                );

            _listener.Stop();
        }
        public void TestAcceptSelfSignedCertWithPinnedCertificate()
        {
            _listener = CreateListener();
            _listener.TlsIdentity.Should()
            .NotBeNull("because otherwise the TLS identity was not created for the listener");
            _listener.TlsIdentity.Certs.Should().HaveCount(1,
                                                           "because otherwise bogus certs were used");

            // listener = cert1; replicator.pin = cert2; acceptSelfSigned = true => fail
            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,              //authenticator
                true,              //accept only self signed server cert
                DefaultServerCert, //server cert
                (int)CouchbaseLiteError.TLSCertUnknownRoot,
                CouchbaseLiteErrorType.CouchbaseLite
                );

            // listener = cert1; replicator.pin = cert1; acceptSelfSigned = false => pass
            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,
                false,                          //accept only self signed server cert
                _listener.TlsIdentity.Certs[0], //server cert
                0,
                0
                );

            _listener.Stop();
        }
        public void TestMultipleListenersOnSameDatabase()
        {
            _listener = CreateListener();
            var _listener2 = CreateNewListener();

            using (var doc1 = new MutableDocument("doc1"))
                using (var doc2 = new MutableDocument("doc2")) {
                    doc1.SetString("name", "Sam");
                    Db.Save(doc1);
                    doc2.SetString("name", "Mary");
                    OtherDb.Save(doc2);
                }

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,
                false, //accept only self signed server cert
                _listener.TlsIdentity.Certs[0],
                0,
                0
                );

            _listener.Stop();
            _listener2.Stop();

            OtherDb.Count.Should().Be(2);
        }
        public void TestDoNotAcceptSelfSignedMode() //aka testPinnedServerCertificate in iOS
        {
            _listener = CreateListener();
            _listener.TlsIdentity.Should()
            .NotBeNull("because otherwise the TLS identity was not created for the listener");
            _listener.TlsIdentity.Certs.Should().HaveCount(1,
                                                           "because otherwise bogus certs were used");

            DisableDefaultServerCertPinning = true;

            // Replicator - TLS Error
            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,
                false, //accept only self signed server cert
                null,
                (int)CouchbaseLiteError.TLSCertUnknownRoot,
                CouchbaseLiteErrorType.CouchbaseLite
                );

            // Replicator - Success
            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,
                false, //accept only self signed server cert
                _listener.TlsIdentity.Certs[0],
                0,
                0
                );

            _listener.Stop();
        }
Пример #5
0
        public void TestPasswordAuthenticator()
        {
            var auth = new ListenerPasswordAuthenticator((sender, username, password) =>
            {
                return(username == "daniel" && new NetworkCredential(string.Empty, password).Password == "123");
            });

            _listener = CreateListener(false, true, auth);

            // Replicator - No authenticator
            var targetEndpoint = _listener.LocalEndpoint();
            var config         = new ReplicatorConfiguration(Db, targetEndpoint);

            RunReplication(config, (int)CouchbaseLiteError.HTTPAuthRequired, CouchbaseLiteErrorType.CouchbaseLite);
            var          pw                  = "123";
            var          wrongPw             = "456";
            SecureString pwSecureString      = null;
            SecureString wrongPwSecureString = null;

            unsafe
            {
                fixed(char *pw_ = pw)
                fixed(char *wrongPw_ = wrongPw)
                {
                    pwSecureString      = new SecureString(pw_, pw.Length);
                    wrongPwSecureString = new SecureString(wrongPw_, wrongPw.Length);
                }
            }

            // Replicator - Wrong Credentials
            config = new ReplicatorConfiguration(Db, targetEndpoint)
            {
                Authenticator = new BasicAuthenticator("daniel", wrongPwSecureString)
            };
            RunReplication(config, (int)CouchbaseLiteError.HTTPAuthRequired, CouchbaseLiteErrorType.CouchbaseLite);

            // Replicator - Success
            config = new ReplicatorConfiguration(Db, targetEndpoint)
            {
                Authenticator = new BasicAuthenticator("daniel", pwSecureString)
            };
            RunReplication(config, 0, 0);

            _listener.Stop();
            pwSecureString.Dispose();
            wrongPwSecureString.Dispose();
        }
        public void TestListenerWithImportIdentity()
        {
            byte[] serverData = null;
            using (var stream = typeof(URLEndpointListenerTest).Assembly.GetManifestResourceStream("client.p12"))
                using (var reader = new BinaryReader(stream)) {
                    serverData = reader.ReadBytes((int)stream.Length);
                }

            // Cleanup
            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);

            // Import identity
            var id = TLSIdentity.ImportIdentity(_store, serverData, "123", ServerCertLabel, null);

            // Create listener and start
            var config = CreateListenerConfig(true, true, null, id);

            _listener = Listen(config);

            _listener.TlsIdentity.Should().NotBeNull();

            using (var doc1 = new MutableDocument("doc1")) {
                doc1.SetString("name", "Sam");
                Db.Save(doc1);
            }

            OtherDb.Count.Should().Be(0);

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null,                           //authenticator
                false,                          //accept only self signed server cert
                _listener.TlsIdentity.Certs[0], //server cert
                0,
                0
                );

            OtherDb.Count.Should().Be(1);

            _listener.Stop();
        }
        public void TestStopListener()
        {
            ManualResetEventSlim waitIdleAssert    = new ManualResetEventSlim();
            ManualResetEventSlim waitStoppedAssert = new ManualResetEventSlim();

            var config = CreateListenerConfig(false);

            _listener = Listen(config);

            var target  = _listener.LocalEndpoint();
            var config1 = CreateConfig(target, ReplicatorType.PushAndPull, true,
                                       serverCert: null);

            using (var repl = new Replicator(config1)) {
                var token = repl.AddChangeListener((sender, args) =>
                {
                    if (args.Status.Activity == ReplicatorActivityLevel.Idle)
                    {
                        waitIdleAssert.Set();
                        // Stop listener aka server
                        _listener.Stop();
                    }
                    else if (args.Status.Activity == ReplicatorActivityLevel.Stopped)
                    {
                        waitStoppedAssert.Set();
                    }
                });

                repl.Start();

                // Wait until idle then stop the listener
                waitIdleAssert.Wait(TimeSpan.FromSeconds(15)).Should().BeTrue();

                // Wait for the replicator to be stopped
                waitStoppedAssert.Wait(TimeSpan.FromSeconds(20)).Should().BeTrue();

                // Check error
                var error = repl.Status.Error.As <CouchbaseWebsocketException>();
                error.Error.Should().Be((int)CouchbaseLiteError.WebSocketGoingAway);
            }
        }
        public void TestClientCertAuthRootCertsError()
        {
            byte[] caData;
            using (var stream = typeof(URLEndpointListenerTest).Assembly.GetManifestResourceStream("client-ca.der"))
                using (var reader = new BinaryReader(stream)) {
                    caData = reader.ReadBytes((int)stream.Length);
                }

            var rootCert = new X509Certificate2(caData);
            var auth     = new ListenerCertificateAuthenticator(new X509Certificate2Collection(rootCert));

            _listener = CreateListener(true, true, auth);

            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);
            // Create wrong client identity
            var id = TLSIdentity.CreateIdentity(false,
                                                new Dictionary <string, string>()
            {
                { Certificate.CommonNameAttribute, "daniel" }
            },
                                                null,
                                                _store,
                                                ClientCertLabel,
                                                null);

            id.Should().NotBeNull();
            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                new ClientCertificateAuthenticator(id),
                true,
                _listener.TlsIdentity.Certs[0],
                (int)CouchbaseLiteError.TLSHandshakeFailed,  //not TLSClientCertRejected as mac has..
                CouchbaseLiteErrorType.CouchbaseLite
                );

            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);
            _listener.Stop();
        }
        public void TestClientCertAuthenticatorRootCerts()
        {
            byte[] caData, clientData;
            using (var stream = typeof(URLEndpointListenerTest).Assembly.GetManifestResourceStream("client-ca.der"))
                using (var reader = new BinaryReader(stream)) {
                    caData = reader.ReadBytes((int)stream.Length);
                }

            using (var stream = typeof(URLEndpointListenerTest).Assembly.GetManifestResourceStream("client.p12"))
                using (var reader = new BinaryReader(stream)) {
                    clientData = reader.ReadBytes((int)stream.Length);
                }

            var rootCert = new X509Certificate2(caData);
            var auth     = new ListenerCertificateAuthenticator(new X509Certificate2Collection(rootCert));

            _listener = CreateListener(true, true, auth);
            var serverCert = _listener.TlsIdentity.Certs[0];

            // Cleanup
            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);

            // Create client identity
            var id = TLSIdentity.ImportIdentity(_store, clientData, "123", ClientCertLabel, null);

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                new ClientCertificateAuthenticator(id),
                true,
                serverCert,
                0,
                0
                );

            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);
            _listener.Stop();
        }
        private void WithActiveReplicationsAndURLEndpointListener(bool isCloseNotDelete)
        {
            var waitIdleAssert1    = new ManualResetEventSlim();
            var waitIdleAssert2    = new ManualResetEventSlim();
            var waitStoppedAssert1 = new ManualResetEventSlim();
            var waitStoppedAssert2 = new ManualResetEventSlim();

            using (var doc = new MutableDocument()) {
                OtherDb.Save(doc);
            }

            _listener = CreateListener();
            _listener.Config.Database.ActiveStoppables.Count.Should().Be(1);

            using (var doc1 = new MutableDocument()) {
                Db.Save(doc1);
            }

            var target  = new DatabaseEndpoint(Db);
            var config1 = CreateConfig(target, ReplicatorType.PushAndPull, true, sourceDb: OtherDb);
            var repl1   = new Replicator(config1);

            Database.Delete("urlepTestDb", Directory);
            var urlepTestDb = OpenDB("urlepTestDb");

            using (var doc2 = new MutableDocument()) {
                urlepTestDb.Save(doc2);
            }

            var config2 = CreateConfig(_listener.LocalEndpoint(), ReplicatorType.PushAndPull, true,
                                       serverCert: _listener.TlsIdentity.Certs[0], sourceDb: urlepTestDb);
            var repl2 = new Replicator(config2);

            EventHandler <ReplicatorStatusChangedEventArgs> changeListener = (sender, args) =>
            {
                if (args.Status.Activity == ReplicatorActivityLevel.Idle && args.Status.Progress.Completed ==
                    args.Status.Progress.Total)
                {
                    if (sender == repl1)
                    {
                        waitIdleAssert1.Set();
                    }
                    else
                    {
                        waitIdleAssert2.Set();
                    }
                }
                else if (args.Status.Activity == ReplicatorActivityLevel.Stopped)
                {
                    if (sender == repl1)
                    {
                        waitStoppedAssert1.Set();
                    }
                    else
                    {
                        waitStoppedAssert2.Set();
                    }
                }
            };

            repl1.AddChangeListener(changeListener);
            repl2.AddChangeListener(changeListener);
            repl1.Start();
            repl2.Start();

            WaitHandle.WaitAll(new[] { waitIdleAssert1.WaitHandle, waitIdleAssert2.WaitHandle }, _timeout)
            .Should().BeTrue();

            OtherDb.ActiveStoppables.Count.Should().Be(2);
            urlepTestDb.ActiveStoppables.Count.Should().Be(1);

            if (isCloseNotDelete)
            {
                urlepTestDb.Close();
                OtherDb.Close();
            }
            else
            {
                urlepTestDb.Delete();
                OtherDb.Delete();
            }

            OtherDb.ActiveStoppables.Count.Should().Be(0);
            urlepTestDb.ActiveStoppables.Count.Should().Be(0);
            OtherDb.IsClosedLocked.Should().Be(true);
            urlepTestDb.IsClosedLocked.Should().Be(true);

            WaitHandle.WaitAll(new[] { waitStoppedAssert1.WaitHandle, waitStoppedAssert2.WaitHandle }, TimeSpan.FromSeconds(20))
            .Should().BeTrue();

            waitIdleAssert1.Dispose();
            waitIdleAssert2.Dispose();
            waitStoppedAssert1.Dispose();
            waitStoppedAssert2.Dispose();

            Thread.Sleep(500);
        }
        public void TestReplicatorAndListenerOnSameDatabase()
        {
            using (var doc = new MutableDocument()) {
                OtherDb.Save(doc);
            }

            CreateListener();
            using (var doc1 = new MutableDocument()) {
                Db.Save(doc1);
            }

            var target  = new DatabaseEndpoint(Db);
            var config1 = CreateConfig(target, ReplicatorType.PushAndPull, true, sourceDb: OtherDb);
            var repl1   = new Replicator(config1);

            Database.Delete("urlepTestDb", Directory);
            var urlepTestDb = OpenDB("urlepTestDb");

            using (var doc2 = new MutableDocument()) {
                urlepTestDb.Save(doc2);
            }

            var config2 = CreateConfig(_listener.LocalEndpoint(), ReplicatorType.PushAndPull, true,
                                       serverCert: _listener.TlsIdentity.Certs[0], sourceDb: urlepTestDb);
            var repl2 = new Replicator(config2);

            var wait1 = new ManualResetEventSlim();
            var wait2 = new ManualResetEventSlim();
            EventHandler <ReplicatorStatusChangedEventArgs> changeListener = (sender, args) =>
            {
                if (args.Status.Activity == ReplicatorActivityLevel.Idle && args.Status.Progress.Completed ==
                    args.Status.Progress.Total)
                {
                    if (OtherDb.Count == 3 && Db.Count == 3 && urlepTestDb.Count == 3)
                    {
                        ((Replicator)sender).Stop();
                    }
                }
                else if (args.Status.Activity == ReplicatorActivityLevel.Stopped)
                {
                    if (sender == repl1)
                    {
                        wait1.Set();
                    }
                    else
                    {
                        wait2.Set();
                    }
                }
            };

            var token1 = repl1.AddChangeListener(changeListener);
            var token2 = repl2.AddChangeListener(changeListener);

            repl1.Start();
            repl2.Start();
            WaitHandle.WaitAll(new[] { wait1.WaitHandle, wait2.WaitHandle }, TimeSpan.FromSeconds(20))
            .Should().BeTrue();

            repl1.RemoveChangeListener(token1);
            repl2.RemoveChangeListener(token2);

            Db.Count.Should().Be(3, "because otherwise not all docs were received into Db");
            OtherDb.Count.Should().Be(3, "because otherwise not all docs were received into OtherDb");
            urlepTestDb.Count.Should().Be(3, "because otherwise not all docs were received into urlepTestDb");

            repl1.Dispose();
            repl2.Dispose();
            wait1.Dispose();
            wait2.Dispose();
            urlepTestDb.Delete();

            _listener.Stop();

            Thread.Sleep(500); // wait for everything to stop
        }
        public void TestClientCertAuthWithCallback()
        {
            var auth = new ListenerCertificateAuthenticator((sender, cert) =>
            {
                if (cert.Count != 1)
                {
                    return(false);
                }

                return(cert[0].SubjectName.Name?.Replace("CN=", "") == "daniel");
            });

            var badAuth = new ListenerCertificateAuthenticator((sender, cert) =>
            {
                return(cert.Count == 100); // Obviously fail
            });

            _listener = CreateListener(true, true, auth);

            // User Identity
            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);
            var id = TLSIdentity.CreateIdentity(false,
                                                new Dictionary <string, string>()
            {
                { Certificate.CommonNameAttribute, "daniel" }
            },
                                                null,
                                                _store,
                                                ClientCertLabel,
                                                null);

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                new ClientCertificateAuthenticator(id),
                false,
                _listener.TlsIdentity.Certs[0],
                0,
                0
                );

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                null, // Don't send client cert
                false,
                _listener.TlsIdentity.Certs[0],
                (int)CouchbaseLiteError.TLSHandshakeFailed,
                CouchbaseLiteErrorType.CouchbaseLite
                );

            _listener.Stop();
            _listener = CreateListener(true, true, badAuth);

            RunReplication(
                _listener.LocalEndpoint(),
                ReplicatorType.PushAndPull,
                false,
                new ClientCertificateAuthenticator(id), // send wrong client cert
                false,
                _listener.TlsIdentity.Certs[0],
                (int)CouchbaseLiteError.TLSHandshakeFailed,
                CouchbaseLiteErrorType.CouchbaseLite
                );

            TLSIdentity.DeleteIdentity(_store, ClientCertLabel, null);
        }
        public void TestStatus()
        {
            ulong maxConnectionCount = 0UL;
            ulong maxActiveCount     = 0UL;

            //init and start a listener
            _listener = CreateListener(false);

            //listener is started at this point
            _listener.Status.ConnectionCount.Should().Be(0, "Listener's connection count should be 0 because no client connection has been established.");
            _listener.Status.ActiveConnectionCount.Should().Be(0, "Listener's active connection count should be 0 because no client connection has been established.");

            using (var doc1 = new MutableDocument())
                using (var doc2 = new MutableDocument()) {
                    doc1.SetString("name", "Sam");
                    Db.Save(doc1);
                    doc2.SetString("name", "Mary");
                    OtherDb.Save(doc2);
                }

            var targetEndpoint = _listener.LocalEndpoint();
            var config         = new ReplicatorConfiguration(Db, targetEndpoint);

            using (var repl = new Replicator(config)) {
                var waitAssert = new WaitAssert();
                var token      = repl.AddChangeListener((sender, args) =>
                {
                    WriteLine($"Yeehaw {_listener.Status.ConnectionCount} / {_listener.Status.ActiveConnectionCount}");

                    maxConnectionCount = Math.Max(maxConnectionCount, _listener.Status.ConnectionCount);
                    maxActiveCount     = Math.Max(maxActiveCount, _listener.Status.ActiveConnectionCount);

                    waitAssert.RunConditionalAssert(() =>
                    {
                        return(args.Status.Activity == ReplicatorActivityLevel.Stopped);
                    });
                });

                repl.Start();
                while (repl.Status.Activity != ReplicatorActivityLevel.Busy)
                {
                    Thread.Sleep(100);
                }

                // For some reason running on mac throws off the timing enough so that the active connection count
                // of 1 is never seen.  So record the value right after it becomes busy.
                maxConnectionCount = Math.Max(maxConnectionCount, _listener.Status.ConnectionCount);
                maxActiveCount     = Math.Max(maxActiveCount, _listener.Status.ActiveConnectionCount);

                try {
                    waitAssert.WaitForResult(TimeSpan.FromSeconds(100));
                } finally {
                    repl.RemoveChangeListener(token);
                }
            }

            maxConnectionCount.Should().Be(1);
            maxActiveCount.Should().Be(1);

            //stop the listener
            _listener.Stop();
            _listener.Status.ConnectionCount.Should().Be(0, "Listener's connection count should be 0 because the connection is stopped.");
            _listener.Status.ActiveConnectionCount.Should().Be(0, "Listener's active connection count should be 0 because the connection is stopped.");
        }