Files
123123/ZA.CoreService.ESBCertificateManager/Services/WindowsCredentialManagerSecretProvider.cs
T
2026-07-28 08:03:12 +02:00

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;
}
}