EternalWindows
アクセスコントロール / アクセス権

前節で述べたように、アカウントがオブジェクトのアクセスに成功するためには、 そのオブジェクトのDACLに、呼び出し側アカウントへアクセスを許可するACEが含まれている必要があります。 具体的にどのようなアクセスが成功するかは、ACEのアクセスマスクで定義されており、 これにはアカウントが指定可能なアクセス権が格納されています。 アクセス権とは、オブジェクトをどのように使用するかを示す定数であり、 主にオブジェクトのハンドルを取得する関数で指定することになります。

hFile = CreateFile(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

CreateFileの第2引数は、オブジェクトに対するアクセス権を指定します。 つまり、このアクセス権がACEのアクセスマスクに含まれていれば、 CreateFileの呼び出し側はそのアクセス権に準じた動作を行えるようになります。 GENERIC_READは、ファイルを読み取る際に指定するアクセス権ですから、 呼び出し側はReadFileなどの関数を呼び出せるようになります。 指定したアクセス権が本当にアクセスマスクに含まれているかを確認するには、 ACEのアクセスマスクを2進数で表示してみると分かりやすいでしょう。 次のようなアクセスマスクを持つACEがあったとします。

0000 0000 0001 1111 0000 0001 1111 1111

このアクセスマスクは16進数表記で0x001F01FFであり、前節のプログラムで表示した結果と同一であるはずです。 このアクセスマスクがGENERIC_READを許可しているかどうかは、 GENERIC_READ(0x80000000)を2進数で表し、アクセスマスクと比較することで分かります。

1000 0000 0000 0000 0000 0000 0000 0000 // 0x80000000(アクセス権)
0000 0000 0001 1111 0000 0001 1111 1111 // 0x001F01FF(アクセスマスク)

ここで注目すべきところは、アクセス権のビット列で1になっている部分が、 アクセスマスクの同じ部分でも1になっているかどうかです。 上記の例では、アクセス権のビット列の最上位ビットが1であるため、 アクセスマスクの最上位ビットも1になっている必要がありますが、 実際には0になっています。 このため、このアクセスマスクはGENERIC_READアクセス権を許可していないように思えますが、 実際にはそうではありません。 GENERIC_READのようなGENERIC_XXXアクセス権は汎用アクセス権と呼ばれますが、 こうしたアクセス権はアクセスマスクとの照合の前に、 標準アクセス権と特殊アクセス権にマッピング(変換)されるからです。 たとえば、ファイルへのアクセスの場合は、GENERIC_READはFILE_GENERIC_READへ変換されることになります。 FILE_GENERIC_READは、次のように定義されています。

#define FILE_GENERIC_READ         (STANDARD_RIGHTS_READ     |\
                                   FILE_READ_DATA           |\
                                   FILE_READ_ATTRIBUTES     |\
                                   FILE_READ_EA             |\
                                   SYNCHRONIZE)

本来、指定しなければならないアクセス権は、 FILE_READ_DATAやFILE_READ_ATTRIBUTESなどの特殊アクセス権です。 特殊アクセス権は、オブジェクト固有のアクセス権と考えてよいでしょう。 しかし、こうしたアクセス権を1つずつ覚えるのは大変ですから、 読み取りに必要なアクセス権をまとめたFILE_GENERIC_READが定義されています。 一般的に、FILE_GENERIC_READを指定せずにGENERIC_READを指定するのは、 GENERIC_READがどのようなオブジェクトへのアクセスでも利用できるからです。 たとえば、レジストリキーへのアクセスにGENERIC_READを指定すれば、 KEY_READにマッピングされるため、オブジェクト固有のアクセス権を理解する必要がなくなります。 FILE_GENERIC_READ(0x00120089)が先のアクセスマスクに含まれているかを確認してみましょう。

0000 0000 0001 0011 0000 0000 1000 1001 // 0x00120089(アクセス権)
0000 0000 0001 1111 0000 0001 1111 1111 // 0x001F01FF(アクセスマスク)

見て分かるように、上のアクセス権のビット列で1になっている部分は、 下のアクセスマスクの同じ部分でも1になっています。 よって、このACEへのFILE_GENERIC_READ(GENERIC_READ)は許可され、 オブジェクトへの読み取りアクセスができるようになります。 アクセス権を指定しすぎると、対応するビットがアクセスマスクで0になっている可能性が高くるため、 必要のないアクセス権は指定しないようにします。

アクセス権には、特殊アクセス権と汎用アクセス権の他に、標準アクセス権があります。 標準アクセス権は、どのようなオブジェクトに対しても有効なアクセス権です。 たとえば、オブジェクトからセキュリティ記述子を取得することは、 どのようなオブジェクトでも共通して起こり得ることですから、 こうしたアクセス権は標準アクセス権と呼ばれます。 次に、各種アクセス権がアクセスマスクで占める割合を見てみます。

