Programmieren mit teilweiser Vertrauenswürdigkeit

Veröffentlicht: 08. Mai 2006

Von Keith Brown

Sicherheitsexperte Keith Brown vermittelt Ihnen praktisches Wissen für den Umgang mit teilweiser Vertrauenswürdigkeit. (12 gedruckte Seiten).

Auf dieser Seite

 Einführung
 Erste Erfahrungen mit CAS
 Wo können Anwendungsdaten gespeichert werden?
 Isolierte Speicherung
 Netzwerkkommunikation
 GUI
 Einschränkungen
 Gateways
 Neue Features in Visual Studio 2005
 Schlussbemerkung
 Der Autor

Einführung

In diesem Artikel wird Ihnen praktisches Wissen für den Umgang mit teilweiser Vertrauenswürdigkeit vermittelt. Ich werde Ihnen einige Programmierstrategien erläutern, wie z. B. das Speichern eines Zustands mithilfe isolierter Speicherung. Darüber hinaus stelle ich Ihnen Tools vor, mit denen Sie potenzielle Probleme ermitteln können, bevor diese auftreten. Außerdem erhalten Sie einen kurzen Einblick in einige neue Features von Visual Studio 2005, die die Entwicklung für teilweise vertrauenswürdige Umgebungen vereinfachen.

 

Erste Erfahrungen mit CAS

Viele Entwickler machen erste unangenehme Erfahrungen mit teilweiser Vertrauenswürdigkeit, wenn sie versehentlich Projekte in einer Netzwerkfreigabe statt auf dem lokalen Laufwerk ausführen. Da durch die Standardrichtlinien für Code, der nicht auf dem lokalen Laufwerk gespeichert ist, eingeschränkte Berechtigungen gewährt werden, werden für Programmvorgänge, die zuvor ordnungsgemäß ausgeführt werden konnten, Sicherheitsausnahmen ausgelöst. Aktionen, die offensichtlich mit der Sicherheit in Zusammenhang stehen, wie z. B. Aufrufe von File.Open, lösen SecurityExceptions aus. Jedoch werden solche Ausnahmen auch für anscheinend nicht sicherheitsrelevante Programmteile ausgelöst, z B. für das Steuerelement PropertyGrid in einer Windows Forms-Anwendung. Diese Probleme werden häufig in Newsgroups diskutiert.

Oft lautet die Lösung einfach: "Führen Sie das Programm auf dem lokalen Laufwerk aus." Das funktioniert auch, wenn Sie versehentlich ein Projekt in einer Netzwerkfreigabe erstellt haben. Wenn Sie eine Bereitstellung jedoch absichtlich über das Netzwerk vornehmen möchten, beispielsweise für eine Bereitstellung mit NTD (No-Touch Deployment), ist das Problem auf diese Weise sicher nicht zu lösen.

In der Praxis ergeben sich für Sie zwei Möglichkeiten. Erstens können Sie die Richtlinien ändern, sodass dem Programm die für dessen Ausführung erforderlichen Berechtigungen gewährt werden. Wenn Sie dem Programm tatsächlich volle Vertrauenswürdigkeit gewähren möchten und auch die Möglichkeit dazu haben, müssen Sie diesen Artikel nicht weiter lesen. Häufig sind Sie jedoch nicht in der Position, den Systemadministrator dazu zu bringen, die bereitgestellten .NET-Sicherheitsrichtlinien zu ändern, oder eine Änderung der Richtlinien erfordert einen unverhältnismäßigen Aufwand. In diesem Fall sollten Sie einfach die vorhandenen Berechtigungen akzeptieren und versuchen, ein Programm zu schreiben, das auch mit einem eingeschränkten Berechtigungssatz funktionsfähig ist.

Zurzeit stellt das Schreiben eines solchen Programms eine Herausforderung dar, da es unter Umständen schwer ist, die für die Anwendung tatsächlich erforderlichen Berechtigungen zu ermitteln. Beispielsweise finden Sie am Ende der Dokumentation von File.Open den Hinweis, dass für den Aufruf dieser Methode die Berechtigung FileIOPermission erforderlich ist. Sie werden jedoch – zumindest zum Zeitpunkt des Verfassens dieses Artikels – keinen solchen Hinweis für die PropertyGrid-Klasse finden, und dennoch erfordert diese Klasse bereits zum Instanzieren volle Vertrauenswürdigkeit.

