7 Stimmen

dcomcnfg-Funktionalität programmatisch

Ich kann alles Mögliche darüber finden, wie man für DCOM programmiert, aber praktisch nichts darüber, wie man die Sicherheit programmatisch einstellt/prüft.

Ich versuche nicht, dcomcnfg neu zu erstellen, aber wenn ich wüsste, wie ich die gesamte Funktionalität von dcomcnfg in C# (bevorzugt, oder VB.net) reproduzieren kann, dann ist mein Ziel in Sicht.

Ich kann nicht scheinen, um in der Lage zu sein, jede gute Ressource zu finden, keine Open-Source-APIs oder sogar schnelle Beispiele, wie jeder Schritt zu tun. Auch hier DCOM oder dcomcnfg gibt nur wenige Ergebnisse und keine wirklich über wie zu setzen/überprüfen/Liste Sicherheit.

Wenn jemand Hinweise auf eine offene API oder einige Beispiele hat, wäre ich dankbar.

12voto

longofest Punkte 596

Die Antwort von Daniel war SEHR hilfreich. Vielen Dank, Daniel!

Ein Problem mit Microsofts Dokumentation ist, dass sie anzeigen, dass die Registrierungswerte eine ACL in binärer Form enthalten. Wenn Sie also beispielsweise versuchen, den Standardzugriff des Rechners (und nicht pro Prozess) festzulegen, würden Sie auf den Registrierungsschlüssel HKEY_LOCAL_MACHINE \SOFTWARE\Microsoft\Ole\DefaultAccessPermission. Meine ersten Versuche, mit der Klasse System.Security.AccessControl.RawACL auf diesen Schlüssel zuzugreifen, schlugen jedoch fehl.

Wie Daniels Code zeigt, ist der Wert nicht wirklich eine ACL, sondern ein SecurityDescriptor mit der ACL darin.

Auch wenn ich weiß, dass dieser Beitrag alt ist, werde ich meine Lösung für die Überprüfung und Einstellung der Sicherheitseinstellungen und das Hinzufügen von NetworkService für den standardmäßigen lokalen Zugriff posten. Natürlich können Sie diese Lösung übernehmen und verbessern, aber für den Anfang müssen Sie lediglich den Schlüssel und die Zugriffsmaske ändern.

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 Stimmen

Sie und Daniel scheinen beide auf dem richtigen Weg zu sein. Es ist alles noch so schmerzhaft, aber es funktioniert. Ich bin hin- und hergerissen, wem ich die Ehre geben soll. Aber du siehst aus, als könntest du die Punkte besser gebrauchen :)

1 Stimmen

Sie sind willkommen. Die meisten Details habe ich herausgefunden, indem ich den Quellcode von DCOMPerm aufgespürt und analysiert habe, was er tut (in C++).

1 Stimmen

Dies könnte ebenfalls hilfreich sein: github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/com/

7voto

Daniel Bruce Punkte 10889

In einer ähnlichen Situation (Konfiguration der DCOM-Sicherheit über eine MSI) habe ich eine Lösung gefunden, die das Gewünschte bewirkt, indem ich die Registrierungsschlüsselwerte in HKEY_CLASSES_ROOT geändert habe \AppID {APP-GUID-GOES-HERE}. Vielen Dank an Arnout's Antwort, die mich auf den richtigen Weg gebracht hat.

Konkret habe ich eine Methode zum Bearbeiten der Sicherheitsberechtigungen für DCOM-Objekte erstellt, die in den Registrierungsschlüsselwerten LaunchPermission und AccessPermission gespeichert sind. Dies sind serialisierte Sicherheitsdeskriptoren, auf die Sie zugreifen können, indem Sie die binären Daten durch RawSecurityDescriptor . Diese Klasse vereinfacht viele Details auf köstliche .NET-Art, aber Sie müssen immer noch alle logischen Details in Bezug auf Windows ACL beachten, und Sie müssen sicherstellen, dass Sie den Sicherheitsdeskriptor zurück in die Registrierung schreiben, indem Sie RawSecurityDescriptor.GetBinaryForm .

Die Methode, die ich erstellt habe, heißt EditOrCreateACE . Mit dieser Methode wird entweder ein vorhandener ACE für ein Konto bearbeitet oder ein neuer eingefügt und sichergestellt, dass die Zugriffsmaske die übergebenen Flags gesetzt hat. Ich füge sie hier als ejemplo Dies ist keineswegs eine Autorität, wie man damit umgeht, da ich noch sehr wenig über Windows ACL weiß:

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

Bitte beachten Sie, dass dieser Code keineswegs perfekt ist. Wenn der gesamte Registrierungsschlüsselwert für diese ACL in der Registrierung fehlt, wird die synthetisierte ACL NUR Zugriff auf das übergebene Konto gewähren und nichts anderes. Ich bin auch sicher, dass es viele Fehlerbedingungen gibt, die ich nicht richtig behandelt habe, und Details, die ich übergangen habe. Nochmals, es ist ein ejemplo wie man mit DCOM ACL in .NET umgeht.

0 Stimmen

Igitt! Ich habe gerade Ihre Antwort bemerkt, das tut mir leid. Ich werde es ausprobieren, hoffentlich bald, und mich wieder bei Ihnen melden. Sieht aus, als bräuchten wir eine ganze Bibliothek zu diesem Thema.

4voto

Dror Punkte 7175

Ich konnte keine .NET-Möglichkeit finden, dies zu tun - Sie können das MS-Befehlszeilendienstprogramm verwenden DCOMPerm (auch ici ), die Teil des SDK ist.

1 Stimmen

Besteht die Möglichkeit, dass es noch eine dcomper.exe da draußen gibt? Ich kann nirgendwo mehr eine vorkompilierte Version finden, die Links dazu scheinen tot zu sein

4voto

Arnout Punkte 2750

Diese Informationen werden gespeichert in HKCR\AppID\{Your-AppID}\LaunchPermission y AccessPermission . Dies sind REG_BINARY-Werte, die serialisierte Sicherheitsbeschreibungen enthalten. Keine Ahnung, ob es irgendetwas gibt, das bequemen Zugriff auf diese von .NET aus bietet...

Mehr Informationen über MSDN .

0voto

Thomas Punkte 5289

Ich habe diese Lösung gefunden, die funktioniert:

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

Falls es anderen hilft...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X