Example #1
0
        public bool LoginToServer(ServerAccount newServerAccount, string recoveryPasswordPlaintext)
        {
            // Duplicate check
            var existingServers = Model.ServerAccounts.Find(new ServerAccount
            {
                ServerHost = newServerAccount.ServerHost,
                ServerPort = newServerAccount.ServerPort,
                EmailAddress = newServerAccount.EmailAddress
            });
            if (existingServers.Any())
            {
                MessageBox.Show(@"You are already logged in to this server. ");
                return false;
            }

            var newKeyPair = AsymmetricCryptoUtil.GenerateKeyPair();
            var recoveryPasswordHash = HashUtil.GenerateServerRecoveryPasswordHash(
                newServerAccount.EmailAddress, recoveryPasswordPlaintext);

            var apiClientUnauthenticated = new ServerAPI.ApiClient(newServerAccount.HttpsEnabled,
                newServerAccount.ServerHost, newServerAccount.ServerPort, newServerAccount.ServerApiVersion);

            var loginRequest = new ServerAPI.Requests.Unauthenticated.LoginWithDatabaseRecoveryKey
            {
                EmailAddress = newServerAccount.EmailAddress,
                RecoveryPasswordClientHash = recoveryPasswordHash,
                DeviceLabel = "My Desktop App",
                DeviceType = "desktop",
                DeviceSubtype = "windows",
                PublicKeyPem = newKeyPair.PublicPem
            };

            ServerAPI.Requests.Unauthenticated.LoginWithDatabaseRecoveryKey.ResponseParams loginResponse;
            try
            {
                loginResponse = loginRequest.GetResponse(apiClientUnauthenticated);
            }
            catch (UnauthorizedException)
            {
                MessageBox.Show(@"Incorrect email address or recovery passphrase.");
                return false;
            }
            catch (RequestException)
            {
                MessageBox.Show(@"There was an error attempting to log in to the server.");
                return false;
            }
            
            var apiClient = new ServerAPI.ApiClient(
                newServerAccount.HttpsEnabled,
                newServerAccount.ServerHost,
                newServerAccount.ServerPort,
                newServerAccount.ServerApiVersion,
                loginResponse.ApiKey,
                newKeyPair.PrivatePem);
            
            var serverInfo = apiClient.GetServerInfo(new ServerAPI.GetServerInfoRequest());

            newServerAccount.ServerIdentifier = serverInfo.ServerIdentifier;
            newServerAccount.ServerLabel = serverInfo.ServerLabel;
            newServerAccount.UserIdentifier = loginResponse.UserIdentifier;
            newServerAccount.DeviceIdentifier = loginResponse.DeviceIdentifier;
            newServerAccount.ApiKey = loginResponse.ApiKey;
            newServerAccount.BackupEncryptionPassword = 
                HashUtil.GenerateDatabaseBackupPasswordHash(newServerAccount.EmailAddress, recoveryPasswordPlaintext);

            var newCryptoKeyId = Model.CryptoKeys.Create(new CryptoKey
            {
                OwnKey = true,
                Trust = true,
                PrivateKeyPem = newKeyPair.PrivatePem,
                PublicKeyPem = newKeyPair.PublicPem
            });
            newServerAccount.CryptoKeyId = newCryptoKeyId;

            ServerAPI.GetUserResponse userInfo;
            try
            {
                userInfo = apiClient.GetUser(new ServerAPI.GetUserRequest());

                if (userInfo.SecondDeviceSetupCompleted)
                {
                    // Retrieve the linked device public key
                    var linkedDeviceResponse = new GetLinkedDevice().GetResponse(apiClient);
                    var linkedDeviceCryptoKeyId = Model.CryptoKeys.Create(new CryptoKey
                    {
                        PublicKeyPem = linkedDeviceResponse.PublicKeyPem,
                        PublicKeyPemHash = HashUtil.Sha256(linkedDeviceResponse.PublicKeyPem)
                    });
                    newServerAccount.LinkedDeviceCryptoKeyId = linkedDeviceCryptoKeyId;
                }
            }
            catch (RequestException)
            {
                MessageBox.Show(@"There was an error attempting to retrieve linked device details.");
                return false;
            }
            
            var newServerAccountId = Model.ServerAccounts.Create(newServerAccount);
            
            if (!userInfo.SecondDeviceSetupCompleted)
            {
                Model.ServerAccounts.Update(newServerAccountId, new ServerAccount {LinkedDeviceSetup = true});
                
                if (userInfo.Links.Count == 0)
                    NewDatabase("My Database", newServerAccountId);
            }
            
            if (!_syncServers.ContainsKey(newServerAccountId))
            {
                _syncServers.Add(newServerAccountId, new Sync(this, newServerAccountId));
                _syncServers[newServerAccountId].Start();
            }

            UpdateHomePage();

            return true;
        }
