我可以找到各种关于如何为DCOM编程的东西,但实际上没有关于如何以编程方式设置/检查安全性的内容.
我不是要重新创建dcomcnfg,但如果我知道如何在C#(首选或VB.net)中重现dcomcnfg的所有功能,那么我的目标就在眼前.
我似乎无法在此找到任何好的资源,没有开源API或甚至是如何执行每个步骤的快速示例.即使在这里,DCOM或dcomcnfg也没有返回任何结果,也没有关于如何设置/验证/列出安全性的结果.
如果有人对开放API或某些示例有一些指示,我将不胜感激.
丹尼尔发布的答案很有帮助.谢谢你,丹尼尔!
Microsoft文档的一个问题是它们表明注册表值包含二进制形式的ACL.所以,举例来说,如果你试图设置机器的默认访问(而不是每个进程),你会被访问的注册表项HKEY_LOCAL_MACHINE\SOFTWARE \微软\的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); } }
面对类似的情况(配置从MSI DCOM安全),我成功地创建一个解决方案,做什么,我想在HKEY_CLASSES_ROOT \的AppID更改注册表键值{APP-GUID-GOES-HERE}.感谢Arnout的回答,让我走上了正确的道路.
具体来说,我创建了一种方法来编辑DCOM对象的安全权限,这些权限存储在LaunchPermission和AccessPermission注册表项值中.这些是序列化的安全描述符,您可以通过传递二进制数据来访问它们RawSecurityDescriptor
.这个类简化了很多的美味.NET-Y时尚的细节,但你还是要顾及所有有关的Windows ACL的逻辑细节,你必须确保通过编写安全描述符回注册表 RawSecurityDescriptor.GetBinaryForm
.
我创建的方法被调用EditOrCreateACE
.此方法将编辑帐户的现有ACE,或插入新帐户,并确保访问掩码已设置传递的标志.我在这里附上它作为一个例子,这绝不是如何处理它的任何权威,因为我对Windows ACL的东西知之甚少:
// 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; }
请注意,此代码绝不是完美的.如果注册表中缺少这些ACL的整个注册表项值,则合成的ACL将仅授予对已通过帐户的访问权限,而不允许其他任何内容.我也确定有很多错误情况,我没有正确处理,细节我已经掩盖了.同样,它是如何在.NET中处理DCOM ACL 的一个示例.