c - GetExplicitEntriesFromAcl() Win32 API 函数的对应函数是什么?

标签 c winapi acl

GetExplicitEntriesFromAcl Win32 API 函数允许检索文件 ACL 的显式条目。但是当我更改一些条目时,使用 SetEntriesInAcl 将结果转换为新的 ACL最后将 ACL 应用回文件 SetSecurityInfo所有继承的条目似乎都丢失了,只留下(更改的)显式条目。

是否有一个对应函数“SetExplicitEntriesInAcl”,仅替换 ACL 结构中的显式条目并保持继承的条目完整?

编辑1:代码示例

我使用类似于以下几行的代码进行 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;
}

编辑2:文件和父目录的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;
}

最佳答案

根据最新编辑中的信息,我现在可以复制您的问题。仅当您从 DACL 中删除所有显式条目时才会发生这种情况。

事实证明 SetEntriesInAcl 中有一个令人讨厌的(据我所知,没有记录的)陷阱。 :如果您向其传递零长度数组,它会默默地返回 NULL 作为新 ACL,而不是像您合理预期的那样返回空 ACL。

SetSecurityInfo 的文档解释了在这种情况下会发生什么:

If the value of the SecurityInfo parameter includes the DACL_SECURITY_INFORMATION flag and the value of this parameter is set to NULL, full access to the object is granted to everyone.

这会隐式删除继承的权限(无论如何都是多余的)。

解决问题的一种方法:

ACL empty_acl;
if (!InitializeAcl(&empty_acl, sizeof(empty_acl), ACL_REVISION)) 
    goto _CleanUp;

// Create a new ACL from the explicit entries of the existing DACL
r = SetEntriesInAcl(EntryCount, EntryList, &empty_acl, &NewAcl);
if ( r != ERROR_SUCCESS )
    goto _CleanUp;

关于c - GetExplicitEntriesFromAcl() Win32 API 函数的对应函数是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35227184/

相关文章:

c++ - 如何使用 Windows API 正确检查对文件的有效读/写访问?

cakephp - ACL,ARO和ACO,如果有新的部分如何更新它们?

apache-kafka - 如何授权 ACL 中某个主题的每个组

c - execvp() 不处理写入输出 >filename.log

c - 反转数组(不使用第二个数组)

c++ - DeleteIPAddress 和 AddIpAddress 问题

c# - 如何制作可在 C# 应用程序中引用的 Win32 DLL?

c++ - 如何在更改形状坐标时重新绘制窗口?

c - 组织数字直到输入 0 0 0

c - C中getopt的错误处理