ADSI、ASP、およびいくつかのトリックによる仮想ディレクトリの自動作成 - Part 2

Tom Moran
Jeff Sandquist
Microsoft Corporation

February 22, 1999
日本語版最終更新日 1999 年 9 月 9 日

この記事は、もともと Site Builder Network Magazine のコラム "Servin' It Up" (現在は MSDN Online Voices のコラム "Servin' It Up")として掲載されたものです。

お久しぶりです。期待の高かった Part 2 がついに登場です

今月、Jeff Sandquist と私は Active Directory Services Interfaces (ADSI) アプリケーションを完成させる予定です。少し出遅れた方も心配はいりません。このシリーズの Part 1 を見てください。先月、われわれはユーザーが特権グループのメンバであるかどうかを確認しました。その後、特定のユーザー グループの全メンバのユーザー名をリスト ボックスに格納しました。このフォームでは、ユーザーを選択し、そのユーザーの新しい仮想ディレクトリに対する権限を選択できるようになっています。今月は、データをフォームから取得し、Web サーバー上に新しい仮想ディレクトリを作成し、これをアプリケーションとして定義し、スクリプト権限をオフにするオプションを与え、フォルダに適切な権限を割り当てます。これらの作業は Jeff Sandquist に説明してもらいます。

また、この記事の終わりには、大きな、悲しい、大地を揺るがすような発表があります。これに比べれば、クリントン、O.J.、クレメンスなどは問題にもなりません。AP がきっとこのニュースを配信するでしょうが、この記事の読者は AP よりも先に目にすることになります。とにかく最後まで読み進めてください。

ショーの始まり

先月作成したフォームは、Servin という名前の仮想ディレクトリの中に置かれていました。われわれは、Internet Information Server (IIS) の IUSR_<Machine Name> というセキュリティ コンテキストを使って、必要な操作を実行することができました。ディレクトリを作成して権限を割り当てるためには、管理者である必要があります。

これを行うための 1 つの方法は、IUSR_<Machine Name> アカウントを管理者グループに移動するというものです。しかし、これよりよい方法は、Web サーバー上に新しい仮想ディレクトリを作成し (これには ServinSecure という名前を付けました)、IUSR_<machine name> ではなく Administrator のコンテキストの下で動作するように設定するという方法です。われわれのフォームは Servin ディレクトリの中に置かれ、フォームの処理プログラムは ServinSecure という名前のディレクトリの中に置かれることになります。

新しい仮想ディレクトリを作成するには、Microsoft Management Console (MMC) を起動し、Default Web Site を右クリックします。[New/Virtual Directory] を選択します。"ServinSecure" (引用符なし)という名前の仮想ディレクトリを作成します。また、Web サーバーのファイル システム上に以前に作成したフォルダへの物理パスも指定する必要があります。仮想ディレクトリを作成したら、新しく作成した仮想ディレクトリを MMC で右クリックし、[Properties] を選択して、仮想ディレクトリのプロパティを表示します。

[Directory Security] タブを選択し、[Enable anonymous ...] の横の [Edit] ボタンを選択し、このリソースの認証方式を編集します。[Authentication Methods] というタイトルのダイアログ ボックスが表示されます。[Account used for Anonymous Access] の横の [Edit] ボタンを選択します。[Anonymous User Account] というタイトルの最後のダイアログ ボックスが表示されます。Username のデフォルト値を IUSR_<machine name> から administrator に変更し、パスワードの同期を選択解除し、administrator アカウントのパスワードを指定します。残りのダイアログ ボックスでは [OK] を選択して、変更点を適用します。

次に、これらのダイアログ ボックスの図を示します。

Dialog boxes

ASP コード

では、コードの内容を見ていきましょう。アプリケーションのためにいくつかの変数を定義します。CreateDirectory.asp という名前の Active Server Pages (ASP) ファイルを作成し、次のコードを挿入します。


<%@ Language=VBScript %>
<% Option Explicit %>
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
</HEAD>
<BODY>

