Windows ではセキュリティ設定が可能なオブジェクト (securable object) のオーナーやアクセス権設定などはセキュリティ記述子 (security descriptor) で表現することになっています。

で、 .NET においてセキュリティ記述子を表すクラスはいくつかあります。

1つは GenericSecurityDescriptor 派生クラスです。クラス階層は以下のようになります。

Object
 `- GenericSecurityDescriptor
     +- CommonSecurityDescriptor
     `- RawSecurityDescriptor

こちらのグループは Win32 API を直で触るのに近いインターフェースになっています。ただし、securable object について GenericSecurityDescriptor クラスのオブジェクトを取得or設定する .NET API は軽く調べた限りでは存在しないようです(あったら教えて)。仕方がないので、例えば GetSecurityInfo Win32 API でアンマネージバイナリ表現を取得し、Marshal.Copy で byte[] に変換し、コンストラクタに渡す、という手順を踏む必要があります。

もう1つは ObjectSecurity 派生クラスです。クラス階層は以下のようになります。

Object
 `- ObjectSecurity
     +- CommonObjectSecurity
     |   `- NativeObjectSecurity
     |       +- FileSystemSecurity
     |       |   +- DirectorySecurity
     |       |   `- FileSecurity
     |       +- RegistrySecurity
     |       `- 他にもいっぱい
     `- DirectoryObjectSecurity

こちらのグループは securable object の種類ごとにクラスが分かれており、例えばファイルでは FileSecurity、レジストリキーでは RegistrySecurity、といった対応になります。また、例えばファイルなら File.GetAccessControl メソッドで取得し、File.SetAccessControl メソッドで設定することができます。GenericSecurityDescriptor のグループより最初の一歩がお手軽です。

で、私が把握している範囲では、両者の主な差異は以下のようになります。

RawSecurityDescriptor CommonSecurityDescriptor ObjectSecurity 派生クラス
暗黙的な ACL の最適化 なし あり
trustee の表現クラス SecurityIdentifier IdentityReference 派生クラス (SecurityIdentifier または NTAccount)
ACL (DACL/SACL) の表現クラス RawAcl DiscretionaryAcl および SystemAcl AuthorizationRuleCollection
ACE の表現クラス GenericAce 派生クラス (主に CommonAce クラス) クラスによって異なる (たとえば FileSystemAccessRule クラス)
ACL の取得方法 DiscritionaryAcl/SystemAcl プロパティ GetAccessRules/GetAuditRules メソッドでコピーを取得
ACL の変更方法 ACL を組み立てて DiscritionaryAcl/SystemAcl プロパティにセット または プロパティから返るオブジェクトを直接操作 AddAccessRule メソッド等で ACE を1つずつ操作する

「暗黙的な ACL の最適化」とは、AddAccessRule 等で ACL を操作したり、SetSecurityDescriptorSddlForm 等で ACL を変更した時に、ACE の数が少なくなるように結合したり順序を入れ替えたりすることです(GetAccessControl メソッドで取得した時には最適化は行われない)。たとえば、「Users に書き込みを許可」と「Users に読み込みを許可」の2つの ACE があると、暗黙的に「Users に読み書きを許可」という1つの ACE に結合されます。

ちなみに、最適化のルールはセキュリティ記述子がコンテナ(ディレクトリやレジストリキー)に対するものかコンテナ以外(ファイルやサービス)に対するものかどうか、あるいはディレクトリサービスオブジェクトに対するものかどうかで異なります。この差異は ObjectSecurity 派生クラスではクラス自体によって表現されますが、CommonSecurityDescriptor クラスではコンストラクタにフラグを渡すことによって実現されます。RawSecurityDescriptor クラスでは最適化は行われないので、これらのフラグは持ちません。

「ACL の変更方法」も大きな違いがあります。ObjectSecurity 派生クラスは ACL を一括で変更する方法が無いので、1つずつ追加削除する必要があり、めんどくさいことになります。さらに、追加と削除が混在した操作を行おうとすると、前述の暗黙的な ACL の最適化が介入して、予想とは異なった結果が発生することがあります。

Trackback

no comment untill now

Add your comment now