Logo address

CGI 環境の構築

目次

2003/01/03

Pegasus で CGI 環境を構築する場合に考えるべきことは、CGI プログラムを実行するのに必要な環境です。UNIX あるいは他の OS の web サーバと異なり、Plan9 の Pegasus は選択的に環境を構築でき、その場合、明示的に必要な環境を構築する必要があるからです。
CGI を実行するには結構多くのものが必要です。例えば CGI プログラムが、来るはずのないデータを待って、いつまでも終らないかも知れません。Pegasus は(特に指定がない限り) 5 秒待っても CGI プログラムが終了しない場合には強制的に終了させます。そのためには /proc が準備されていなければなりません。

/usr/web の構成

配布ファイルの example/usr/web に次のディレクトリとファイルが含まれています。
	d-rwxrwxr-x M 8 arisawa arisawa	bin/386
	d-rwxrwxr-x M 8 arisawa arisawa	bin/rc
	d-rwxrwxr-x M 8 arisawa arisawa	dev
	d-rwxrwxr-x M 8 arisawa arisawa	doc
	d-rwxrwxr-x M 8 arisawa arisawa	env
	d-rwxrwxr-x M 8 arisawa arisawa	etc
	d-rwxrwxr-x M 8 arisawa arisawa	lib
	d-rwxrwxr-x M 8 arisawa arisawa	mnt
	d-rwxrwxr-x M 8 arisawa arisawa	proc
	d-rwxrwxr-x M 8 arisawa arisawa	rc/lib
	d-rwxrwxr-x M 8 arisawa arisawa	sys/log
	d-rwxrwxr-x M 8 arisawa arisawa	sys/lib
	d-rwxrwxr-x M 8 arisawa arisawa	sys/man
	d-rwxrwxr-x M 8 arisawa arisawa	tmp
	--r-------- M 8 arisawa arisawa	unreadable
これらのディレクトリやファイルには、ユーザ none や ユーザ web による書き込み権を与えてはいけません。最後の unreadable はサーバが allow モードで動作しているか否かの判定に使用されています。(allow モードで動作しているときには Pegasus は CGI の実行サービスを停止します。)
これらのディレクトリは bin/386bin/rc を除けば空です。筆者は bin/386bin/rc に CGI のサービスに固有のプログラムを置いています。次に紹介する /lib/namespace.httpd の内容は、その事を前提にしています。
CGI プログラムにとってこれらの全てが必要ではありませんが、ゆとりをもってとった方が良いでしょう。
読者は配布ファイルの
	example/usr/web
以下のディレクトリをそのまま /usr/web にコピーするのが無難です。筆者の cpdir を使うと簡単にコピーできます。
	cpdir -mv example/usr/web /usr/web

/lib/namespace.httpd

Pegasus のサービス空間は /usr/web を基に構成されます。それに内容を与えるために
	/lib/namespace.httpd
で実体を bind しなければなりません。配布ファイルの
	example/lib/namespace.httpd
にその例が載っています。それによると、そのファイルの内容は(コメントを省くと)
	bind -a /usr/web/bin/$cputype /bin
	bind -a /usr/web/bin/rc /bin
	bind /sys/log/http /usr/web/sys/log/http
	bind /sys/lib /usr/web/sys/lib
	bind /sys/man /usr/web/sys/man
	bind /lib /usr/web/lib
	bind /bin /usr/web/bin
	bind /rc/lib /usr/web/rc/lib
	bind -c #e /usr/web/env
	bind #c /usr/web/dev
	bind /proc /usr/web/proc
ここに載せた全てが必要な訳ではありません。また
	bind /sys/lib /usr/web/sys/lib
では、/sys/lib 以下の全てがサービス空間の中に入り、CGI からアクセス可能になります。必要なファイル(あるいはディレクトリ)だけを選択的に bind した方が良いかも知れません。(/sys/lib/ssh/sys/lib/tls に秘密にすべき情報をオープンにしたまま入れているかも知れませんよ)

/lib/namespace.httpd で設定した CGI 環境は

	/usr/web/doc
	/usr/web/etc
を除けば全て、仮想ホストや一般のユーザに引き継がれます。従ってセキュリティには充分に注意を払う必要があります。

$web の構成

以下の説明では web ルートを $web で表します。
例えば、ユーザ alice の場合には $web は(特に指定しない限り)
	/usr/alice/web
です。実ホストと仮想ホストの $web の値は /sys/lib/httpd.rewrite によって決定されます。例えば /sys/lib/httpd.rewrite
	/	*/usr/bob/www
とした場合には実ホストの $web
	/usr/bob/www
となります。
各ドキュメント管理者は $web の下に以下のディレクトリを持ちます。
	doc
	etc
	bin/386
	bin/rc

$web/etc/handler

実行ハンドラ定義ファイル $web/etc/handler はホームページの運営者が自分で管理します。自分で管理しやすいように運営者のホームディレクトリの下に置かれています。これらはサービス空間の
	/etc/handler
となります。このファイルの役割は、クライアントからのリクエストの処理を、指定されたプログラムに渡すことです。
典型的な実行ハンドラは
# suffix             mimetype  unused   execpath arg ...
/netlib/*/index.html text/html 	0 	/bin/ftp2html
*.http                  -       0       $target
*.html               text/html	1       $target
*.dx_html            text/html  0       /bin/dx $target
のようなものです。(これは筆者が plan9.aichi-u.ac.jp で現在使用しているものです。) 最初の行はコメントです。従って2番目以降の行だけが意味を持っています。(第3フィールドは今回の版では使用されていません。)
*.html を含む行によって、いわゆる CGI ファイルが定義されています。この行の言っている事は、
リクエストされたファイルの拡張子が .html の場合、第4フィールドのファイルが実行ファイル(others に対して実行フラグが立っている)であれば、それを実行しなさい。そのときの引数は(もしも存在すれば)第5フィールド以下で与えられています。$target と言うのはリクエストされたファイルです。出力のMIME 形式は text/html ですよ。

つまり、CGI ファイルの拡張子は Pegasus が決めてるのではなく、ユーザ定義であることを理解してください。(ついでに、CGI は拡張子によって定められているのではなく、リクエストのパスパターンであることも理解してください。)

$web/etc/handler のテーブルは、リクエストに対するアクションを定めているので、リクエストされたファイルが実際に存在する必要もありません。もっと詳しい解説については、実行ハンドラを見て下さい。

$web/etc/namespace_80

ホームページの運営者は自分の名前空間を再編成できます。(しかしそのような必要は殆どないでしょう。)
$web/etc/namespace_80 はポート 80 に対する名前空間の編成ファイルです。このファイルの名前から分かるように、使用されるポートごとに名前空間の編成ファイルを作成します。(名前空間を再編成する必要が無い場合にはファイルは必要ありません)

$web/etc/namespace_80 が実行される段階で Pegasus は既にサービス空間にいます。従ってこのファイルの中で指定されるパスは $web をルートとしたパスです。

セキュリティの関係で、全ての再編成が許されているわけではありません。(httpd-m オプションが指定されていない限り)このファイルの中では bind だけが許されます。すなわち本来見えているディレクトリを隠したり、配置を変更したりするだけです。さらに、システムのファイルをドキュメント空間の中に bind する行為も許されていません。

隠すためには何か空のディレクトリを作成し(例えば /doc/nil) それを bind してください。)

	bind /doc/nil /doc/private
Pegasus 2.0 では
	$web/etc/bin/386
	$web/etc/bin/rc
に置かれたプログラムは自動的に /bin に(追加モードで) bind されます。

CGI とセキュリティ

Pegasus は他の web サーバと異なり、CGI はシステム管理者だけの特権ではないと考えています。/lib/namesspace.httpd の編成の結果は全てのドキュメント管理者が利用できます。/lib/namesspace.httpd の編成はそのことを念頭に置く必要があります。
Pegasus は、悪質なユーザが CGI を使って企みそうな事をいろいろ考えた上で設計されていますが、実際に悪質なユーザがいる環境での運用実験はされていません。

listen の管理下で httpd を実行すると、ユーザ none のプロセスとして振る舞います。ホームページへの書き込みを目的として CGI を実行する場合には、ファイルのアクセスモードについて充分に考慮する必要があります。無難なのは

	alrw-rw-rw-		# 読み取りが必要な場合
あるいは
	alrw--w--w-		# 他人に見られたくない場合
にすることでしょう。大切なデータを消されない、或いは不正に変更されないと言う事が何よりも大切です。

httpd だけに読み取りを許可して、システムの他のユーザからの読み取りは阻止したい場合にはサーバモードで httpd を実行して下さい。