<%
Dim strVirtualDirectoryName  'IIS Virtual Directory Name
Dim bolInProcessApplication  'IIS In Process Application Flag
Dim objIIS                   'ADSI IIS Object
Dim strVirtualDirectoryPath  'IIS Virtual Directory Path
Dim objFileSystem            'VBScript FileSystemObject
Dim strOwner                 'NT Folder Owner
Dim objVirtualDirectory      'ADSI IIS Virtual Directory Object
Dim bolScriptPermissions     'IIS script permissions flag
Dim strHTTPReferer           'IIS Referrer Page
Dim strServerName            'NT local machine name
Dim objWSH                   'Windows Scripting Host Object
Dim objRTC                   'Return
Dim strACLCommand            'Command Line string to set ACLs

ユーザーが、サーバーをだまそうとしているのではなく、確かにわれわれのフォームから来たことを確認するために、HTTPReferer サーバー変数とサーバー名を取得します。ここでは他にもさまざまなチェックを行うことができます。われわれが使用しているテストは、必ずしも完全ではありません。サイトのセキュリティに関する初心者用の記事としては、Dmitry Khanine の「Easy Application State Securely Non-MS link」を参照してください。

最後のコードのすぐ後に、次のコードを挿入します。


strHTTPReferer = Request.ServerVariables("HTTP_REFERER")
strServerName = Request.ServerVariables("SERVER_NAME")

' Did we come from our form?If not then deny access

If strHTTPReferer <> "http://" & strServerName 
& "/Servin/Default.asp" then
 Response.Write("Access Denied")
 Response.End
End If

ユーザーが結果をわれわれのフォームから送信していることを確認したら、フォームから Virtual Directory、Owner、および Script Permissions フラグの値を取得します。checkboxScript の値を、それが選択されていた場合には True、選択されていなかった場合には false に変更していることに注意してください。最後のコードのすぐ後に、次のコードを挿入します。


strVirtualDirectoryName = Request.Form("textVirtualDirectory")
strOwner= Request.Form("selectOwner")

If Request.Form("checkboxScript") = "on" Then 
 bolScriptPermissions = "True"
Else
 bolScriptPermissions = "False"
End If

IIS アプリケーションが存在しているかどうかを確認する必要があります。IIS Admin オブジェクトを使って、アプリケーションがすでに存在しているかどうかをチェックし、それに応じてユーザーに警告を発します。

' Does this IIS application already exist in the metabase?

On Error Resume Next
Set objIIS = GetObject("IIS://localhost/W3SVC/1/Root/"
& strVirtualDirectoryName)

