Exemplo n.º 1
0
        /// <summary>
        /// Establishes the SSL certificate we will use for communication with
        /// RPC clients and starts a seperate thread to listen for connections
        /// </summary>
        /// <param name="port">port to listen on</param>
        /// <param name="service">The KeePassRPCService the server should interact with.</param>
        public KeePassRPCServer(int port, KeePassRPCService service, KeePassRPCExt keePassRPCPlugin, bool useSSL)
        {
            _useSSL = useSSL;
            if (keePassRPCPlugin.logger != null)
            {
                keePassRPCPlugin.logger.WriteLine("Starting KPRPCServer");
            }
            Service          = service;
            KeePassRPCPlugin = keePassRPCPlugin;

            if (_useSSL)
            {
//                if (true)
                if (Type.GetType("Mono.Runtime") == null)
                {
                    _store = new System.Security.Cryptography.X509Certificates.X509Store();
                    _store.Open(OpenFlags.ReadWrite);

                    // Find any certificates in this user's certificate store and re-use
                    // them rather than suffer the overhead of creating an entirly new
                    // certificate. Our certificates are considered "invalid" by the
                    // store (probably becuase they are self-signed)
                    X509Certificate2Collection matchingCertificates = _store.Certificates
                                                                      .Find(X509FindType.FindBySubjectDistinguishedName,
                                                                            "CN=KeePassRPC certificate for " + Environment.MachineName, false);

                    //foreach (X509Certificate2 temp in matchingCertificates)
                    //    _store.Remove(temp);

                    //matchingCertificates = _store.Certificates
                    //    .Find(X509FindType.FindBySubjectDistinguishedName,
                    //        "CN=KeePassRPC TLS aaa for " + Environment.MachineName, false);

                    if (keePassRPCPlugin.logger != null)
                    {
                        keePassRPCPlugin.logger.WriteLine("Matching certificates from store: " + matchingCertificates.Count);
                    }
                    if (matchingCertificates.Count > 0)
                    {
                        _serverCertificate = matchingCertificates[0];
                    }
                    else
                    {
                        //_serverCertificate = (X509Certificate2)X509Certificate2.CreateFromCertFile(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC"), "cert.p12"));

                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Generating new certificate (MS).");
                        }
                        // We can use the MakeCert feature from Mono to generate a new
                        // certificate for use by this user on this machine. This means
                        // that every KeePassRPC user will establish TLS connections
                        // that are protected by a private key held on their own
                        // system, rather than a key that is disclosed in this open
                        // source code. NB: The local server is assumed to be secure!
                        PKCS12 p12  = MakeCertKPRPC.Generate("KeePassRPC certificate for " + Environment.MachineName, "KeePassRPC Automated Self-Signed Key Generator", keePassRPCPlugin);
                        byte[] cert = p12.GetBytes();
                        _serverCertificate = new X509Certificate2(cert, (string)null, X509KeyStorageFlags.PersistKeySet);
                        _store.Add(_serverCertificate);
                    }
                }
                else
                {
                    /*
                     * Problem 1:
                     *   For Linux/Mono, we cannot use the X509Store. It appears that only a .cer file is saved. That certificate does not include
                     *   the private key that we need for SSL. So we will need to save the key ourselves.
                     *
                     * Problem 2:
                     *   When using PKCS12 SaveToFile to save the key ourselves, it appears that it is not possible to save a private key that is not
                     *   password protected.
                     *
                     */
                    string certdir  = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC");
                    string certfile = Path.Combine(certdir, "cert.p12");
                    _serverCertificate = null;

                    // Check if cert directory exists, if not, we need to create it
                    if (!System.IO.Directory.Exists(certdir))
                    {
                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Cert directory does not exist, creating " + certdir);
                        }

                        System.IO.Directory.CreateDirectory(certdir);

                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Cert directory created");
                        }
                    }
                    else
                    {
                        // Attempt to load cert
                        try {
                            if (keePassRPCPlugin.logger != null)
                            {
                                keePassRPCPlugin.logger.WriteLine("Looking for existing certificate (Mono)");
                            }
                            _serverCertificate = new X509Certificate2();
                            _serverCertificate.Import(certfile, pkcs12_password, X509KeyStorageFlags.PersistKeySet);
                            if (keePassRPCPlugin.logger != null)
                            {
                                keePassRPCPlugin.logger.WriteLine("Existing certificate loaded(Mono) : " + certfile);
                            }
                        }
                        catch (Exception ex) {
                            _serverCertificate = null;
                        }
                    }
                    // If we didn't load a cert, create one and save it
                    if (_serverCertificate == null)
                    {
                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Generating new certificate (Mono).");
                        }

                        PKCS12 p12 = MakeCertKPRPC.Generate("KeePassRPC certificate for " + Environment.MachineName, "KeePassRPC Automated Self-Signed Key Generator", pkcs12_password, keePassRPCPlugin);
                        p12.SaveToFile(certfile);
                        byte[] cert = p12.GetBytes();
                        _serverCertificate = new X509Certificate2(cert, pkcs12_password, X509KeyStorageFlags.PersistKeySet);
                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Generated new certificate (Mono) : " + certfile);
                        }
                    }
                }
            }

            if (keePassRPCPlugin.logger != null)
            {
                keePassRPCPlugin.logger.WriteLine("Server certificate has private key? " + _serverCertificate.HasPrivateKey);
            }

            try
            {
                this._tcpListener  = new TcpListener(IPAddress.Loopback, port);
                this._listenThread = new Thread(new ThreadStart(ListenForClients));
                this._listenThread.Start();
                this._isListening = true; // just in case the main thread checks
                // for successful startup before the thread has got going.
            }
            catch (Exception e)
            {
                if (keePassRPCPlugin.logger != null)
                {
                    keePassRPCPlugin.logger.WriteLine("Failed to start TCP listener: " + e.ToString());
                }
            }
            if (keePassRPCPlugin.logger != null)
            {
                keePassRPCPlugin.logger.WriteLine("Started KPRPCServer");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Establishes the SSL certificate we will use for communication with
        /// RPC clients and starts a seperate thread to listen for connections
        /// </summary>
        /// <param name="port">port to listen on</param>
        /// <param name="service">The KeePassRPCService the server should interact with.</param>
        public KeePassRPCServer(int port, KeePassRPCService service, KeePassRPCExt keePassRPCPlugin, bool useSSL)
        {
            _useSSL = useSSL;
            if (keePassRPCPlugin.logger != null)
            {
                keePassRPCPlugin.logger.WriteLine("Starting KPRPCServer");
            }
            Service          = service;
            KeePassRPCPlugin = keePassRPCPlugin;

            if (_useSSL)
            {
                if (Type.GetType("Mono.Runtime") == null)
                {
                    _store = new X509Store();
                    _store.Open(OpenFlags.ReadWrite);

                    // Find any certificates in this user's certificate store and re-use
                    // them rather than suffer the overhead of creating an entirly new
                    // certificate. Our certificates are considered "invalid" by the
                    // store (probably becuase they are self-signed)
                    X509Certificate2Collection matchingCertificates = _store.Certificates
                                                                      .Find(X509FindType.FindBySubjectDistinguishedName,
                                                                            "CN=KeePassRPC certificate for " + Environment.MachineName, false);

                    //foreach (X509Certificate2 temp in matchingCertificates)
                    //    _store.Remove(temp);

                    //matchingCertificates = _store.Certificates
                    //    .Find(X509FindType.FindBySubjectDistinguishedName,
                    //        "CN=KeePassRPC TLS aaa for " + Environment.MachineName, false);

                    if (keePassRPCPlugin.logger != null)
                    {
                        keePassRPCPlugin.logger.WriteLine("Matching certificates from store: " + matchingCertificates.Count);
                    }
                    if (matchingCertificates.Count > 0)
                    {
                        _serverCertificate = matchingCertificates[0];
                    }
                    else
                    {
                        //_serverCertificate = (X509Certificate2)X509Certificate2.CreateFromCertFile(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC"), "cert.p12"));

                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Generating new certificate (MS).");
                        }
                        // We can use the MakeCert feature from Mono to generate a new
                        // certificate for use by this user on this machine. This means
                        // that every KeePassRPC user will establish TLS connections
                        // that are protected by a private key held on their own
                        // system, rather than a key that is disclosed in this open
                        // source code. NB: The local server is assumed to be secure!
                        byte[] cert = MakeCertKPRPC.Generate("KeePassRPC certificate for " + Environment.MachineName, "KeePassRPC Automated Self-Signed Key Generator", keePassRPCPlugin);
                        _serverCertificate = new X509Certificate2(cert, (string)null, X509KeyStorageFlags.PersistKeySet);
                        _store.Add(_serverCertificate);
                    }
                }
                else
                {
                    if (keePassRPCPlugin.logger != null)
                    {
                        keePassRPCPlugin.logger.WriteLine("Looking for existing certificate (Mono)");
                    }

                    _serverCertificate = (X509Certificate2)X509Certificate2.CreateFromCertFile(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC"), "cert.p12"));

                    if (_serverCertificate == null)
                    {
                        if (keePassRPCPlugin.logger != null)
                        {
                            keePassRPCPlugin.logger.WriteLine("Generating new certificate (Mono).");
                        }

                        MakeCertKPRPC.Generate("KeePassRPC certificate for " + Environment.MachineName, "KeePassRPC Automated Self-Signed Key Generator", keePassRPCPlugin);
                        _serverCertificate = (X509Certificate2)X509Certificate2.CreateFromCertFile(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "KeePassRPC"), "cert.p12"));
                    }
                }
            }
            if (keePassRPCPlugin.logger != null)
            {
                keePassRPCPlugin.logger.WriteLine("Server certificate has private key? " + _serverCertificate.HasPrivateKey);
            }

            try
            {
                this._tcpListener  = new TcpListener(IPAddress.Loopback, port);
                this._listenThread = new Thread(new ThreadStart(ListenForClients));
                this._listenThread.Start();
                this._isListening = true; // just in case the main thread checks
                // for successful startup before the thread has got going.
            }
            catch (Exception e)
            {
                if (keePassRPCPlugin.logger != null)
                {
                    keePassRPCPlugin.logger.WriteLine("Failed to start TCP listener: " + e.ToString());
                }
            }
            if (keePassRPCPlugin.logger != null)
            {
                keePassRPCPlugin.logger.WriteLine("Started KPRPCServer");
            }
        }