2009-01-18 59 views
6

我可以找到關於如何編程DCOM的各種東西,但幾乎沒有關於如何設置/檢查安全編程。編程的dcomcnfg功能

我不想重新創建dcomcnfg,但是如果我知道如何在C#(首選或VB.net)中重現dcomcnfg的所有功能,那麼我的目標就在眼前。

我似乎無法找到任何好的資源,沒有開源的API,甚至沒有如何做每一步的快速例子。即使在這裏,DCOM或dcomcnfg也沒有什麼結果,也沒有真正涉及如何設置/驗證/列出安全性。

如果任何人有一些指向開放API或一些例子,我將不勝感激。

回答

10

Daniel發佈的答案很有幫助。丹尼爾,非常感謝你!

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

你和丹尼爾似乎都走在了正確的軌道上。這一切仍然如此痛苦,但它的工作原理。我被剝奪了誰給予信用。但是你看起來像你可以更多地使用這些點。 :) – PerryJ 2013-04-12 22:40:08

4

我找不到任何.NET的方法 - 你可以使用MS命令行工具DCOMPerm(也是here),它是SDK的一部分。

+1

任何機會,仍然有dcomper.exe在那裏?我找不到任何地方的預編譯版本,它的鏈接似乎已經死了 – Max 2016-12-22 13:16:43

4

此信息存儲在HKCR\AppID\{Your-AppID}\LaunchPermissionAccessPermission中。這些是包含序列化安全描述符的REG_BINARY值。不知道是否有任何東西提供方便的.NET訪問者...

更多關於MSDN的信息。

6

面對類似的情況(從MSI配置DCOM安全性)我設法創建一個解決方案,通過更改HKEY_CLASSES_ROOT \ AppID {APP-GUID-GOES-HERE}中的註冊表項值來完成我想要的操作。感謝Arnout的回答讓我走上了正確的道路。

具體而言,我創建了一種方法來編輯DCOM對象的安全權限,該權限存儲在LaunchPermission和AccessPermission註冊表項值中。這些是序列化的安全描述符,您可以通過將二進制數據傳遞到RawSecurityDescriptor來訪問它們。這個類以美味的.NET-y方式簡化了大量細節,但是您仍然需要關注有關Windows ACL的所有邏輯細節,並且必須確保使用RawSecurityDescriptor.GetBinaryForm將安全描述符寫回註冊表中。

我創建的方法叫做EditOrCreateACE。此方法將編輯帳戶的現有ACE或插入新的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。

+0

Yikes!剛剛注意到你的答案,對此感到遺憾。我會盡快嘗試,並儘快回覆您。 看起來我們需要一個完整的庫。 – PerryJ 2012-08-02 18:26:20

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

在情況下,幫助他人......