Modifying Existing DACLs of an Object Program Example
// 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.
Then verify through the C:\NewDACLDir directory property pages again.
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.
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.
It is same when we want to open the folder, it is not accessible.
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.