If Err.Number = 0 Then
 Response.Write ("An application with this name
 already exists.Click ")
 Response.Write ("<A HREF=http:// "
 & strServerName & " /servin/default.asp>")
 Response.Write ("here</A> to choose a different name.")
 Response.End
End If

Set objIIS = Nothing

次に IIS Administration オブジェクトを使って、メタベースの中に IIS アプリケーションを作成します。


'Create the IIS application

Set objIIS = GetObject("IIS://localhost/W3SVC/1/Root")
strVirtualDirectoryPath = objIIS.Path
& "\" & strVirtualDirectoryName

Visual Basic® Scripting Edition (VBScript) の FileSystemObject オブジェクトを使って、フォルダがファイル システム内に存在しているかどうかをテストします。存在していなければ、CreateFolder コマンドを使って作成します。


Set objFileSystem = Server.
CreateObject("Scripting.FileSystemObject")

'Test to see if the folder exists in the filesystem.
' If not, create it

On Error Resume Next
Set Folder = objFileSystem.GetFolder(strVirtualDirectoryPath)
If Hex(Err.number) = "4C" Then
 objFileSystem.CreateFolder strVirtualDirectoryPath
End If

Set objFileSystem = Nothing

IIS Administration オブジェクトを使って(この記事では頻繁に使用しています)、スクリプト権限をオンにし(ユーザーがこのオプションを選択していた場合)、仮想ディレクトリをインプロセス アプリケーションとして定義します。


'Create the folder in the filesystem
Set objVirtualDirectory = objIIS.Create("IISWebVirtualDir",
strVirtualDirectoryName)
objVirtualDirectory.AccessScript = bolScriptPermissions
objVirtualDirectory.Path = strVirtualDirectoryPath
objVirtualDirectory.SetInfo 
objVirtualDirectory.AppCreate bolInProcessApplication

さて、権限を設定するトリックの部分です。われわれは最初のうち、これは簡単だろうと思っていました。しかし残念ながら、ADSI には仮想ディレクトリの権限を設定するためのオブジェクトはありませんでした。パニックとともに、気分が悪くなるのを感じました(それとも、その前の晩にタイ料理を食べ過ぎたのが原因だったのでしょうか?)。

しかし、15seconds.com ADSI リスト サーバーを調べたところ、DOS CACLS.EXE file Non-MS link ファイルと、これを DOS CMD ファイルから使用する方法について述べたポストが見つかりました。

この機能の Visual Basic ラッパーを作成し、これをカスタム コンポーネントでくるむ(来月の記事のアイデアです)という方法を思いつきましたが、これよりも手軽な方法があるはずです!

われわれは Ian Morris による Windows Scripting Host FAQ を調べ、Windows Scripting Host から DOS コマンドを呼び出す数行のコードを発見しました。

われわれは、Windows Scripting Host を使って ASP ファイルから CACLS.exe を呼び出そうとしましたが、ページは実行できませんでした。アプリケーションが実行に失敗するのです。なぜでしょうか? DOS コマンド プロンプトからコマンドをステップ実行してみたところ、CACLS.EXE コマンドが操作を行うことを指示する "Y" という入力を待っていることがわかりました。デフォルトとして "Yes" を指示する方法があるはずです。

コマンド ライン オプションを見ても、隠しスイッチは見つかりませんでした。この時点で、Web ブラウザを開き、Support Online を訪れて、CACLS.EXE を検索するのがいいだろうと考えました。

幸いなことに、「Q135268:How to Use CACLS.EXE in a Batch File Non-MSDN Online link」という記事が見つかりました。古き良き DOS のリダイレクションです。CACLS.exe に対して Y をパイプで入力してやれば、Yes の答えを強制的に指示することができるのです。

次に、コマンド文字列を作成し、ASP ファイルから Windows Scripting Host シェルを呼び出すために使用したコードを示します。


'Set Change Permissions for the developer using CACLS.exe
strACLCommand = "cmd /c echo y| CACLS "
strACLCommand = strACLCommand & strVirtualDirectoryPath
strACLCommand = strACLCommand & " /g "
& strOwner & ":C"

Set objWSH = Server.CreateObject("WScript.Shell")
objRTC = objWSH.Run (strACLCommand , 0, True)

Set objWSH = Nothing

これは高度にスケーラブルなソリューションとはいえないかもしれません。大規模なアプリケーションでは、カスタム コンポーネントを使う方がいいでしょう。そちらの方がご希望であれば、Software Artisans が、オブジェクト モデルを通してフォルダの権限を変更できる 無償のコンポーネント Non-MS link を提供しています(これ以外にも、画像とデータベース BLOB の間でのインポート/エクスポート、.ini ファイルの操作といったクールな機能がたくさんあります)。

最後のコードは、これまでに行ったアクションの確認を表示します。


Response.Write("<B>Web Application Created Sucessfully</B>
<BR>")
Response.Write("Path : "& strVirtualDirectoryPath & "<BR>")
Response.Write("Script Permissions : "& bolScriptPermissions &
"<BR>")
Response.Write( strOwner & " has been granted 
change permissions<BR>")
%>
</BODY>
</HTML>

これで完成です。覚えておきたい教訓は、問題に対する解決策を探すときには、複数のリソースを使うべきだということです。この記事を完成させる上では、リスト サーバー、FAQ、および Microsoft Knowledge Base が大いに役立ちました。

さて、ニュースの件です。ASP に関するコラムが非常に好評なため、われわれはこのコラムで ASP テクノロジのみに焦点を当てることにしました。この変更に対応するために、有能なる Jeff Sandquist を執筆スタッフとして迎え入れました。悲しいニュースは? Tom Moran が Servin' It Up の担当から外れます。しかし、今後も他のコラムで彼の姿を見掛けることになるでしょう。

Tom Moran は、 Microsoft Developer Support のプログラムマネージャで、MSDN Online Web Workshop チームと多くの時間を過ごしています。

Jeff Sandquist は、Developer Support の Active Server Pages Escalation Team の一員であり、 Visual InterDev MVP Non-MSDN Online link プログラムの最高責任者です。