Correct two bugs related to key file opening

Bettter error messages with composite key
Show an error message if save has failed and don't close the database
This commit is contained in:
BONNEVILLE Geoffroy
2017-11-13 11:28:14 +01:00
parent 2779e5b7c7
commit abb12accc7
6 changed files with 65 additions and 27 deletions

View File

@@ -14,6 +14,9 @@ namespace ModernKeePass.Common
{ {
public enum DatabaseStatus public enum DatabaseStatus
{ {
Error = -3,
NoCompositeKey = -2,
CompositeKeyError = -1,
Closed = 0, Closed = 0,
Opening = 1, Opening = 1,
Opened = 2 Opened = 2
@@ -77,11 +80,11 @@ namespace ModernKeePass.Common
/// <param name="key">The database composite key</param> /// <param name="key">The database composite key</param>
/// <param name="createNew">True to create a new database before opening it</param> /// <param name="createNew">True to create a new database before opening it</param>
/// <returns>An error message, if any</returns> /// <returns>An error message, if any</returns>
public string Open(CompositeKey key, bool createNew = false) public void Open(CompositeKey key, bool createNew = false)
{ {
try try
{ {
if (key == null) return "No composite key"; if (key == null) Status = DatabaseStatus.NoCompositeKey;
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile); var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
if (createNew) _pwDatabase.New(ioConnection, key); if (createNew) _pwDatabase.New(ioConnection, key);
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger()); else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
@@ -92,19 +95,14 @@ namespace ModernKeePass.Common
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null); RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
} }
} }
catch (ArgumentNullException)
{
return "Password cannot be empty";
}
catch (InvalidCompositeKeyException) catch (InvalidCompositeKeyException)
{ {
return "Wrong password"; Status = DatabaseStatus.CompositeKeyError;
} }
catch (Exception ex) catch (Exception ex)
{ {
return ex.Message; Status = DatabaseStatus.Error;
} }
return string.Empty;
} }
/// <summary> /// <summary>
@@ -121,11 +119,19 @@ namespace ModernKeePass.Common
/// <summary> /// <summary>
/// Commit the changes to the currently opened database to file /// Commit the changes to the currently opened database to file
/// </summary> /// </summary>
public void Save() public bool Save()
{ {
// TODO: Save is disabled for now for Argon2Kdf because it corrupts DB (read works) if (_pwDatabase == null || !_pwDatabase.IsOpen) return false;
if (_pwDatabase == null || !_pwDatabase.IsOpen /*|| KdfPool.Get(KeyDerivation.KdfUuid) is Argon2Kdf*/) return; try
_pwDatabase.Save(new NullStatusLogger()); {
_pwDatabase.Save(new NullStatusLogger());
return true;
}
catch (Exception ex)
{
MessageDialogHelper.ShowErrorDialog(ex);
}
return false;
} }
/// <summary> /// <summary>

View File

@@ -23,5 +23,17 @@ namespace ModernKeePass.Common
// Show the message dialog // Show the message dialog
await messageDialog.ShowAsync(); await messageDialog.ShowAsync();
} }
public static async void ShowErrorDialog(Exception exception)
{
// Create the message dialog and set its content
var messageDialog = new MessageDialog(exception.Message, "Error occured");
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("OK"));
// Show the message dialog
await messageDialog.ShowAsync();
}
} }
} }

View File

@@ -47,7 +47,7 @@
Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushConverter}}" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushConverter}}"
Visibility="{Binding ShowComplexityIndicator, ElementName=UserControl, Converter={StaticResource BooleanToVisibilityConverter}}" /> Visibility="{Binding ShowComplexityIndicator, ElementName=UserControl, Converter={StaticResource BooleanToVisibilityConverter}}" />
<CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding HasKeyFile, Mode=TwoWay}" /> <CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding HasKeyFile, Mode=TwoWay}" />
<HyperlinkButton Grid.Row="1" Grid.Column="1" Margin="-15,0,0,0" Content="Select key file from disk..." IsEnabled="{Binding HasKeyFile}" Click="KeyFileButton_Click" /> <HyperlinkButton Grid.Row="1" Grid.Column="1" Margin="-15,0,0,0" Content="{Binding KeyFileText}" IsEnabled="{Binding HasKeyFile}" Click="KeyFileButton_Click" />
<Button Grid.Column="0" Grid.Row="2" Content="OK" Click="OpenButton_OnClick" Background="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" IsEnabled="{Binding IsValid}" /> <Button Grid.Column="0" Grid.Row="2" Content="OK" Click="OpenButton_OnClick" Background="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" IsEnabled="{Binding IsValid}" />
<TextBlock Grid.Column="1" Grid.Row="2" Height="28" FontSize="14" FontWeight="Light" HorizontalAlignment="Right" Text="{Binding Status}" Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" /> <TextBlock Grid.Column="1" Grid.Row="2" Height="28" FontSize="14" FontWeight="Light" HorizontalAlignment="Right" Text="{Binding Status}" Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" />
</Grid> </Grid>

