如何检查用户是否具有使用windows api访问文件的权限

如何检查用户是否具有使用windows api访问文件的权限,windows,security,winapi,Windows,Security,Winapi,我正试图为windows编写一个简单的函数来回答以下问题 用户(U)是否对文件(F)拥有权限(R) 其中, R是(泛型读取、泛型写入、泛型执行)的某种组合 U不必登录或模拟 我编写的代码如下所示。应用程序调用显示的第一个UserHasPermission GetEffectiveRightsFromAcl返回的访问权限对于我测试的所有用户/文件组合都是相同的($001200A9)。我仔细检查了一下,$001200A9不仅仅是指向访问权限实际存储位置的指针 我的问题有两个: 1.有更好的方法吗?

我正试图为windows编写一个简单的函数来回答以下问题

用户(U)是否对文件(F)拥有权限(R)
其中,
R是(泛型读取、泛型写入、泛型执行)的某种组合
U不必登录或模拟

我编写的代码如下所示。应用程序调用显示的第一个UserHasPermission

GetEffectiveRightsFromAcl返回的访问权限对于我测试的所有用户/文件组合都是相同的($001200A9)。我仔细检查了一下,$001200A9不仅仅是指向访问权限实际存储位置的指针

我的问题有两个:
1.有更好的方法吗?
2.谁能告诉我哪里出了问题

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; 函数UserHasPermission(APermission:Longword;out-HasPermission:Boolean;AFileName:WideString;AUserName:String;ADomainName:String):Boolean; 变量 SID:PSID; ACL:PACL; 开始 SID:=零; ACL:=零; 尝试 结果:=GetUserSID(SID、AUserNAme、ADomainName); 结果:=结果和GetFileDACL(AFileName,ACL); 结果:=结果和用户HasPermission(APermission、HasPermission、ACL、SID); 最后 处置(SID); 结束; 结束; 函数UserHasPermission(APermission:Longword;out-HasPermission:Boolean;AACL:PACL;AUserSID:PSID):Boolean; 变量 T:受托人; 权限:访问权限; 开始 buildTrusteeWithId(@T,auserId); 结果:=GetEffectiveRightsFromAcl(AACL,@T,@Rights)=错误\成功; HasPermission:=(权利和授权)=授权; 结束; 函数GetUserSID(out ASID:PSID;AUserName:WideString;const ADomainName:WideString):布尔; 变量 NSID,NDomain:Longword; 用途:SID_NAME_Use; 域名:WideString; 开始 结果:=假; 如果长度(AUserName)>0,则 开始 如果长度(ADomainName)>0,则 AUserName:=ADomainName+'\'+AUserName; //确定内存需求 NSID:=0; NDomain:=0; LookupAccountNameW(nil,PWideChar(AUserName),nil,NSID,nil,NDomain,Use); //分配内存 GetMem(ASID、NSID); SetLength(域名,域名); 结果:=LookupAccountNameW(nil,PWideChar(AUserName),ASID,NSID,PWideChar(DomainName),NDomain,Use); 结束; 结束; 函数GetFileDACL(AFileName:WideString;out-AACL:PACL):布尔; 变量 SD:PSecurityDescriptor; NSD,NNEEED:长单词; 现在,解除辩论:朗布尔; 开始 GetFileSecurityW(PWideChar(AFileName),DACL\u安全信息,nil,0,NNeeded); GetMem(SD、NNEEED); 尝试 NSD:=NNEED; 结果:=GetFileSecurityW(PWideChar(AFileName)、DACL\u安全信息、SD、NSD、NNeeded); 结果:=结果和GetSecurityDescriptorRDACL(SD、Present、AACL、Defualted); 结果:=结果和当前; 最后 处置(SD); 结束; 结束; GetEffectiveRightsFromAcl对于我测试的所有用户/文件组合都是相同的($001200A9)

这一切都取决于ACL,例如,如果每个人都被授予完全控制权,那么任何使用都将拥有完全控制权

代码看起来很合理,您正在使用一个Win32安全API()来完成繁重的工作


建议:创建非常特定的ACL来测试您的代码(使之更容易),首先是一个不授予权限的ACL,然后是一个只包含不同用户的ACL。

您的权利代码非常正确。我在测试时感到疲劳和沮丧,即粗心。感谢您的代码审阅,一切正常,现在我了解了发生的情况。请注意GetEffectiveRightsFromAcl不考虑复杂的嵌套组结构和权限。这意味着函数可以授予或拒绝访问权限,尽管它不应该这样做。AccessCheck API函数是检查它的最安全的方法。不幸的是,应用程序需要在调用AccessCheck时模拟用户。最后,这两个函数在远程对象上使用时可能会产生不正确的结果,因为远程系统会进行额外的访问检查。