Click here to Skip to main content
Click here to Skip to main content

Low-level Security Classes

By , 1 Mar 2000
 
  • Download demo project - 17 Kb
  • Download source files - 4 Kb
  • If you have ever tried to do something simple like set a security descriptor for a Registry key you know what a pain the Win32 Security APIs can be. The process of initializing the various structures, allocating and deallocating memory and testing for error conditions is tedious and you end up with at least a page and a half of code which is difficult to read and doesn't lend itself to being reused next time you want to do the same thing. There had to be a better way, I thought. So I wrote a set of classes which take care of much of the donkey-work for you.

    All of the classes correspond to the structures used by the low-level Security APIs - ACEs, ACLs, SIDs, TRUSTEEs, Security Descriptors. Their member functions are in most cases the same as the calls you would use when working with the API. The crucial differences are:

    1. Often, a single constructor call is all that is needed to allocate and initialize an object
    2. The classes which need to allocate memory will release it safely when the object goes out of scope.

    Other than that, they are just thin wrappers. You can still get at the underlying objects if you need to, and you can also pass them to any of the API functions expecting a security object.

    The best documentation I can give you is some sample code, so here is an example of how to create a secure Registry key which can be read by any user but only changed by administrators. To compare this with code which does the same thing using only API calls, see Setting a Security Descriptor for a new object in the MSDN library. Notice how much longer it is.

    // Create a Registry key, granting KEY_READ access to everyone and 
    // full control to the Administrators group.
    
    // Initialize 2 EXPLICIT_ACCESS structures: 1 for Everyone,
    // 1 for Administrators. 
    CSid sidEveryone(CSid::WST_EVERYONE);
    CSid sidAdmins(CSid::WST_LOCALADMINS);
    
    CTrustee trEveryone(TRUSTEE_IS_WELL_KNOWN_GROUP, sidEveryone);
    CTrustee trAdmins(TRUSTEE_IS_GROUP, sidAdmins);
    
    EXPLICIT_ACCESS ea[2];
    
    ea[0] = CExplicitAccess(KEY_READ, SET_ACCESS, NO_INHERITANCE, trEveryone);
    ea[1] = CExplicitAccess(KEY_ALL_ACCESS, SET_ACCESS, NO_INHERITANCE, trAdmins);		
    

    Note the constructor for CSid which allows you to create a SID for any of the well-known groups such as Administrators, ordinary users, etc.

    // Create a new ACL and set the EA entries in it
    CAcl acl;
    if(acl.SetEntriesInAcl(2, ea) == ERROR_SUCCESS)
    {
    
    	// Initialize a security descriptor and add our ACL to it  
    	CSecurityDescriptor sd;
    	if(sd.SetSecurityDescriptorDacl(
    		TRUE,     // fDaclPresent flag   
    		acl, 
    		FALSE))   // not a default DACL 
    	{
    
    		// Initialize a security attributes structure.
    		CSecurityAttributes sa(sd, FALSE);
    
    		// Use the security attributes to set the security descriptor 
    		// when you create a key.
    		DWORD	dwDisposition;
    		HKEY	hKey;
     
    		RegCreateKeyEx(HKEY_CURRENT_USER, "mykey1", 0, "", 0, 
    			KEY_READ | KEY_WRITE, sa, &hKey, &dwDisposition); 
    
    	}
    
    }
    

    That's it! If you have any suggestions or problems to report, post them here. There are plenty of ways this idea could be extended if you are of an inclination to do so.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    About the Author

    Peter Kenyon
    Web Developer
    New Zealand New Zealand
    Member
    No Biography provided

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    QuestionHow can I create a new windows user?memberpengok7 Dec '04 - 14:17 
    How can I create a new windows user ?
     
    Anybody knows?
     
    Thanks
    Generaldoes not work :-(memberemmi18 Jul '04 - 20:44 
    hi.
    the example does not running on my machine. sorry. Frown | :-(
    the problem:
     
    DWORD dwRes = ::SetEntriesInAcl(cCountOfExplicitEntries, pListOfExplicitEntries, m_pACL, &paclNew);
    returns ErrorCode 87 (Invalid Parameter).
     
    But I don't know which parameter is wrong.
     
    I don't know, but the methode "InitializeAcl" is never called. is this right ?
    who is allocating the memory for m_pACL ?
     
    Thank you for your help
     
    best regards
    emmi
    GeneralRe: Please see response of the first message on this board!memberBehzad Ebrahimi24 Jul '04 - 0:00 
    First read previuos questionsSuspicious | :suss:
    http://www.codeproject.com/system/secdesc.asp?msg=5989#xx5989xx[^]
    GeneralWrite access rightmemberJianping Yan15 May '04 - 12:36 
    Hi Peter:
     
    In your sample code, you set KEY_READ TO "everyone" in first section of code and the return value of RegCreateKeyEx()in secod section of code is 5 under any acconts except administrator, which means err_access_fail.
     
    ea[0] = CExplicitAccess(KEY_READ, SET_ACCESS, NO_INHERITANCE,
    CTrustee(TRUSTEE_IS_WELL_KNOWN_GROUP,
    CSid(CSid::WST_EVERYONE)));
     
    RegCreateKeyEx(HKEY_CURRENT_USER, "mykey1", 0, "", 0,
    KEY_READ | KEY_WRITE, sa, &hKey, &dwDisposition);
     
    After take off KEY_WRITE in RegCreateKeyEx(), it works fine to read value from the mykey1. However, is there any way that can read/write
    value under "everyone".
     
    OS I tested is Win XP home edition.
     
    Thanks,
    JP
     

    GeneralWorks fine on NT 4.0, too.sussAnonymous1 Aug '03 - 10:12 
    I had a problem where an application run as Administrator created a LOCAL_MACHINE key, but when the application was run as a non-adminstrator account, the app could not read the key. I assume this means that the default security was set that way on purpose.
     
    By using this code, I just set the ACL to allow Everyone full access to the key, so the application could read/write the key no matter what user was running the app. Just what I needed... THANKS!
    Generalone Questionmemberosirix15 Jul '03 - 6:23 
    How can i list on C++ the ACL of file, thank U so much
     
    Osirix
    Generalchange permissions of an existing keysussM.Pester6 Mar '03 - 2:07 
    Does anyone know how to programatically change permissions of an existing registry key?
     
    The return code of RegCreateKeyEx(HKEY_LOCAL_MACHINE, sKey, 0, "", 0, KEY_ALL_ACCESS, sa, &hKey, &dwDisposition) is 0, but nothing was changed in the registry.
     
    The value of dwDisposition says me that I have opened an existing key (==REG_OPENED_EXISTING_KEY).
    If I then try to change the key with RegSetKeySecurity I get return code 87.
     
    What could be wrong ???
     

     

     

    GeneralRe: change permissions of an existing keymemberlesashwad25 Jan '06 - 10:36 
    // Use the security attributes to set the security descriptor
    // when you create a key.
    lRes = RegCreateKeyEx(HKEY_LOCAL_MACHINE, directory, 0, "", 0,
    KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition);
     

    //In case key already existed:
    //Close the key
    //Open the key
    //Change Permissions
    //Why?? I don't know...
     
    if (hkSub)
    {
    RegCloseKey(hkSub);
    RegOpenKey(HKEY_LOCAL_MACHINE, directory, &hkSub);
    if (hkSub)
    {
    RegSetKeySecurity(hkSub,DACL_SECURITY_INFORMATION, pSD);
    }
    }
     
    law
    GeneralRe: change permissions of an existing keymemberAtlence31 Jan '06 - 2:59 
    Hi!
     
    What is pSD in your code? I test it but it doesn't work, RegSetKeySecurity doesn't return ERROR_SUCCESS and my key permissions remains the same.
     
    Thks in advance!
    Appstmd
    http://www.atlence.com
    Generalregistry security templatessusstravisowenjones22 Jan '03 - 9:57 
    Does anyone know how to programatically change registry permissions in accordance with a security template like the NSA's.
     
    An example is:
    "machine\system\currentcontrolset\hardware profiles",0,"D:PAR(A;CI;KA;;;BA)(A;CIIO;KA;;;CO)(A;CI;KA;;;SY)(A;CI;KR;;;BU)"

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Permalink | Advertise | Privacy | Mobile
    Web04 | 2.6.130523.1 | Last Updated 2 Mar 2000
    Article Copyright 2000 by Peter Kenyon
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid