Esempio n. 1
0
        private void ListenLoop()
        {
            if (scheduler.Verbose)
            {
                Console.WriteLine("Starting to listen on {0}", myEndpoint);
            }

            listener = new TcpListener(myEndpoint);
            listener.ExclusiveAddressUse = true;
            listener.Start();
            while (true)
            {
                if (scheduler.Verbose)
                {
                    Console.WriteLine("Waiting for the next incoming connection");
                }

                TcpClient client = listener.AcceptTcpClient();

                CertificateValidator myValidator = new CertificateValidator(scheduler);
                SslStream            sslStream   = new SslStream(client.GetStream(), leaveInnerStreamOpen: false, myValidator.ValidateSSLCertificate);
                sslStream.AuthenticateAsServer(scheduler.MyCert, clientCertificateRequired: true, checkCertificateRevocation: false);

                var remoteCert = sslStream.RemoteCertificate as X509Certificate2;

                if (scheduler.Verbose)
                {
                    Console.WriteLine("Received an incoming connection from remote certified as {0}",
                                      IoScheduler.CertificateToString(remoteCert));
                }

                ReceiverThread.Create(scheduler, sslStream);
                ServerSenderThread.Create(scheduler, sslStream);
            }
        }
Esempio n. 2
0
        private void SendDispatchLoop()
        {
            while (true)
            {
                if (scheduler.Verbose)
                {
                    Console.WriteLine("Waiting for the next send to dispatch");
                }

                SendTask sendTask = sendQueue.Receive();

                if (scheduler.Verbose)
                {
                    Console.WriteLine("Dispatching send of message of size {0} to {1}",
                                      sendTask.Message.Length, IoScheduler.PublicKeyToString(sendTask.DestinationPublicKey));
                }

                SenderThread senderThread = scheduler.FindSenderForDestinationPublicKey(sendTask.DestinationPublicKey);

                if (senderThread == null)
                {
                    senderThread = ClientSenderThread.Create(scheduler, sendTask.DestinationPublicKey);
                }

                senderThread.EnqueueSendTask(sendTask);
            }
        }
Esempio n. 3
0
        public static ReceiverThread Create(IoScheduler scheduler, SslStream stream)
        {
            ReceiverThread receiverThread = new ReceiverThread(scheduler, stream);
            Thread         t = new Thread(receiverThread.Run);

            t.Start();
            return(receiverThread);
        }
Esempio n. 4
0
 protected SenderThread(IoScheduler i_scheduler, byte[] i_destinationPublicKey, SslStream i_stream,
                        X509Certificate2 i_remoteCert)
 {
     scheduler            = i_scheduler;
     destinationPublicKey = i_destinationPublicKey;
     stream          = i_stream;
     remoteCert      = i_remoteCert;
     sendQueue       = new BufferBlock <SendTask>();
     currentSendTask = null;
 }
Esempio n. 5
0
 public void Run()
 {
     try
     {
         ReceiveLoop();
     }
     catch (Exception e)
     {
         scheduler.ReportException(e, "receiving from " + IoScheduler.GetCertificatePublicKey(remoteCert));
     }
 }
Esempio n. 6
0
        public static ClientSenderThread Create(IoScheduler scheduler, byte[] destinationPublicKey)
        {
            if (scheduler.Verbose)
            {
                Console.WriteLine("Creating sender thread to send to remote public key {0}",
                                  scheduler.LookupPublicKeyAsString(destinationPublicKey));
            }

            ClientSenderThread senderThread = new ClientSenderThread(scheduler, destinationPublicKey);

            senderThread.Start();
            return(senderThread);
        }
Esempio n. 7
0
        private void StartServer(PrivateIdentity myIdentity, string localHostNameOrAddress, int localPort)
        {
            onlyClient = false;

            try {
                myCert = new X509Certificate2(myIdentity.Pkcs12, "" /* empty password */, X509KeyStorageFlags.Exportable);
            }
            catch (Exception e) {
                Console.Error.WriteLine("Could not import private key. Exception:{0}", e);
                throw new Exception("Can't start server because private key not decryptable");
            }

            // The `local` parameters override the parameters in
            // `myIdentity`, unless they're empty or zero.

            if (localHostNameOrAddress == null || localHostNameOrAddress.Length == 0)
            {
                localHostNameOrAddress = myIdentity.HostNameOrAddress;
            }
            if (localPort == 0)
            {
                localPort = myIdentity.Port;
            }

            var address = LookupHostNameOrAddress(localHostNameOrAddress);

            if (address == null)
            {
                Console.Error.WriteLine("ERROR:  Could not find any addresses when resolving {0}, which I'm supposed to bind to.");
                throw new Exception("Can't resolve binding address");
            }
            var myEndpoint = new IPEndPoint(address, localPort);

            if (verbose)
            {
                Console.WriteLine("Starting I/O scheduler as server listening to {0} certified as {1}",
                                  myEndpoint, IoScheduler.CertificateToString(myCert));
            }

            sendDispatchThread = new SendDispatchThread(this);
            Thread st = new Thread(sendDispatchThread.Run);

            st.Start();

            // Start a thread to listen on my binding endpoint.

            listenerThread = new ListenerThread(this, myEndpoint);
            Thread lt = new Thread(listenerThread.Run);

            lt.Start();
        }
Esempio n. 8
0
        public static IoScheduler CreateClient(List <PublicIdentity> serverIdentities, bool verbose = false,
                                               bool connectToAllServers = true, int maxSendTries = 3)
        {
            var scheduler = new IoScheduler(null, null, 0, serverIdentities, verbose, maxSendTries);

            if (connectToAllServers)
            {
                foreach (var serverIdentity in serverIdentities)
                {
                    scheduler.Connect(serverIdentity.PublicKey);
                }
            }
            return(scheduler);
        }
Esempio n. 9
0
        private void ReceiveLoop()
        {
            bool success;

            if (scheduler.Verbose)
            {
                Console.WriteLine("Starting receive loop with remote identified as {0}", IoScheduler.CertificateToString(remoteCert));
            }

            while (true)
            {
                // Read the next message's size.

                UInt64 messageSize;
                success = IoEncoder.ReadUInt64(stream, out messageSize);
                if (!success)
                {
                    if (scheduler.Verbose)
                    {
                        Console.Error.WriteLine("Failed to receive message size from {0}", IoScheduler.CertificateToString(remoteCert));
                    }
                    return;
                }
                if (scheduler.Verbose)
                {
                    Console.WriteLine("Received message size {0} from {1}", messageSize, IoScheduler.CertificateToString(remoteCert));
                }

                byte[] messageBuf = new byte[messageSize];
                success = IoEncoder.ReadBytes(stream, messageBuf, 0, messageSize);
                if (!success)
                {
                    if (scheduler.Verbose)
                    {
                        Console.Error.WriteLine("Failed to receive message of size {0} from {1}",
                                                messageSize, IoScheduler.CertificateToString(remoteCert));
                    }
                    return;
                }
                if (scheduler.Verbose)
                {
                    Console.WriteLine("Received message of size {0} from {1}", messageSize, IoScheduler.CertificateToString(remoteCert));
                }

                ReceivedPacket packet = new ReceivedPacket(remoteCert, messageBuf);
                scheduler.NoteReceivedPacket(packet);
            }
        }
Esempio n. 10
0
        public static ServerSenderThread Create(IoScheduler scheduler, SslStream stream)
        {
            var remoteCert           = stream.RemoteCertificate as X509Certificate2;
            var destinationPublicKey = IoScheduler.GetCertificatePublicKey(remoteCert);

            if (scheduler.Verbose)
            {
                Console.WriteLine("Creating sender thread to send to remote certified as {0}",
                                  IoScheduler.CertificateToString(remoteCert));
            }

            ServerSenderThread senderThread = new ServerSenderThread(scheduler, destinationPublicKey, stream, remoteCert);

            senderThread.Start();
            return(senderThread);
        }
Esempio n. 11
0
        ///////////////////////////////////
        // API for IoNative.cs
        ///////////////////////////////////

        public void ReceivePacket(Int32 timeLimit, out bool ok, out bool timedOut, out byte[] remotePublicKey, out byte[] message)
        {
            ReceivedPacket packet;

            try {
                if (timeLimit == 0)
                {
                    timedOut = !receiveQueue.TryReceive(out packet);
                }
                else
                {
                    TimeSpan timeSpan = TimeSpan.FromMilliseconds(timeLimit);
                    packet   = receiveQueue.Receive(timeSpan);
                    timedOut = false;
                }

                ok = true;
                if (timedOut)
                {
                    remotePublicKey = null;
                    message         = null;
                }
                else
                {
                    remotePublicKey = IoScheduler.GetCertificatePublicKey(packet.SenderCert);
                    message         = packet.Message;
                    if (verbose)
                    {
                        Console.WriteLine("Dequeueing a packet of size {0} from {1}",
                                          message.Length, CertificateToString(packet.SenderCert));
                    }
                }
            }
            catch (TimeoutException) {
                remotePublicKey = null;
                message         = null;
                ok       = true;
                timedOut = true;
            }
            catch (Exception e) {
                Console.Error.WriteLine("Unexpected error trying to read packet from packet queue. Exception:\n{0}", e);
                remotePublicKey = null;
                message         = null;
                ok       = false;
                timedOut = false;
            }
        }
