解説

インサイド .NET Framework

第10回 コード・アクセス・セキュリティ(その2)

インフォテリア株式会社
吉松 史彰
2002/10/18 改訂版はこちら(2003/08/20)

Page1 Page2 Page3 Page4

始めに

 前回は、アセンブリがロードされるときに共通言語ランタイム(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はポリシーの確認を始めるわけだ。


 INDEX
  解説 インサイド .NET Framework
  第10回 コード・アクセス・セキュリティ(その2)
  1.収集されたエビデンスの取得
    2.厳密名やロード方法により変化するエビデンス
    3.X.509証明書によるエビデンスの提供
    4.コラム:テスト用の証明書の利用方法
 
インデックス・ページヘ  「解説:インサイド .NET Framework 」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間