Windows Access Control List (ACL) Example 28

 

 

 

 

Taking the Object Ownership Program Example

 

The following example tries to change the DACL of a file object by taking ownership of that object.  This will succeed only if the caller has WRITE_DAC access to the object or is the owner of the object.  If the initial attempt to change the DACL fails, an administrator can take ownership of the object.  To give the administrator ownership, the example enables the SE_TAKE_OWNERSHIP_NAME privilege in the caller's access token, and makes the local system's Administrators group the new owner of the object.  If the caller is a member of the Administrators group, the code will then be able to change the object's DACL.  Firstly we login as usergedik, a normal user.  Then we create a folder named UserGedikDir and verify the folder through the UserGedikDir property page as shown below.

 

Taking the Object Ownership Program Example: Viewing the owner of the file object

 

Taking the Object Ownership Program Example: The folder permission entries

 

The previous figure shows the property page for the UserGedikDir directory.  It is confirmed that it is created by normal user, usergedik.

 

Taking the Object Ownership Program Example: Viewing the directory owner from the folder property's page

 

The Advanced property page for the UserGedikDir directory shows that the file was created by normal user, usergedik which of course the owner. To make thing 'worse' we remove all the permissions except usergedik.

Un-tick the Inherit from parent the permission entries that apply to the child object. Include these with entries explicitly defined here tick box.

 

Taking the Object Ownership Program Example: Removing users other than the owner of the directory object (not to inherit)

 

Click Remove button for the following Security message box.

 

Taking the Object Ownership Program Example: The folder object security alert message when removing users other than the owner

 

Then, only user usergedik has the full control of the folder.

 

Taking the Object Ownership Program Example: Only the owner has the sole permission to the folder

 

Then, add the usergedik user for the permission.

 

Taking the Object Ownership Program Example: Adding the owner to the permission entries

 

Taking the Object Ownership Program Example: The owner is the sole owner of the folder with Full Control permission

 

Taking the Object Ownership Program Example: The Advanced Security Settings showing the sole directory owner in the permission entries

 

Then we log off and re login as Mike spoon, a user that is a member of Administrators group. Mike as Administrators group when trying to open (double click) the folder (owned solely by usergedik), was denied the access.

 

Taking the Object Ownership Program Example: Opening the folder is denied for other than the owner even the Administrators group

 

When opening the folder's property page, the following security alert should be displayed.

 

Taking the Object Ownership Program Example: The don't have permission alert security message

 

The Security page does not show any user. Click the Advanced button.

 

Taking the Object Ownership Program Example: Other than the owner, we can't see the permission entries

 

The Permission of the Advanced page also does not show any user or group.

 

Taking the Object Ownership Program Example: The details of the permission entries cannot be seen by other than the owner

 

The owner also cannot be displayed. All this thing happened because Administrators group (which include Mike spoon) has been denied the access to the folder.

 

Taking the Object Ownership Program Example: The owner also does not displayed for non-owner

 

Then, Mike spoon run the following program to take the ownership of the UserGedikDir and then modify the DACL by adding Everyone group can write and Administrators group with full control.

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

 

Taking the Object Ownership Program Example: Creating new Win32 C++ console application project

 

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

 

Taking the Object Ownership Program Example: Adding new C++ source file

 

Next, add the following source code.

 

// Taking object ownership

#include <windows.h>

#include <stdio.h>

#include <accctrl.h>

#include <aclapi.h>

 

//****** Cleanup routine *******

void Cleanup(PSID pSIDAdmin, PSID pSIDEveryone, PACL pACL, HANDLE hToken)

{

      if(pSIDAdmin)

            FreeSid(pSIDAdmin);

    if(pSIDEveryone)

        FreeSid(pSIDEveryone);

    if(pACL)

       LocalFree(pACL);

    if(hToken)

       CloseHandle(hToken);

}

 