定義 ビット 意味 権限
オブジェクトによって異なる 1〜16 オブジェクト固有のアクセス権 特殊
DELETE 17 このビットが立っておらず、尚且つコンテナオブジェクトがリーフオブジェクトの削除を認めていない場合、 削除は失敗となる。 標準
READ_CONTROL 18 セキュリティ記述子(所有者SID, DACLなど)の読み取りアクセス。 このアクセス権は、オブジェクトの所有者には暗黙のうちに付与される。 標準
WRITE_DAC 19 DACLとグループSIDへの書き込みアクセス。 このアクセス権は、オブジェクトの所有者には暗黙のうちに付与される。 標準
WRITE_OWNER 20 所有者SIDへの書き込みアクセス。 このアクセス権が許可されてなくても、SE_TAKE_OWNERSHIP_NAME特権が有効であれば、 書き込みは許可される。 標準
SYNCHRONIZE 21 WaitForSingleObjectを筆頭とする待機関数の利用。 オブジェクトによっては、このビットが立ってないとあらゆるアクセスが許可されないこともある。 標準
定義されていない 22〜23 復合権限 標準
ACCESS_SYSTEM_SECURITY 24 SACLを修正できるかどうか。 別個、SE_SECURITY_NAME特権が必要となる。 ---
MAXIMUM_ALLOWED 25 アカウントに許可されている最大のアクセス権をハンドルに割り当てる。 ---
定義されていない 26〜28 予約 ---
GENERIC_ALL 29 このアクセス権が許可されたならば、 そのオブジェクトに対しての全ての特殊アクセス権要求は成功する。 汎用
GENERIC_EXECUTE 30 実行や動作に関する特殊権限にマッピングされる。 汎用
GENERIC_WRITE 31 書き込みや変更に関する特殊権限にマッピングされる。 汎用
GENERIC_READ 32 読み込みや問い合わせに関する特殊権限にマッピングされる。 汎用

MAXIMUM_ALLOWEDは、アクセスマスク内でビットが立っていることはありません。 また、GENERIC_READなどの汎用アクセス権は、関数に指定した際にマッピングされるため、 同じくアクセスマスク内でビットが立っていることはありません。

汎用アクセス権のGENERIC_ALLは、 GENERIC_READ、GENERIC_WRITE、GENERIC_EXECUTEを 足し合わせた結果と等しくないことに注意してください。 次に、GENERIC_READ、GENERIC_WRITE、GENERIC_EXECUTEのいずれか、 あるいは全部を指定したときの標準アクセス権を示します。

10010

※右から
  DELETE       (削除)
  READ_CONTROL (セキュリティ記述子の取得)
  WRITE_DAC    (DACLの書き込み)
  WRITE_OWNER  (所有者SIDの書き込み)
  SYNCRONIZE   (待機関数の使用)

この結果から分かるように、GENERIC_ALLを指定しない場合は、 DACLの書き込みや所有者SIDの書き込みに失敗することになります。 ただし、削除に関しては、場合によっては成功することがあります。 GENERIC_ALLを指定した場合は、上記ビットが全て1となります。

次に、汎用アクセス権がオブジェクトによってどのようにマッピングされるのかを示します。 たとえば、ファイルにGENERIC_READを指定した場合は、 FILE_GENERIC_READにマッピングされます。 STANDARD_RIGHTS_REQUIREDは、DELETEからWRITE_OWNERまでの組み合わせです。

オブジェクトタイプ GENERIC_READ GENERIC_WRITE GENERIC_EXECUTE GENERIC_ALL
ファイル FILE_GENERIC_READ FILE_GENERIC_WRITE FILE_GENERIC_EXECUTE FILE_ALL_ACCESS
ディレクトリ STANDARD_RIGHTS_READ FILE_LIST_DIRECTORY FILE_ADD_FILE STANDARD_RIGHTS_WRITE FILE_ADD_SUBDIRECTORY FILE_READ_EA STANDARD_RIGHTS_EXECUTE FILE_LIST_DIRECTORY FILE_ADD_FILE STANDARD_RIGHTS_REQUIRED FILE_LIST_DIRECTORY FILE_ADD_FILE FILE_ADD_SUBDIRECTORY FILE_READ_EA
サービス STANDARD_RIGHTS_READ SERVICE_QUERY_CONFIG SERVICE_QUERY_STATUS SERVICE_ENUMERATE_DEPENDENTS SERVICE_INTERROGATE SERVICE_USER_DEFINED_CONTROL STANDARD_RIGHTS_WRITE STANDARD_CHANGE_CONFIG STANDARD_RIGHTS_EXECUTE SERVICE_START SERVICE_STOP SERVICE_PAUSE_CONTINUE SERVICE_USER_DEFINED_CONTROL SERVICE_ALL_ACCESS
プリンタ PRINTER_READ PRINTER_WRITE PRINTER_EXECUTE PRINTER_ALL_ACCESS
レジストリキー KRY_READ KEY_WRITE KEY_EXECUTE KEY_ALL_ACCESS
プロセス STANDARD_RIGHTS_READ PROCESS_VM_READ PROCESS_QUERY_INFORMATION STANDARD_RIGHTS_WRITE PROCESS_CREATE_PROCESS PROCESS_CREATE_THREAD PROCESS_VM_OPERATION PROCESS_VM_WRITE PROCESS_DUP_HANDLE PROCESS_TERMINATE PROCESS_SET_QUOTA PROCESS_SET_INFORMATION STANDARD_RIGHTS_EXECUTE SYNCHRONIZE PROCESS_ALL_ACCESS
スレッド STANDARD_RIGHTS_READ THREAD_GET_CONTEXT THREAD_QUERY_INFORMATION STANDARD_RIGHTS_WRITE THREAD_TERMINATE THREAD_SUSPEND_RESUME THREAD_SET_INFORMATION THREAD_SET_CONTEXT STANDARD_RIGHTS_EXECUTE SYNCHRONIZE THREAD_ALL_ACCESS
ジョブ STANDARD_RIGHTS_READ JOB_OBJECT_QUERY STANDARD_RIGHTS_WRITE JOB_OBJECT_ASSIGN_PROSESS JOB_OBJECT_SET_ATTRIBUTES STANDARD_RIGHTS_EXECUTE SYNCHRONIZE JOB_OBJECT_ALL_ACCESS
セマフォ STANDARD_RIGHTS_READ MUTANT_QUERY_STATE STANDARD_RIGHTS_WRITE SEMAPHORE_MODIFY_STATE STANDARD_RIGHTS_EXECUTE SYNCHRONIZE SEMAPHORE_ALL_ACCESS
イベント STANDARD_RIGHTS_READ MUTANT_QUERY_STATE STANDARD_RIGHTS_WRITE EVENT_MODIFY_STATE STANDARD_RIGHTS_EXECUTE SYNCHRONIZE EVENT_ALL_ACCESS
ミューテックス STANDARD_RIGHTS_READ MUTANT_QUERY_STATE STANDARD_RIGHTS_WRITE STANDARD_RIGHTS_EXECUTE SYNCHRONIZE MUTEX_ALL_ACCESS
ファイルマップドオブジェクト STANDARD_RIGHTS_READ FILE_MAP_COPY FILE_MAP_READ STANDARD_RIGHTS_WRITE FILE_MAP_WRITE STANDARD_RIGHTS_EXECUTE FILE_MAP_EXECUTE FILE_MAP_ALL_ACCESS
ウェイタブルタイマ STANDARD_RIGHTS_READ TIMER_QUERY_STATE STANDARD_RIGHTS_WRITE TIMER_MODIFY_STATE STANDARD_RIGHTS_EXECUTE SYNCHRONIZE TIMER_ALL_ACCESS
アクセストークン TOKEN_READ TOKEN_WRITE TOKEN_EXECUTE TOKEN_ALL_ACCESS
ウインドウステーション STANDARD_RIGHTS_READ WINSTA_ENUMDESKTOPS WINSTA_READATTRIBUTES WINSTA_ENUMERATE WINSTA_READSCREEN STANDARD_RIGHTS_WRITE WINSTA_ACCESSCLIPBOARD WINSTA_CREATEDESKTOP WINSTA_WRITEATTRIBUTES STANDARD_RIGHTS_EXECUTE WINSTA_ACCESSGLOBALATOMS WINSTA_EXITWINDOWS STANDARD_RIGHTS_REQUIRED WINSTA_ENUMDESKTOPS WINSTA_READATTRIBUTES WINSTA_ENUMERATE WINSTA_READSCREEN WINSTA_ACCESSCLIPBOARD WINSTA_CREATEDESKTOP WINSTA_WRITEATTRIBUTES WINSTA_ACCESSGLOBALATOMS WINSTA_EXITWINDOWS
デスクトップ STANDARD_RIGHTS_READ DESKTOP_READOBJECTS DESKTOP_ENUMERATE STANDARD_RIGHTS_READ DESKTOP_READOBJECTS DESKTOP_ENUMERATE DESKTOP_CREATEWINDOW DESKTOP_CREATEMENU DESKTOP_HOOKCONTROL DESKTOP_JOURNALRECORD DESKTOP_JOURNALPLAYBACK STANDARD_RIGHTS_EXECUTE DESKTOP_SWITCHDESKTOP STANDARD_RIGHTS_REQUIRED DESKTOP_READOBJECTS DESKTOP_WRITEOBJECTS DESKTOP_ENUMERATE DESKTOP_CREATEWINDOW DESKTOP_CREATEMENU DESKTOP_HOOKCONTROL DESKTOP_JOURNALRECORD DESKTOP_JOURNALPLAYBACK DESKTOP_SWITCHDESKTOP


戻る