Dcomcnfg functionality programmatically

I can find all kinds of materials on how to program DCOM, but practically nothing on how to install / check security programmatically.

I am not trying to recreate dcomcnfg, but if I knew how to reproduce all the functionality of dcomcnfg in C # (preferably VB.net), then my goal is visible.

I cannot find any good resource for this, without an open source API or even quick examples of how to take each step. Even here, DCOM or dcomcnfg returns multiple results and no one knows how to set / check / save the list.

If anyone has pointers to an open API or some examples, I would appreciate it.

+6
security c # permissions dcom
source share
5 answers

The answer posed by Daniel was very helpful. Thank you so much Daniel!

The problem with Microsoft documentation is that they indicate that registry values ​​contain binary ACLs. For example, if you tried to set default access for the computer (and not for each process), you will get access to the registry key HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Ole \ DefaultAccessPermission. However, in my initial attempts to access this key using the System.Security.AccessControl.RawACL class, it failed.

As Daniel's code shows, the value is not an ACL, but is actually a SecurityDescriptor with an ACL in it.

So, although I know this post is out of date, I will post my solution to check and configure security settings and add NetworkService default network access. Of course, you can accept this and do it better, I'm sure, but first you just need to change the key and access mask.

static class ComACLRights{ public const int COM_RIGHTS_EXECUTE= 1; public const int COM_RIGHTS_EXECUTE_LOCAL = 2; public const int COM_RIGHTS_EXECUTE_REMOTE = 4; public const int COM_RIGHTS_ACTIVATE_LOCAL = 8; public const int COM_RIGHTS_ACTIVATE_REMOTE = 16; } class Program { static void Main(string[] args) { var value = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", null); RawSecurityDescriptor sd; RawAcl acl; if (value == null) { System.Console.WriteLine("Default Access Permission key has not been created yet"); sd = new RawSecurityDescriptor(""); }else{ sd = new RawSecurityDescriptor(value as byte[], 0); } acl = sd.DiscretionaryAcl; bool found = false; foreach (CommonAce ca in acl) { if (ca.SecurityIdentifier.IsWellKnown(WellKnownSidType.NetworkServiceSid)) { //ensure local access is set ca.AccessMask |= ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL; //set local access. Always set execute found = true; break; } } if(!found){ //Network Service was not found. Add it to the ACL SecurityIdentifier si = new SecurityIdentifier( WellKnownSidType.NetworkServiceSid, null); CommonAce ca = new CommonAce( AceFlags.None, AceQualifier.AccessAllowed, ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL, si, false, null); acl.InsertAce(acl.Count, ca); } //re-set the ACL sd.DiscretionaryAcl = acl; byte[] binaryform = new byte[sd.BinaryLength]; sd.GetBinaryForm(binaryform, 0); Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", "DefaultAccessPermission", binaryform, RegistryValueKind.Binary); } } 
+10
source share

Before similar circumstances (setting DCOM security from MSI) I managed to create a solution that does what I want by changing the registry key values ​​in HKEY_CLASSES_ROOT \ AppID {APP-GUID-GOES-HERE}. Thanks to Arnot for setting me on the right track.

In particular, I created a method for editing security permissions for DCOM objects that are stored in the registry key values ​​of LaunchPermission and AccessPermission. These are serialized security descriptors that you can access by passing binary data through RawSecurityDescriptor . This class simplifies a lot of the details in the amazing .NET-y style, but you still need to keep track of all the logical details of the Windows ACLs and you must definitely write the security descriptor to the registry using RawSecurityDescriptor.GetBinaryForm .

