Getting the ACE Order Right

Getting the ACE Order Right

I've already touched on getting the ACE ordering correct in the ACL. If you use the Windows ACL dialog boxes, the operating system will always order ACEs correctly. However, you do not have this luxury when writing code to build ACLs, and it's imperative that you get the order right. This is especially important when your code reads an ACL from a resource, such as a registry key, adds an ACE, and then updates the registry. If you're building ACLs in code, the correct ACE order is

  • Explicit Deny

  • Explicit Allow

  • Inherited Deny from parent

  • Inherited Allow from parent

  • Inherited Deny from grandparent

  • Inherited Allow from grandparent

  • Inherited Deny from great grand-parent

  • Inherited Allow from great grandparent

  • and so on.

Perform the following steps to correctly add a new ACE to an existing ACL:

  1. Use the GetSecurityInfo or GetNamedSecurityInfo function to get the existing ACL from the object's security descriptor.

  2. For each new ACE, fill an EXPLICIT_ACCESS structure with the information that describes the ACE.

  3. Call SetEntriesInAcl, specifying the existing ACL and an array of EXPLICIT_ACCESS structures for the new ACEs.

  4. Call the SetSecurityInfo or SetNamedSecurityInfo function to attach the new ACL to the object's security descriptor.

The following C++ code outlines the process. Note that it uses a new function, CreateWellKnownSid (added to Windows 2000 SP3, Windows XP, and Windows .NET Server), which is similar to the ATL CSid class.

/* SetUpdatedACL.cpp */ #define _WIN32_WINNT 0x0501 #include "windows.h" #include "aclapi.h" #include <sddl.h> int main(int argc, char* argv[]) { char *szName = "c:\\junk\\data.txt"; PACL pDacl = NULL; PACL pNewDacl = NULL; PSECURITY_DESCRIPTOR sd = NULL; PSID sidAuthUsers = NULL; DWORD dwErr = 0; try { dwErr = GetNamedSecurityInfo(szName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &sd); if (dwErr != ERROR_SUCCESS) throw dwErr; EXPLICIT_ACCESS ea; ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); DWORD cbSid = SECURITY_MAX_SID_SIZE; sidAuthUsers = LocalAlloc(LMEM_FIXED,cbSid); if (sidAuthUsers == NULL) throw ERROR_NOT_ENOUGH_MEMORY; if (!CreateWellKnownSid(WinAuthenticatedUserSid, NULL, sidAuthUsers, &cbSid)) throw GetLastError(); BuildTrusteeWithSid(&ea.Trustee, sidAuthUsers); ea.grfAccessPermissions = GENERIC_READ; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = NO_INHERITANCE; ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; dwErr = SetEntriesInAcl(1,&ea,pDacl,&pNewDacl); if (dwErr != ERROR_SUCCESS) throw dwErr; dwErr = SetNamedSecurityInfo(szName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL); } catch(DWORD e) { //error } if (sidAuthUsers) LocalFree(sidAuthUsers); if (sd) LocalFree(sd); if (pNewDacl) LocalFree(pNewDacl); return dwErr; }

Note that functions such as AddAccessAllowedAceEx and AddAccessAllowedObjectAce add an ACE to the end of an ACL. It is the caller's responsibility to ensure that the ACEs are added in the proper order.

Finally, be wary of AddAccessAllowedACE because it does not allow you to control ACL inheritance. Instead, you should use AddAccessAllowedACEEx.



Writing Secure Code
Writing Secure Code, Second Edition
ISBN: 0735617228
EAN: 2147483647
Year: 2001
Pages: 286

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net