Функциональность dcomcnfg программно - PullRequest
6 голосов
/ 18 января 2009

Я могу найти всевозможные материалы о том, как программировать для DCOM, но практически ничего о том, как программно установить / проверить безопасность.

Я не пытаюсь воссоздать dcomcnfg, но если бы я знал, как воспроизвести все функции dcomcnfg в C # (предпочтительно, или VB.net), тогда моя цель уже видна.

Я не могу найти ни одного хорошего ресурса по этому вопросу, ни API с открытым исходным кодом, ни даже быстрых примеров того, как выполнять каждый шаг. Даже здесь DCOM или dcomcnfg возвращают мало результатов, и ни один из них о том, как установить / проверить / перечислить безопасность,

Если у кого-то есть ссылки на открытый API или примеры, я был бы признателен.

Ответы [ 5 ]

10 голосов
/ 26 марта 2013

Ответ, опубликованный Даниэлем, был НАСТОЯТЕЛЬНО полезным. Большое спасибо, Даниэль!

Проблема с документацией Microsoft заключается в том, что они указывают, что значения реестра содержат ACL в двоичном виде. Так, например, если вы пытаетесь установить доступ к компьютеру по умолчанию (а не к процессу), вы получите доступ к разделу реестра HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Ole \ DefaultAccessPermission. Однако в моих первоначальных попытках доступа к этому ключу с помощью класса System.Security.AccessControl.RawACL не получалось.

Как показывает код Даниэля, значение на самом деле не ACL, а действительно SecurityDescriptor с ACL в нем.

Итак, хотя я знаю, что этот пост старый, я собираюсь опубликовать свое решение для проверки и настройки параметров безопасности и добавления 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);
    }
}
6 голосов
/ 25 июля 2012

Столкнувшись с аналогичными обстоятельствами (настройка безопасности DCOM из MSI), мне удалось создать решение, которое делает то, что я хочу, изменив значения ключа реестра в HKEY_CLASSES_ROOT \ AppID {APP-GUID-GOES-HERE}. Спасибо ответу Арно за то, что он направил меня по правильному пути.

В частности, я создал метод для редактирования разрешений безопасности для объектов 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 предоставит ТОЛЬКО доступ к переданной учетной записи и ничего больше. Я также уверен, что есть много состояний ошибок, которые я не обработал должным образом, и детали, которые я замаскировал. Опять же, это пример того, как работать с DCOM ACL в .NET.

4 голосов
/ 19 января 2009

Эта информация хранится в HKCR\AppID\{Your-AppID}\LaunchPermission и AccessPermission. Это значения REG_BINARY, содержащие сериализованные дескрипторы безопасности. Не знаю, есть ли что-нибудь, обеспечивающее удобный доступ к ним из .NET ...

Подробнее о MSDN .

4 голосов
/ 19 января 2009

Я не смог найти .NET способ сделать это - вы можете использовать утилиту командной строки MS DCOMPerm (также здесь ), которая является частью SDK.

0 голосов
/ 03 августа 2017

Я нашел, что это решение работает:

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

Если это поможет другим ...

...