The method I created was called EditOrCreateACE . This method will either edit the existing ACE for the account or insert a new one and make sure that the set flags are set in the access mask. I am attaching it here as an example , it is by no means any authority on how to deal with this, since I know a little about the Windows ACL file:

 // These are constants for the access mask on LaunchPermission. // I'm unsure of the exact constants for AccessPermission private const int COM_RIGHTS_EXECUTE = 1; private const int COM_RIGHTS_EXECUTE_LOCAL = 2; private const int COM_RIGHTS_EXECUTE_REMOTE = 4; private const int COM_RIGHTS_ACTIVATE_LOCAL = 8; private const int COM_RIGHTS_ACTIVATE_REMOTE = 16; void EditOrCreateACE(string keyname, string valuename, string accountname, int mask) { // Get security descriptor from registry byte[] keyval = (byte[]) Registry.GetValue(keyname, valuename, new byte[] { }); RawSecurityDescriptor sd; if (keyval.Length > 0) { sd = new RawSecurityDescriptor(keyval, 0); } else { sd = InitializeEmptySecurityDescriptor(); } RawAcl acl = sd.DiscretionaryAcl; CommonAce accountACE = null; // Look for the account in the ACL int i = 0; foreach (GenericAce ace in acl) { if (ace.AceType == AceType.AccessAllowed) { CommonAce c_ace = ace as CommonAce; NTAccount account = c_ace.SecurityIdentifier.Translate(typeof(NTAccount)) as NTAccount; if (account.Value.Contains(accountname)) { accountACE = c_ace; } i++; } } // If no ACE found for the given account, insert a new one at the end // of the ACL, otherwise just set the mask if (accountACE == null) { SecurityIdentifier ns_account = (new NTAccount(accountname)).Translate(typeof(SecurityIdentifier)) as SecurityIdentifier; CommonAce ns = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed, mask, ns_account, false, null); acl.InsertAce(acl.Count, ns); } else { accountACE.AccessMask |= mask; } // Write security descriptor back to registry byte[] binarySd = new byte[sd.BinaryLength]; sd.GetBinaryForm(binarySd, 0); Registry.SetValue(keyname, valuename, binarySd); } private static RawSecurityDescriptor InitializeEmptySecurityDescriptor() { var localSystem = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null); var new_sd = new RawSecurityDescriptor(ControlFlags.DiscretionaryAclPresent, localSystem, localSystem, null, new RawAcl(GenericAcl.AclRevision, 1)); return new_sd; } 

Please note that this code is by no means perfect. If the registry does not have the full registry key value for these ACLs, the ACL that is synthesized ONLY provides access to the passed account and nothing more. I am also sure that there are a lot of errors that I did not handle properly, and the details that I was silent about. Again, this is an example of how to handle DCOM ACLs in .NET.

+6
source share

I could not find any .NET way to do this - you can use the MS DCOMPerm command line utility (also here ), which is part of the SDK.

+4
source share

This information is stored in HKCR\AppID\{Your-AppID}\LaunchPermission and AccessPermission . These are REG_BINARY values ​​that contain serialized security descriptors. I don't know if there is anything providing convenient access to those from .NET ...

Learn more about MSDN .

+4
source share

I found this solution:

  public static void SetUp() { SetCOMSercurityAccess("DefaultAccessPermission"); SetCOMSercurityAccess("DefaultLaunchPermission"); } private static void SetCOMSercurityAccess(string regKey) { //This is the magic permission! byte[] binaryform = new string[] { "01","00","04","80","80","00","00","00","90","00","00","00","00","00","00","00","14","00","00","00","02","00","6c","00","04", "00","00","00","00","00","14","00","1f","00","00","00","01","01","00","00","00","00","00","05","12","00","00","00","00","00", "24","00","0b","00","00","00","01","05","00","00","00","00","00","05","15","00","00","00","a3","53","d8","c8","94","bd","63", "84","88","bf","fa","cf","a7","2b","00","00","00","00","18","00","1f","00","00","00","01","02","00","00","00","00","00","05", "20","00","00","00","20","02","00","00","00","00","14","00","1f","00","00","00","01","01","00","00","00","00","00","05","04", "00","00","00","01","02","00","00","00","00","00","05","20","00","00","00","20","02","00","00","01","02","00","00","00","00", "00","05","20","00","00","00","20","02","00","00" }.Select(o=> Convert.ToByte(o,16)).ToArray(); Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", regKey, binaryform, RegistryValueKind.Binary); } 

In case it helps others ...

0
source share

All Articles