View File

@@ -3,7 +3,6 @@ using Windows.Storage.Pickers;
using Windows.System; using Windows.System;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Input;
using ModernKeePass.Common;
using ModernKeePass.Events; using ModernKeePass.Events;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
@@ -56,7 +55,7 @@ namespace ModernKeePass.Controls
ValidationChecking?.Invoke(this, new EventArgs()); ValidationChecking?.Invoke(this, new EventArgs());
if (UpdateKey) Model.UpdateKey(); if (UpdateKey) Model.UpdateKey();
else if (Model.OpenDatabase(CreateNew) == DatabaseHelper.DatabaseStatus.Opened) else if (Model.OpenDatabase(CreateNew))
{ {
ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup)); ValidationChecked?.Invoke(this, new PasswordEventArgs(Model.RootGroup));
} }
@@ -78,7 +77,9 @@ namespace ModernKeePass.Controls
picker.FileTypeFilter.Add(".key"); picker.FileTypeFilter.Add(".key");
// Application now has read/write access to the picked file // Application now has read/write access to the picked file
Model.KeyFile = await picker.PickSingleFileAsync(); var file = await picker.PickSingleFileAsync();
if (file == null) return;
Model.KeyFile = file;
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using Windows.Storage; using System.Text;
using Windows.Storage;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
@@ -24,6 +25,7 @@ namespace ModernKeePass.ViewModels
private string _status; private string _status;
private StatusTypes _statusType; private StatusTypes _statusType;
private StorageFile _keyFile; private StorageFile _keyFile;
private string _keyFileText = "Select key file from disk...";
public bool HasPassword public bool HasPassword
{ {
@@ -45,7 +47,7 @@ namespace ModernKeePass.ViewModels
} }
} }
public bool IsValid => HasPassword || HasKeyFile; public bool IsValid => HasPassword || HasKeyFile && KeyFile != null;
public string Status public string Status
{ {
@@ -76,18 +78,37 @@ namespace ModernKeePass.ViewModels
set set
{ {
_keyFile = value; _keyFile = value;
UpdateStatus($"Key file: {value.Name}", StatusTypes.Normal); KeyFileText = value?.Name;
OnPropertyChanged("IsValid");
} }
} }
public string KeyFileText
{
get { return _keyFileText; }
set { SetProperty(ref _keyFileText, value); }
}
public GroupVm RootGroup { get; set; } public GroupVm RootGroup { get; set; }
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray()); public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray());
public DatabaseHelper.DatabaseStatus OpenDatabase(bool createNew) public bool OpenDatabase(bool createNew)
{ {
UpdateStatus(_app.Database.Open(CreateCompositeKey(), createNew), StatusTypes.Error); _app.Database.Open(CreateCompositeKey(), createNew);
RootGroup = _app.Database.RootGroup; switch (_app.Database.Status)
return _app.Database.Status; {
case DatabaseHelper.DatabaseStatus.Opened:
RootGroup = _app.Database.RootGroup;
return true;
case DatabaseHelper.DatabaseStatus.CompositeKeyError:
var errorMessage = new StringBuilder("Error: wrong ");
if (HasPassword) errorMessage.Append("password");
if (HasPassword && HasKeyFile) errorMessage.Append(" or ");
if (HasKeyFile) errorMessage.Append("key file");
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
break;
}
return false;
} }
public void UpdateKey() public void UpdateKey()

View File

@@ -8,9 +8,7 @@ namespace ModernKeePass.ViewModels
public void Save(bool close = true) public void Save(bool close = true)
{ {
var app = (App)Application.Current; var app = (App)Application.Current;
app.Database.Save(); if (close && app.Database.Save()) app.Database.Close();
if (!close) return;
app.Database.Close();
} }
internal void Save(StorageFile file) internal void Save(StorageFile file)