Windows Access Control List (ACL) Example 19

 

 

 

 

 

Modifying Existing DACLs of an Object Program Example

 

The following example adds an ACE to the DACL of an existing object.  The AccessMode parameter, a member of the EXPLICIT_ACCESS structure determines the type of new ACE and how the new ACE is combined with any existing ACEs for the specified trustee. You can use the GRANT_ACCESS, SET_ACCESS, DENY_ACCESS, or REVOKE_ACCESS flags in the AccessMode parameter.  Similar code can be used to work with a SACL.  Specify SACL_SECURITY_INFORMATION in the GetNamedSecurityInfo() and SetNamedSecurityInfo() functions to get and set the SACL for the object.  Use the SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE, and REVOKE_ACCESS flags in the AccessMode parameter.  This code example can be used to add an object-specific ACE to the DACL of a directory service object.  To specify the GUIDs in an object-specific ACE, set the TrusteeForm parameter to TRUSTEE_IS_OBJECTS_AND_NAME or TRUSTEE_IS_OBJECTS_AND_SID and set the pszTrustee parameter to be a pointer to an OBJECTS_AND_NAME or OBJECTS_AND_SID structure.  This example uses the GetNamedSecurityInfo() function to get the existing DACL.  Then it fills an EXPLICIT_ACCESS structure with information about an ACE and uses the SetEntriesInAcl() function to merge the new ACE with any existing ACEs in the DACL.  Finally, the example calls the SetNamedSecurityInfo() function to attach the new DACL to the security descriptor of the object. The following figures are the NewDACLDir directory property pages before the program been run.

 

Modifying Existing DACLs of an Object Program Example: The Administrators group has Full Control

 

 

Modifying Existing DACLs of an Object Program Example: The permission entries of the folder

 

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

 

Modifying Existing DACLs of an Object Program Example: Creating new C++ console mode application project

 

Then, add the source file and give it a suitable name.

 

Modifying Existing DACLs of an Object Program Example: Adding new C++ source file and code

 

Next, add the following source code.

 

// Modifying DACL of an object. In ACL there are ACEs...

// Here we are going to add deny standard right

// access for Administrators group. This Win XP machine is

// logged in by user named Mike spoon who is a member of Administrators group

#include <windows.h>

#include <aclapi.h>

#include <stdio.h>

 

// Clean up the allocated resources

void Cleanup(PSECURITY_DESCRIPTOR pSD, PACL pNewDACL)

{

      if(pSD != NULL)

            LocalFree((HLOCAL) pSD);

      else

            wprintf(L"pSD freed up\n");

      if(pNewDACL != NULL)

            LocalFree((HLOCAL) pNewDACL);

      else

            wprintf(L"pNewDACL freed up\n");

}

 

int wmain(int argc, WCHAR **argv)

{

      // Name of object, here we will add ACE for a directory

      // the directory is already created

      LPTSTR pszObjName = L"\\\\?\\C:\\NewDACLDir";

      // Type of object, file or directory.  Here we test on directory

      SE_OBJECT_TYPE ObjectType = SE_FILE_OBJECT;

      // Access mask for new ACE equal to 0x001F0000 flags (bit 0 till 15)

      DWORD dwAccessRights = STANDARD_RIGHTS_ALL;

      // Type of ACE, Access denied ACE

      ACCESS_MODE AccessMode = DENY_ACCESS;

      // Inheritance flags for new the ACE. The OBJECT_INHERIT_ACE and

      // CONTAINER_INHERIT_ACE flags are

      // not propagated to an inherited ACE.

      DWORD dwInheritance = NO_PROPAGATE_INHERIT_ACE;

      // format of trustee structure, the trustee is name

      TRUSTEE_FORM TrusteeForm = TRUSTEE_IS_NAME;

     

      // Trustee for new ACE.  This just for fun...When you run once, only one

      // element will take effect.  By changing the first array element we

      // can change to other trustee and re run the program....

      // Other than Mike spoon, they are all well known trustees

      // Take note the localization issues

      WCHAR pszTrustee[4][15] = {L"Administrators", L"System", L"Users", L"Mike spoon"};

     

      // Result

      DWORD dwRes = 0;

      // Existing and new DACL pointers...

      PACL pOldDACL = NULL, pNewDACL = NULL;

      // Security descriptor

      PSECURITY_DESCRIPTOR pSD = NULL;

      SecureZeroMemory(&pSD, sizeof(PSECURITY_DESCRIPTOR));

      // EXPLICIT_ACCESS structure.  For more than one entries,

      // declare an array of the EXPLICIT_ACCESS structure

      EXPLICIT_ACCESS ea;

 

      // Verify the object name validity

      if(pszObjName == NULL)

      {

            wprintf(L"The object name is invalid!\n");

            return ERROR_INVALID_PARAMETER;

      }

      else

            wprintf(L"The object name is valid, \"%s\"\n", pszObjName);

     

      // Verify that our new trustee strings is OK

      for(int i = 0; i <= 3; i++)

            wprintf(L"Test pointer #%d: %s\n", i, pszTrustee[i]);

     

      // Get a pointer to the existing DACL.

      dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,

            DACL_SECURITY_INFORMATION,

            NULL,

            NULL,

            &pOldDACL,

            NULL,

            &pSD);

     

      // Verify

      if(dwRes != ERROR_SUCCESS)

      {

            wprintf(L"GetNamedSecurityInfo() failed, error %u\n", dwRes);

            Cleanup(pSD, pNewDACL);

      }

      else

            wprintf(L"GetNamedSecurityInfo() is OK\n");

     

      // Initialize an EXPLICIT_ACCESS structure for the new ACE.

      // For more entries, declare an array of the EXPLICIT_ACCESS structure

      SecureZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));

      ea.grfAccessPermissions = dwAccessRights;

      ea.grfAccessMode = AccessMode;

      ea.grfInheritance= dwInheritance;

      ea.Trustee.TrusteeForm = TrusteeForm;

     

      // Test for Administrators group, a new trustee for the ACE

      // For other trustees, you can try changing

      // the array index to 1, 2 and 3 and rerun, see the effect

      ea.Trustee.ptstrName = (LPTSTR)(pszTrustee[0]);

     

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

      dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);

     

      //  Verify

      if(dwRes != ERROR_SUCCESS)

      {

            wprintf(L"SetEntriesInAcl() failed, error %u\n", dwRes);

            Cleanup(pSD, pNewDACL);

      }

      else

            wprintf(L"SetEntriesInAcl() working fine!\n");

     

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

      dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,

            DACL_SECURITY_INFORMATION,

            NULL,

            NULL,

            pNewDACL,

            NULL);

     

      if(dwRes != ERROR_SUCCESS)

      {

            wprintf(L"SetNamedSecurityInfo() failed, error %u\n", dwRes);

            Cleanup(pSD, pNewDACL);

      }

      wprintf(L"SetNamedSecurityInfo() is OK\n");

      return 0;

}

 

Build and run the project. The following screenshot is a sample output.

 

Modifying Existing DACLs of an Object Program Example: Sample console program output

 

Then verify through the C:\NewDACLDir directory property pages again.

 

Modifying Existing DACLs of an Object Program Example: Access denied for Administrators group

 

Under the Permission for Administrators group, the Special Permissions is ticked for the Deny permission.  Keep in mind that Deny overrides the Allow permission.  The following figure also confirmed that our new ACE for the Deny is not inherited.

 

Modifying Existing DACLs of an Object Program Example: The advanced security settings also show the Administrators group was denied access

 

Remember that, DENY overwrites ALLOW permission.  For this case because Mike spoon is a member of the Administrators group, however he cannot delete or open the C:\\NewDACLDir directory.  We have to log off and login again as other Administrators group user or create another user that is a member of Administrators or take the object’s ownership or just edit the permission entries (shown at the end of this section).  When we try to delete the folder, the following message was displayed. Well, it funny isn’t it? A user of Administrators group cannot delete/open his/her own folder.

 

Modifying Existing DACLs of an Object Program Example: Administrators group member cannot delete a folder

 

It is same when we want to open the folder, it is not accessible.

 

Modifying Existing DACLs of an Object Program Example: Administrators group member cannot access the folder

 

So, whatever it is, please don’t mess up your machine. The following steps show how to re-enable the Full Control for Administrators group.

 

Modifying Existing DACLs of an Object Program Example: Re-enabling the Administrators group Full Control permission on a folder

 

Modifying Existing DACLs of an Object Program Example: Administrators group with full control access on a folder

 

 

 

 

< Windows ACL Example 18 | Windows Access Control List (ACL) Main | Win32 Programming | Windows ACL Example 20 >