Sometimes it's necessary to store security descriptors for later use. For example, when deploying software in an enterprise setting, it might be necessary to set ACLs on files, directories, or even other types of objects like services or registry keys from an installation program that may run on many different machines. While you could hardwire these ACL modifications into your code (I show an example of this in HowToProgramACLs), it's usually best to provide a user interface that allows an administrator to construct the required ACLs graphically, using a familiar tool, and then simply persist these ACLs for later deployment 1. To see an example of such a tool, download the "EditSD" sample from the book's Web site.
There are two ways to persist a Windows security descriptor: in binary form and in text form, the latter of which uses a language called Security Descriptor Description Language (SDDL). Version 2.0 of the .NET Framework provides support for round-tripping a security descriptor to and from its text (SDDL) form. Here's some code that shows how to take SDDL as input and apply the security descriptor it represents to various types of objects.
void ApplySDDLToFile(string sddl, string path) {
FileSecurity sd = new FileSecurity();
sd.SetSecurityDescriptorSddlForm(sddl);
File.SetAccessControl(path, sd);
}
void ApplySDDLToRegistryKey(string sddl, RegistryKey key) {
RegistrySecurity sd = new RegistrySecurity();
sd.SetSecurityDescriptorSddlForm(sddl);
key.SetAccessControl(sd);
}
void ApplySDDLToMutex(string sddl, Mutex mutex) {
MutexSecurity sd = new MutexSecurity();
sd.SetSecurityDescriptorSddlForm(sddl);
mutex.SetAccessControl(sd);
}
Where can you store SDDL? In a text file, registry key, XML configuration file, and so on. Just make sure to consider attacks against these locations in your threat model (WhatIsThreatModeling). Here's some code that shows how to stringify a security descriptor, after which you can persist the string to any appropriate media.
string GetSDDL(ObjectSecurity sd) {
return sd.GetSecurityDescriptorSddlForm(
AccessControlSections.Owner |
AccessControlSections.Group | // primary group
AccessControlSections.Access); // DACL
}
1 Keep group scope in mind (WhatIsAGroup) if you decide to do this sort of thing. For example, you should discourage (or, better yet, prevent) the administrator from using custom local groups, which don't have any meaning when deployed to another machine. However, the built-in local groups (Administrators, Users, etc.) are the same everywhere and are safe to use. The same thing goes with domain local groups, which have meaning only in the domain where they're defined.