Search code examples
c#.netsecuritypermissionsdcom

dcomcnfg functionality programmatically


I can find all sorts of stuff on how to program for DCOM, but practically nothing on how to set/check the security programmatically.

I'm not trying to recreate dcomcnfg, but if I knew how to reproduce all the functionality of dcomcnfg in C# (preferred, or VB.net) then my goal is in sight.

I can't seem to be able to find any good resource on this, no open source API's or even quick examples of how to do each step. Even here DCOM or dcomcnfg returns few results and none really about how to set/verify/list security.

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


Solution

  • The answer posted by Daniel was HUGELY helpful. Thank you so much, Daniel!

    An issue with Microsoft's documentation is that they indicate that the registry values contain an ACL in binary form. So, for instance, if you were trying to set the machine's default access (rather than per-process), you would be accessing 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 were failing.

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

    So, even though I know this post is old, I'm going to post my solution for checking and setting the security settings and adding NetworkService for Default local access. Of course, you could take this and make it better I'm sure, but to get started you would simply need to change the key and the 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);
        }
    }