Example #2
0
        private void RegisterServerComplete(string registrationIdentifier, string clientToken, 
            string recoveryPasswordPlaintext)
        {
            var managementAccount = GetServerManagementAccount();
            var managementApiClient = GetApiClientForServerManagement();

            var serversRequest = new GetUser();
            GetUser.ResponseParams serversResponse;
            try
            {
                serversResponse = serversRequest.GetResponse(managementApiClient);
            }
            catch (RequestException)
            {
                if (Program.AppEnvDebug) throw;

                MessageBox.Show(@"There was an error downloading the required information to setup your account.");
                return;
            }

            if (serversResponse.Servers.Count != 1)
            {
                if (Program.AppEnvDebug) throw new Exception ("Unsupported number of servers for user");

                MessageBox.Show(@"There was an error downloading the required information to setup your account.");
                return;
            }

            var server = serversResponse.Servers[0];
            var serverApiClient = new ServerAPI.ApiClient(
                server.HttpsEnabled, server.Hostname, server.Port, server.ApiVersion);
            var newKeypair = AsymmetricCryptoUtil.GenerateKeyPair();
            var registerRequest = new ServerAPI.Requests.Unauthenticated.RegisterComplete
            {
                RegisterRequestIdentifier = registrationIdentifier,
                ClientToken = clientToken,
                DeviceLabel = "My Desktop App",
                DeviceType = "desktop",
                DeviceSubtype = "windows",
                PublicKeyPem = newKeypair.PublicPem,
                RecoveryPasswordClientHash = HashUtil.GenerateServerRecoveryPasswordHash(
                    managementAccount.EmailAddress, recoveryPasswordPlaintext)
            };

            ServerAPI.Requests.Unauthenticated.RegisterComplete.ResponseParams registerResponse;
            try
            {
                registerResponse = registerRequest.GetResponse(serverApiClient);
            }
            catch (RequestException e)
            {
                if (Program.AppEnvDebug)
                    throw new Exception("Unexpected network error", e);

                MessageBox.Show(@"There was an error downloading the required information to setup your account.");
                return;
            }

            var cryptoKeyId = Model.CryptoKeys.Create(new CryptoKey
            {
                OwnKey = true,
                Trust = true,
                PrivateKeyPem = newKeypair.PrivatePem,
                PublicKeyPem = newKeypair.PublicPem
            });
            var newServer = new ServerAccount
            {
                Managed = true,
                HttpsEnabled = server.HttpsEnabled,
                ServerIdentifier = server.Identifier,
                ServerLabel = server.Label ?? "",
                ServerHost = server.Hostname,
                ServerPort = server.Port,
                ServerApiVersion = server.ApiVersion,
                UserIdentifier = registerResponse.UserIdentifier,
                DeviceIdentifier = registerResponse.DeviceIdentifier,
                EmailAddress = managementAccount.EmailAddress,
                ApiKey = registerResponse.ApiKey,
                CryptoKeyId = cryptoKeyId,
                BackupEncryptionPassword =
                    HashUtil.GenerateDatabaseBackupPasswordHash(managementAccount.EmailAddress, recoveryPasswordPlaintext)
            };
            var newServerAccountId = Model.ServerAccounts.Create(newServer);
            newServer.Id = newServerAccountId;

            //var serverApiClientAuthenticated = new ServerAPI.ApiClient(server.HttpsEnabled,
            //    server.Hostname, server.Port, server.ApiVersion, registerResponse.ApiKey, newKeypair.PrivatePem);

            /*var deviceRegisterRequest = new InitiateDeviceLogin();
            InitiateDeviceLogin.ResponseParams deviceRegisterResponse;
            try
            {
                deviceRegisterResponse = deviceRegisterRequest.GetResponse(serverApiClientAuthenticated);
            }
            catch (RequestException)
            {
                if (Program.AppEnvDebug) throw;

                MessageBox.Show(@"There was an unknown error registering mobile device with the server");
                return;
            }
            
            var linkCode = new LinkCodeRegisterInitialOtpDevice(newServer.HttpsEnabled,
                newServer.ServerHost, newServer.ServerPort, newServer.ServerApiVersion,
                deviceRegisterResponse.LoginRequestIdentifier, newServer.EmailAddress, HashUtil.Sha256(newKeypair.PublicPem));

            using (var form = new SetupOtpDeviceLink(this, linkCode.ToString(), newServer,
                deviceRegisterResponse.LoginRequestIdentifier))
            {
                form.ShowDialog();
                if (!form.Success)
                {
                    MessageBox.Show(@"Link to second device was not established.");
                    return;
                }
            }*/
            
            // We need to verify the new keys with the second device.
            /*var publicKeyHash = HashUtil.Sha256(newKeypair.PublicPem);
            RequestKeyVerification.ResponseParams verificationResponse;
            try
            {
                verificationResponse = new RequestKeyVerification().GetResponse(serverApiClientAuthenticated);
            }
            catch (RequestException)
            {
                if (Program.AppEnvDebug) throw;

                MessageBox.Show(@"There was an error verifying keys with your mobile device.");
                return;
            }

            using (var form = new VerifyKeyOnSecondDevice(
                this, newServerAccountId, publicKeyHash, verificationResponse.MessageIdentifier))
            {
                form.ShowDialog();
                if (!form.Success)
                {
                    MessageBox.Show(
                        @"Could not verify encryption keys with device.\r\n\r\n" +
                        @"You will encounter a lack of functionality until this has been completed.");
                }
            }*/

//            // TODO: Verify the linked device key properly.
//            GetLinkedDevice.ResponseParams linkedDeviceResponse;
//            try
//            {
//                linkedDeviceResponse = new GetLinkedDevice().GetResponse(serverApiClientAuthenticated);
//            }
//            catch (RequestException)
//            {
//                if (Program.AppEnvDebug) throw new Exception("Error getting linked device info");
//
//                MessageBox.Show(@"There was an error verifying mobile device key.");
//                return;
//            }
//             
//            var linkedDeviceCryptoKeyId = Model.CryptoKeys.Create(new CryptoKey
//            {
//                Trust = true,
//                PublicKeyPem = linkedDeviceResponse.PublicKeyPem
//            });
//            Model.ServerAccounts.Update(newServerAccountId, new ServerAccount
//            {
//                LinkedDeviceCryptoKeyId = linkedDeviceCryptoKeyId
//            });


//            ServerAPI.GetUserResponse userInfoResponse;
//            try
//            {
//                userInfoResponse = serverApiClientAuthenticated.GetUser(new ServerAPI.GetUserRequest());
//            }
//            catch (RequestException e)
//            {
//                if (Program.AppEnvDebug)
//                    throw new Exception("Unexpected error getting user info", e);
//
//                MessageBox.Show(@"There was an error retrieving server information.");
//                return;
//            }

            // We can't do this yet. The server sends this to the second device as it is right now,
            // which hasn't been set.
            //if (userInfoResponse.Links.Count == 0)
            //    NewDatabase("My Database", newServerAccountId);

            if (!_syncServers.ContainsKey(newServerAccountId))
            {
                _syncServers.Add(newServerAccountId, new Sync(this, newServerAccountId));
                _syncServers[newServerAccountId].Start();
            }

            UpdateHomePage();
        }