Windows Credential Storage/de

From Free Pascal wiki
Revision as of 15:56, 17 September 2022 by Socke (talk | contribs) (angelegt)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Deutsch (de) English (en)

Windows logo - 2012.svg

Dieser Artikel behandelt ausschließlich Windows.

Siehe auch: Multiplatform Programming Guide/de

Mit der Windows *Anmeldeinformationsverwaltung* (EN: Credential Manager) kann eine Anwendung sensible Benutzernamen und Kennworte sicher speichern ohne diese in einer offen einsehbaren Konfigurationsdatei ablegen zu müssen.

Die hier bereitgestellte Unit stellt drei Funktionen bereit um die Kennworte zu lesen, schreiben und zu löschen. Bei jedem Aufruf muss eine Identifikation der Anmeldeinformationen (Parameter *Target*) mitgegeben werden.

unit uwincred;

// Original Source https://stackoverflow.com/questions/13145112/secure-way-to-store-password-in-windows
// Angepasst für Free Pascal

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, windows, JwaWinCred;

function CredReadGenericCredentials(const Target: UnicodeString; var Username, Password: UnicodeString): Boolean;
function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
function CredDeleteGenericCredentials(const Target: UnicodeString): Boolean;

implementation

function WideCharToWideString(s: PWideChar; UnicodeCharCount: SizeInt): UnicodeString;
begin
  SetLength(Result{%H-}, UnicodeCharCount);
  strmove(PWideChar(Result), s, UnicodeCharCount);
end;

function CredReadGenericCredentials(const Target: UnicodeString; var Username, Password: UnicodeString): Boolean;
var
    credential: PCREDENTIALW;
    le: DWORD;
    s: UnicodeString;
begin
    Result := False;

    credential := nil;
    if not CredReadW(PWideChar(Target), CRED_TYPE_GENERIC, 0, {var}credential) then
    begin
        le := GetLastError;
        s := 'Could not get "'+Target+'" generic credentials: '+SysErrorMessage(le)+' '+IntToStr(le);
        OutputDebugStringW(PWideChar(s));
        Exit;
    end;

    try
        username := Credential^.UserName;
        password := WideCharToWideString(PWideChar(Credential^.CredentialBlob), Credential^.CredentialBlobSize div 2); //By convention blobs that contain strings do not have a trailing NULL.
    finally
        CredFree(Credential);
    end;

    Result := True;
end;

function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
var
    Credentials: CREDENTIALW;
begin
    ZeroMemory(@Credentials, SizeOf(Credentials));
    Credentials.TargetName := PWideChar(Target); //cannot be longer than CRED_MAX_GENERIC_TARGET_NAME_LENGTH (32767) characters. Recommended format "Company_Target"
    Credentials.Type_ := CRED_TYPE_GENERIC;
    Credentials.UserName := PWideChar(Username);
    Credentials.Persist := CRED_PERSIST_LOCAL_MACHINE;
    Credentials.CredentialBlob := PByte(Password);
    Credentials.CredentialBlobSize := 2*(Length(Password)); //By convention no trailing null. Cannot be longer than CRED_MAX_CREDENTIAL_BLOB_SIZE (512) bytes
    Credentials.UserName := PWideChar(Username);
    Result := CredWriteW(@Credentials, 0);
end;

function CredDeleteGenericCredentials(const Target: UnicodeString): Boolean;
begin
    Result := CredDeleteW(PWideChar(Target), CRED_TYPE_GENERIC, 0);
end;

end.

Die Verwendung funktioniert wie folgend. Als *Target* wird der Programmname verwendet.

var
  StoredUserName, StoredPassword: UnicodeString;
begin
  StoredUserName := '';
  StoredPassword := '';
  // Anmeldeinformationen lesen
  CredReadGenericCredentials(Application.ExeName, StoredUserName, StoredPassword);
  // Anmeldeinformationen speichern
  CredWriteGenericCredentials(Application.ExeName, StoredUserName, StoredPassword);  
  // Anmeldeinformationen löschen
  CredDeleteGenericCredentials(Application.ExeName);
end;