dcomcnfg以编程方式运行

时间:2009-01-18 00:21:51

标签: c# .net security permissions dcom

我可以找到各种有关如何为DCOM编程的内容,但几乎没有关于如何以编程方式设置/检查安全性的内容。

我不是要重新创建dcomcnfg,但如果我知道如何在C#(首选或VB.net)中重现dcomcnfg的所有功能,那么我的目标就在眼前。

我似乎无法在此找到任何好的资源,没有开源API或甚至是如何执行每个步骤的快速示例。即使在这里,DCOM或dcomcnfg也没有返回任何结果,也没有关于如何设置/验证/列出安全性。

如果有人对开放API或某些示例有一些指示,我将不胜感激。

5 个答案:

答案 0 :(得分:10)

丹尼尔发布的答案很有帮助。谢谢你,丹尼尔!

Microsoft's documentation的一个问题是它们表明注册表值包含二进制形式的ACL。因此,例如,如果您尝试设置计算机的默认访问权限(而不是按进程),则将访问注册表项HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Ole \ DefaultAccessPermission。但是,在我最初尝试使用System.Security.AccessControl.RawACL类访问此密钥时失败。

由于Daniel的代码表明该值实际上不是ACL,但实际上是一个带有ACL的SecurityDescriptor。

所以,即使我知道这篇文章已经过时了,我也会发布我的解决方案来检查和设置安全设置,并为默认本地访问添加NetworkService。当然,你可以采取这种方式并使其更好我确定,但是要开始使用,你只需要更改密钥和访问掩码。

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

答案 1 :(得分:6)

面对类似的情况(从MSI配置DCOM安全性)我设法创建了一个解决方案,通过更改HKEY_CLASSES_ROOT \ AppID {APP-GUID-GOES-HERE}中的注册表项值来实现我想要的。感谢Arnout的回答让我走上了正确的道路。

具体来说,我创建了一种方法来编辑DCOM对象的安全权限,这些权限存储在LaunchPermission和AccessPermission注册表项值中。这些是序列化的安全描述符,您可以通过RawSecurityDescriptor传递二进制数据来访问它们。这个类以美味的.NET-y方式简化了许多细节,但您仍然需要关注有关Windows ACL的所有逻辑细节,并且必须确保使用{将安全描述符写回注册表。 {1}}。

我创建的方法称为RawSecurityDescriptor.GetBinaryForm。此方法将编辑帐户的现有ACE,或插入新帐户,并确保访问掩码已设置传递的标志。我将它作为示例附加在此处,这绝不是如何处理它的任何权限,因为我对Windows ACL的知识仍然很少:

EditOrCreateACE

请注意,此代码绝不是完美的。如果注册表中缺少这些ACL的整个注册表项值,则合成的ACL将仅授予对已传递帐户的访问权限,而不会授予任何其他权限。我也确定有很多错误情况,我没有正确处理,细节我已经掩盖了。同样,它是如何在.NET中处理DCOM ACL的示例

答案 2 :(得分:4)

我找不到任何.NET方法 - 您可以使用作为SDK一部分的MS命令行实用程序DCOMPerm(也是here)。

答案 3 :(得分:4)

此信息存储在HKCR\AppID\{Your-AppID}\LaunchPermissionAccessPermission中。这些是包含序列化安全描述符的REG_BINARY值。不知道是否有任何东西可以方便地访问.NET的那些......

有关MSDN的更多信息。

答案 4 :(得分:0)

我发现这个解决方案有效:

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

如果它能帮助别人......