Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/Exceptions/KeyStorageException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace KeePassWinHello
{
[Serializable]
public class KeyStorageException : KeePassWinHelloException
{
public override bool IsPresentable { get { return true; } }

public KeyStorageException(string message) : base(message) { }
public KeyStorageException(string message, Exception inner) : base(message, inner) { }
protected KeyStorageException() { }
protected KeyStorageException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}
3 changes: 2 additions & 1 deletion src/KeePassWinHello.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<Compile Include="Exceptions\AuthProviderInvalidKeyException.cs" />
<Compile Include="Exceptions\AuthProviderSystemErrorException.cs" />
<Compile Include="Exceptions\AuthProviderException.cs" />
<Compile Include="Exceptions\KeyStorageException.cs" />
<Compile Include="AuthProviders\IAuthProvider.cs" />
<Compile Include="AuthProviders\UIContext.cs" />
<Compile Include="AuthProviders\WinHelloProviderForegroundDecorator.cs" />
Expand Down Expand Up @@ -124,4 +125,4 @@
<Message Importance="normal" Text="Copy artifacts to KeePass plugins directory." />
<Exec ContinueOnError="true" Command="powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File &quot;$(ProjectDir)..\Deploy-Plugin.ps1&quot; -ForDebug -Verbose" WorkingDirectory="$(ProjectDir).." />
</Target>
</Project>
</Project>
4 changes: 4 additions & 0 deletions src/KeyManagement/KeyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ private void Lock(bool isDbLocking, string dbPath, CompositeKey databaseMasterKe
{
// it's OK
}
catch (KeyStorageException ex)
{
_uiContextManager.CurrentContext.ShowError(ex);
}
}

public void RevokeAll()
Expand Down
35 changes: 34 additions & 1 deletion src/KeyManagement/Storage/KeyWindowsStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal class KeyWindowsStorage : IKeyStorage
{
#region Credential Manager API
private const int ERROR_NOT_FOUND = 0x490;
private const int ERROR_NO_SUCH_LOGON_SESSION = 0x520;

private const int CRED_TYPE_GENERIC = 0x1;

Expand Down Expand Up @@ -96,7 +97,7 @@ public void AddOrUpdate(string dbPath, ProtectedKey protectedKey)
Marshal.Copy(data, 0, ncred.CredentialBlob, data.Length);
ncred.CredentialBlobSize = (uint)data.Length;

CredWrite(ref ncred, 0).ThrowOnError("CredWrite");
WriteCredential(ref ncred);
}
finally
{
Expand All @@ -111,6 +112,38 @@ public void AddOrUpdate(string dbPath, ProtectedKey protectedKey)
}
}

private static void WriteCredential(ref CREDENTIAL credential)
{
if (CredWrite(ref credential, 0).Result)
return;

int errorCode = Marshal.GetLastWin32Error();
if (errorCode == ERROR_NO_SUCH_LOGON_SESSION)
throw new KeyStorageException(GetNoLogonSessionMessage());

throw new EnviromentErrorException("CredWrite", errorCode);
}

private static string GetNoLogonSessionMessage()
{
string message = "Windows Credential Manager cannot save the database key because Windows reported that the current logon session is not available. The database key was not saved persistently.";
if (IsCurrentProcessElevatedSafe())
message += " This can happen when KeePass is running as Administrator; restart KeePass without elevation to use Credential Manager storage.";
return message;
}

private static bool IsCurrentProcessElevatedSafe()
{
try
{
return UAC.IsCurrentProcessElevated;
}
catch
{
return false;
}
}

public bool ContainsKey(string dbPath)
{
IntPtr ncredPtr = IntPtr.Zero;
Expand Down