Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GetExplicitEntriesFromAcl()Win32 API函数的对应项是什么?_C_Winapi_Acl - Fatal编程技术网

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

GetExplicitEntriesFromAcl()Win32 API函数的对应项是什么?,c,winapi,acl,C,Winapi,Acl,Win32 API函数允许检索文件ACL的显式条目。但是当我更改一些条目时,使用将结果转换为新的ACL,最后将ACL应用回文件,所有继承的条目似乎都丢失了,只剩下(更改的)显式条目 是否有一个对应函数“SetExplicientRiesInACL”只替换ACL结构中的显式条目,并保持继承条目的完整性 Edit1:代码示例 我在ACL更新中使用的代码与以下代码类似: int RemoveAclAccessRights( HANDLE hFile, PSID SidPtr, DWORD Acc

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

是否有一个对应函数“SetExplicientRiesInACL”只替换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;
}
父目录上的
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)
该文件有一个显式条目,即“vordineiert\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;
}
if((EntryItem->Trustee.TrusteeForm==Trustee_IS_SID)和&EqualSid(EntryItem->Trustee.ptstrName,SidPtr)){
如果(入口索引<(入口计数-1))
MoveMemory(&EntryList[EntryIndex],&EntryList[EntryIndex+1],(EntryCount-EntryIndex-1)*sizeof(EntryList[0]);
入口计数--;
继续;
}

以下代码似乎有效,但使用了
GetAclInformation
GetAce
而不是
GetExplicitEntriesFromAcl
,这需要进行指针类型检查,因此不太方便:

int UpdateAclAccessRights( HANDLE hFile, PSID SidPtr,
   DWORD AccessRights, ACCESS_MODE AccessMode )
{
   PACL DiscAcl = NULL;
   PSECURITY_DESCRIPTOR SecDesc = NULL;
   ACL_SIZE_INFORMATION AclSizeInfo;
   PACCESS_ALLOWED_ACE AceItem;
   int AceIndex;
   int r;

   // Get a pointer to the existing DACL
   r = GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
      NULL, NULL, &DiscAcl, NULL, &SecDesc);
   if ( r != ERROR_SUCCESS )
      goto _CleanUp;

   ZeroMemory(&AclSizeInfo, sizeof(AclSizeInfo));
   if (!GetAclInformation(DiscAcl, &AclSizeInfo, sizeof(AclSizeInfo), AclSizeInformation))
      goto _CleanUp;
   for (AceIndex = AclSizeInfo.AceCount-1; AceIndex >= 0; AceIndex--) {
      if (!GetAce(DiscAcl, AceIndex, &((void*)AceItem)))
         continue;
      if ( (AceItem->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) &&
           (AceItem->Header.AceType != ACCESS_DENIED_ACE_TYPE) )
         continue;  // entry pointer structure does not match AceItem
      if ( (AceItem->Header.AceFlags && INHERITED_ACE) > 0 )
         continue;  // not an explicit entry

      // ... update/delete access entry in case it matches SidPtr ...
   }

   // Attach updated ACL to the file object
   r = SetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
      NULL, NULL, DiscAcl, NULL);

   _CleanUp:
   LocalFree(SecDesc);

   return r;
}

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

事实证明,存在一个令人讨厌的(据我所知,是未记录的)陷阱:如果您向它传递一个零长度数组,它会以静默方式返回
NULL
作为新ACL,而不是像您合理预期的那样返回空ACL

的文档说明了在这种情况下发生的情况:

如果SecurityInfo参数的值包括DACL_SECURITY_信息标志,并且此参数的值设置为NULL,则将向所有人授予对对象的完全访问权限

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

解决此问题的一种方法:

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;

没有这样的函数,因为ACE的顺序很重要,系统无法猜测您希望现有继承的ACE相对于您正在设置的显式条目出现的顺序。您需要指定所有ACE,以便知道顺序。Raymond的观察在技术上是正确的(最好的!),但在这种情况下可能会产生误导。默认情况下,SetSecurityInfo将从父级向指定的ACL添加继承的ACE(使用首选顺序),但如果文件已移动,则可能与最初继承的ACE不同。。。。因此,您需要检查父目录是否具有您希望应用于文件的可继承ACE,并且您没有指定受保护的\u DACL\u SECURITY\u信息标志。如果仍然不起作用,请显示您的代码,因为它非常适合我。@HarryJohnston:在我的测试中,继承的ACE仅在处理目录时由
SetSecurityInfo
添加,而不是在处理文件时添加。您是否检查过在父目录上标记有问题的权限(OI)和(CI)?
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;