Privilege and SACL Program Example
In the following example we will try to enable a privilege that needed in order to set the SACL using the same program example. First of all let create the PrivilegeSACLDir directory and verify the Auditing from property page (should be none).
Then execute the following program which is a modified previously created program.
Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.
Then, add the source file and give it a suitable name.
Next, add the following source code.
// In this program we are going to
// add Allow standard right access and set an ACE for SACL.
// This Win XP machine is logged in by user named Mike spoon
// who is a member of Administrators group...
// To access a SACL using the GetNamedSecurityInfo()
// or SetNamedSecurityInfo() functions, you have to enable
// the SE_SECURITY_NAME privilege
#include <windows.h>
#include <aclapi.h>
#include <stdio.h>
//********* Enabling/Disabling the privilege *********
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable (or disable privilege)
)
{
TOKEN_PRIVILEGES tp;
// Used by local system to identify the privilege
LUID luid;
if(!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
wprintf(LLookupPrivilegeValue() failed to find %s privilege, error: %u\n, lpszPrivilege, GetLastError());
return FALSE;
}
else
wprintf(LLookupPrivilegeValue() is OK - Privilege \%s\ was found!\n, lpszPrivilege);
// Set the privilege count
tp.PrivilegeCount = 1;
// Assign luid to the first count
tp.Privileges[0].Luid = luid;
// If TRUE
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
wprintf(L\%s\ privilege successfully enabled!\n, lpszPrivilege);
}
else
{
tp.Privileges[0].Attributes = 0;
wprintf(L\%s\ privilege successfully disabled!\n, lpszPrivilege);
}
// Adjust to the new privilege
if(!AdjustTokenPrivileges(
hToken,
FALSE, // If TRUE, function disables all privileges,
// if FALSE the function modifies privileges based on the tp
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
wprintf(LAdjustTokenPrivileges() failed, error: %u\n, GetLastError());
return FALSE;
}
else
{
wprintf(LAdjustTokenPrivileges() - Privilege token was adjusted successfully!\n);
}
return TRUE;
}
//************** Clean up routine ***************
void Cleanup(PSECURITY_DESCRIPTOR pSS, PACL pNewSACL)
{
if(pSS != NULL)
LocalFree((HLOCAL) pSS);
else
wprintf(LpSS was freed-up\n);
if(pNewSACL != NULL)
LocalFree((HLOCAL) pNewSACL);
else
wprintf(LpNewSACL was freed-up\n);
}
//******** The main() **********
int main(int argc, WCHAR **argv)
{
// Name of object, here we will add an ACE for a directory
LPTSTR pszObjName = LC:\\PrivilegeSACLDir;
// Ttype of object, file or directory, a directory
SE_OBJECT_TYPE ObjectType = SE_FILE_OBJECT;
// Access mask for new ACE equal to 0X11000000 - GENERIC_ALL and ACCESS_SYSTEM_SECURITY
DWORD dwAccessRights = 0X11000000;
// ACCESS_MODE AccessMode = SET_AUDIT_FAILURE;
// Type of ACE, set audit for success
ACCESS_MODE AccessMode = SET_AUDIT_SUCCESS;
// Inheritance flags for new 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;
// The needed privilege
LPCTSTR lpszPrivilege = LSeSecurityPrivilege;
// The new trustee for the ACE is set to Mike spoon,
// a normal user of Administrators group
LPTSTR pszTrustee = LMike spoon;
// Result
DWORD dwRes = 0;
// Existing and new SACL pointers...
PACL pOldSACL = NULL, pNewSACL = NULL;
// Security descriptor
PSECURITY_DESCRIPTOR pSS = NULL;
// EXPLICIT_ACCESS structure
EXPLICIT_ACCESS ea;
// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
// Handle to the running process that is this (running) program
HANDLE hToken;
BOOL bRetVal = FALSE;
// Verify the object name validity
if(pszObjName == NULL)
{
wprintf(LThe object name is invalid, error %u\n, GetLastError());
return ERROR_INVALID_PARAMETER;
}
else
wprintf(LThe object name is valid\n);
//*************** Get the handle to the process ********************
// Open a handle to the access token for the calling process
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
wprintf(LOpenProcessToken() failed, error %u\n, GetLastError());
return 1;
}
else
wprintf(LOpenProcessToken() is OK, got the handle!\n);
//******* Enabling privilege ********
// Call the user defined SetPrivilege() function to enable privilege
bRetVal = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
// Verify
if(!bRetVal)
{
wprintf(LFailed to enable the privilege, error %u\n\n, GetLastError());
return 1;
}
else
wprintf(LPrivilege was successfully enabled!\n\n);
//******* End enabling privilege ********
// By assuming that we have enabled the required privilege,
// accomplish our task. Here, get a pointer to the existing SACL
dwRes = GetNamedSecurityInfo(pszObjName,
ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL,
&pOldSACL, &pSS);
// Verify
if(dwRes != ERROR_SUCCESS)
{
wprintf(LGetNamedSecurityInfo() failed, error %u\n, dwRes);
Cleanup(pSS, pNewSACL);
return 1;
}
else
wprintf(LGetNamedSecurityInfo() is OK!\n);
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
// For more ACE 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;
// Other structure elements that might be needed...
// ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
// ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
// The trustee is Mike spoon
ea.Trustee.ptstrName = pszTrustee;
// Create a new ACL that merges the new ACE into the existing ACL.
dwRes = SetEntriesInAcl(1, &ea, pOldSACL, &pNewSACL);
if(dwRes != ERROR_SUCCESS)
{
wprintf(LSetEntriesInAcl() failed, error %u\n, dwRes);
Cleanup(pSS, pNewSACL);
return 1;
}
else
wprintf(LSetEntriesInAcl() - ACL was successfully merged!\n);
// Attach the new ACL as the object's SACL.
dwRes = SetNamedSecurityInfo(pszObjName,
ObjectType,
SACL_SECURITY_INFORMATION,
NULL, NULL, NULL,
pNewSACL);
if(dwRes != ERROR_SUCCESS)
{
wprintf(LSetNamedSecurityInfo() failed, error %u\n, dwRes);
Cleanup(pSS, pNewSACL);
return 1;
}
else
wprintf(LSetNamedSecurityInfo() - New ACE/SACL was successfully set!\n\n);
// Disable the privilege
//****************** Disabling privilege *******************
bEnablePrivilege = FALSE;
bRetVal = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
// Verify
if(!bRetVal)
{
wprintf(L\nFailed to disable the privilege, error %u\n, GetLastError());
return 1;
}
else
wprintf(L\nPrivilege was successfully disabled!\n);
//****************** End disabling privilege ***************
// Close the process handle by calling the CloseHandle(hToken)
CloseHandle(hToken);
return 0;
}
Build and run the project. The following screenshot is a sample output.
Well, it seems that we have enabled the privilege successfully and set the SACL. Let verify through the PrivilegeSACLDir directory property, the Advanced Security Settings property page.