Die Dokumentationen und Tools werden laufend verbessert. Beispielsweise wird mit Version 2.0 des Frameworks ein neues Tool namens PermCalc bereitgestellt, mit dem eine Assembly analysiert und die für die Assembly erforderlichen Berechtigungen berechnet werden können. Jedoch müssen Sie auch mit diesen Tools auf der Hut sein, um spätere Überraschungen zu vermeiden. Das Erstellen von Prototypen und Durchführen von Tests unter teilweiser Vertrauenswürdigkeit sind extrem wichtige Aufgaben, da Sie sicher vermeiden möchten, dass ein Feature mit teilweiser Vertrauenswürdigkeit nicht funktionsfähig ist, nachdem Sie bereits einige Arbeit in dieses Feature investiert haben.

In diesem Artikel werden die Probleme dargestellt, die beim Schreiben teilweise vertrauenswürdiger Anwendungen auftreten können, und Verfahren zur Problembehandlung erläutert. Ich gehe vom ungünstigsten Fall aus: Sie führen ein Programm im Internet oder lokalen Intranet aus, und Sie haben keine Möglichkeit, die Sicherheitsrichtlinien zu ändern. Wenn das Programm so geschrieben werden kann, dass es mit den vorhandenen Richtlinien auskommt, ist das Problem gelöst, da für die Funktionsfähigkeit des Programms keine Änderungen der Richtlinien erforderlich sind.

 

Wo können Anwendungsdaten gespeichert werden?

Nur sehr wenige Programme sind funktionsfähig, ohne jegliche Zustandsinformationen zu speichern. Datenbanken, Verzeichnisse und Dateisysteme dienen alle als Speicherorte für den Anwendungszustand. Wie Sie sich jedoch sicher denken können, wird jeder dieser drei Typen vertraulich behandelt und steht Programmen mit geringer Vertrauenswürdigkeit praktisch nicht zur Verfügung.

Wenn Sie auf eine Datenbank oder ein Verzeichnis ohne Richtlinienänderungen zugreifen möchten, müssen Sie dies direkt tun. Während Sie über keine Berechtigungen verfügen, um mit SQL Server oder Active Directory direkt zu kommunizieren, sind Sie berechtigt, über das Netzwerk mithilfe eines Webdiensts zu kommunizieren. Ziehen Sie also einen Webdienst in Betracht, um auf Daten zuzugreifen.

Wenn der Zustand auf dem lokalen Computer gespeichert werden muss, ermitteln Sie zunächst, von welchem Typ der Zustand ist. Für Dateien, die der Benutzer direkt anzeigen und ändern darf, beispielsweise Dokument- oder Bilddateien, müssen Sie Dateien erstellen, die der Benutzer problemlos findet. Da Sie mit teilweiser Vertrauenswürdigkeit arbeiten, ist es ratsam, zum Öffnen und Speichern dieser Dateien gewöhnliche Dateidialogfelder zu verwenden. Hierfür sind niedrigere Berechtigungen erforderlich als zum automatischen Öffnen der Dateien, da vom Benutzer festgelegt wird, welche Dateien verwendet werden dürfen. Im folgenden Beispiel wird mithilfe von OpenFileDialog eine Datei geöffnet und gelesen.

private void button1_Click(object sender,
                           System.EventArgs e) {
    OpenFileDialog dlg = new OpenFileDialog();
    if (DialogResult.OK == dlg.ShowDialog(this)) {
        using (Stream s = dlg.OpenFile()) 
        using (StreamReader r = new StreamReader(s)) {
            textBox1.Text = r.ReadToEnd();
        }
    }
}

Beachten Sie, dass zum Öffnen des Dateistreams jetzt OpenFileDialog.OpenFile verwendet wird. Beachten Sie außerdem, dass die Verwendung von OpenFileDialog.FileName vermieden wird, da Sie mit teilweiser Vertrauenswürdigkeit voraussichtlich nicht berechtigt sind, Informationen zur Form des Benutzerdateisystems abzurufen. Wenn Sie diese Eigenschaft lesen oder schreiben, wird sehr wahrscheinlich eine SecurityException ausgelöst.

