Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change COM Security settings programmatically by c#?

Tags:

c#

.net

I need to change COM security permissions programmatically using .NET methods. I mean these settings:

enter image description here

How can I do this? Thanks!

like image 965
Maksim Nikitin Avatar asked Oct 20 '22 06:10

Maksim Nikitin


2 Answers

As far as I know there is no API to do this. However COM and DCOM access control are set in the registry, mainly under the "incognito" OLE (because of historical reasons). At the same time .NET has standard classes to manipulate registry.

So here is what I should do when facing this task:

  • Launch a registry monitor, like Mark Russinovich's formerly SysInternals, now Microsoft

  • Set some COM setting interactively using the windows UI, and monitor registry changes.

  • Optional but strongly recommended: After having some very well targeted search keyword (the registry keys) try to in google for doc/code, or what is better search in github within the code

  • Implement my C# classes what are manipulating the appropriate registry classes

like image 139
g.pickardou Avatar answered Oct 22 '22 00:10

g.pickardou


I know this tropic is old, but here is the solution I ended up using in case any one needs it. As stated above I could not find any API to do it and had to work directly on the registry key that stores the sitting. The fillowing keys should be edited:

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole\DefaultAccessPermission
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole\DefaultLaunchPermission

The permissions are stored in binary form. You can try my code:

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;
}

static void Main(string[] args)
{
     SetCOMSercurityAccess("testuser", "DefaultAccessPermission");
     SetCOMSercurityAccess("testuser", "DefaultLaunchPermission");
}

private static void SetCOMSercurityAccess(string username, string regKey)
{
    //Get sid from username
    NTAccount f = new NTAccount(username);
    SecurityIdentifier sid = (SecurityIdentifier)f.Translate(typeof(SecurityIdentifier));

    //Read reg key responsible for COM Sercurity
    var accessKey = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", regKey, null);

    RawSecurityDescriptor sd;

    if (accessKey == null)
    {
        //Key does not exist
        sd = new RawSecurityDescriptor("");
    }
    else
    {
        //read security settings
        sd = new RawSecurityDescriptor(accessKey as byte[], 0);
    }

    //Look fo input foruser
    var acl = sd.DiscretionaryAcl;
    var found = false;
    foreach (CommonAce ca in acl)
    {
        if (ca.SecurityIdentifier == sid)
        {
            //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)
    {
        CommonAce ca = new CommonAce(
            AceFlags.None,
            AceQualifier.AccessAllowed,
            ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL,
                sid,
                false,
                null);
        acl.InsertAce(acl.Count, ca);
    }
    //re-set the ACL
    sd.DiscretionaryAcl = acl;

    //Convert back to binary and save
    byte[] binaryform = new byte[sd.BinaryLength];
    sd.GetBinaryForm(binaryform, 0);
    Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Ole", regKey, binaryform, RegistryValueKind.Binary);
}

This code is mostly inspired by this answer

like image 31
Christian Avatar answered Oct 21 '22 22:10

Christian