private void SyncLocal(PwDatabase pwDatabase, SafeVaultWebClient webClient, string databaseUuid, SafeVaultConf vaultConf) { SetStatusText("Check changes..."); var value = GetRemoteLastModified(webClient, databaseUuid); if (value == null) { SetStatusText("Database not found on SafeVault. Nothing to sync"); return; } var lastModified = value.Value; if (vaultConf.SyncRemoteLastModified == lastModified.ToString("u")) { SetStatusText("No changes"); return; } SetStatusText("Downloading..."); var dbData = Async.Invoke(() => DownloadFile(webClient, databaseUuid, vaultConf)); SetStatusText("Sync..."); SyncDatabase(pwDatabase, dbData, false); SetStatusText("Successfull Sync Local <= Remote"); vaultConf.SyncRemoteLastModified = lastModified.ToString("u"); vaultConf.Save(); pwDatabase.Save(new NullStatusLogger()); }
private static DateTime?GetRemoteLastModified(SafeVaultWebClient webClient, string databaseUuid) { try { return(Async.Invoke(() => webClient.DbxGetLastModified(databaseUuid))); } catch (HttpChannelException httpEx) { if (httpEx.StatusCode != (int)HttpStatusCode.NotFound) { throw; } return(null); } }
private byte[] DownloadFile(SafeVaultWebClient webClient, string databaseUuid, SafeVaultConf vaultConf) { byte[] databaseData; try { databaseData = webClient.DbxDownload(databaseUuid, progress => { SetStatusText(string.Format("Download {0}%", progress)); }); } catch (HttpChannelException httpEx) { if (httpEx.StatusCode == (int)HttpStatusCode.NotFound) { throw new SynchronizeException("Database not found on SafeVault. Please sync with SafeVault first."); } throw; } return(databaseData); }
private void SyncUpload(PwDatabase pwDatabase, SafeVaultWebClient webClient, string databaseUuid, SafeVaultConf vaultConf) { var lastModified = GetLastModified(pwDatabase); var location = _host.Database.IOConnectionInfo.Path; SetStatusText("Saving to SafeVault..."); Async.Invoke(() => { webClient.DbxUpload( databaseUuid, File.ReadAllBytes(location), lastModified); }); SetStatusText("Successfull Upload to SafeVault"); vaultConf.SyncRemoteLastModified = lastModified.ToString("u"); vaultConf.Save(); }
private void SyncRemote(PwDatabase pwDatabase, SafeVaultWebClient webClient, string databaseUuid, SafeVaultConf vaultConf) { SetStatusText("Check changes..."); var localLastModified = GetLastModified(pwDatabase); var lastModified = GetRemoteLastModified(webClient, databaseUuid); if (lastModified != null && lastModified == localLastModified) { SetStatusText("No changes."); return; } if (lastModified != null && lastModified.Value.ToString("u") != vaultConf.SyncRemoteLastModified) { SetStatusText("Downloading..."); var dbData = Async.Invoke(() => DownloadFile(webClient, databaseUuid, vaultConf)); if (dbData != null) { SetStatusText("Sync..."); SyncDatabase(pwDatabase, dbData, true); _host.MainWindow.Enabled = false; localLastModified = GetLastModified(pwDatabase); } } SetStatusText("Saving to SafeVault..."); Async.Invoke(() => { webClient.DbxUpload( databaseUuid, File.ReadAllBytes(pwDatabase.IOConnectionInfo.Path), localLastModified); }); SetStatusText("Successfull Sync Local <=> Remote"); vaultConf.SyncRemoteLastModified = localLastModified.ToString("u"); vaultConf.Save(); pwDatabase.Save(new NullStatusLogger()); }
private void SyncDownload(PwDatabase pwDatabase, SafeVaultWebClient webClient, string databaseUuid, SafeVaultConf vaultConf) { var lastModified = GetRemoteLastModified(webClient, databaseUuid); if (lastModified != null) { SetStatusText("Downloading..."); var dbData = Async.Invoke(() => DownloadFile(webClient, databaseUuid, vaultConf)); ReplaceDatabase(pwDatabase, dbData); SetStatusText("Download Done."); vaultConf.ChangeDatabase(_host.Database); vaultConf.SyncRemoteLastModified = lastModified.Value.ToString("u"); vaultConf.Save(); pwDatabase.Save(new NullStatusLogger()); } else { SetStatusText("Database not found. Nothing to sync"); } }
private void SyncWithSafeVault(SyncCommand syncCommand) { PwDatabase pwDatabase = _host.Database; if (!pwDatabase.IsOpen) { ShowMessageBox("You first need to open a database."); return; } if (!pwDatabase.IOConnectionInfo.IsLocalFile()) { ShowMessageBox("Only databases stored locally or on a network share are supported.\n" + "Save your database locally or on a network share and try again."); return; } if (pwDatabase.Modified) { ShowMessageBox("Database has not saved changes. Save it first."); return; } SafeVaultConf vaultConf = new SafeVaultConf(pwDatabase); if (!IsSyncConfigured(vaultConf)) { SetStatusText("Sync not Configured."); return; } _host.MainWindow.FileSaved -= OnFileSaved; // disable to not trigger when saving ourselves _host.MainWindow.FileOpened -= OnFileOpened; // disable to not trigger when opening ourselves _host.MainWindow.Enabled = false; _lastStatus = ""; try { var databaseUuid = Path.GetFileNameWithoutExtension(pwDatabase.IOConnectionInfo.Path); SafeVaultWebClient webClient = new SafeVaultWebClient(vaultConf); if (syncCommand == SyncCommand.Download) { try { SyncDownload(pwDatabase, webClient, databaseUuid, vaultConf); } catch (Exception ex) { ShowMessageBox(ex.Message); SetStatusText("SyncDownload Failed"); } } if (syncCommand == SyncCommand.Upload) { try { SyncUpload(pwDatabase, webClient, databaseUuid, vaultConf); } catch (Exception ex) { ShowMessageBox(ex.Message); SetStatusText("SyncUpload Failed"); } } if (syncCommand == SyncCommand.SyncLocal) { try { SyncLocal(pwDatabase, webClient, databaseUuid, vaultConf); } catch (Exception ex) { ShowMessageBox(ex.Message); SetStatusText("SyncLocal Failed"); } } if (syncCommand == SyncCommand.SyncRemote) { try { SyncRemote(pwDatabase, webClient, databaseUuid, vaultConf); } catch (Exception ex) { ShowMessageBox(ex.Message); SetStatusText("SyncRemote Failed"); } } } catch (Exception ex) { ShowMessageBox(ex.Message); SetStatusText("Unknown Err: " + ex.Message); } _host.MainWindow.UpdateUI(false, null, true, null, true, null, false); _host.MainWindow.Enabled = true; _host.MainWindow.FileSaved += OnFileSaved; _host.MainWindow.FileOpened += OnFileOpened; if (_lastStatus != "") { SetStatusText(_lastStatus); } }
private byte[] Create(KeyProviderQueryContext ctx) { var vaultConf = new SafeVaultConf(ctx.DatabaseIOInfo); var vaultConnectionForm = new VaultConnectionConfigForm(); vaultConnectionForm.InitEx(vaultConf); if (UIUtil.ShowDialogAndDestroy(vaultConnectionForm) != DialogResult.OK) { return(null); } VaultKeyCreateForm createForm = new VaultKeyCreateForm(); createForm.InitEx(vaultConf, ctx); if (UIUtil.ShowDialogAndDestroy(createForm) != DialogResult.OK) { return(null); } vaultConf.Type = PROVIDER_TYPE; vaultConf.Version = PROVIDER_VERSION; var masterKey = Encoding.UTF8.GetBytes(vaultConf.DatabaseKeyA); var keyLen = (masterKey.Length > 254) ? masterKey.Length : 254; var keyA = new byte[keyLen + 2]; Array.Copy(BitConverter.GetBytes((ushort)masterKey.Length), keyA, 2); Array.Copy(masterKey, 0, keyA, 2, masterKey.Length); var keyB = Random.Get(keyA.Length); for (int i = 0; i < keyB.Length; i++) { keyA[i] ^= keyB[i]; } var salt = Random.Get(64); using (var aes = new Aes256Cipher()) { aes.SetPassPhrase(salt); keyA = aes.Encrypt(keyA); keyB = aes.Encrypt(keyB); } using (var rsa = RsaCipher.LoadFromX509Store(vaultConf.ClientCertificateName)) { salt = rsa.Encrypt(salt); } vaultConf.Salt = Convert.ToBase64String(salt); vaultConf.DatabaseKeyA = Convert.ToBase64String(keyA); vaultConf.VaultKeyname = Guid.NewGuid().ToString(); var databaseKeyB = Convert.ToBase64String(keyB); VaultKeyPromptForm promptForm = new VaultKeyPromptForm(); promptForm.InitEx("Enter SafeVault Password", "Save KeyB to SafeVault", (oneTimePassword) => { string status = ""; var query = new SafeVaultWebClient(vaultConf); try { status = Async.Invoke(() => query.SetDbxKey(vaultConf.VaultKeyname, databaseKeyB, oneTimePassword)); if (status == "OK") { return(true); } MessageService.ShowWarning( query.Utc != null ? "DateTime: " + DateTime.Parse(query.Utc).ToLocalTime() : "", status); } catch (CryptographicException ex) { MessageService.ShowWarning( query.Utc != null ? "DateTime: " + DateTime.Parse(query.Utc).ToLocalTime() : "", ex.Message); } return(false); }); if (UIUtil.ShowDialogAndDestroy(promptForm) != DialogResult.OK) { return(null); } try { vaultConf.Save(); } catch (Exception e) { MessageService.ShowWarning(e.Message); return(null); } return(masterKey); }
private byte[] OpenInternal(KeyProviderQueryContext ctx) { SafeVaultConf conf = new SafeVaultConf(ctx.DatabaseIOInfo); var required = new[] { conf.ClientCertificateName, conf.ServerUrl, conf.ServerCertificateName, conf.Salt, conf.Username, conf.VaultKeyname, conf.DatabaseKeyA }; if (required.Any(string.IsNullOrEmpty)) { throw new ConfigurationException("SafeVault not configured."); } byte[] salt = Convert.FromBase64String(conf.Salt); using (var rsa = RsaCipher.LoadFromX509Store(conf.ClientCertificateName)) { salt = rsa.Decrypt(salt); } string sKeyB = string.Empty; VaultKeyPromptForm promptForm = new VaultKeyPromptForm(); promptForm.InitEx("Enter SafeVault Password", "Open Database", (oneTimePassword) => { var query = new SafeVaultWebClient(conf); try { sKeyB = query.GetDbxKey(conf.VaultKeyname, oneTimePassword); return(true); } catch (SafeVaultException ex) { MessageService.ShowWarning( query.Utc != null ? "DateTime: " + DateTime.Parse(query.Utc).ToLocalTime() : "", ex.Message ); } return(false); }); if (UIUtil.ShowDialogAndDestroy(promptForm) != DialogResult.OK) { return(null); } byte[] keyA = Convert.FromBase64String(conf.DatabaseKeyA); byte[] keyB = Convert.FromBase64String(sKeyB); using (var aes = new Aes256Cipher()) { aes.SetPassPhrase(salt); keyA = aes.Decrypt(keyA); keyB = aes.Decrypt(keyB); } if (keyA.Length != keyB.Length) { throw new SafevaultKeyProviderException("Incompatible KEYA and KEYB"); } for (int i = 0; i < keyB.Length; i++) { keyA[i] ^= keyB[i]; } int keyL = BitConverter.ToUInt16(keyA, 0); if (keyL > keyA.Length) { throw new SafevaultKeyProviderException("Invalid KEYB"); } byte[] masterKey = new byte[keyL]; Array.Copy(keyA, 2, masterKey, 0, masterKey.Length); return(masterKey); }