coLinux日記

coLinuxはフリーソフトを種として、よろずのシステムとぞなれりける。

apache httpd 2.4.2 mod_cgid のソケットについて

2012-07-13 23:10:42 | Apache httpd
前回、apache httpd 2.4.2 を利用していて、mod_cgi が mod_cgid に変更になっていた(2.2.4では、Makefile を作成する configure のデフォルトが --enable-cgi で、 --enable-cgid がオプションでした。)ことに気が付いたので、古い 2.2.4 とちょっと比較しました。

インストールした /usr/local/httpd242 ディレクトリの下は、APRが独立したので lib ディレクトリが無くなった他にはディレクトリ構成は変わりませんが、ほとんどの機能がモジュール化(Apache で 動的共有オブジェクト Dynamic Shared Objeect (DSO) サポートと httpd.conf の中でコメントされています。)されて、modules ディレクトリの下に多数置かれるようになりました。httpd.conf の中で、 LoadModule ディレクティブによってこれらのモジュールを使うか使わないかを指定するので、これらを示すリストのようになっています。

さて、mod_cgid に戻って、それが使うソケット(logs/cgisock.*)に関して気が付いた点を示します。

まず、ソケットの作成権限が無い場合のエラーです。

$ ls /usr/local/httpd242/logs
access_log error_log
$
$ /usr/local/httpd242/bin/apachectl start
(13)Permission denied: AH00072: make_sock: could not bind to address [::]:80
(13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs
$

これは、ソケット作成権限を持つ、例えば root で行えば以下のように解決します。

# ls /usr/local/httpd242/logs
access_log error_log
#
# /usr/local/httpd242/bin/apachectl start
#
# ls /usr/local/httpd242/logs
access_log cgisock.1715 error_log httpd.pid
#

このように新しいソケットが作成されます。ここでリスタートしてみます。
(ps コマンドの出力は少し縮めてあります。)
# ps -ef |grep httpd
root   1715     1  0 xx:08 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1896  1715  0 xx:12 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1897  1715  0 xx:12 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1898  1715  0 xx:12 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1899  1715  0 xx:12 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
root   1984  1710  0 xx:14 pts/0 00:00:00 grep httpd
#
# /usr/local/httpd242/bin/apachectl restart
#
# ps -ef |grep httpd
root   1715     1  0 xx:08 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1988  1715  0 xx:14 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1989  1715  0 xx:14 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1990  1715  0 xx:14 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
daemon 1991  1715  0 xx:14 ?     00:00:00 /usr/local/httpd242/bin/httpd -k start
root   2074  1710  0 xx:14 pts/0 00:00:00 grep httpd
#
# ls /usr/local/httpd242/logs
access_log  cgisock.1715  error_log  httpd.pid
#

このようにリスタートすると親プロセスは残って、子プロセスだけを立ち上げ直しています。つまり、先ほど作成したソケットは再利用されます。

ここで、httpd を終了してみます。

# /usr/local/httpd242/bin/apachectl stop
#
# ps -ef |grep httpd
root 2079 1710 0 xx:20 pts/0 00:00:00 grep httpd
#
# ls /usr/local/httpd242/logs/
access_log error_log
#

全てのプロセスが終了し、ソケットも消去されます。

もし、何らかの理由で(今回の例は、Windowsをアップデートしたら再起動して、coLinux が強制終了したときのものです。)ソケットが消去できなかった場合は、

# ls /usr/local/httpd242/logs
access_log cgisock.1731 error_log httpd.pid
#
# /usr/local/httpd242/bin/apachectl start
#
# ls /usr/local/httpd242/logs
access_log cgisock.1715 cgisock.1731 error_log httpd.pid
#

のように、残ってしまった、cgisock.1731 はそのままで、新しいソケットが作成されます。その場合は、消しておく必要があります。

# rm /usr/local/httpd242/logs/cgisock.1731

注意したい点です。httpd.pid は、毎回作成されますのでそのままで問題ないのは従来どおりです。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

apache httpd 2.4.2 の mod_sed 入力フィルタ機能

2012-07-06 01:58:19 | Apache httpd
またまた、apache httpd 2.4.2 の mod_sed ですが、今回は入力時のフィルタ機能について試してみました。ディレクティブで言うと、AddInputFilterInputSed ですね。

httpd に対して、POST されたときにこの機能が適用されます。そのためには、CGIが動作できるように設定する必要があります。

実は現在の apache httpd では、CGI 用のモジュールとして、mod_cgi ではなくて、mod_cgid が標準でインストールされています。つまり、前回のインストールでは、mod_cgi は作成されず、どうしても mod_cgi が必要なら、configure のオプションで、

--enable-cgi

を追加する必要があります。mod_cgid の通信はソケットで行うので、ScriptSock ディレクティブが用意されています。標準ではソケット名は、

/usr/local/httpd242/logs/cgisock

です。cgi の設定は、httpd.conf で以下を指定します。

LoadModule cgid_module modules/mod_cgid.so

後は以前と同様です。

再起動すると、

# ls -l /usr/local/httpd242/logs/cgisock.*
srwx------ 1 daemon root 0 Jul x xx:xx /usr/local/httpd242/logs/cgisock.1731
#
というソケットが作成されます。ちなみに1731 は、httpd のプロセスIDです。これで CGI の準備はできました。

今回の mod_sed の入力フィルタを試すには、htmlファイルと CGI 用のプログラムが必要です。早速用意してみます。

html ファイルは、/usr/local/httpd242/htdocs/sed/test2-sed.html として、

<html><head></head><body>
<form action="/sed/program/prog1.sh" method="post">
<label>data1: <input type="text" name="data1"></label><br>
<label>data2: <input type="text" name="data2"></label><br>
<input type="submit" value="OK">
<input type="reset" value="Reset"><br>
</form>
</body></html>

とします。

そこで呼び出される CGI プログラム /usr/local/httpd242/htdocs/sed/program/prog1.sh は、bash で作ります。


#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "<html><head></head><body><pre>"
read Line

echo $Line

echo "</pre></body></html>"


テストするためにブラウザで、data1 に <b>abc</b> 、data2 に<u>def</u>を入れて prog1.sh を動かすと、

data1=%3Cb%3Eabc%3C%2Fb%3E&data2=%3Cu%3Edef%3C%2Fu%3E

のように POST によって送られてきたデータがそのまま表示されます。

準備が出来たので、mod_sed の入力フィルタのテスト用にはクロスサイトスクリプティング対策で基本のエスケープ処理を実施してみます。

< が %3C 、> が %3E 、& が %26 、" が%22 、' が %27 ですから、

%3C なら、%26lt%3B 、%3E なら %26gt%3B 、
%26 なら %26amp%3B 、 %22なら %26quot%3B
%27 なら、%26%2339%3B に変換してしまいましょう。最初に %26 を処理してしまうのがコツです。

ディレクティブはこうなります。
<Directory "/usr/local/httpd242/htdocs/sed/program">
   Options +ExecCGI
   AddHandler cgi-script .sh
   AddInputFilter Sed sh
   InputSed "s/%26/%26amp%3B/g"
   InputSed "s/%3C/%26lt%3B/g"
   InputSed "s/%3E/%26gt%3B/g"
   InputSed "s/%22/%26quot%3B/g"
   InputSed "s/%27/%26%2339%3B/g"
</Directory>

これは入力フィルタなので、出力フィルタで問題になった 304 を返さないように htmlファイルを更新しておく必要はないのでテストは楽です。

data1 に <b>a&b</b> 、 data2 に <u>"de'</u> を与えてみますと、

data1=%26lt%3Bb%26gt%3Ba%26amp%3Bb%26lt%3B%2Fb%26gt%3B&
data2=%26lt%3Bu%26gt%3B%26quot%3Bde%26%2339%3B%26lt%3B%2Fu%26gt%3B

のようになりました。(適当に改行してあります。)

念のために変換された入力データをデコードして表示してみます。bash で、POSTされたデータをデコードする方法は、
http://betu-masea.cocolog-nifty.com/blog/2006/10/bash3_1cf1.html
が参考になります。そこで定義されている urldecode() という関数をそのまま使って、先ほどのprog1.sh スクリプトの echo $Line の部分を、

urldecode Line
echo $RESULT

とすれば、上述の結果は、

data1=&lt;b&gt;a&amp;b&lt;/b&gt;&data2=&lt;u&gt;&quot;de&#39;&lt;/u&gt;

となりました。これだと既存のプログラムの & 文字処理を修正する必要があるかもしれませんので、実際に使う場合はデコード前のパラメタの分離とこの辺の工夫が必要です。

POSTで mod_sed に渡されたデータは丸ごとパターンスーペースに入力してしまうので1サイクルで処理が行われるようです。つまり、N コマンドのような次の行を読み込むものは意味がなさそうです。

ざっと調べたところ InputSed の例はほとんど見当たりませんが、今回試してみて以外に役立つような気がしました。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

apache httpd 2.4.2 の mod_sed 続き

2012-07-01 02:20:20 | Apache httpd
apache httpd 2.4.2 の mod_sed の続きです。前回提示した例が動作しなかった原因を探ってみました。

まず分岐が正しく動作するかどうかを試してみます。

sed の分岐は、

b ラベル の通常の分岐と、
t ラベル の条件分岐です。

そこで、httpd-sed-scripts.conf を以下のようにします。
<Directory "/usr/local/httpd242/htdocs/sed">
   AddOutputFilter Sed html
   OutputSed   "b loop1"
   OutputSed ":loop2"
   OutputSed   "s/good line/GOOD bad LINE/"
   OutputSed   "b"
   OutputSed ":loop1"
   OutputSed   "s/bad/good/"
   OutputSed   "t loop2"
</Directory>

・最初の b コマンドで loop1 へ分岐し、
・行内に bad の文字があったら、good に変換して、
・t コマンドによって loop2 へ分岐します。
・badの文字が無ければそのままサイクルを終了して次の行へ行きます。
・loop2 へ分岐した場合は、good line を GOOD bad LINE に変えて、
・ラベルなし b コマンドでサイクルを終了して次の行へ行きます。

これによって、b,t コマンドが正しく動作しているかを調べるのがねらいです。早速、htmlファイルの次の部分を変換させます。

(例1)
First line<br>
good line<br>
bad line<br>
Last line<br>

結果は次のとおりです。

First line<br>
good line<br>
GOOD bad LINE<br>
Last line<br>

t コマンドの分岐で戻る動作や、b コマンドの終了動作もうまくいっています。

実は、b にアドレスを付けると、分岐先のラベルが無い場合でもサイクルを終了しないようですのでご注意ください。それで、以降の設定では、アドレス付きの b コマンドは必ずラベルを指定してあります。

次にアドレスを見てみます。! が使えないことは分かりましたので、以下を試してみます。
(以降は OutputSed のところのみ示します。)

OutputSed "/<pre>/,/<¥/pre>/ {"
OutputSed "/<pre>/ b next"
OutputSed "/<¥/pre>/ b next"
OutputSed "s/^.*$/IN &/"
OutputSed ":next"
OutputSed "}"

htmlファイルのこの部分を変換してみます。

(例2)
First line<br>
<pre>
good line
</pre>
2nd line<br>
<pre>
good line
bad line
</pre>
Last line<br>

結果は次のとおりです。

First line<br>
<pre>
IN good line
</pre>
2nd line<br>
<pre>
IN good line
IN bad line
</pre>
Last line<br>

これもうまく動作しています。

最後に s コマンドの気になるところを試します。

OutputSed "s/\(One\)\(Two\)\(Three\)/¥3¥2¥1/"
OutputSed "/^Three/ s/^.*$/\n&\n/"

残念ながら以下の行が、

OneTwoThree

正しく変換されません。改行文字 \n が無視されて n とみなされます。

nThreeTwoOnen

どうやら、s/regexp/replacement/flags において、「replacement」の \n は認識されず n となり、「regexp」 の \n は認識されるようで、

OutputSed "N"
OutputSed "s/\(.*\)\n\(.*\)/¥1@¥2/"

は、2つの行が @ をはさんで1行として変換されます。

そこで改行文字は諦めて、@ 文字を使ってうまく動作しなかった sed スクリプトを修正してみます。

OutputSed "/<pre>/,/<¥/pre>/ {"
OutputSed "/<pre>/ b next"
OutputSed "/<¥/pre>/ b next"
OutputSed "/^$/ b next"
OutputSed "/^.$/ b next"
OutputSed "s/^.*$/@&@/"
OutputSed "t loop"
OutputSed ":loop"
OutputSed "s/\(@.\)\(.*\)\(.@\)/¥3¥2¥1/"
OutputSed "t loop"
OutputSed "s/@//g"
OutputSed "s/^\(.*[^ ]\)\( *\)$/¥2¥1/"
OutputSed ":next"
OutputSed "}"

(例2)は以下のようになり、何とかうまくいきました。

First line<br>
<pre>
enil doog
</pre>
2nd line<br>
<pre>
enil doog
enil dab
</pre>
Last line<br>

OutputSed修正後に動作確認を行う際には、

# touch /usr/local/httpd242/htdocs/sed/*

を忘れないようにしましょう。

というわけで、mod_sed には多少の問題点がありますが、Experimental ですし、たいていのものは出来るので、積極的に利用したいと思います。それに今回調べたことで、sed コマンドの奥深さが改めて分かったので、そちらも得した気分です。

(行間が無駄に開いている部分がありますが、gooブログの仕様です。)
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする