I have a function that can deny FILE_EXECUTE
right in the file's DACL. To deny FILE_EXECUTE
right, I call the function like this (see full code in the main function):
AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);
After I deny the FILE_EXECUTE
permission, I want to undo that operation. In other words, I want to remove from the DACL the entry that FILE_EXECUTE
was denied.
What is the correct way to do this?
To run my code, set the variable trusteeSID
to the correct value and the variable objectName
to the correct path to the file
#include <aclapi.h>
#include <windows.h>
#include <stdio.h>
#include <iostream>
DWORD AddAceToObjectsSecurityDescriptor(
LPTSTR pszObjName, // name of object
SE_OBJECT_TYPE ObjectType, // type of object
LPTSTR pszTrustee, // trustee for new ACE
TRUSTEE_FORM TrusteeForm, // format of trustee structure
DWORD dwAccessRights, // access mask for new ACE
ACCESS_MODE AccessMode, // type of ACE
DWORD dwInheritance // inheritance flags for new ACE
)
{
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea;
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
// Get a pointer to the existing DACL.
dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);
if (ERROR_SUCCESS != dwRes) {
printf("GetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance = dwInheritance;
ea.Trustee.TrusteeForm = TrusteeForm;
ea.Trustee.ptstrName = pszTrustee;
// Create a new ACL that merges the new ACE
// into the existing DACL.
dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
goto Cleanup;
}
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwRes) {
printf("SetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
Cleanup:
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
return dwRes;
}
#include <sddl.h>
int main()
{
wchar_t objectName[] = L"C:\\Users\\Username\\Desktop\\acl.txt";
wchar_t trusteeSID[] = L"S-1-5-21-#-#-#-#";
PSID pSid;
if (!ConvertStringSidToSid(trusteeSID, &pSid)) {
std::cout << "ConvertStringSidToSid failed\n";
return 0;
}
AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);
}
I have a function that can deny FILE_EXECUTE
right in the file's DACL. To deny FILE_EXECUTE
right, I call the function like this (see full code in the main function):
AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);
After I deny the FILE_EXECUTE
permission, I want to undo that operation. In other words, I want to remove from the DACL the entry that FILE_EXECUTE
was denied.
What is the correct way to do this?
To run my code, set the variable trusteeSID
to the correct value and the variable objectName
to the correct path to the file
#include <aclapi.h>
#include <windows.h>
#include <stdio.h>
#include <iostream>
DWORD AddAceToObjectsSecurityDescriptor(
LPTSTR pszObjName, // name of object
SE_OBJECT_TYPE ObjectType, // type of object
LPTSTR pszTrustee, // trustee for new ACE
TRUSTEE_FORM TrusteeForm, // format of trustee structure
DWORD dwAccessRights, // access mask for new ACE
ACCESS_MODE AccessMode, // type of ACE
DWORD dwInheritance // inheritance flags for new ACE
)
{
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea;
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
// Get a pointer to the existing DACL.
dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);
if (ERROR_SUCCESS != dwRes) {
printf("GetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance = dwInheritance;
ea.Trustee.TrusteeForm = TrusteeForm;
ea.Trustee.ptstrName = pszTrustee;
// Create a new ACL that merges the new ACE
// into the existing DACL.
dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
goto Cleanup;
}
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwRes) {
printf("SetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
Cleanup:
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
return dwRes;
}
#include <sddl.h>
int main()
{
wchar_t objectName[] = L"C:\\Users\\Username\\Desktop\\acl.txt";
wchar_t trusteeSID[] = L"S-1-5-21-#-#-#-#";
PSID pSid;
if (!ConvertStringSidToSid(trusteeSID, &pSid)) {
std::cout << "ConvertStringSidToSid failed\n";
return 0;
}
AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);
}
Share
Improve this question
asked Mar 3 at 17:44
Joe JJoe J
4839 bronze badges
1
- direct remove ace entry from acl – RbMm Commented Mar 3 at 19:40
1 Answer
Reset to default 1really only way here manual parse ACL and remove some ACE.
as example such function add/remove ACCESS_DENIED_ACE
with concrete SID
and FILE_EXECUTE
access
extern volatile const UCHAR guz = 0;
ULONG AddRemoveAce(PCWSTR lpFileName, PSID Sid, BOOL bSet)
{
UNICODE_STRING ObjectName;
NTSTATUS status = RtlDosPathNameToNtPathName_U_WithStatus(lpFileName, &ObjectName, 0, 0);
if (0 <= status)
{
HANDLE hFile;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
IO_STATUS_BLOCK iosb;
status = NtOpenFile(&hFile, READ_CONTROL|WRITE_DAC, &oa, &iosb, 0, FILE_OPEN_REPARSE_POINT);
RtlFreeUnicodeString(&ObjectName);
if (0 <= status)
{
PVOID stack = alloca(guz);
ULONG cb = 0, rcb = 0x100;
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(SecurityDescriptor = alloca(rcb - cb), stack);
}
status = NtQuerySecurityObject(hFile, DACL_SECURITY_INFORMATION, SecurityDescriptor, cb, &rcb);
} while (STATUS_BUFFER_TOO_SMALL == status);
PACL Dacl;
BOOLEAN bPresent, bDefault;
if (0 <= status && 0 <= (status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &bPresent, &Dacl, &bDefault)))
{
if (bPresent && Dacl)
{
SECURITY_DESCRIPTOR sd = {
SECURITY_DESCRIPTOR_REVISION, 0, SE_DACL_PRESENT
};
if (bSet)
{
EXPLICIT_ACCESS ea = {
FILE_EXECUTE,
DENY_ACCESS,
NO_INHERITANCE,
{0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_UNKNOWN, (PWSTR)Sid }
};
bPresent = (NOERROR == (status = SetEntriesInAcl(1, &ea, Dacl, &sd.Dacl)));
SecurityDescriptor = &sd;
}
else
{
if (ULONG AceCount = Dacl->AceCount)
{
bPresent = FALSE;
union {
PACE_HEADER pah;
PVOID pv;
PACCESS_DENIED_ACE pada;
ULONG_PTR up;
};
pv = Dacl + 1;
union {
PACE_HEADER pah_new;
ULONG_PTR up_new;
};
pah_new = pah;
do
{
USHORT AceSize = pah->AceSize;
if (ACCESS_DENIED_ACE_TYPE == pah->AceType &&
FILE_EXECUTE == pada->Mask &&
RtlEqualSid(&pada->SidStart, Sid))
{
Dacl->AceCount--;
Dacl->AclSize -= AceSize;
bPresent = TRUE;
}
else
{
if (pah_new != pah)
{
memcpy(pah_new, pah, AceSize);
up_new += AceSize;
}
}
up += AceSize;
} while (--AceCount);
}
}
if (bPresent)
{
status = NtSetSecurityObject(hFile, DACL_SECURITY_INFORMATION, SecurityDescriptor);
}
if (sd.Dacl)
{
LocalFree(sd.Dacl);
}
}
}
NtClose(hFile);
}
}
return status;
}