In einigen Fällen ist es erforderlich, Anwendungseinstellungen zu speichern, die für den Benutzer vollständig transparent sind. In diesem Fall ist die Anzeige eines Dateidialogfelds nicht sinnvoll. Verwenden Sie stattdessen isolierten Speicher, um einen Dateistream abzurufen, in den Sie die Einstellungen schreiben, um sie zu einem späteren Zeitpunkt zu lesen.

 

Isolierte Speicherung

Isolierter Speicher wird als "isoliert" bezeichnet, da jede Assembly mit einem scheinbar eigenen, privaten Dateisystem arbeitet, das für keine andere Assembly sichtbar ist (unter der Voraussetzung teilweiser Vertrauenswürdigkeit – mit voller Vertrauenswürdigkeit werden Assemblys nicht daran gehindert, den isolierten Speicher anderer Assemblys zu lesen).

Es gibt verschiedene Ebenen der Isolierung, von denen Sie eine auswählen müssen, die für das Programm geeignet ist. Es ist nicht möglich, die Isolierungsebene zu einem späteren Zeitpunkt zu ändern. Benutzer- und assemblybasierte Isolierung ist mindestens erforderlich. Eine Benutzerisolierung ist erforderlich, da das Framework isolierte Speicherdateien in einem Unterverzeichnis des Benutzerprofils vorhält. Das Framework verwaltet die Assemblyisolierung, um sicherzustellen, dass jede Assembly im Benutzerprofil über ein eigenes Unterverzeichnis verfügt, das diese als Stamm ihres isolierten Dateispeichers behandelt.

Darüber hinaus können Sie auf Grundlage der Hostanwendung isolieren. Dies wird mit dem möglicherweise etwas irreführenden Begriff "Domänenisolierung" bezeichnet. Dies bedeutet lediglich, dass das Unterverzeichnis nicht nur auf Grundlage des Assemblynamens ausgewählt wird, sondern auch auf Grundlage des Assemblynamens der verwalteten EXE-Datei, durch die der Code geladen wurde. Die einzige praktische Anwendung für Domänenisolierung sind DLLs, die von mehreren Anwendungen gemeinsam genutzt werden. Beispielsweise arbeitet Math.dll auf dieser Isolierungsebene mit einem anderen isolierten Dateisystem, wenn sie in Calculator.exe geladen wird, als wenn sie von SalesForcaster.exe geladen wird.

Des Weiteren können Sie bei der Auswahl der Isolierungsebene festlegen, ob die Dateien auf dem Server gespeichert werden, wenn der Benutzer über ein Roaming-Profil verfügt. Sie können sich dies als computerbasierte Isolierung vorstellen.

Abhängig von der Vertrauenswürdigkeitsebene stehen Ihnen nicht alle dieser Isolierungsebenen zur Verfügung. In der Standardeinstellung müssen Sie in der lokalen Intranetzone lediglich auf Grundlage der Assembly und des Benutzers isolieren. D. h., Sie können ohne Einschränkung festlegen, ob die Dateien auf dem Server gespeichert werden, oder ob Sie darüber hinaus auf Grundlage der Hostanwendung isolieren möchten (Domänenisolierung). In der Internetzone wird in der Standardeinstellung die höchste Isolierungsebene erzwungen: Assembly, Benutzer, Domäne und Computer.

Nachdem Sie ermittelt haben, welche Isolierungsebene in Ihrem Fall geeignet ist, ist die eigentliche Verwendung von isoliertem Speicher tatsächlich ziemlich einfach. Wenn Sie mit der Verwendung eines Dateistreams vertraut sind, ist dies von Vorteil, da IsolatedStorageFileStream von FileStream erbt. Tatsächlich spielt für heutige Implementierungen lediglich ein Unterverzeichnis im Benutzerprofil eine Rolle, sodass Sie im Grunde nur mit normalen Dateien in einem normalen Dateisystem arbeiten. Wenn Sie bereits über Code verfügen, der normale Dateien öffnet, diese liest oder schreibt und dann schließt, müssen Sie für die Verwendung von isoliertem Speicher nur Code ändern, der die Datei tatsächlich öffnet. Im folgenden Beispiel wird generischer Code dargestellt, durch den Formulareinstellungen von einem XML-DOM geladen werden:

void LoadSettings(Stream s) {
    XmlDocument dom = new XmlDocument();
    dom.Load(s);
    string x = dom.SelectSingleNode("/settings/x").InnerText;
    string y = dom.SelectSingleNode("/settings/y").InnerText;
    this.Location = new Point(Int32.Parse(x), Int32.Parse(y));
    // ...
}

Dieser Code ist unabhängig davon, ob Sie eine normale Datei oder eine Datei im isolierten Speicher verwenden. Der einzige Unterschied besteht im physischen Speicherort der Datei auf dem Datenträger und in Bezug auf den Programmcode zum Öffnen der Datei. Im Folgenden finden Sie den restlichen Code, der zum Laden der Einstellungen aus dem isolierten Speicher erforderlich ist:

private void Form1_Load(object sender, System.EventArgs e) {
    using (Stream s = ReadFileFromIsoStore("settings.xml")) {
        LoadSettings(s);
    }
}

FileStream ReadFileFromIsoStore(string path) {
    IsolatedStorageFile fileSystem =
        IsolatedStorageFile.GetStore(MY_SCOPE, null, null);
    return new IsolatedStorageFileStream(path,
        FileMode.Open, FileAccess.Read, fileSystem);
}

const IsolatedStorageScope MY_SCOPE =
    IsolatedStorageScope.User |
    IsolatedStorageScope.Assembly |
    IsolatedStorageScope.Domain;

Beachten Sie, dass der verwendete Bereich (MY_SCOPE) die sicherste bzw. isolierteste Ebene darstellt. Es findet keine Speicherung auf dem Server statt, und Isolierungen basieren nicht nur auf Benutzer und Assembly, sondern auch auf der Domäne. Auf diese Weise können die Einstellungen sogar in der Internetzone gelesen und geschrieben werden.

Ein entscheidender Unterschied zwischen der lokalen Intranetzone und der Internetzone ist das Kontingent, das in den isolierten Speicher geschrieben werden kann. Dies kann in Zukunft zu Problemen führen, wenn Sie nicht sorgfältig sind, da diese Kontingente in Version 1.1 von .NET Framework noch nicht erzwungen werden: Das Standardkontingent für die lokale Intranetzone ist praktisch unbeschränkt. Das Kontingent für die Internetzone ist jedoch auf eine Gesamtdatenmenge von 10 KB begrenzt, die von einer Assembly in den isolierten Speicher geschrieben werden kann. Achten Sie also immer auf die Größe der geschriebenen Daten.

Ein weiterer häufiger Fehler bei der Verwendung von isoliertem Speicher ist, dass die Assembly auf Grundlage ihrer URL-Beweise identifiziert wird, solange sie nicht über einen starken Namen verfügt. Wenn der URL, von dem Sie die Assembly herunterladen, geändert wird, ändert sich auch das Verzeichnis für den isolierten Speicher. Unter Umständen gehen dadurch alle Anwendungseinstellungen verloren. Wenn Sie sich entscheiden, einen starken Namen zu verwenden, beachten Sie, dass dieser Name eine Versionsnummer enthält. Wenn Sie also die Versionsnummer ändern, stehen Sie vor demselben Problem. Wenn Benutzer zum Übernehmen ihrer alten Einstellungen berechtigt sein sollen, müssen Sie im Voraus planen.

 

Netzwerkkommunikation

Wenn Sie mit teilweiser Vertrauenswürdigkeit arbeiten, ist der Zugriff auf das Netzwerk erheblich eingeschränkt. Sie haben in diesem Fall keine Möglichkeit, auf Remotedatenbanken zuzugreifen, da hierfür Datenbankberechtigungen erforderlich sind, die durch die Standardrichtlinien normalerweise nicht gewährt werden. Darüber hinaus können Sie weder .NET Remoting noch COM+ verwenden, da deren Verwendung volle Vertrauenswürdigkeit erfordert.

Die Standardrichtlinien schließen eine spezielle Codegruppe namens NetCodeGroup ein, die eingeschränkten Zugriff auf das Netzwerk im lokalen Intranet oder dem Internet gewährt. Diese Codegruppe generiert die Gewährung einer dynamischen WebPermission auf Grundlage der Beweise für die Assembly. Beispiel: Sie möchten eine intelligente Clientanwendung von der Website http://www.pluralsight.com/ herunterladen. In diesem Fall berechnet NetCodeGroup eine WebPermission, mit der die Anwendung berechtigt wird, HTTP- oder HTTPS-Anforderungen an pluralsight.com zurückzusenden. Das heißt, der Code kann eine direkte HttpWebRequest-Anforderung oder einen Webdienst verwenden, der eines der beiden Protokolle unterstützt. Beachten Sie, dass der Code auf die Verwendung von HTTPS-Anforderungen eingeschränkt wird, wenn der intelligente Client über HTTPS (anstelle von HTTP) heruntergeladen wird. Durch diese Einschränkung wird die vom Benutzer erwartete minimale Sicherheitsebene gewährleistet, wenn der Code ursprünglich über HTTPS heruntergeladen wurde.

Ein häufig auftretendes Problem ist beispielsweise, dass die Proxy-Eigenschaft für HttpWebRequest eine uneingeschränkte WebPermission erfordert. Wie die FileName-Eigenschaft von OpenFileDialog ist dies ein Beispiel für ein Feature einer Klasse, das andere Berechtigungen erfordert als die Klasse selbst.

 

GUI

Eine Tatsache, die Entwickler von intelligenten Clients häufig überrascht, ist, dass für viele GUI-Komponenten bestimmte Berechtigungen erforderlich sind, um mit teilweiser Vertrauenswürdigkeit fehlerfrei zu funktionieren. Beispiel: Sie erstellen ein PropertyGrid für eine intelligente Clientanwendung. Während der Entwicklung der Anwendung treten keine Probleme auf, bei der Bereitstellung in einer Umgebung mit teilweiser Vertrauenswürdigkeit löst das PropertyGrid jedoch SecurityExceptions aus.

Das Grid verwendet Reflection, um die Form der dargestellten Klasse zu ermitteln und Eigenschaften für die Klasse abzurufen und festzulegen. Reflection ist jedoch nicht eingeschränkt, wenn diese nur für öffentliche Member verwendet wird. Das PropertyGrid zeigt nur öffentliche Member an, sodass der Grund für die Ausnahmen an dieser Stelle nicht zu finden ist. Wenn Sie für System.Windows.Forms.dll das Programm Permview.exe ausführen (ein mit dem .NET Framework SDK bereitgestelltes Tool), wird ein Verknüpfungsaufruf für die PropertyGrid-Klasse angezeigt, durch den für das Erstellen einer Verknüpfung mit der Klasse uneingeschränkte Berechtigungen erforderlich sind. Daher sind teilweise vertrauenswürdige Aufrufer nicht zur Verwendung des PropertyGrid berechtigt. Wenn ein solcher Verknüpfungsaufruf vorhanden ist, sollten Sie beachten, dass der vom Verknüpfungsaufruf geschützte Code unter Umständen von teilweise vertrauenswürdigem Code verwendet wird, um die Berechtigungsebene in irgendeiner Weise zu erhöhen.

Zum Zeitpunkt des Verfassens dieses Artikels wird in der Dokumentation für PropertyGrid nicht erwähnt, dass bestimmte Berechtigungen erforderlich sind, obwohl ich bereits eine Anfrage eingereicht habe, um diese Auslassung zu korrigieren. Tatsächlich umfasst die Dokumentation solche Probleme nicht immer zu 100 %, und auch wenn dies der Fall wäre, würden wir uns wahrscheinlich eher auf IntelliSense verlassen, als auf die Dokumentation. Glücklicherweise wird dieses Problem in Visual Studio 2005 behandelt, wie weiter unten in diesem Artikel erläutert.

Letzten Endes ist das Durchführen von Tests unter teilweiser Vertrauenswürdigkeit der beste Weg, um ggf. vorhandene Probleme dieser Art zu einem frühen Zeitpunkt zu ermitteln. Erstellen Sie Prototypen mit teilweiser Vertrauenswürdigkeit, und führen Sie bereits zu einem frühen Zeitpunkt häufige Tests durch.

 

Einschränkungen

