【问题标题】:REVOKE_ACCESS : how to remove 'revoke' an inherited ACE?REVOKE_ACCESS:如何删除“撤销”继承的 ACE?
【发布时间】:2012-02-21 04:41:54
【问题描述】:

下面的代码适用于各种 ACE 更改以及添加和撤销 - 当我尝试删除 ACL 中的 ACE(显然存在)时它不起作用,但这个 ACE 是继承的。

用于撤销非继承 ACE 的 SetEntriesInAcl() 有效,减少了 ACL ACE 计数,随后的 SetNamedSecurityInfo() 执行撤销并且 ACE 消失了。

当 ACE 被继承时 - 这两个 API 返回 SUCCESS - 但 ACE 未被删除/撤销,ACL ACE 计数保持不变。

我还编写了 DeleteAce() 的代码,但是当在 SetNamedSecurityInfo() 中再次使用该 DACL 时,RC 为 SUCCESS(无返回码)并且 ACE 保留在我正在处理的文件夹中 - 显然有一个技巧关于如何删除继承的 ACE。

顺便说一句,对于有问题的同一个文件夹,SUBINACL 命令行工具可以毫无问题地撤销这个继承的 ACE。

                 if( EqualSid( pSid_for_ace, pSid )  )
                    { /* ACE SID matched edit SID */

                    if( cmd_se_edit == SE_REM )
                       { /* remove */

                       rem_lst[ ace_idx ] = x;

                       exp_ace[ ace_idx ].grfAccessPermissions = dwAccessRights;
                       exp_ace[ ace_idx ].grfAccessMode        = REVOKE_ACCESS;
                       exp_ace[ ace_idx ].grfInheritance       = dwInheritance;
                       exp_ace[ ace_idx ].Trustee.TrusteeForm  = TRUSTEE_IS_SID;
                       exp_ace[ ace_idx ].Trustee.TrusteeType  = TRUSTEE_IS_WELL_KNOWN_GROUP;
                       exp_ace[ ace_idx ].Trustee.ptstrName    = pSid;

                       if( ace_idx < (REMMAX-1) ) ++ace_idx;

                       } /* remove */

                    } /* ACE SID matched edit SID */

              pBA = (BYTE *)p_aceHdr;

              ace_sz = p_aceHdr->AceSize;

              p_aceHdr = (PACE_HEADER)&pBA[ ace_sz ];

              } /* loop through ACEs */


           // Create a new ACL that merges the new ACE
           // into the existing DACL.

           if( ace_idx )
              { /* ACEs to remove */

              dwRes = SetEntriesInAcl( ace_idx, &exp_ace[0],
                                                        pDacl, &pNewDacl );
              if( ERROR_SUCCESS != dwRes )
                 {
                 printf( "SetEntriesInAcl Error %u\n", dwRes );
                 goto Cleanup2;
                 }

              // Attach the new ACL as the object's DACL.

              dwRes = SetNamedSecurityInfo(    ObjName,
                                               ObjectType,
                                               DACL_SECURITY_INFORMATION,
                                               NULL,
                                               NULL,
                                              pNewDacl,
                                               NULL );

              if( ERROR_SUCCESS != dwRes )
                 {
                 rc3 = GetLastError();
                 printf( "SetNamedSecurityInfo Error %u\n", dwRes );
                 goto Cleanup2;
                 }

              } /* ACEs to remove */

【问题讨论】:

  • 访问权限掩码和继承设置与被撤销的 ACE 相同 - 根据 MS 指南(我找到的唯一指南。) - 使用上述代码设置此 ACE 会生成一个匹配的新 ACE我设置的内容——但原始继承的 ACE 仍然存在——该测试的 ACL 增加了 1——然后该测试 ACE 的撤销正常工作——原始继承的 ACE 再次保留。
  • 删除继承的 ACE 会破坏 ACL 的规则。高级 API 不允许您这样做;低级 API 会,但你不应该。相反,请关闭目标对象的继承并复制您想要保留的那些 ACE,或者考虑改用拒绝条目。
  • 感谢 Harry - 以编程方式(通过 API)如何关闭目标对象的继承? - 我无法做到这一点(grrr).....一旦关闭继承 - 我知道如何复制 ACE - 在你的评论中你说复制我希望保留的 ACE - 将它们复制到哪里?一旦到了那里,您如何将它们放回“文件夹的”安全描述符-我知道一些API可以做到这一点-我很好奇您的想法/见解....再次感谢凯文·韦特(Kevin Waite)
  • 我的第一个目标是在根目录下创建一个文件夹,类似于“c:\program files”,将其命名为“c:\ti001”——我的第二个目标是调用两个组my_admins 和 my_users——我希望“c:\ti001”文件夹将这些组添加到其 ACL 中......首先要做的事情——需要删除“经过身份验证的用户”
  • 新文件夹是否需要从其父文件夹继承其他(未知)权限,或者您是否已经确切知道您希望该文件夹拥有哪些权限?

标签: windows acl file-permissions


【解决方案1】:

目前,您似乎正在从文件夹中检索现有 ACL 并对其进行修改。在您的情况下,您最好从头开始构建新的 ACL。为此,请构建一个 EXPLICIT_ACCESS 结构数组来描述您想要的权限,然后调用 SetEntriesInAcl 为 OldAcl 传递 NULL。

要应用新的 DACL,请以与您在代码中相同的方式调用 SetNamedSecurityInfo,但将 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION 传递给 SecurityInfo。 PROTECTED_DACL_SECURITY_INFORMATION 标志禁用从父级继承。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 2019-10-07
  • 2018-02-11
  • 2021-05-19
  • 2018-05-21
  • 2013-09-29
相关资源
最近更新 更多