Windows Access Control List (ACL) Example 32

 

 

 

 

Creating a Security Descriptor from Scratch for a New Object, a Registry key Code Example

 

The following example creates a security descriptor for a new registry key using the following steps. Similar code can be used to create a security descriptor for other object types.

The example fills an array of EXPLICIT_ACCESS structures with the information for two ACEs.  One ACE allows read access to everyone; the other ACE allows full access to administrators. The EXPLICIT_ACCESS array is passed to the SetEntriesInAcl() function to create a DACL for the security descriptor. After allocating memory for the security descriptor, the example calls the InitializeSecurityDescriptor() and SetSecurityDescriptorDacl() functions to initialize the security descriptor and attach the DACL. The security descriptor is then stored in a SECURITY_ATTRIBUTES structure and passed to the RegCreateKeyEx() function, which attaches the security descriptor to the newly created key.

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

 

Creating a Security Descriptor from Scratch for a New Object, a Registry key Code Example: Creating new console Win32 C++ empty console mode application

 

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

 

Creating a Security Descriptor from Scratch for a New Object, a Registry key Code Example: Adding new C++ source file for the C++ source code

 

Next, add the following source code.

 

// Creating a security descriptor for a new object, a registry key...

#include <windows.h>

#include <stdio.h>

#include <aclapi.h>

 

// Buffer clean up routine

void Cleanup(PSID pEveryoneSID, PSID pAdminSID, PACL pACL, PSECURITY_DESCRIPTOR pSD, HKEY hkSub)

{

      if(pEveryoneSID)

        FreeSid(pEveryoneSID);

    if(pAdminSID)

        FreeSid(pAdminSID);

    if(pACL)

        LocalFree(pACL);

    if(pSD)

        LocalFree(pSD);

    if(hkSub)

        RegCloseKey(hkSub);

}

 

int wmain(int argc, WCHAR **argv)

{

      DWORD dwRes, dwDisposition;

    PSID pEveryoneSID = NULL, pAdminSID = NULL;

    PACL pACL = NULL;

      PSECURITY_DESCRIPTOR pSD = {0};

    // An array of EXPLICIT_ACCESS structure

    EXPLICIT_ACCESS ea[2];

    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;

    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;

      SECURITY_ATTRIBUTES sa = {0};

    LONG lRes;

    HKEY hkSub = NULL;

 

    // Create a well-known SID for the Everyone group.

    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))

    {

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

            Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);

    }

    else

        wprintf(LSID for the Everyone group was allocated and initialized!\n);

 

    // Initialize an EXPLICIT_ACCESS structure for an ACE.

    // The ACE will allow Everyone read access to the key.

    ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));

    ea[0].grfAccessPermissions = KEY_READ;

    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) pEveryoneSID;

 

    // 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,

            &pAdminSID))

      {

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

        Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);

    }

    else

        wprintf(LSID for the BUILTIN\\Administrators group was allocated and initialized!\n);

 

    // Initialize an EXPLICIT_ACCESS structure for an ACE.

    // The ACE will allow the Administrators group full access to the key.

    ea[1].grfAccessPermissions = KEY_ALL_ACCESS;

    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) pAdminSID;

 

    // Create a new ACL that contains the new ACEs.

    dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);

    if(dwRes != ERROR_SUCCESS)

    {

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

        Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);

    }

    else

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

 

    // Initialize a security descriptor.

    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);

    if(pSD == NULL)

    {

        wprintf(LLocalAlloc() for pSD failed, error %u\n, GetLastError());

        Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);

    }

    else

            wprintf(LLocalAlloc() for pSD is OK!\n);

 

    if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))

    {

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

        Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);

    }

    else

       wprintf(LInitializeSecurityDescriptor() is pretty fine!\n);

 

    // Add the ACL to the security descriptor.

    if(!SetSecurityDescriptorDacl(pSD,

            TRUE,       // bDaclPresent flag

            pACL,

            FALSE))           // not a default DACL

    {

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

        Cleanup(pEveryoneSID, pAdminSID, pACL, pSD, hkSub);

    }

    else

       wprintf(LSetSecurityDescriptorDacl() is OK!\n);

 

    // Initialize a security attributes structure.

    sa.nLength = sizeof (SECURITY_ATTRIBUTES);

    sa.lpSecurityDescriptor = pSD;

    sa.bInheritHandle = FALSE;

    // Use the security attributes to set the security descriptor

      // when you create a registry key.

    lRes = RegCreateKeyEx(

            HKEY_CURRENT_USER,      // handle to an open key

            LMyTestRegKey// name of the subkey

            0,                            // Reserved

            L,                    // class or object type of this key, may be ignored

            0,                            // Options

            KEY_READ | KEY_WRITE, // Access right for the key

            &sa,                    // Pointer to security attribute structure,

                                          // can be inherited or not. NULL is not inherited

            &hkSub,                       // variable that receives a handle to the opened or created key

            &dwDisposition);  // variable that receives:

                                          // REG_CREATED_NEW_KEY - create new key (non-exist)

                                          // REG_OPENED_EXISTING_KEY - just open the existing key (already exist)

      // If successful

      if(lRes == 0)

      {

            wprintf(LThe value of the \'dwDisposition\': %u\n, dwDisposition);

            wprintf(LHKEY_CURRENT_USER\\MyTestRegKey successfully created.\n);

      }

      else

            wprintf(LCreating and opening HKEY_CURRENT_USER\\MyTestRegKey was failed, error %u.\n, GetLastError());

 

    return 0;

}

 

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

 

Creating a Security Descriptor from Scratch for a New Object, a Registry key Code Example: A sample console output showing the registry successfully created after having the required privilege

 

Then, let verify the result using the regedt32/regedit registry tool.

 

Creating a Security Descriptor from Scratch for a New Object, a Registry key Code Example: Verifying the creating registry key task after getting the privilege

 

Don’t forget to delete the registry key that has been created.

 

 

 

< Windows ACL Example 31 | Windows Access Control List (ACL) Main | Win32 Programming | Windows ACL Example 33 >