J'essaie d'écrire une fonction simple pour Windows qui répond à la question suivante.Comment vérifier si un utilisateur a des droits d'accès pour un fichier avec l'API Windows
L'utilisateur (U) a-t-il des droits (R) sur le fichier (F)?
Où,
R est une combinaison de (GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE)
U ne doit pas être connecté ou personnifié
Le code que j'ai écrit est illustré ci-dessous. L'application appelle la première UserHasPermission qui est affichée.
Les droits d'accès renvoyés par GetEffectiveRightsFromAcl sont les mêmes pour toutes les combinaisons utilisateur/fichier que j'ai testées ($ 001200A9). J'ai vérifié et $ 001200A9 n'est pas seulement un pointeur vers l'endroit où les droits d'accès sont réellement stockés.
Ma question est double:
1. Y a-t-il une meilleure façon de procéder?
2. Quelqu'un peut-il me dire où je vais mal?
function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AFileName: WideString; AUserName: String; ADomainName: String): Boolean; var SID: PSID; ACL: PACL; begin SID := nil; ACL := nil; try Result := GetUserSID(SID, AUserNAme, ADomainName); Result := Result and GetFileDACL(AFileName, ACL); Result := Result and UserHasPermission(APermission, HasPermission, ACL, SID); finally Dispose(SID); end; end; function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AACL: PACL; AUserSID: PSID): Boolean; var T: TRUSTEE; Rights: ACCESS_MASK; begin BuildTrusteeWithSid(@T, AUserSID); Result := GetEffectiveRightsFromAcl(AACL, @T, @Rights) = ERROR_SUCCESS; HasPermission := (Rights and APermission) = APermission; end; function GetUserSID(out ASID: PSID; AUserName: WideString; const ADomainName: WideString): Boolean; var NSID, NDomain: Longword; Use: SID_NAME_USE; DomainName: WideString; begin Result := False; if Length(AUserName) > 0 then begin if Length(ADomainName) > 0 then AUserName := ADomainName + '\' + AUserName; // determine memory requirements NSID := 0; NDomain := 0; LookupAccountNameW(nil, PWideChar(AUserName), nil, NSID, nil, NDomain, Use); // allocate memory GetMem(ASID, NSID); SetLength(DomainName, NDomain); Result := LookupAccountNameW(nil, PWideChar(AUserName), ASID, NSID, PWideChar(DomainName), NDomain, Use); end; end; function GetFileDACL(AFileName: WideString; out AACL: PACL): Boolean; var SD: PSecurityDescriptor; NSD, NNeeded: Longword; Present, Defualted: Longbool; begin GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, nil, 0, NNeeded); GetMem(SD, NNeeded); try NSD := NNeeded; Result := GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, SD, NSD, NNeeded); Result := Result and GetSecurityDescriptorDacl(SD, Present, AACL, Defualted); Result := Result and Present; finally Dispose(SD); end; end;
Votre droit le code était à peu près correct. J'étais fatigué et frustré, c'est-à-dire négligent, pendant les tests. Merci pour la révision du code, tout fonctionne et maintenant je comprends ce qui se passe. –
Sachez que GetEffectiveRightsFromAcl ne prend pas en compte les structures de groupe et les privilèges complexes imbriqués. Cela signifie que la fonction peut accorder ou refuser l'accès, même si ce n'est pas le cas. La fonction API AccessCheck est le moyen le plus sûr de le vérifier. Malheureusement, l'application doit emprunter l'identité de l'utilisateur en appelant AccessCheck. En fin de compte, les deux fonctions peuvent créer des résultats incorrects lorsqu'elles sont utilisées sur des objets distants car des vérifications d'accès supplémentaires sont effectuées par le système distant. – ChristianWimmer