【发布时间】:2016-02-05 15:00:55
【问题描述】:
GetExplicitEntriesFromAcl Win32 API 函数允许检索文件 ACL 的显式条目。但是当我更改一些条目时,使用SetEntriesInAcl 将结果转换为新的ACL,最后使用SetSecurityInfo 将ACL 应用回文件,所有继承的条目似乎都丢失了,只剩下(更改的)显式条目。
是否有一个对应函数“SetExplicitEntriesInAcl”只替换 ACL 结构中的显式条目并保持继承的条目完整?
Edit1:代码示例
我正在使用类似于以下行的代码进行 ACL 更新:
int RemoveAclAccessRights( HANDLE hFile, PSID SidPtr,
DWORD AccessRights, ACCESS_MODE AccessMode )
{
PACL OldAcl = NULL, NewAcl = NULL;
PSECURITY_DESCRIPTOR SecDesc = NULL;
PEXPLICIT_ACCESS EntryList = NULL, EntryItem;
ULONG EntryCount, EntryIndex;
int r;
// Get a pointer to the existing DACL
r = GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
NULL, NULL, &OldAcl, NULL, &SecDesc);
if ( r != ERROR_SUCCESS )
goto _CleanUp;
r = GetExplicitEntriesFromAcl(OldAcl, &EntryCount, &EntryItem);
if ( r != ERROR_SUCCESS )
goto _CleanUp;
EntryList = EntryItem;
EntryIndex = 0;
while ( EntryIndex < EntryCount ) {
// ... update access entry ...
EntryIndex++;
EntryItem++;
}
// Create a new ACL from the explicit entries of the existing DACL
r = SetEntriesInAcl(EntryCount, EntryList, NULL, &NewAcl);
if ( r != ERROR_SUCCESS )
goto _CleanUp;
// Attach the new ACL as the object's DACL
r = SetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
NULL, NULL, NewAcl, NULL);
_CleanUp:
LocalFree(NewAcl);
LocalFree(EntryList);
LocalFree(SecDesc);
return r;
}
Edit2:文件和父目录的 ACL
文件上icacls的输出:
> icacls TestAcl01.txt
TestAcl01.txt VORDEFINIERT\Gäste:(R)
VORDEFINIERT\Administratoren:(I)(F)
NT-AUTORITÄT\SYSTEM:(I)(F)
NT-AUTORITÄT\Authentifizierte Benutzer:(I)(M)
VORDEFINIERT\Benutzer:(I)(RX)
父目录上icacls的输出:
> icacls .
. VORDEFINIERT\Administratoren:(I)(F)
VORDEFINIERT\Administratoren:(I)(OI)(CI)(IO)(F)
NT-AUTORITÄT\SYSTEM:(I)(F)
NT-AUTORITÄT\SYSTEM:(I)(OI)(CI)(IO)(F)
NT-AUTORITÄT\Authentifizierte Benutzer:(I)(M)
NT-AUTORITÄT\Authentifizierte Benutzer:(I)(OI)(CI)(IO)(M)
VORDEFINIERT\Benutzer:(I)(RX)
VORDEFINIERT\Benutzer:(I)(OI)(CI)(IO)(GR,GE)
该文件有一个明确的条目,即“VORDEFINIERT\Gäste:(R)”(SID“S-1-5-32-546”)。其他条目是从父目录继承的。
在上面的 while 循环中,如果显式条目与 SID 匹配,我会尝试使用类似的代码删除显式条目
if ( (EntryItem->Trustee.TrusteeForm == TRUSTEE_IS_SID) && EqualSid(EntryItem->Trustee.ptstrName, SidPtr) ) {
if ( EntryIndex < (EntryCount-1) )
MoveMemory(&EntryList[EntryIndex], &EntryList[EntryIndex+1], (EntryCount-EntryIndex-1)*sizeof(EntryList[0]));
EntryCount--;
continue;
}
【问题讨论】:
-
没有这样的功能,因为 ACE 的顺序很重要,并且系统无法猜测您希望现有继承的 ACE 出现的顺序,相对于您正在设置的显式条目。您需要指定所有 ACE,以便知道顺序。
-
Raymond 的观察在技术上是正确的(最好的那种!),但在这种情况下可能会产生误导。默认情况下,SetSecurityInfo 会将继承自父级的 ACE 添加到您指定的 ACL(使用首选顺序),但如果文件已被移动,则可能与最初继承的 ACE 不同。
-
... 所以您需要检查父目录是否具有您希望应用于文件的可继承 ACE,并且您没有指定 PROTECTED_DACL_SECURITY_INFORMATION 标志。如果这仍然不起作用,请显示您的代码,因为它对我来说非常有效。
-
@HarryJohnston:在我的测试中,继承的 ACE 仅由
SetSecurityInfo在处理目录时添加,而不是在处理文件时添加。 -
您是否检查过相关权限在父目录上是否标记为 (OI) 以及 (CI)?