Technically Impossible

Lets look at the weak link in your statement. Anything "Technically Impossible" basically means we haven't figured out how yet.

VBScriptでフォルダの参照権限を参照する。Vol.2

これは2005年に投稿したエントリーで、以前のブログから引き継いだものです。

前回:VBScriptでフォルダの参照権限を参照する。Vol.1

続いてフォルダの参照権限を変更します。既存の参照権限を変更する分には文句なしに簡単ですが、アカウントを追加してそこに新たな参照権限を加えるとなると、非常に厄介です。まず、参照権限の変更から。

参考文献は例によって、Subject:General Permission notesです。


参照権限を変更したいアカウントが既に判明していると言う前提で、testフォルダのアカウントtest_playerに割り当てられているFull Control権限をRead Onlyに変更する場合です。先日紹介したオブジェクトACEのプロパティAccessMaskへ適切な値を設定し、setSecurityDescriptorを実行します。具体的には、こんな感じ。

set myWMI = getObject("winmgmts:\root\cimv2:Win32_LogicalFileSecuritySetting='c:\test'")
msgbox "now, looking at " & myWMI.path

if myWMI.getSecurityDescriptor(mySD) = 0 then
    for each myACE in mySD.dacl
        if ucase(myAce.trustee.name) = ucase("test_player") then
            myAce.AccessMask = 1179817
        end if
    next
end if

if myWMI.setSecurityDescriptor(mySD) = 0 then
    msgbox "setting security complete"
else
    msgbox "can't set security"
end if

参照権限の適切な値を設定した後で、そのオブジェクトに対してsetSecurityDescriptorを実行するのがポイントですね。コレが実行されるまで、参照権限は変更されません。

アカウントを新規追加して、その参照権限を変更する方法ですが...コードを交えながら解説する前に、その手順について説明します。以下の手順を辿ることになります。

  1. 対象アカウントのSIDを取得する。
  2. 新規Trusteeオブジェクトを作成し、適切なプロパティを設定する。
  3. 新規ACEオブジェクトを作成し、適切なプロパティを設定する。
  4. ACEオブジェクトをDACLへ追加する。
  5. setSecurityDescriptorを実行する。

4がポイントです。一見すると、今までやってきたことで大丈夫、最後にsetSecurityDescriptorを実行すれば良いだけだと思うのですが、違うのです。何がポイントかと言うと、

  1. ACEは配列で、resizeしてなければならない。
  2. DACLは配列であるが、動的配列ではない。

ということ。そのため、

  1. 適切なサイズの配列を作成する。
  2. 既存のACE、DACLを新規ACEと共に、1の配列へコピーする。
  3. 2の配列を既存のDACLと置き換える。

と言う手順を踏まなければなりません。技術的には全然不可能ではなく、サンプルも非常にシンプルではあるものの、深みに陥りやすい個所だと思います。

参考文献のサンプルでは、この処理のために次の手順を踏んでいます。

  1. 動的変更を容易にするため、Dictionaryを作成する。
  2. DACLをループさせ、適切な参照権限を持つACEだけをDictionaryに移す。

コードにすると、こんな感じ。すでにmySDに新規アカウントが設定されていると言う前提です。

set myDictionary = createObject("Scripting.Dictionary")

for i = lbound(mySD.dacl) to ubound(mySD.dacl)
    if not mySD.dacl(i).AceFlags and 16 then
        myDictionary.add i, mySD.dacl(i)
    end if
next

mySD.dacl = myDictionary.items

if myWMI.setSecurityDescriptor(mySD) = 0 then
    msgbox "settin security complete"
else
    msgbox "can't set security"
end if

長くなったため、1-3の手順はエントリーを分けました。次のエントリーをどうぞ。

最後に、SecurityDescriptorについてもっと詳細に調べたい方は、コチラをどうぞ。