Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Coriandolo - Settembre 30, 2021, 10:06:29 pm

Titolo: Auto login sicuro al DB
Inserito da: Coriandolo - Settembre 30, 2021, 10:06:29 pm
Sto creando una piccola applicazione, essendo nuovo nel mondo della programmazione. Siccome vorrei collegarmi tramite app a vari DB mi tornerebbe molto utile crearne un auto login. Cioè immettere la prima volta le credenziali per ogni login e dalla volta successiva trovarmele già memorizzate. Il pc lo utilizzerei solo io ma per sicurezza, oltre all'account windows protetto da password volevo mettere al sicuro anche le password memorizzato dal programmino.
Ho letto svariati articoli, il modo che mi sembra sicuro ed allo stesso tempo non esagerato in quanto a fattibilità presumo sia la memorizzazione delle credenziali nel 'gestione credenziali' di windows. Quello che conserva le credenziali di diverse app nel pc, ad esempio accessi in desktop remoto.

L'unico problema è che non riesco ad applicarlo. Ho rubacchiato un po' di codice qua e la ma non riesco a terminare il puzzle.
Quello che ho è questo:

Codice: [Seleziona]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

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

    credential := nil;
    if not CredReadW(Target, CRED_TYPE_GENERIC, 0, {var}credential) then
    begin
        le := GetLastError;
        s := 'Could not get "'+Target+'" generic credentials: '+SysErrorMessage(le)+' '+IntToStr(le);
        OutputDebugString(PChar(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
    persistType: DWORD;
    Credentials: CREDENTIALW;
    le: DWORD;
    s: string;
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;   
end.

Non vi dico quanti errori ho:
(https://i.postimg.cc/gcgwcWjY/Cattura.png)
Titolo: Re:Auto login sicuro al DB
Inserito da: Mimmo - Ottobre 01, 2021, 08:19:59 am
Ciao,
non l'ho mai usato però qui sembra ci sia un esempio, con delphi, funzionante, più o meno:

https://stackoverflow.com/questions/48568435/username-and-password-switched-when-using-windows-credential-manager
Titolo: Re:Auto login sicuro al DB
Inserito da: Coriandolo - Ottobre 01, 2021, 09:24:41 am
L'ho già provato:
Codice: [Seleziona]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Windows, SysUtils;

type
  CREDENTIAL_ATTRIBUTE = packed record
    Keyword: LPTSTR;
    Flags: DWORD;
    ValueSize: DWORD;
    Value: LPBYTE;
  end;
  PCREDENTIAL_ATTRIBUTE = ^CREDENTIAL_ATTRIBUTE;

  CREDENTIALW = packed record
    Flags: DWORD;
    Type_: DWORD;
    TargetName: LPTSTR;
    Comment: LPTSTR;
    LastWritten: FILETIME;
    CredentialBlobSize: DWORD;
    CredentialBlob: LPBYTE;
    Persist: DWORD;
    AttributeCount: DWORD;
    Attributes: PCREDENTIAL_ATTRIBUTE;
    TargetAlias: LPTSTR;
    UserName: LPTSTR;
  end;
  PCREDENTIALW = ^CREDENTIALW;

function CredWriteW(Credential: PCREDENTIALW; Flags: DWORD): Boolean; stdcall; external 'Advapi32.dll';

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

implementation

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
    Result := CredWriteW(@Credentials, 0);
end;

end.

Non mi trova degli identificatori.
(https://i.postimg.cc/9FRR2Cs0/Cattura.png) (https://postimages.org/)
Titolo: Re:Auto login sicuro al DB
Inserito da: DragoRosso - Ottobre 01, 2021, 10:36:12 am
Manca una unit, in questo caso una unit importata da jedi che l'ha "traslata" dalle originali di Microsoft:

jwawincred

da aggiungere alla USES.

Dove c'è "$mode objfpc" sostituisci "$mode Delphi".

Dove c'è "PWideChar" usa "PChar".

Non ho mai usato le credenziali integrate di Windows e non pensavo  che si potesse "leggere" le credenziali così facilmente. Per salvare le credenziali per le mie applicazioni ho sempre usato un banalissimo "chiper", metodo più che sufficiente visto che generalmente non mantengo segreti di stato.

Ciao