Question

I have an interesting issue that I'm hoping someone can shed some light on. We are doing the following:

  1. Create a registry key.
  2. Add an ACCESS_ALLOWED_ACE to the DACL using SetSecurityDescriptorDacl.
  3. View key in Regedit (permissions look fine)
  4. In Regedit, add a new sub key.
  5. View permissions of sub key.

Regedit reports that the permissions are not ordered correctly (and appears to have added a couple of unexpected permissions).

However.

If you create the first key in Regedit rather than programmatically, and then repeat steps 3-5, the sub key is created correctly.

Using some additional code (not included below) I have compared the DACL from the Regedit created key, and from the key created programmatically, and they are identical. But it seems if you create the key via code then something is wrong.

Below is some example code that creates the key and modifies the access. It is basically a MSDN example, just tweaked to modify a registry key. Again, it creates the key correctly, but sub keys are not correct.

Any clues would be greatly appreciated.

#include "stdafx.h"
#include <Windows.h>
#include <Sddl.h>

BOOL AddAceToKey(HKEY hKey, PSID psid)
{
   ACCESS_ALLOWED_ACE   *pace = NULL;
   ACL_SIZE_INFORMATION aclSizeInfo;
   BOOL                 bDaclExist;
   BOOL                 bDaclPresent;
   BOOL                 bSuccess = FALSE;
   DWORD                dwNewAclSize;
   DWORD                dwSidSize = 0;
   DWORD                dwSdSizeNeeded = 0;
   PACL                 pacl;
   PACL                 pNewAcl = NULL;
   PSECURITY_DESCRIPTOR psd = NULL;
   PSECURITY_DESCRIPTOR psdNew = NULL;
   PVOID                pTempAce;
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
   unsigned int         i;

   __try
   {
      // Obtain the DACL for the key.

       LONG lResult = RegGetKeySecurity
        ( hKey
        , si
        , 0
        , &dwSdSizeNeeded
        );

      if ( lResult != ERROR_SUCCESS )
      if ( lResult == ERROR_INSUFFICIENT_BUFFER)
      {
         psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
               GetProcessHeap(),
               HEAP_ZERO_MEMORY,
               dwSdSizeNeeded);

         if (psd == NULL)
            __leave;

         psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
               GetProcessHeap(),
               HEAP_ZERO_MEMORY,
               dwSdSizeNeeded);

         if (psdNew == NULL)
            __leave;

         dwSidSize = dwSdSizeNeeded;

         if (RegGetKeySecurity(
               hKey,
               si,
               psd,
               &dwSdSizeNeeded) != ERROR_SUCCESS
         )
            __leave;
      }
      else
         __leave;

      // Create a new DACL.

      if (!InitializeSecurityDescriptor(
            psdNew,
            SECURITY_DESCRIPTOR_REVISION)
      )
         __leave;

      // Get the DACL from the security descriptor.

      if (!GetSecurityDescriptorDacl(
            psd,
            &bDaclPresent,
            &pacl,
            &bDaclExist)
      )
         __leave;

      // Initialize the ACL.

      ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
      aclSizeInfo.AclBytesInUse = sizeof(ACL);

      // Call only if the DACL is not NULL.

      if (pacl != NULL)
      {
         // get the file ACL size info
         if (!GetAclInformation(
               pacl,
               (LPVOID)&aclSizeInfo,
               sizeof(ACL_SIZE_INFORMATION),
               AclSizeInformation)
         )
            __leave;
      }

      // Compute the size of the new ACL.

      dwNewAclSize = aclSizeInfo.AclBytesInUse +
            sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD);

      // Allocate memory for the new ACL.

      pNewAcl = (PACL)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            dwNewAclSize);

      if (pNewAcl == NULL)
         __leave;

      // Initialize the new DACL.

      if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
         __leave;

      // Add the ACE to the key

      pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
                  sizeof(DWORD));

      if (pace == NULL)
         __leave;

      pace->Header.AceType  = ACCESS_ALLOWED_ACE_TYPE;
      pace->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
      pace->Header.AceSize  = LOWORD(sizeof(ACCESS_ALLOWED_ACE) +
                   GetLengthSid(psid) - sizeof(DWORD));
      pace->Mask            = KEY_ALL_ACCESS;

      if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
         __leave;

      if (!AddAce(
            pNewAcl,
            ACL_REVISION,
            MAXDWORD,
            (LPVOID)pace,
            pace->Header.AceSize)
      )
         __leave;

      // If DACL is present, copy it to a new DACL.

      if (bDaclPresent)
      {
         // Copy the ACEs to the new ACL.
         if (aclSizeInfo.AceCount)
         {
            for (i=0; i < aclSizeInfo.AceCount; i++)
            {
               // Get an ACE.
               if (!GetAce(pacl, i, &pTempAce))
                  __leave;

               // Add the ACE to the new ACL.
               if (!AddAce(
                     pNewAcl,
                     ACL_REVISION,
                     MAXDWORD,
                     pTempAce,
                    ((PACE_HEADER)pTempAce)->AceSize)
               )
                  __leave;
            }
         }
      }

      // Set a new DACL for the security descriptor.

      if (!SetSecurityDescriptorDacl(
            psdNew,
            TRUE,
            pNewAcl,
            FALSE)
      )
         __leave;

      // Set the new security descriptor for the window station.

      if (RegSetKeySecurity( hKey, si, psdNew ) != ERROR_SUCCESS)
         __leave;

      // Indicate success.

      bSuccess = TRUE;
   }
   __finally
   {
      // Free the allocated buffers.

      if (pace != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)pace);

      if (pNewAcl != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);

      if (psd != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)psd);

      if (psdNew != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
   }

   return bSuccess;

}

int _tmain(int argc, _TCHAR* argv[])
{
    HKEY hKey;
    DWORD dwDisposition;

    LONG lResult = RegCreateKeyEx
        ( HKEY_LOCAL_MACHINE
        , L"SOFTWARE\\MyCompany"
        , 0
        , NULL
        , REG_OPTION_NON_VOLATILE
        , KEY_ALL_ACCESS | KEY_WOW64_64KEY
        , NULL
        , &hKey
        , &dwDisposition
        );

    if ( lResult != ERROR_SUCCESS )
    {
        return 1;
    }

    PSID pSid;

    // The 'Users' SID.
    ConvertStringSidToSid( L"S-1-5-32-545", &pSid );

    AddAceToKey( hKey, pSid );

    LocalFree( pSid );

    RegCloseKey( hKey );

    return 0;
}

No correct solution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top