示例#1
0
        /// <summary>
        /// Loads the given database file using the provided password
        /// </summary>
        /// <param name="databaseFile"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public async Task LoadDatabaseAsync(StorageFile databaseFile, PasswordParameter password)
        {
            _databaseFile = databaseFile;

            IsLoading = true;

            try
            {
                // Open the database (may trigger exceptions)
                await openDatabaseAsync(databaseFile, password);

                DatabaseOpened = true;
                // And only if everything went fine, store the tokens and database names

                // Store the selected file token in the future access list to easily retrieve it later
                string token = StorageApplicationPermissions.FutureAccessList.Add(databaseFile);
                // Add or replace the token value for the last database file
                ApplicationData.Current.LocalSettings.Values[FUTURE_LIST_DATABASE_TOKEN_KEY] = token;
                ApplicationData.Current.LocalSettings.Values[LAST_DATABASE_NAME_KEY]         = databaseFile.Name;
            }
            finally
            {
                IsLoading = false;
            }
        }
        /// <summary>
        /// Save the given credentials in the os password vault
        /// </summary>
        /// <param name="password"></param>
        private static void StoreDatabasePassword(string databaseName, PasswordParameter password)
        {
            var vault = new Windows.Security.Credentials.PasswordVault();

            vault.Add(
                new PasswordCredential(databaseName, PASSWORD_VAULT_USER_NAME, password.Password));
        }
        private async static Task <PasswordParameter> ShowPasswordDialogAsync(string databaseName)
        {
            // Builds a custom dialog with a text field
            PasswordDialog pwdDialog = new PasswordDialog(databaseName);

            // The result is
            PasswordParameter pwd = new PasswordParameter();

            await pwdDialog.ShowAsync();

            if (pwdDialog.Result)
            {
                if (pwdDialog.ViewModel.UsePassword)
                {
                    pwd.Password = pwdDialog.ViewModel.Password;
                }

                if (pwdDialog.ViewModel.UseKeyFile && pwdDialog.ViewModel.KeyFile != null)
                {
                    pwd.KeyFile = pwdDialog.ViewModel.KeyFile;
                }
                // User validated the password
                return(pwd);
            }
            else
            {
                throw new TaskCanceledException();
            }
        }
示例#4
0
        /// <summary>
        /// Asks the user to selecte a database
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void OpenDatabaseButton_Click(object sender, RoutedEventArgs e)
        {
            var picker = new FileOpenPicker();

            picker.FileTypeFilter.Add(".kdbx");

            string databaseName = String.Empty;

            try
            {
                var file = await picker.PickSingleFileAsync();

                if (file != null)
                {
                    databaseName = file.Name;
                    // Ask for password
                    PasswordParameter password = await DatabasePasswordProvider.GetDatabasePasswordAsync(databaseName);

                    // Then load the database
                    await ViewModel.LoadDatabaseAsync(file, password);

                    // Once loaded, navigate to the collection page
                    if (SettingsViewModel.Instance.ViewCollectionAsTree)
                    {
                        this.Frame.Navigate(typeof(EntryCollectionTreeViewPage));
                    }
                    else
                    {
                        this.Frame.Navigate(typeof(EntryCollectionPage));
                    }
                }
            }
            catch (WinKeeLib.Keys.InvalidCompositeKeyException)
            {
                DatabasePasswordProvider.ClearSavedPasswordForDatabase(databaseName);
                MessageDialog err = new MessageDialog(
                    ResourceLoader.GetForCurrentView().GetString("MessageDialog_IncorrectKey"));
                await err.ShowAsync();
            }
            catch (TaskCanceledException)
            {
                // User cancelled password entering
            }
            catch (Exception ex)
            {
                // Error opening the database
                MessageDialog err = new MessageDialog(
                    ResourceLoader.GetForCurrentView().GetString("MessageDialog_ErrorOpeningDatabase") + "\n\"" + ex.Message + "\"");
                await err.ShowAsync();
            }
        }
示例#5
0
        private async Task LoadPreviousDatabaseAsync()
        {
            try
            {
                // Ask for password
                PasswordParameter password = await DatabasePasswordProvider.GetDatabasePasswordAsync(ViewModel.LastDatabaseName);

                // Then load the database
                await ViewModel.LoadPreviouslyOpenedDatabase(password);

                // Once loaded, navigate to the collection page
                if (SettingsViewModel.Instance.ViewCollectionAsTree)
                {
                    this.Frame.Navigate(typeof(EntryCollectionTreeViewPage));
                }
                else
                {
                    this.Frame.Navigate(typeof(EntryCollectionPage));
                }
            }
            catch (WinKeeLib.Keys.InvalidCompositeKeyException)
            {
                // Invalid key, ensure it is not saved
                DatabasePasswordProvider.ClearSavedPasswordForDatabase(ViewModel.LastDatabaseName);
                MessageDialog err = new MessageDialog(
                    ResourceLoader.GetForCurrentView().GetString("MessageDialog_IncorrectKey"));
                await err.ShowAsync();
            }
            catch (TaskCanceledException)
            {
                // User cancelled password entering
            }
            catch (Exception ex)
            {
                // Error opening the database
                MessageDialog err = new MessageDialog(
                    ResourceLoader.GetForCurrentView().GetString("MessageDialog_ErrorOpeningDatabase") + "\n\"" + ex.Message + "\"");
                await err.ShowAsync();
            }
        }