Teilweise Vertrauenswürdigkeit wird nicht vom gesamten .NET Framework unterstützt. Wenn eine Frameworkassembly nicht über das AllowPartiallyTrustedCallers-Attribut (APTCA) verfügt, unterstützt diese keine teilweise Vertrauenswürdigkeit. Vor einiger Zeit habe ich das Programm FindAPTC geschrieben, das immer noch unter www.pluralsight.com/samples.aspx zur Verfügung steht. Dieses Programm listet sämtliche DLLs im aktuellen Verzeichnis auf und zeigt an, welche Bibliotheken über APTCA verfügen und welche nicht. Wenn Sie dieses Programm im v1.1.4322-Unterverzeichnis von .NET Framework ausführen, erhalten Sie eine Ausgabe wie im folgenden Code. Zu den wichtigeren Subsystemen, die keine teilweise Vertrauenswürdigkeit unterstützen, zählen .NET Remoting, System.EnterpriseServices, System.DirectoryServices, System.Management und System.Messaging. Wenn Sie eine dieser Assemblys in teilweise vertrauenswürdigem Code verwenden, stehen Sie vor dem Problem eines Verknüpfungsaufrufs für volle Vertrauenswürdigkeit.

FindAPTC-Ausgabe für Version 1.1 von .NET Framework

Allows partially trusted callers:
Accessibility.dll
IEExecRemote.dll
Microsoft.JScript.dll
Microsoft.VisualBasic.dll
Microsoft.Vsa.dll
mscorlib.dll
System.Data.dll
System.dll
System.Drawing.dll
System.Web.dll
System.Web.Mobile.dll
System.Web.RegularExpressions.dll
System.Web.Services.dll
System.Windows.Forms.dll
System.XML.dll

Does NOT allow partially trusted callers:
cscompmgd.dll
CustomMarshalers.dll
envdte.dll
IEHost.dll
IIEHost.dll
ISymWrapper.dll
Microsoft.VisualBasic.Compatibility.Data.dll
Microsoft.VisualBasic.Compatibility.dll
Microsoft.VisualBasic.Vsa.dll
Microsoft.VisualC.Dll
Microsoft.Vsa.Vb.CodeDOMProcessor.dll
Microsoft_VsaVb.dll
mscorcfg.dll
office.dll
RegCode.dll
System.Configuration.Install.dll
System.Data.OracleClient.dll
System.Design.dll
System.DirectoryServices.dll
System.Drawing.Design.dll
System.EnterpriseServices.dll
System.Management.dll
System.Messaging.dll
System.Runtime.Remoting.dll
System.Runtime.Serialization.Formatters.Soap.dll
System.Security.dll
System.ServiceProcess.dll
vjscor.dll
VJSharpCodeProvider.DLL
vjslib.dll
vjslibcw.dll
vjswfc.dll
VJSWfcBrowserStubLib.dll
vjswfccw.dll
vjswfchtml.dll

Sogar unter den Assemblys, die teilweise Vertrauenswürdigkeit unterstützen, gibt es Ausnahmen. Einige Klassen verfügen über FullTrust-Verknüpfungsaufrufe, um deren Verwendung auf voll vertrauenswürdigen Code einzuschränken. Ein bemerkenswertes Beispiel ist das zuvor erwähnte PropertyGrid. In anderen Fällen sind Anforderungen für Berechtigungen vorhanden, über die normalerweise nur voll vertrauenswürdiger Code verfügt, häufig UnmanagedCode. Beispielsweise schlägt der Versuch, den systemeigenen Fensterhandle in einem Windows Forms-Steuerelement unter teilweiser Vertrauenswürdigkeit abzurufen, aus genau diesem Grund fehl. Wenn Sie denken, dass das .NET Framework umgangen wird (z. B. durch den direkten Zugriff auf Fensterhandles), ist dies wahrscheinlich tatsächlich der Fall, und Sie können den fraglichen Vorgang mit teilweiser Vertrauenswürdigkeit nicht ausführen.

Im Folgenden werde ich ein Verfahren erläutern, mit dem Sie Klassen oder Member von Klassen mit Verknüpfungsaufrufen für volle Vertrauenswürdigkeit oder besonders hohe Berechtigungen schnell ermitteln können. Beachten Sie jedoch, dass auf diese Weise nicht alle Fehler gefunden werden können, die mit teilweiser Vertrauenswürdigkeit zusammenhängen. Führen Sie Permview.exe mit der Option /decl für alle Frameworkassemblys aus, die Sie verwenden möchten, und suchen Sie insbesondere nach LinktimeDemand-Einträgen. Wenn Sie das Programm für System.Windows.Forms.dll ausführen, können Sie sofort erkennen, dass das PropertyGrid teilweise vertrauenswürdigen Code nicht unterstützt (Namespaces sind hier der Übersichtlichkeit halber ausgelassen).

