kevinwaite
kevinwaite

Reputation: 649

REVOKE_ACCESS : how to remove 'revoke' an inherited ACE?

I have the code below working for various ACE changes and adds and revoking - it just does NOT work when I try and remove an ACE that is in the ACL (clearly there), but this ACE is inherited.

The SetEntriesInAcl() for revoke of non-inherited ACEs works, reduces the ACL ACE count and the following SetNamedSecurityInfo() does the revoke and the ACE is gone.

When the ACE is inherited though - both these API return SUCCESS - but the ACE is not removed/revoked, the ACL ACE count remains the same.

I have also coded doing DeleteAce() but when that DACL is used in SetNamedSecurityInfo() again the RC is SUCCESS (no return codes) and the ACE remains for the folder I am dealing with - clearly there is a trick on how to remove an inherited ACE.

Btw, for the same folder in question SUBINACL command line tool does the revoke of this inherited ACE without problem.

                 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 */

Upvotes: 2

Views: 1861

Answers (1)

Harry Johnston
Harry Johnston

Reputation: 36318

At present it looks as if you are retrieving the existing ACL from the folder and modifying it. In your situation, you will be better off building a new ACL from scratch. To do this, build an array of EXPLICIT_ACCESS structures describing the permissions that you want, and call SetEntriesInAcl passing NULL for OldAcl.

To apply the new DACL, call SetNamedSecurityInfo in the same way you do in your code, but pass DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION for SecurityInfo. The PROTECTED_DACL_SECURITY_INFORMATION flag disables inheritance from the parent.

Upvotes: 1

Related Questions