|
|
解説
インサイド .NET Framework [改訂版]
第7回 コード・アクセス・セキュリティ(その2)
吉松 史彰
2003/08/20 改訂(改訂前の記事はこちら) |
本稿は、2002/10/18に公開された記事を、.NET Frameworkの新しいバージョンである「.NET Framework 1.1」に対応させ、全面的に加筆・修正を行った改訂版です。 |
はじめに
前回は、アセンブリがロードされるときに共通言語ランタイム(CLR)が行う、コード・アクセス・セキュリティのセットアップ手順を解説した。そこで、今回は実際にエビデンス(証拠)が収集される様子をコードで確認しながら、よりコード・アクセス・セキュリティの内部に迫ってみようと思う。
収集されたエビデンスの取得
前回も利用したMainClass.exeとFileReader.dllを使って、FileReaderアセンブリがロードされるときに収集されたエビデンスを確認してみる。.NET Frameworkでは、収集されたエビデンスはSystem.Security.Policy.Evidenceクラスによりアクセスすることができる。アセンブリに対して収集されたエビデンスは、System.Reflection.AssemblyクラスのEvidenceプロパティからアクセス可能なので、次のようなコードでFileReaderアセンブリに対して収集されたエビデンスを確認することができる(太字が前回のコード(MainClass.cs)からの変更点)。
using System;
class MainClass {
static void Main(string[] args) {
FileReader reader = new FileReader(args[0]);
System.Reflection.Assembly asm
= reader.GetType().Assembly;
System.Security.Policy.Evidence evidence
= asm.Evidence;
System.Collections.IEnumerator e1
= evidence.GetAssemblyEnumerator();
int i = 0;
while(e1.MoveNext()) {
Console.WriteLine(e1.Current.GetType());
i++;
}
System.Collections.IEnumerator e2
= evidence.GetHostEnumerator();
int j = 0;
while(e2.MoveNext()) {
Console.WriteLine(e2.Current.GetType());
j++;
}
Console.WriteLine("{0}:{1}", i, j);
// Console.WriteLine(reader.ReadWhole());
}
}
|
|
収集されたエビデンスを確認するために前回のMainClass.csを修正したサンプル・コード |
このサンプル・コードを実行するためには、前回掲載したFileReader.csが必要となる。 |
まず、FileReaderクラスのオブジェクトからGetTypeメソッドで型情報を取得し、その型が所属するアセンブリをAssemblyプロパティから取得する。次に、そのアセンブリのEvidenceプロパティにアクセスしてEvidenceクラスのオブジェクトを取得する。このオブジェクトが、今回FileReaderアセンブリに対して収集されたエビデンスをすべて管理している。
Evidenceクラスはコレクションになっており、内部に配列のようなイメージで収集された複数のエビデンスを保管している。実は、前回解説した7種類のエビデンスは「ホスト・エビデンス」と呼ばれる種類のもので、CLRがデフォルトで収集するエビデンスである。エビデンスにはもう1種類、「アセンブリ・エビデンス」という種類がある。こちらは、必要に応じて開発者が自ら追加できるエビデンスだ。今回は特に何も追加していないので、ホスト・エビデンスだけが収集されているはずである。
上記のコードで、GetAssemblyEnumeratorメソッドを呼び出して取得するIEnumeratorインターフェイスは、エビデンス中に含まれるアセンブリ・エビデンスを1つ1つたどるためのものだ。今回は、アセンブリ・エビデンスは1つもないので、実際には変数e1に対するwhileループは1回も回らない。
GetHostEnumeratorメソッドを呼び出して取得するIEnumeratorインターフェイスは、エビデンス中に含まれるホスト・エビデンスを1つ1つたどるためのものだ。こちらはいくつか存在する。実際に上記のコードを実行すると、次のような結果を得ることができる。
C:\TEMP>MainClass.exe C:\Boot.ini
System.Security.Policy.Zone
System.Security.Policy.Url
System.Security.Policy.Hash
0:3
|
|
上記サンプル・コードの実行結果例 |
FileReaderアセンブリに対して3つのエビデンスが含まれていることが分かる。最後の表示「0:3」は、アセンブリ・エビデンスが0で、ホスト・エビデンスが3つあることを示している。 |
アセンブリ・エビデンスが0で、ホスト・エビデンスは3つあるので、最後の表示は「0:3」となる。3つのホスト・エビデンスの中身は、上記のとおり3種類のクラス(のオブジェクト)になっている。それぞれ前回説明した「アセンブリの出所に関するエビデンス(Zone、Url)」が2つと、「アセンブリそのものを指すエビデンス(Hash)」になっている。
中身が分かったので、実際のデータ(どのZoneやUrlが適用されたのか)を知るために、次のようなコードを書くことができる。上記のwhileループを変更して、エビデンスの種類ごとにオブジェクトをキャストし、中身を取り出している。
while(e2.MoveNext()) {
switch(e2.Current.GetType().ToString()) {
case "System.Security.Policy.Zone":
System.Security.Policy.Zone zone
= (System.Security.Policy.Zone)e2.Current;
Console.WriteLine("Zone:{0}", zone.SecurityZone.ToString());
break;
case "System.Security.Policy.Url":
System.Security.Policy.Url url
= (System.Security.Policy.Url)e2.Current;
Console.WriteLine("Url:{0}", url.Value);
break;
case "System.Security.Policy.Hash":
System.Security.Policy.Hash hash
= (System.Security.Policy.Hash)e2.Current;
Console.Write("Hash:");
foreach(byte b in hash.SHA1)
Console.Write(b.ToString("X") + " ");
Console.WriteLine();
break;
}
j++;
}
|
|
アセンブリの各ホスト・エビデンスの値を調べるためのコード |
上記の修正したMainClass.csの2つ目のwhileループをこのコードに置き換える。 |
実行してみると、結果は次のようになる(ディレクトリやハッシュ値などは異なるだろう)。
C:\TEMP>MainClass.exe C:\Boot.ini
Zone:MyComputer
Url:file://C:/TEMP/FileReader.DLL
Hash:9E C4 8 62 2A BB 2D 7F D3 98 38 9E FD 89 73 41 4 B8 91 56
0:3
|
|
whileループを置き換えたサンプル・コードの実行結果例 |
3つのホスト・エビデンス(Zone、Url、Hash)の持つ値が表示される。 |
FileReaderアセンブリはMyComputerゾーンに属し、file://C:/TEMP/FileReader.DLLからダウンロードされて実行されたことが分かる。このエビデンスを持って、CLRはポリシーの確認を始めるわけだ。
Insider.NET 記事ランキング
本日
月間