//************ Enable/disable 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 = {0};

      LUID luid;

     

      if(!LookupPrivilegeValue(

            NULL,            // lookup privilege on local system

            lpszPrivilege,   // privilege to lookup

            &luid))          // receives LUID of privilege

      {

            wprintf(LLookupPrivilegeValue() failed, error %u\n, GetLastError());

            return FALSE;

      }

      else

            wprintf(LLookupPrivilegeValue() - %s privilege found!\n, lpszPrivilege);

     

      tp.PrivilegeCount = 1;

      tp.Privileges[0].Luid = luid;

     

      // Don't forget to disable the privilege after you enable them,

      // Change the bEnablePrivilege to TRUE or FALSE to enable or

      // disable the privilege respectively

      if(bEnablePrivilege)

      {

            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

            wprintf(LPrivilege was enabled!\n);

      }

      else

      {

            tp.Privileges[0].Attributes = 0;

            wprintf(LPrivilege was disabled!\n);

      }

     

      // Adjust the 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() - token privilege was adjusted!\n);

            return TRUE;

      }

}

 

//***** Take ownership routine ******

BOOL TakeOwnership(LPTSTR lpszDir)

{

      // Return value

    BOOL bRetval = FALSE;

    // Handle to token

    HANDLE hToken = NULL;

    // Pointer to SID for Administrators group

    PSID pSIDAdmin = NULL;

    // Pointer to SID for Everyone group

    PSID pSIDEveryone = NULL;

    // Pointer to access control list

    PACL pACL = NULL;

    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;

    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;

    const int NUM_ACCESS  = 2;

    // Explicit access arrays structure.  Here only two entries. Change the array size for more entries

    EXPLICIT_ACCESS ea[NUM_ACCESS];

    // Result

    DWORD dwRes;

 

    // Specify the DACL to use.  Allow write for Everyone and full

      // control for Administrators group. Create a SID for the Everyone group.

    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,

                     SECURITY_WORLD_RID,

                     0,

                     0, 0, 0, 0, 0, 0,

                     &pSIDEveryone))

      {

            wprintf(LAllocateAndInitializeSid() - Failed to allocate and initilize Everyone SID, error %u\n, GetLastError());

            Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

      }

      else

            wprintf(LAllocateAndInitializeSid() - Everyone SID was allocated and initialized!\n);

     

      // Create a SID for the BUILTIN\Administrators group.

      if(!AllocateAndInitializeSid(&SIDAuthNT, 2,

            SECURITY_BUILTIN_DOMAIN_RID,

            DOMAIN_ALIAS_RID_ADMINS,

            0, 0, 0, 0, 0, 0,

            &pSIDAdmin))

      {

            wprintf(LAllocateAndInitializeSid() - failed to allocate and initialize Administrators group SID, error %u\n, GetLastError());

            Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

      }

      else

            wprintf(LAllocateAndInitializeSid() - Administrators group SID was allocated and initialized!\n);

 

      SecureZeroMemory(&ea, NUM_ACCESS * sizeof(EXPLICIT_ACCESS));

    //***************** EXPLICIT ACCESS structure ******************

    // Construct the structure, add other entries as needed by

      // changing the array size. Set write access for Everyone.

    ea[0].grfAccessPermissions = GENERIC_WRITE;

    ea[0].grfAccessMode = SET_ACCESS;

    ea[0].grfInheritance = NO_INHERITANCE;

    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;

    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;

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

    // Set full control for Administrators.

    ea[1].grfAccessPermissions = GENERIC_ALL;

    ea[1].grfAccessMode = SET_ACCESS;

    ea[1].grfInheritance = NO_INHERITANCE;

    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;

    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;

    ea[1].Trustee.ptstrName = (LPTSTR) pSIDAdmin;

 

    //**************************************************************

    if(SetEntriesInAcl(NUM_ACCESS, ea, NULL, &pACL) != ERROR_SUCCESS)

    {

        wprintf(LSetEntriesInAcl() for Everyone and Administrators group failed, error %u\n, GetLastError());

        Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

    }

    else

       wprintf(LSetEntriesInAcl() for Everyone and Administrators group is OK\n);

    //***************************************************************

 

    // Try to modify the object's DACL.

    dwRes = SetNamedSecurityInfo(

        lpszDir,                   // name of the object

        SE_FILE_OBJECT,            // type of object, directory

        DACL_SECURITY_INFORMATION, // change only the object's DACL

        NULL, NULL,                // do not change owner or group

        pACL,                      // DACL specified

        NULL);                     // do not change SACL

 

    if(dwRes == ERROR_SUCCESS)

    {

            wprintf(LSetNamedSecurityInfo()-Modifying the DACL is OK!\n);

            // No more processing needed. Just return/exit

        bRetval = TRUE;

        Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

      }

      else if (dwRes == ERROR_ACCESS_DENIED)

      {

            wprintf(LSetNamedSecurityInfo()-Modifying the DACL failed! Error %u\n, dwRes);

            wprintf(LPlease get a proper permission!\n\n);

            // If the previous call failed because access was denied,

            // enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for

            // the Administrators group, take ownership of the object, and

            // disable the privilege. Then try again to set the object's DACL.

 

            //**********************************************************************

            // Open a handle to the access token for the calling process

            // that is the currently login access token

            if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))

            {

                  wprintf(LOpenProcessToken() failed, error %u\n, GetLastError());

                  Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

            }

            else

                  wprintf(LOpenProcessToken()-Got the handle to access token!\n);

            //**********************************************************************

           

            // Enable the SE_TAKE_OWNERSHIP_NAME privilege.

            if(!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))

            {

                  // Verify the login

                  wprintf(LYou must logged on as Administrator.\n);

                  wprintf(LSetPrivilege()-Enable the SE_TAKE_OWNERSHIP_NAME privilege failed, error %u\n, GetLastError());

                  Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

            }

            else

            {

                  wprintf(LYour login credential is fine!\n);

                  wprintf(LSetPrivilege()-The SE_TAKE_OWNERSHIP_NAME privilege was enabled!\n);

            }

           

            //*********************************************************************

            // Set the new owner in the object's security descriptor.

            dwRes = SetNamedSecurityInfo(

                  lpszDir,          // name of the object

                  SE_FILE_OBJECT,   // type of object

                  OWNER_SECURITY_INFORMATION,   // change only the object's owner

                  pSIDAdmin,        // SID of Administrator group

                  NULL,

                  NULL,

                  NULL);

           

            if(dwRes != ERROR_SUCCESS)

            {

                  wprintf(LSetNamedSecurityInfo()-Could not set the new owner, error: %u\n, dwRes);

                  Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

            }

            else

                  wprintf(LSetNamedSecurityInfo()-The owner was changed successfully!\n);

           

            //***********************************************************************

            // Try again to modify the object's DACL, now that we are the owner.

            dwRes = SetNamedSecurityInfo(

                  lpszDir,          // name of the object

                  SE_FILE_OBJECT,   // type of object

                  DACL_SECURITY_INFORMATION,    // change only the object's DACL

                  NULL, NULL,       // do not change owner or group

                  pACL,             // DACL specified

                  NULL);                  // do not change SACL

           

            if(dwRes == ERROR_SUCCESS)

            {

                  wprintf(LSetNamedSecurityInfo()-The DACL was successfully changed!\n);

                  bRetval = TRUE;

            }

            else

            {

                  wprintf(LSetNamedSecurityInfo()-Failed to change the DACL, error %u\n, dwRes);

            }

           

            //**********************************************************************

            // Verify that the SE_TAKE_OWNERSHIP_NAME privilege is disabled.

            if(SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))

            {

                  wprintf(LSetPrivilege()-The SE_TAKE_OWNERSHIP_NAME privilege was disabled!\n);

                  Cleanup(pSIDAdmin, pSIDEveryone, pACL, hToken);

            }

            else

            {

                  wprintf(LSetPrivilege()-Failed to disable the SE_TAKE_OWNERSHIP_NAME privilege!\n);

                  wprintf(LOr the privilege might be already disabled, error %u\n, GetLastError());

            }

      }

      return bRetval;

}

 

//***** wmain() *******

int wmain(int argc, WCHAR **argv)

{

       LPTSTR lpszDir = L\\\\?\\C:\\UserGedikDir;

        

         wprintf(L\n);

       BOOL bRetVal = TakeOwnership(lpszDir);

       wprintf(L\nTakeOwnership() returns %u\n\n, bRetVal);

 

       return 0;

}

 

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

 

Taking the Object Ownership Program Example: A sample working console output showing the flow of the program execution

 

Well, let verify through the UserGedikDir property page.  It seems that Mike spoon successfully accomplished his mission!

 

 

Taking the Object Ownership Program Example: Now we have Administrators group and Everyone who have taken the ownership of the folder

 

 

Taking the Object Ownership Program Example: The details of the permission entries showing the Everyone and Administrators group

 

Taking the Object Ownership Program Example: The new owner of the directory is Administrators group

 

 

 

< Windows ACL Example 27 | Windows Access Control List (ACL) Main | Win32 Programming | Windows ACL Example 29 >