diff --git a/src/AuthProviders/IAuthProvider.cs b/src/AuthProviders/IAuthProvider.cs index 460b4b3..1ed63bb 100644 --- a/src/AuthProviders/IAuthProvider.cs +++ b/src/AuthProviders/IAuthProvider.cs @@ -13,17 +13,18 @@ public interface IAuthProvider byte[] Encrypt(byte[] data); byte[] PromptToDecrypt(byte[] data); void ClaimCurrentCacheType(AuthCacheType authCacheType); - AuthCacheType CurrentCacheType { get; } + AuthCacheType CurrentCacheType { get; set; } } static class AuthProviderFactory { - public static IAuthProvider GetInstance(IntPtr keePassWindowHandle, AuthCacheType authCacheType) + public static IAuthProvider Create(IntPtr keePassWindowHandle) { + var authCacheType = Settings.Instance.GetAuthCacheType(); #if DEBUG var provider = new XorProvider(authCacheType); #else - var provider = WinHelloProvider.CreateInstance(authCacheType); + var provider = new WinHelloProvider(authCacheType); #endif if (UAC.IsCurrentProcessElevated) return new WinHelloProviderForegroundDecorator(provider, keePassWindowHandle); @@ -31,4 +32,4 @@ public static IAuthProvider GetInstance(IntPtr keePassWindowHandle, AuthCacheTyp return provider; } } -} \ No newline at end of file +} diff --git a/src/AuthProviders/WinHelloProvider.cs b/src/AuthProviders/WinHelloProvider.cs index e2999c3..672735b 100644 --- a/src/AuthProviders/WinHelloProvider.cs +++ b/src/AuthProviders/WinHelloProvider.cs @@ -123,15 +123,15 @@ private static extern SECURITY_STATUS NCryptDecrypt(SafeNCryptKeyHandle hKey, #endregion private static readonly Lazy _currentSID = new Lazy(WindowsIdentity.GetCurrent().User.ToString); - private static readonly object _mutex = new object(); - private static WeakReference _instance; private const string Domain = Settings.ProductName; private const string SubDomain = ""; private const string PersistentName = Settings.ProductName; private const string InvalidatedKeyMessage = "Persistent key has not met integrity requirements. It might be caused by a spoofing attack. Try to recreate the key."; + private AuthCacheType _currentCacheType; + private static string LocalKeyName { get @@ -154,99 +154,45 @@ private static string PersistentKeyName private string CurrentKeyName { - get { return CurrentCacheType == AuthCacheType.Local ? LocalKeyName : PersistentKeyName; } + get { return _currentCacheType == AuthCacheType.Local ? LocalKeyName : PersistentKeyName; } } - private WinHelloProvider(AuthCacheType authCacheType) + public WinHelloProvider(AuthCacheType authCacheType) { - CurrentCacheType = authCacheType; - - if (authCacheType == AuthCacheType.Local) - { - DeletePersistentKey(); - } - else - { - System.Diagnostics.Debug.Assert(authCacheType == AuthCacheType.Persistent); - - SafeNCryptKeyHandle ngcKeyHandle; - if (!TryOpenPersistentKey(out ngcKeyHandle)) - throw new AuthProviderKeyNotFoundException("Persistent key does not exist."); - - using (ngcKeyHandle) - { - if (!VerifyPersistentKeyIntegrity(ngcKeyHandle)) - { - ngcKeyHandle.Close(); - DeletePersistentKey(); - throw new AuthProviderInvalidKeyException(InvalidatedKeyMessage); - } - } - } + _currentCacheType = authCacheType; } - public AuthCacheType CurrentCacheType { get; private set; } - - public static WinHelloProvider CreateInstance(AuthCacheType authCacheType) + public AuthCacheType CurrentCacheType { - EnsureWinHelloAvailability(); - - lock (_mutex) - { - WinHelloProvider winHelloProvider = null; - if (_instance != null && (winHelloProvider = _instance.Target as WinHelloProvider) != null) - { - if (winHelloProvider.CurrentCacheType == authCacheType) - return winHelloProvider; - else - throw new AuthProviderException("Incompatible cache type with existing instance."); - } - - winHelloProvider = new WinHelloProvider(authCacheType); - _instance = new WeakReference(winHelloProvider); - - return winHelloProvider; - } + get { return EnsureKeyAvailability(_currentCacheType); } + set { _currentCacheType = EnsureKeyAvailability(value); } } public void ClaimCurrentCacheType(AuthCacheType authCacheType) { - if (CurrentCacheType == authCacheType) - return; - lock (_mutex) { - if (authCacheType == AuthCacheType.Local) + try { - DeletePersistentKey(); + CurrentCacheType = authCacheType; } - else + catch (AuthProviderKeyNotFoundException) { Debug.Assert(authCacheType == AuthCacheType.Persistent); - - SafeNCryptKeyHandle ngcKeyHandle; - if (TryOpenPersistentKey(out ngcKeyHandle)) - { - try - { - if (!VerifyPersistentKeyIntegrity(ngcKeyHandle)) - throw new AuthProviderInvalidKeyException(InvalidatedKeyMessage); - ngcKeyHandle.Dispose(); - } - catch - { - ngcKeyHandle.Dispose(); - DeletePersistentKey(); - throw; - } - } - else - { - CreatePersistentKey(false).Dispose(); - } + CreatePersistentKey(false).Dispose(); + _currentCacheType = authCacheType; + } + catch (AuthProviderInvalidKeyException) + { + Debug.Assert(authCacheType == AuthCacheType.Persistent); + CreatePersistentKey(true).Dispose(); + _currentCacheType = authCacheType; + } + finally + { + if (authCacheType == AuthCacheType.Local) + DeletePersistentKey(); } - - CurrentCacheType = authCacheType; } } @@ -256,7 +202,8 @@ public byte[] Encrypt(byte[] data) { try { - return Encrypt(data, retry: i > 0); + var verifyIntegrity = _currentCacheType == AuthCacheType.Persistent; + return Encrypt(data, CurrentKeyName, verifyIntegrity); } catch (AuthProviderSystemErrorException ex) { @@ -283,7 +230,8 @@ public byte[] PromptToDecrypt(byte[] data) { try { - return PromptToDecrypt(data, retry: i > 0); + var verifyIntegrity = _currentCacheType == AuthCacheType.Persistent; + return PromptToDecrypt(data, CurrentKeyName, verifyIntegrity, retry: i > 0); } catch (AuthProviderSystemErrorException ex) { @@ -304,7 +252,7 @@ public byte[] PromptToDecrypt(byte[] data) } } - private byte[] Encrypt(byte[] data, bool retry) + private static byte[] Encrypt(byte[] data, string keyName, bool verifyIntegrity) { byte[] cbResult; SafeNCryptProviderHandle ngcProviderHandle; @@ -312,10 +260,10 @@ private byte[] Encrypt(byte[] data, bool retry) using (ngcProviderHandle) { SafeNCryptKeyHandle ngcKeyHandle; - NCryptOpenKey(ngcProviderHandle, out ngcKeyHandle, CurrentKeyName, 0, CngKeyOpenOptions.Silent).ThrowOnError("NCryptOpenKey"); + NCryptOpenKey(ngcProviderHandle, out ngcKeyHandle, keyName, 0, CngKeyOpenOptions.Silent).ThrowOnError("NCryptOpenKey"); using (ngcKeyHandle) { - if (CurrentCacheType == AuthCacheType.Persistent && !VerifyPersistentKeyIntegrity(ngcKeyHandle)) + if (verifyIntegrity && !VerifyPersistentKeyIntegrity(ngcKeyHandle)) throw new AuthProviderInvalidKeyException(InvalidatedKeyMessage); int pcbResult; @@ -323,14 +271,14 @@ private byte[] Encrypt(byte[] data, bool retry) cbResult = new byte[pcbResult]; NCryptEncrypt(ngcKeyHandle, data, data.Length, IntPtr.Zero, cbResult, cbResult.Length, out pcbResult, NCRYPT_PAD_PKCS1_FLAG).ThrowOnError("NCryptEncrypt"); - System.Diagnostics.Debug.Assert(cbResult.Length == pcbResult); + Debug.Assert(cbResult.Length == pcbResult); } } return cbResult; } - private byte[] PromptToDecrypt(byte[] data, bool retry) + private static byte[] PromptToDecrypt(byte[] data, string keyName, bool verifyIntegrity, bool retry) { byte[] cbResult; SafeNCryptProviderHandle ngcProviderHandle; @@ -338,10 +286,10 @@ private byte[] PromptToDecrypt(byte[] data, bool retry) using (ngcProviderHandle) { SafeNCryptKeyHandle ngcKeyHandle; - NCryptOpenKey(ngcProviderHandle, out ngcKeyHandle, CurrentKeyName, 0, CngKeyOpenOptions.None).ThrowOnError("NCryptOpenKey"); + NCryptOpenKey(ngcProviderHandle, out ngcKeyHandle, keyName, 0, CngKeyOpenOptions.None).ThrowOnError("NCryptOpenKey"); using (ngcKeyHandle) { - if (CurrentCacheType == AuthCacheType.Persistent && !VerifyPersistentKeyIntegrity(ngcKeyHandle)) + if (verifyIntegrity && !VerifyPersistentKeyIntegrity(ngcKeyHandle)) throw new AuthProviderInvalidKeyException(InvalidatedKeyMessage); ApplyUIContext(ngcKeyHandle, retry); @@ -353,14 +301,47 @@ private byte[] PromptToDecrypt(byte[] data, bool retry) cbResult = new byte[data.Length * 2]; int pcbResult; NCryptDecrypt(ngcKeyHandle, data, data.Length, IntPtr.Zero, cbResult, cbResult.Length, out pcbResult, NCRYPT_PAD_PKCS1_FLAG).ThrowOnError("NCryptDecrypt"); - // TODO: secure resize - Array.Resize(ref cbResult, pcbResult); + + if (cbResult.Length > pcbResult) + { + var res = new byte[pcbResult]; + Array.Copy(cbResult, res, pcbResult); + Array.Clear(cbResult, 0, cbResult.Length); + cbResult = res; + } } } return cbResult; } + private static AuthCacheType EnsureKeyAvailability(AuthCacheType authCacheType) + { + EnsureWinHelloAvailability(); + + if (authCacheType == AuthCacheType.Persistent) lock (_mutex) + { + SafeNCryptKeyHandle ngcKeyHandle; + if (!TryOpenPersistentKey(out ngcKeyHandle)) + throw new AuthProviderKeyNotFoundException("Persistent key does not exist."); + + using (ngcKeyHandle) + { + if (!VerifyPersistentKeyIntegrity(ngcKeyHandle)) + throw new AuthProviderInvalidKeyException(InvalidatedKeyMessage); + } + } + else if (authCacheType != AuthCacheType.Local) + throw new NotSupportedException("Unknown cache type: " + authCacheType); + + return authCacheType; + } + + private static void EnsureWinHelloAvailability() + { + var dummy = LocalKeyName; // throw an exception if not available + } + private static void RetrieveKeys(out string localKey, out string persistentKey) { NgcGetDefaultDecryptionKeyName(_currentSID.Value, 0, 0, out localKey); @@ -371,11 +352,6 @@ private static void RetrieveKeys(out string localKey, out string persistentKey) throw new AuthProviderIsUnavailableException("Windows Hello is not available."); } - private static void EnsureWinHelloAvailability() - { - var dummy = LocalKeyName; // throw an exception if not available - } - private static void DeletePersistentKey() { SafeNCryptKeyHandle ngcKeyHandle; @@ -423,10 +399,8 @@ private static bool VerifyPersistentKeyIntegrity(SafeNCryptKeyHandle ngcKeyHandl { NCryptGetProperty(ngcKeyHandle, NCRYPT_NGC_CACHE_TYPE_PROPERTY_DEPRECATED, ref cacheType, sizeof(int), out pcbResult, CngPropertyOptions.None).ThrowOnError("NCRYPT_NGC_CACHE_TYPE_PROPERTY_DEPRECATED"); } - if (cacheType != NCRYPT_NGC_CACHE_TYPE_PROPERTY_AUTH_MANDATORY_FLAG) - return false; - return true; + return cacheType == NCRYPT_NGC_CACHE_TYPE_PROPERTY_AUTH_MANDATORY_FLAG; } private static SafeNCryptKeyHandle CreatePersistentKey(bool overwriteExisting) diff --git a/src/AuthProviders/WinHelloProviderForegroundDecorator.cs b/src/AuthProviders/WinHelloProviderForegroundDecorator.cs index c781e1d..1ebed55 100644 --- a/src/AuthProviders/WinHelloProviderForegroundDecorator.cs +++ b/src/AuthProviders/WinHelloProviderForegroundDecorator.cs @@ -20,10 +20,8 @@ public WinHelloProviderForegroundDecorator(IAuthProvider provider, IntPtr keePas public AuthCacheType CurrentCacheType { - get - { - return _winHelloProvider.CurrentCacheType; - } + get { return _winHelloProvider.CurrentCacheType; } + set { _winHelloProvider.CurrentCacheType = value; } } public void ClaimCurrentCacheType(AuthCacheType newType) diff --git a/src/AuthProviders/XorProvider.cs b/src/AuthProviders/XorProvider.cs index 774679c..569b312 100644 --- a/src/AuthProviders/XorProvider.cs +++ b/src/AuthProviders/XorProvider.cs @@ -13,12 +13,10 @@ public XorProvider(AuthCacheType authCacheType) CurrentCacheType = authCacheType; } - public AuthCacheType CurrentCacheType { get; private set; } // TDB + public AuthCacheType CurrentCacheType { get; set; } public void ClaimCurrentCacheType(AuthCacheType newType) { - CurrentCacheType = newType; - if (newType == AuthCacheType.Persistent) { string message = "Default message for persistent auth type"; @@ -34,6 +32,8 @@ public void ClaimCurrentCacheType(AuthCacheType newType) { MessageBox.Show(AuthProviderUIContext.Current, "Switched to local.", "Keys removed", MessageBoxButtons.OK, MessageBoxIcon.Information); } + + CurrentCacheType = newType; } public byte[] Encrypt(byte[] data) diff --git a/src/Exceptions/AuthProviderKeyNotFoundException.cs b/src/Exceptions/AuthProviderKeyNotFoundException.cs index 0578f3d..588dee4 100644 --- a/src/Exceptions/AuthProviderKeyNotFoundException.cs +++ b/src/Exceptions/AuthProviderKeyNotFoundException.cs @@ -3,7 +3,7 @@ namespace KeePassWinHello { [Serializable] - public class AuthProviderKeyNotFoundException : AuthProviderException // TODO: consider inherit from AuthProviderInvalidKeyException + public class AuthProviderKeyNotFoundException : AuthProviderInvalidKeyException { public override bool IsPresentable { get { return true; } } diff --git a/src/KeePassWinHello.csproj b/src/KeePassWinHello.csproj index c1f92b0..5e3ac20 100644 --- a/src/KeePassWinHello.csproj +++ b/src/KeePassWinHello.csproj @@ -49,7 +49,6 @@ - True True diff --git a/src/KeePassWinHelloExt.cs b/src/KeePassWinHelloExt.cs index 6d2bb39..178cc86 100644 --- a/src/KeePassWinHelloExt.cs +++ b/src/KeePassWinHelloExt.cs @@ -12,7 +12,7 @@ namespace KeePassWinHello public class KeePassWinHelloExt : Plugin { private IPluginHost _host; - private KeyManagerProvider _keyManagerProvider; + private KeyManager _keyManager; private readonly object _unlockMutex = new Object(); public override Image SmallIcon @@ -45,11 +45,19 @@ public override bool Initialize(IPluginHost host) if (_host != null) { Debug.Assert(false); Terminate(); } if (host == null) { return false; } - Settings.Instance.Initialize(host.CustomConfig); + try + { + Settings.Instance.Initialize(host.CustomConfig); - _host = host; - _keyManagerProvider = new KeyManagerProvider(host); + _keyManager = new KeyManager(host.MainWindow.Handle); + } + catch (Exception ex) + { + ErrorHandler.ShowError(ex); + return false; + } + _host = host; _host.MainWindow.FileClosingPre += OnPreFileClosing; GlobalWindowManager.WindowAdded += OnWindowAdded; @@ -64,8 +72,8 @@ public override void Terminate() GlobalWindowManager.WindowAdded -= OnWindowAdded; _host.MainWindow.FileClosingPre -= OnPreFileClosing; - _keyManagerProvider.Dispose(); - _keyManagerProvider = null; + _keyManager.Dispose(); + _keyManager = null; _host = null; } @@ -74,9 +82,7 @@ private void OnPreFileClosing(object sender, FileClosingEventArgs e) { try { - var keyManager = _keyManagerProvider.ObtainKeyManager(); - if (keyManager != null) - keyManager.OnDBClosing(sender, e); + _keyManager.OnDBClosing(sender, e); } catch (Exception ex) { @@ -91,20 +97,15 @@ private void OnWindowAdded(object sender, GwmWindowEventArgs e) var keyPromptForm = e.Form as KeyPromptForm; if (keyPromptForm != null) { - var keyManager = _keyManagerProvider.ObtainKeyManager(); - if (keyManager != null) - { - lock (_unlockMutex) - keyManager.OnKeyPrompt(keyPromptForm, _host.MainWindow); - return; - } + lock (_unlockMutex) + _keyManager.OnKeyPrompt(keyPromptForm, _host.MainWindow); + return; } var optionsForm = e.Form as OptionsForm; if (optionsForm != null) { - var keyManager = _keyManagerProvider.ObtainKeyManager(); - OptionsPanel.OnOptionsLoad(optionsForm, keyManager); + OptionsPanel.OnOptionsLoad(optionsForm, _keyManager); return; } } diff --git a/src/KeyManagement/KeyCipher.cs b/src/KeyManagement/KeyCipher.cs index 03399e6..f987a0f 100644 --- a/src/KeyManagement/KeyCipher.cs +++ b/src/KeyManagement/KeyCipher.cs @@ -20,36 +20,7 @@ public KeyCipher(IntPtr keePassWindowHandle) _randomSeedBits = 256; _encryptionIV = new byte[16]; _cipherEngine = CipherPool.GlobalPool.GetCipher(StandardAesEngine.AesUuid); - _cryptProvider = GetAuthProvider(keePassWindowHandle); - } - - private static IAuthProvider GetAuthProvider(IntPtr keePassWindowHandle) - { - var authCacheType = Settings.Instance.GetAuthCacheType(); - try - { - return AuthProviderFactory.GetInstance(keePassWindowHandle, authCacheType); - } - catch (AuthProviderKeyNotFoundException ex) - { - if (authCacheType == AuthCacheType.Local) - throw; - - Settings.Instance.WinStorageEnabled = false; - authCacheType = Settings.Instance.GetAuthCacheType(); - ErrorHandler.ShowError(ex, "Credential Manager storage has been turned off. Use Options dialog to turn it on."); - return AuthProviderFactory.GetInstance(keePassWindowHandle, authCacheType); - } - catch (AuthProviderInvalidKeyException ex) - { - if (authCacheType == AuthCacheType.Local) - throw; - - Settings.Instance.WinStorageEnabled = false; - authCacheType = Settings.Instance.GetAuthCacheType(); - ErrorHandler.ShowError(ex, "For security reasons Credential Manager storage has been turned off. Use Options dialog to turn it on."); - return AuthProviderFactory.GetInstance(keePassWindowHandle, authCacheType); - } + _cryptProvider = AuthProviderFactory.Create(keePassWindowHandle); } public IAuthProvider AuthProvider { get { return _cryptProvider; } } diff --git a/src/KeyManagement/KeyManager.cs b/src/KeyManagement/KeyManager.cs index e798e5f..3f9f688 100644 --- a/src/KeyManagement/KeyManager.cs +++ b/src/KeyManagement/KeyManager.cs @@ -17,7 +17,8 @@ interface IKeyManager int KeysCount { get; } void RevokeAll(); - void ClaimCurrentCacheType(AuthCacheType authCacheType); + void SwitchCurrentCacheType(AuthCacheType authCacheType); + bool IsAvailable(); } class KeyManager : IKeyManager, IDisposable @@ -38,7 +39,39 @@ public KeyManager(IntPtr windowHandle) { _keePassMainWindowHandle = windowHandle; _keyCipher = new KeyCipher(windowHandle); - _keyStorage = KeyStorageFactory.Create(_keyCipher.AuthProvider); + _keyStorage = KeyStorageFactory.Create(); + + TryInit(); + } + + public bool IsAvailable() + { + try + { + var authCacheType = _keyCipher.AuthProvider.CurrentCacheType; + Debug.Assert(authCacheType == Settings.Instance.GetAuthCacheType()); + return true; + } + catch + { + return false; + } + } + + private void TryInit() + { + try + { + if (_keyCipher.AuthProvider.CurrentCacheType != Settings.Instance.GetAuthCacheType()) + { + // todo: something unexpected, messagebox + SwitchCurrentCacheType(AuthCacheType.Local); + } + } + catch (AuthProviderException ex) + { + HandleAuthProviderException(ex); + } } public void OnKeyPrompt(KeyPromptForm keyPromptForm, MainForm mainWindow) @@ -161,16 +194,17 @@ private void Unlock(KeyPromptForm keyPromptForm, string dbPath) CloseFormWithResult(keyPromptForm, DialogResult.OK); } } - catch (AuthProviderKeyNotFoundException ex) + catch (AuthProviderUserCancelledException) { - // It's expected not to throw exceptions - ClaimCurrentCacheType(AuthCacheType.Local); - ErrorHandler.ShowError(ex, "Credential Manager storage has been turned off. Use Options dialog to turn it on."); + if (Settings.Instance.RevokeOnCancel) + _keyStorage.Remove(dbPath); + CloseFormWithResult(keyPromptForm, DialogResult.Cancel); } - catch (AuthProviderUserCancelledException) + catch (AuthProviderException ex) { - CloseFormWithResult(keyPromptForm, DialogResult.Cancel); + if (!HandleAuthProviderException(ex)) + throw; } } @@ -187,23 +221,43 @@ private void Lock(bool isDbLocking, string dbPath, CompositeKey databaseMasterKe _keyStorage.AddOrUpdate(dbPath, ProtectedKey.Create(databaseMasterKey, _keyCipher)); } } - catch (AuthProviderKeyNotFoundException ex) + catch (AuthProviderException ex) + { + if (!HandleAuthProviderException(ex)) + throw; + } + } + + private bool HandleAuthProviderException(AuthProviderException ex) + { + if (ex is AuthProviderKeyNotFoundException) { // It's expected not to throw exceptions - ClaimCurrentCacheType(AuthCacheType.Local); + SwitchCurrentCacheType(AuthCacheType.Local); ErrorHandler.ShowError(ex, "Credential Manager storage has been turned off. Use Options dialog to turn it on."); } - catch (AuthProviderInvalidKeyException ex) + else if (ex is AuthProviderInvalidKeyException) { + // The key might be compromised so we revoke all stored passwords // It's expected not to throw exceptions - ClaimCurrentCacheType(AuthCacheType.Local); + SwitchCurrentCacheType(AuthCacheType.Local); ErrorHandler.ShowError(ex, "For security reasons Credential Manager storage has been turned off. Use Options dialog to turn it on."); } - catch (AuthProviderUserCancelledException) + else if (ex is AuthProviderUserCancelledException) { // it's OK } + else if (ex is AuthProviderIsUnavailableException) + { + // it's OK + } + else + { + return false; + } + + return true; } public void RevokeAll() @@ -211,11 +265,11 @@ public void RevokeAll() _keyStorage.Clear(); } - public void ClaimCurrentCacheType(AuthCacheType authCacheType) + public void SwitchCurrentCacheType(AuthCacheType authCacheType) { _keyCipher.AuthProvider.ClaimCurrentCacheType(authCacheType); _keyStorage.Clear(); - _keyStorage = KeyStorageFactory.Create(_keyCipher.AuthProvider); + _keyStorage = KeyStorageFactory.Create(authCacheType); if (authCacheType == AuthCacheType.Local) Settings.Instance.WinStorageEnabled = false; // todo migrate @@ -254,31 +308,10 @@ private bool ExtractCompositeKey(string dbPath, out CompositeKey compositeKey) if (!_keyStorage.TryGetValue(dbPath, out encryptedData)) return false; - try - { - using (AuthProviderUIContext.With(Settings.DecryptConfirmationMessage, _keePassMainWindowHandle)) - { - compositeKey = encryptedData.GetCompositeKey(_keyCipher); - return true; - } - } - catch (AuthProviderInvalidKeyException) - { - // The key might be compromised so we revoke all stored passwords - ClaimCurrentCacheType(AuthCacheType.Local); - throw; - } - catch (AuthProviderUserCancelledException) - { - if (Settings.Instance.RevokeOnCancel) - _keyStorage.Remove(dbPath); - throw; - } - catch (Exception) - { - _keyStorage.Remove(dbPath); - throw; - } + using (AuthProviderUIContext.With(Settings.DecryptConfirmationMessage, _keePassMainWindowHandle)) + compositeKey = encryptedData.GetCompositeKey(_keyCipher); + + return true; } private static void SetCompositeKey(KeyPromptForm keyPromptForm, CompositeKey compositeKey) diff --git a/src/KeyManagement/KeyManagerProvider.cs b/src/KeyManagement/KeyManagerProvider.cs deleted file mode 100644 index 65037a0..0000000 --- a/src/KeyManagement/KeyManagerProvider.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using KeePass.Plugins; -using KeePassWinHello.Utilities; - -namespace KeePassWinHello -{ - class KeyManagerProvider : IDisposable - { - private readonly object _initMutex = new Object(); - private readonly IPluginHost _host; - - private KeyManager _keyManager; - private bool? _wasUnavailable = null; - - public KeyManagerProvider(IPluginHost host) - { - _host = host; - } - - public KeyManager ObtainKeyManager() - { - TryInitKeyManager(); - return _keyManager; // Can be null - } - - public void Dispose() - { - lock (_initMutex) - { - if (_keyManager != null) - { - _keyManager.Dispose(); - _keyManager = null; - } - _wasUnavailable = null; - } - } - - private void TryInitKeyManager() - { - lock (_initMutex) - { - if (_wasUnavailable == false) - return; - - try - { - _keyManager = new KeyManager(_host.MainWindow.Handle); - _wasUnavailable = false; - } - catch (AuthProviderIsUnavailableException) - { - _wasUnavailable = true; - } - catch (Exception ex) - { - _wasUnavailable = false; - ErrorHandler.ShowError(ex); - } - } - } - } -} diff --git a/src/KeyManagement/Storage/IKeyStorage.cs b/src/KeyManagement/Storage/IKeyStorage.cs index 67be4fa..63914af 100644 --- a/src/KeyManagement/Storage/IKeyStorage.cs +++ b/src/KeyManagement/Storage/IKeyStorage.cs @@ -16,12 +16,17 @@ interface IKeyStorage static class KeyStorageFactory { - public static IKeyStorage Create(IAuthProvider authProvider) + public static IKeyStorage Create(AuthCacheType authCacheType) { - if (Settings.Instance.WinStorageEnabled && authProvider.CurrentCacheType == AuthCacheType.Persistent) + if (authCacheType == AuthCacheType.Persistent) return new KeyWindowsStorage(); return new KeyMemoryStorage(); } + + public static IKeyStorage Create() + { + return Create(Settings.Instance.GetAuthCacheType()); + } } } \ No newline at end of file diff --git a/src/Settings/OptionsPanel.cs b/src/Settings/OptionsPanel.cs index 907ec36..2088254 100644 --- a/src/Settings/OptionsPanel.cs +++ b/src/Settings/OptionsPanel.cs @@ -29,7 +29,7 @@ private bool IsSettingsEnabled private bool IsStorageAvailable { - get { return _keyManager != null; } + get { return _keyManager.IsAvailable(); } } private OptionsPanel(IKeyManager keyManager) @@ -124,48 +124,46 @@ private void SaveSettings(Settings settings) if (settings.WinStorageEnabled != winKeyStorageCheckBox.Checked) { - if (_keyManager != null) + if (_keyManager.IsAvailable()) { using (AuthProviderUIContext.With(Settings.KeyCreationConfirmationMessage, this.Handle)) { - if (SystemInformation.TerminalServerSession) // RDP - { - MessageBox.Show(AuthProviderUIContext.Current, - "Changing storage location setting on a remote session is not permitted", - Settings.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - try { settings.WinStorageEnabled = winKeyStorageCheckBox.Checked; var authCacheType = settings.GetAuthCacheType(); - _keyManager.ClaimCurrentCacheType(authCacheType); + _keyManager.SwitchCurrentCacheType(authCacheType); } catch (AuthProviderUserCancelledException) { - TryClaimLocalCacheType(); + TrySwitchToLocalCacheType(); MessageBox.Show(AuthProviderUIContext.Current, "Creating persistent key for Credential Manager has been canceled", Settings.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { - TryClaimLocalCacheType(); + TrySwitchToLocalCacheType(); ErrorHandler.ShowError(ex); } } } + else if (SystemInformation.TerminalServerSession) // RDP + { + MessageBox.Show(AuthProviderUIContext.Current, + "Changing storage location setting on a remote session is not permitted", + Settings.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); + } } } } - private void TryClaimLocalCacheType() + private void TrySwitchToLocalCacheType() { try { Settings.Instance.WinStorageEnabled = false; - _keyManager.ClaimCurrentCacheType(AuthCacheType.Local); + _keyManager.SwitchCurrentCacheType(AuthCacheType.Local); } catch (Exception ex) { @@ -254,17 +252,15 @@ private void UpdateStoredKeysPanel() private void RevokeAllKeys() { - if (_keyManager != null) + try { - try - { - _keyManager.RevokeAll(); - } - catch (Exception ex) - { - ErrorHandler.ShowError(ex); - } + _keyManager.RevokeAll(); + } + catch (Exception ex) + { + ErrorHandler.ShowError(ex); } + UpdateStoredKeysPanel(); }