Class PropertyGrid LinktimeDemand permission set:
<PermissionSet class="PermissionSet"
               version="1"
               Unrestricted="true"/>

Das bedeutet, dass zur Verknüpfungszeit volle Vertrauenswürdigkeit gewährt wird: Der aufrufenden Assembly muss der an dieser Stelle aufgelistete Berechtigungssatz gewährt werden.

 

Gateways

In einigen Fällen ist es sinnvoll, einer teilweise vertrauenswürdigen Anwendung spezielle Berechtigungen zu gewähren. Eine einfache Börsentickeranwendung, die von einer Website bereitgestellt wird, muss unter Umständen Börsennotierungen von einer entfernten Website abrufen. Ein Administrator kann ggf. Richtlinien anpassen, um der Börsentickeranwendung eine WebPermission zu gewähren, die zum Herstellen einer Verbindung zur Website mit den Börsennotierungen erforderlich ist. Dies ist ein Beispiel für eine fein abgestufte Anpassung der Richtlinien.

Welche Maßnahmen müssen Sie ergreifen, wenn die gewünschte Funktionalität jedoch mit einer fein abgestuften Richtlinienanpassung nicht erzielt werden kann? Wie müssen Sie vorgehen, wenn Sie mithilfe von System.EnterpriseServices eine COM+-Komponente auf einem Remotecomputer abrufen müssen? Dieser Vorgang kommt in vielen Unternehmen häufig zur Anwendung. Sie können beispielsweise den Administrator bitten, der Anwendung volle Vertrauenswürdigkeit zu gewähren. Dies stellt sicherlich die einfachste Vorgehensweise dar. Wenn Sie jedoch mit teilweiser Vertrauenswürdigkeit arbeiten möchten, sollten Sie den Entwurf eines so genannten Gateways in Betracht ziehen.

.NET Framework enthält bereits eine Reihe von Gateways. Betrachten wir beispielsweise die Funktionsweise der FileStream-Klasse: Diese Klasse ist in verwaltetem Code geschrieben und wird immer in einer voll vertrauenswürdigen Assembly ausgeführt (.NET Framework selbst ist immer voll vertrauenswürdig). Sie kann jedoch von teilweise vertrauenswürdigen Aufrufern aufgerufen werden, und die einzige Anforderung ist, dass diese über die korrekten FileIOPermission-Berechtigungen für die Datei verfügen, auf die sie zugreifen möchten.

Die FileStream-Klasse dient als Gateway, indem eine fein abgestufte Berechtigung (in diesem Fall FileIOPermission) angefordert wird. Anschließend wird eine gröber abgestufte Berechtigung (in diesem Fall SecurityPermission für UnmanagedCode) bestätigt, und die Datei wird geöffnet, indem im Auftrag des teilweise vertrauenswürdigen Aufrufers eine Anforderung an das Betriebssystem gesendet wird. Die Vorgehensweise ist erforderlich, da eine Berechtigungsanforderung normalerweise im Stapel nach oben geschoben wird und alle Aufrufer im Stapelrahmen die angeforderte Berechtigung aufweisen müssen. Da die FileStream-Klasse als Gateway dient, bestätigt sie die eigene Berechtigung, um nicht verwalteten Code aufzurufen, sodass ihre Aufrufer diese Berechtigung nicht benötigen.

Was hat dies mit dem vorliegenden Problem zu tun? Sie können bei Bedarf eigene Gatewayklassen schreiben. In Abbildung 1 wird die Architektur eines COM+-Börsentickergateways dargestellt.

Beispiel für ein COM+-Gateway
Abbildung 1: Beispiel für ein COM+-Gateway