示例#6
0
        /// <summary>
        /// Loads the previously opened database, if possible, using the provided password
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public async Task LoadPreviouslyOpenedDatabase(PasswordParameter password)
        {
            // Read token in settings
            object value   = String.Empty;
            bool   success = ApplicationData.Current.LocalSettings.Values.TryGetValue(FUTURE_LIST_DATABASE_TOKEN_KEY, out value);

            if (success)
            {
                string token = (string)value;

                StorageFile file = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(token);

                if (file != null)
                {
                    await LoadDatabaseAsync(file, password);
                }
            }
            else
            {
                throw new FileNotFoundException("Database file not found");
            }
        }
示例#7
0
        /// <summary>
        /// Opens the given database using the provided password, and the optional keyfile
        /// </summary>
        /// <param name="databaseFile"></param>
        /// <param name="password"></param>
        /// <param name="keyFile"></param>
        /// <returns></returns>
        private async Task openDatabaseAsync(StorageFile databaseFile, PasswordParameter password)
        {
            try
            {
                using (var stream = await databaseFile.OpenReadAsync())
                {
                    // Build up the database
                    var db = new PwDatabase();

                    var key = new CompositeKey();

                    if (!String.IsNullOrEmpty(password.Password))
                    {
                        // Add the password
                        key.AddUserKey(new KcpPassword(password.Password));
                    }

                    if (password.KeyFile != null)
                    {
                        var keyFileStream = await password.KeyFile.OpenReadAsync();

                        if (keyFileStream != null)
                        {
                            key.AddUserKey(new KcpKeyFile(keyFileStream.AsStreamForRead()));
                        }
                    }

                    var cancelToken = new CancellationTokenSource();

                    db.Open(stream.GetInputStreamAt(0).AsStreamForRead(),
                            key,
                            null,
                            cancelToken.Token);

                    // Now iterate all groups entries to create the ViewModel counterpart

                    if (db.RootGroup != null)
                    {
                        if (SettingsViewModel.Instance.ViewCollectionAsTree)
                        {
                            _groups.Add(new PwGroupViewModel(db.RootGroup, true));
                        }
                        else
                        {
                            _groups.Add(new PwGroupViewModel(db.RootGroup));

                            foreach (var group in db.RootGroup.GetGroups(false))
                            {
                                _groups.Add(new PwGroupViewModel(group, true));
                            }
                        }
                    }

                    if (SettingsViewModel.Instance.ViewCollectionAsTree)
                    {
                        // Create the hierarchical group
                        foreach (var groupVM in _groups)
                        {
                            addHierachicalGroup(groupVM, 0);
                        }
                        if (_groups.Count > 0)
                        {
                            CurrentGroup = _groups.FirstOrDefault();
                        }
                    }

                    if (SettingsViewModel.Instance.SortingEnabled)
                    {
                        // Sort groups by name
                        _groups = new ObservableCollection <PwGroupViewModel>(_groups.OrderBy(g => g.Name));
                    }

                    // Initialize the filtered list instances
                    UpdateFilterededEntries(String.Empty);

                    db.Close();
                }
            }
            catch (InvalidCompositeKeyException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// Retrieve the password to use to open the given database
        /// </summary>
        /// <param name="databaseName">name of the database</param>
        /// <returns>credentials to use to open this database</returns>
        public async static Task <PasswordParameter> GetDatabasePasswordAsync(string databaseName)
        {
            PasswordParameter credentials = null;

            // Try to use Windows Hello
            if (SettingsViewModel.Instance.WindowsHelloEnabled &&
                await KeyCredentialManager.IsSupportedAsync()
                )
            {
                // Try to open an already generated Windows Hello credentials
                var passportCredentials = await KeyCredentialManager.OpenAsync(WINDOWS_HELLO_SERVICE_NAME);

                if (passportCredentials.Status == KeyCredentialStatus.Success)
                {
                    var signRes = await passportCredentials.Credential.RequestSignAsync(
                        CryptographicBuffer.ConvertStringToBinary("LoginAuth", BinaryStringEncoding.Utf8));

                    if (signRes.Status == KeyCredentialStatus.Success)
                    {
                        // User confirmed its identity, retrieve the credentials from the system Password Vault
                        try
                        {
                            credentials = await LoadDatabasePasswordAsync(databaseName);
                        }
                        catch (Exception)
                        {
                            // Prompt for credentials, then store them
                            PasswordParameter password = await ShowPasswordDialogAsync(databaseName);

                            StoreDatabasePassword(databaseName, password);
                            credentials = password;
                        }
                    }
                    else if (signRes.Status == KeyCredentialStatus.UserCanceled)
                    {
                        // User cancelled the credential
                        throw new TaskCanceledException();
                    }
                }
                else
                {
                    // No credentials available, need to create it
                    var passportCredentialCreation = await KeyCredentialManager.RequestCreateAsync(WINDOWS_HELLO_SERVICE_NAME, KeyCredentialCreationOption.FailIfExists);

                    if (passportCredentialCreation.Status == KeyCredentialStatus.Success ||
                        passportCredentialCreation.Status == KeyCredentialStatus.CredentialAlreadyExists)
                    {
                        // Prompt for credentials, then store them
                        PasswordParameter password = await ShowPasswordDialogAsync(databaseName);

                        StoreDatabasePassword(databaseName, password);
                        credentials = password;
                    }
                    else if (passportCredentialCreation.Status == KeyCredentialStatus.UserCanceled)
                    {
                        // User cancelled the credential
                        throw new TaskCanceledException();
                    }
                }
            }

            if (credentials == null)
            {
                // No Windows Hello, use standard password
                credentials = await ShowPasswordDialogAsync(databaseName);
            }
            return(credentials);
        }