Esempio n. 12
0
        private void StartClient()
        {
            onlyClient = true;

            myCert = IronfleetCrypto.CreateTransientClientIdentity();

            if (verbose)
            {
                Console.WriteLine("Starting I/O scheduler as client with certificate {0}",
                                  IoScheduler.CertificateToString(myCert));
            }

            sendDispatchThread = new SendDispatchThread(this);
            Thread st = new Thread(sendDispatchThread.Run);

            st.Start();
        }
Esempio n. 13
0
        public static void CreateNewIdentity(string friendlyName, string hostNameOrAddress, int port,
                                             out PublicIdentity publicIdentity, out PrivateIdentity privateIdentity)
        {
            var key     = RSA.Create(4096);
            var subject = string.Format("CN = {0}", friendlyName);
            var req     = new CertificateRequest(subject, key, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
            var now     = DateTime.Now;
            var expiry  = now.AddYears(10);
            var cert    = req.CreateSelfSigned(now, expiry);
            var pkcs12  = cert.Export(X509ContentType.Pkcs12, "" /* empty password */);

            publicIdentity = new PublicIdentity {
                FriendlyName      = friendlyName,
                PublicKey         = IoScheduler.GetCertificatePublicKey(cert),
                HostNameOrAddress = hostNameOrAddress,
                Port = port
            };
            privateIdentity = new PrivateIdentity {
                FriendlyName      = friendlyName,
                Pkcs12            = pkcs12,
                HostNameOrAddress = hostNameOrAddress,
                Port = port
            };
        }
Esempio n. 14
0
 public SendDispatchThread(IoScheduler i_scheduler)
 {
     scheduler = i_scheduler;
     sendQueue = new BufferBlock <SendTask>();
 }
Esempio n. 15
0
 public ListenerThread(IoScheduler i_scheduler, IPEndPoint i_myEndpoint)
 {
     scheduler  = i_scheduler;
     myEndpoint = i_myEndpoint;
 }
Esempio n. 16
0
        protected override bool Connect()
        {
            var destinationPublicIdentity = scheduler.LookupPublicKey(destinationPublicKey);

            if (destinationPublicIdentity == null)
            {
                if (scheduler.Verbose)
                {
                    Console.Error.WriteLine("Could not connect to destination public key {0} because we don't know its address.",
                                            IoScheduler.PublicKeyToString(destinationPublicKey));
                }
                return(false);
            }

            if (scheduler.Verbose)
            {
                Console.WriteLine("Starting connection to {0}", IoScheduler.PublicIdentityToString(destinationPublicIdentity));
            }

            TcpClient client;

            try
            {
                client = new TcpClient(destinationPublicIdentity.HostNameOrAddress, destinationPublicIdentity.Port);
            }
            catch (Exception e)
            {
                scheduler.ReportException(e, "connecting to " + IoScheduler.PublicIdentityToString(destinationPublicIdentity));
                return(false);
            }

            var myCertificateCollection = new X509CertificateCollection();

            myCertificateCollection.Add(scheduler.MyCert);
            var myValidator = new CertificateValidator(scheduler, destinationPublicIdentity);

            try {
                stream = new SslStream(client.GetStream(), leaveInnerStreamOpen: false, myValidator.ValidateSSLCertificate);
                stream.AuthenticateAsClient(destinationPublicIdentity.FriendlyName, myCertificateCollection,
                                            checkCertificateRevocation: false);
            }
            catch (Exception e) {
                scheduler.ReportException(e, "authenticating connection to " + IoScheduler.PublicIdentityToString(destinationPublicIdentity));
                return(false);
            }

            remoteCert = stream.RemoteCertificate as X509Certificate2;

            if (!ByteArrayComparer.Default().Equals(IoScheduler.GetCertificatePublicKey(remoteCert), destinationPublicKey))
            {
                Console.Error.WriteLine("Connected to {0} expecting public key {1} but found public key {2}, so disconnecting.",
                                        IoScheduler.PublicIdentityToString(destinationPublicIdentity),
                                        IoScheduler.PublicKeyToString(destinationPublicKey),
                                        IoScheduler.PublicKeyToString(IoScheduler.GetCertificatePublicKey(remoteCert)));
                return(false);
            }

            if (scheduler.Verbose)
            {
                Console.WriteLine("Successfully connected to {0} and got certificate identifying it as {1}",
                                  IoScheduler.PublicIdentityToString(destinationPublicIdentity),
                                  IoScheduler.CertificateToString(remoteCert));
            }

            // Now that the connection is successful, create a thread to
            // receive packets on it.

            ReceiverThread receiverThread = ReceiverThread.Create(scheduler, stream);

            return(true);
        }
Esempio n. 17
0
 public static string CertificateToString(X509Certificate2 cert)
 {
     return(string.Format("{0} (key {1})",
                          cert.SubjectName.Name, PublicKeyToString(IoScheduler.GetCertificatePublicKey(cert))));
 }
Esempio n. 18
0
 private ClientSenderThread(IoScheduler i_scheduler, byte[] i_destinationPublicKey) :
     base(i_scheduler, i_destinationPublicKey, null, null)
 {
 }
Esempio n. 19
0
 protected override string EndpointDescription()
 {
     return(IoScheduler.CertificateToString(remoteCert));
 }
Esempio n. 20
0
 private ServerSenderThread(IoScheduler i_scheduler, byte[] i_destinationPublicKey, SslStream i_stream,
                            X509Certificate2 i_remoteCert) :
     base(i_scheduler, i_destinationPublicKey, i_stream, i_remoteCert)
 {
 }
Esempio n. 21
0
 public CertificateValidator(IoScheduler i_scheduler, PublicIdentity i_expectedPublicIdentity = null)
 {
     scheduler = i_scheduler;
     expectedPublicIdentity = i_expectedPublicIdentity;
 }
Esempio n. 22
0
        public bool ValidateSSLCertificate(object sender, X509Certificate certificate, X509Chain chain,
                                           SslPolicyErrors sslPolicyErrors)
        {
            const SslPolicyErrors ignoredErrors = SslPolicyErrors.RemoteCertificateChainErrors;

            if ((sslPolicyErrors & ~ignoredErrors) != SslPolicyErrors.None)
            {
                Console.Error.WriteLine("Could not validate SSL certificate for {0} due to errors {1}",
                                        IoScheduler.GetCertificatePublicKey(certificate as X509Certificate2),
                                        sslPolicyErrors & ~ignoredErrors);
                return(false);
            }

            var cert2 = certificate as X509Certificate2;

            // If we were expecting a specific public identity, check that
            // the key in the certificate matches what we were expecting.

            if (expectedPublicIdentity != null)
            {
                if (!ByteArrayComparer.Default().Equals(IoScheduler.GetCertificatePublicKey(cert2), expectedPublicIdentity.PublicKey))
                {
                    Console.Error.WriteLine("Connected to {0} expecting public key {1} but found public key {2}, so disconnecting.",
                                            IoScheduler.PublicIdentityToString(expectedPublicIdentity),
                                            IoScheduler.PublicKeyToString(expectedPublicIdentity.PublicKey),
                                            IoScheduler.PublicKeyToString(IoScheduler.GetCertificatePublicKey(cert2)));
                    return(false);
                }

                if (cert2.SubjectName.Name != "CN=" + expectedPublicIdentity.FriendlyName)
                {
                    Console.Error.WriteLine("Connected to {0} expecting subject CN={1} but found {2}, so disconnecting.",
                                            IoScheduler.PublicIdentityToString(expectedPublicIdentity),
                                            expectedPublicIdentity.FriendlyName,
                                            cert2.SubjectName.Name);
                    return(false);
                }
            }
            else
            {
                // If we weren't expecting any particular public identity,
                // consider the expected public identity to be the known one
                // matching the public key in the certificate we got.  If
                // there is no known one, then this is just an anonymous
                // client, which is fine.  Otherwise, check that the subject
                // matches what we expect.  This is just a paranoid check; it
                // should never fail.

                expectedPublicIdentity = scheduler.LookupPublicKey(IoScheduler.GetCertificatePublicKey(cert2));
                if (expectedPublicIdentity != null)
                {
                    if (cert2.SubjectName.Name != "CN=" + expectedPublicIdentity.FriendlyName)
                    {
                        Console.Error.WriteLine("Received a certificate we expected to have subject CN={1} but found {2}, so disconnecting.",
                                                IoScheduler.PublicIdentityToString(expectedPublicIdentity),
                                                expectedPublicIdentity.FriendlyName,
                                                cert2.SubjectName.Name);
                        return(false);
                    }
                }
            }

            return(true);
        }
Esempio n. 23
0
 private ReceiverThread(IoScheduler i_scheduler, SslStream i_stream)
 {
     scheduler  = i_scheduler;
     stream     = i_stream;
     remoteCert = stream.RemoteCertificate as X509Certificate2;
 }