Der verwaltete Wrapper um die COM+-Komponente wird in einer voll vertrauenswürdigen Assembly zusammengefasst (diese wird üblicherweise im globalen Assemblycache installiert). Eine Klasse namens StockTickerPermission wird von CodeAccessPermission abgeleitet und übergibt dem Gateway eine anzufordernde benutzerdefinierte, fein abgestufte Berechtigung, bevor die Berechtigung zum Aufrufen von nicht verwaltetem Code bestätigt wird. Auf diese Weise kann der Systemadministrator den Zugriff auf die COM+-Komponente über Richtlinien steuern, indem die StockTickerPermission gewährt bzw. nicht gewährt wird, ohne auf die Gewährung voller Vertrauenswürdigkeit zurückgreifen zu müssen. Natürlich ist das Schreiben eines solchen Gateways mit einer großen Verantwortung verbunden, und da das Gateway voll vertrauenswürdig sein muss, ist eine vollständige "No-Touch"-Bereitstellung nicht mehr möglich. Gatewayklassen bieten jedoch Möglichkeiten, mit denen Sie vertraut sein sollten – sie werden Ihnen möglicherweise eines Tages von Nutzen sein.

 

Neue Features in Visual Studio 2005

Die neue Version von Visual Studio verfügt über einige Features, die dem einfacheren Erstellen teilweise vertrauenswürdiger Anwendungen dienen. Das erste Feature heißt "IntelliSense pro Zone" und erlaubt es im Prinzip, für Code eine Zone auszuwählen, damit in allen IntelliSense-Menüs Methoden, Eigenschaften und Klassen abgeblendet werden, die für diese Zone nicht zur Verfügung stehen. Wenn Sie beispielsweise eine Bereitstellung in der Internetzone vornehmen möchten, können Sie auf diese Weise verhindern, dass Sie Features auswählen, die in dieser Zone fehlschlagen. Dies wird in Abbildung 2 dargestellt.

IntelliSense pro Zone
Abbildung 2: IntelliSense pro Zone

Ein weiteres neues Feature ist das ebenfalls in Visual Studio integrierte Tool Permcalc.exe. Dieses Tool untersucht den Code einer Assembly und ermittelt die Berechtigungen, die zum Ausführen der Assembly erforderlich sind. In Abbildung 3 wird die Integration dieses Features auf der Projekteigenschaftenseite von Visual Studio dargestellt. Das Tool bezieht nach Möglichkeit sogar imperative Berechtigungsanforderungen wie Assertions und Demands in die Berechnungen ein.

PermCalc
Abbildung 3: PermCalc

 

Schlussbemerkung

Das Erstellen von Anwendungen, die unter teilweiser Vertrauenswürdigkeit ausgeführt werden, erfordert Geduld und sorgfältige Planung, ist jedoch sehr effektiv. Die Bereitstellung ist wesentlich einfacher, da Sie NTD (No-Touch Deployment) verwenden können. Darüber hinaus müssen Sie die Sicherheitsrichtlinien für den Benutzercomputer selten ändern, da der Code auf natürliche Weise mit dem ihm gewährten Standardberechtigungssatz ausgeführt wird (für Unternehmensanwendungen ist dies normalerweise die lokale Intranetzone). Wenn für die Anwendung keine Änderungen der Sicherheitsrichtlinie erforderlich sind, wird diese mit wesentlich höherer Wahrscheinlichkeit im Unternehmen tatsächlich eingesetzt.

Wenn Sie sorgfältig arbeiten, Prototypen erstellen und konsequent Tests unter teilweiser Vertrauenswürdigkeit durchführen, werden Sie dabei große Erfolge erzielen. Sie sollten einige Zeit damit verbringen, sich mit den in .NET Framework definierten Berechtigungen vertraut zu machen. Auf diese Weise können Sie wesentlich besser einschätzen, welche Vorgänge von vornherein vertraulich behandelt werden müssen. Für den Anfang stellt die Beschäftigung mit dem .NET Framework-Konfigurationstool eine einfache Übung dar. Erstellen Sie einen eigenen Berechtigungssatz, und verwenden Sie den Editor, um jeden der verschiedenen Berechtigungstypen einzeln hinzuzufügen, damit Sie einen Überblick über die jeweiligen Optionen erhalten. Auf diese Weise können Sie eine Menge lernen. Suchen Sie außerdem in der Dokumentation (normalerweise unten auf der Seite) nach einem Abschnitt mit dem Titel "Requirements, .NET Framework Security" ("Anforderungen, .NET Framework-Sicherheit"). Wenn ein solcher Abschnitt vorhanden ist, benötigt das Feature eine Berechtigung. Stellen Sie sicher, dass diese Berechtigung zur Laufzeit zur Verfügung steht.

 

Der Autor