126 lines
3.7 KiB
C#
126 lines
3.7 KiB
C#
using System.ComponentModel;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace ZA.CoreService.ESBCertificateManager.Services;
|
|
|
|
public sealed class WindowsCredentialManagerSecretProvider
|
|
: ISecretProvider
|
|
{
|
|
private const uint GenericCredentialType = 1;
|
|
private const int ErrorNotFound = 1168;
|
|
|
|
public StoredCredential GetCredential(
|
|
string credentialReference)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(credentialReference))
|
|
{
|
|
throw new ArgumentException(
|
|
"Die CredentialReference ist nicht konfiguriert.",
|
|
nameof(credentialReference));
|
|
}
|
|
|
|
bool success = CredRead(
|
|
credentialReference,
|
|
GenericCredentialType,
|
|
0,
|
|
out IntPtr credentialPointer);
|
|
|
|
if (!success)
|
|
{
|
|
int errorCode = Marshal.GetLastWin32Error();
|
|
|
|
if (errorCode == ErrorNotFound)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Die Windows-Anmeldeinformation " +
|
|
$"'{credentialReference}' wurde nicht gefunden.");
|
|
}
|
|
|
|
throw new Win32Exception(
|
|
errorCode,
|
|
"Die Windows-Anmeldeinformation konnte nicht gelesen werden.");
|
|
}
|
|
|
|
try
|
|
{
|
|
NativeCredential nativeCredential =
|
|
Marshal.PtrToStructure<NativeCredential>(
|
|
credentialPointer);
|
|
|
|
string userName =
|
|
Marshal.PtrToStringUni(nativeCredential.UserName)
|
|
?? string.Empty;
|
|
|
|
string secret = string.Empty;
|
|
|
|
if (nativeCredential.CredentialBlob != IntPtr.Zero
|
|
&& nativeCredential.CredentialBlobSize > 0)
|
|
{
|
|
int characterCount = checked(
|
|
(int)nativeCredential.CredentialBlobSize / 2);
|
|
|
|
secret = Marshal.PtrToStringUni(
|
|
nativeCredential.CredentialBlob,
|
|
characterCount)
|
|
?? string.Empty;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(userName))
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Die Windows-Anmeldeinformation " +
|
|
$"'{credentialReference}' enthält keinen Benutzernamen.");
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(secret))
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Die Windows-Anmeldeinformation " +
|
|
$"'{credentialReference}' enthält kein Kennwort.");
|
|
}
|
|
|
|
return new StoredCredential(
|
|
userName,
|
|
secret);
|
|
}
|
|
finally
|
|
{
|
|
CredFree(credentialPointer);
|
|
}
|
|
}
|
|
|
|
[DllImport(
|
|
"advapi32.dll",
|
|
EntryPoint = "CredReadW",
|
|
CharSet = CharSet.Unicode,
|
|
SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
private static extern bool CredRead(
|
|
string target,
|
|
uint type,
|
|
int reservedFlag,
|
|
out IntPtr credentialPointer);
|
|
|
|
[DllImport("advapi32.dll")]
|
|
private static extern void CredFree(
|
|
IntPtr credentialPointer);
|
|
|
|
[StructLayout(
|
|
LayoutKind.Sequential,
|
|
CharSet = CharSet.Unicode)]
|
|
private struct NativeCredential
|
|
{
|
|
public uint Flags;
|
|
public uint Type;
|
|
public IntPtr TargetName;
|
|
public IntPtr Comment;
|
|
public long LastWritten;
|
|
public uint CredentialBlobSize;
|
|
public IntPtr CredentialBlob;
|
|
public uint Persist;
|
|
public uint AttributeCount;
|
|
public IntPtr Attributes;
|
|
public IntPtr TargetAlias;
|
|
public IntPtr UserName;
|
|
}
|
|
} |