I finally got around to finishing up my managed adapter for ISecurityInformation. Turns out the cleanest way was to write a custom CCW in MC++. For those of you who are wondering what the heck I'm talking about, this allows you to add that nifty ACL editor GUI to your managed applications:

...along with all its accoutrements...

The sample application that comes with the adapter uses it to edit service ACLs (something the Windows administration tools don't provide except via group policy):

To use this adapter, write a class that implements ISecurityInformationManaged and pass an instance to AclUIAdapter.EditSecurity(). All this stuff is in a namespace called Pluralsight.Security.Adapters. You can download the code and sample application here. This will be featured in an upcoming article for MSDN Magazine.
Here's an excerpt from the sample app:
class ServiceSecurityModel : ISecurityInformationManaged {
string machineName;
string serviceName;
public ServiceSecurityModel(string machineName, string serviceName) {
this.machineName = machineName;
this.serviceName = serviceName;
}
public ObjectInfo GetObjectInformation() {
return new ObjectInfo(
ObjectInfoFlags.EditAll | ObjectInfoFlags.PageTitle | ObjectInfoFlags.Advanced,
machineName,
serviceName,
"Service Permissions");
}
public AccessRights GetAccessRights(Guid objectType, Pluralsight.Security.Adapters.ObjectInfoFlags flags) {
AccessRights rights = new AccessRights();
Access[] access = rights.Access = new Access[17];
// summary page permissions (note use of AccessFlags.General)
access[0] = new Access(SERVICE_ALL, "Full Control", AccessFlags.General | AccessFlags.Specific);
access[1] = new Access(SERVICE_READ, "Read", AccessFlags.General); // 0x0002008D
access[2] = new Access(SERVICE_WRITE, "Write", AccessFlags.General);
access[3] = new Access(SERVICE_EXECUTE, "Execute", AccessFlags.General);
// permissions specific to services (only show up on advanced page)
access[4] = new Access(0x0001, "Query Configuration", AccessFlags.Specific);
access[5] = new Access(0x0002, "Change Configuration", AccessFlags.Specific);
access[6] = new Access(0x0004, "Query Status", AccessFlags.Specific);
access[7] = new Access(0x0008, "Enumerate Dependents", AccessFlags.Specific);
access[8] = new Access(0x0010, "Start", AccessFlags.Specific);
access[9] = new Access(0x0020, "Stop", AccessFlags.Specific);
access[10] = new Access(0x0040, "Pause or Continue", AccessFlags.Specific);
access[11] = new Access(0x0080, "Interrogate", AccessFlags.Specific);
access[12] = new Access(0x0100, "Send User Defined Control", AccessFlags.Specific);
// standard permissions that apply to services (only show up on advanced page)
access[13] = new Access(0x00010000, "Delete", AccessFlags.Specific);
access[14] = new Access(0x00020000, "Read Permissions", AccessFlags.Specific);
access[15] = new Access(0x00040000, "Change Permissions", AccessFlags.Specific);
access[16] = new Access(0x00080000, "Take Ownership", AccessFlags.Specific);
rights.DefaultIndex = 1; // default mask when you add a new ACE (GENERIC_READ)
return rights;
}
public InheritType[] GetInheritTypes() {
return null; // services are not containers
}
// these generic mappings taken from the service access rights documentation
const int SERVICE_READ = 0x0002008D;
const int SERVICE_WRITE = 0x00020002;
const int SERVICE_EXECUTE = 0x00020170;
const int SERVICE_ALL = 0x000F01FF;
const int GENERIC_READ = unchecked((int)0x80000000);
const int GENERIC_WRITE = 0x40000000;
const int GENERIC_EXECUTE = 0x20000000;
const int GENERIC_ALL = 0x10000000;
GenericMapping ServiceGenericMapping = new GenericMapping(
SERVICE_READ, SERVICE_WRITE, SERVICE_EXECUTE, SERVICE_ALL);
public void MapGeneric(GenericAccess generic) {
MapGenericMask(ref generic.Mask, ref ServiceGenericMapping);
}
public void SetSecurity(SecurityInformation providedInformation, byte[] binarySecurityDescriptor) {
ServiceHelper.SetServiceSecurity(machineName, serviceName,
(int)providedInformation, binarySecurityDescriptor);
}
public byte[] GetSecurity(SecurityInformation requestedInformation, bool wantDefault) {
return ServiceHelper.GetServiceSecurity(machineName,
serviceName, (int)requestedInformation);
}
[DllImport("advapi32.dll")]
static extern void MapGenericMask(ref int mask, ref GenericMapping mapping);
}
Posted
Oct 04 2004, 01:51 PM
by
keith-brown