Apache 2.0.48 で WebDAV を使えるようにする
SERVER
WebDAV
WebDAV とは、簡単に言うと Web サーバのデータを読み書きする仕組み、とでも言うのでしょうか…。これを使うことで HTTP プロトコルをつかってサイトの更新などができるようになります。
Microsoft さまの FrontPage Server Extensions でも同様のことができ、個人的にも愛用しているのですけど、Linux の Apache で FrontPage Server Extensions を使う場合、Apache のバージョンが制限されたりして何かと都合が悪いのでした。
そこで今回、思い切って WebDAV 対応の Apache を用意してみることにしました。
現在もすでに Web サーバが動いていて、そのときには Apache 2.0.39 をインストールしていたのですけど、ついででもあったので Apache 2.0.48 にも差し替えてみることにします。
Apache のインストール
まずは Welcome! - The Apache HTTP Server Project さまから Apache 2.0.48 のソースファイルを入手します。httpd-2.0.48.tar.gz を入手したら、次のように展開します。
tar xvzf httpd-2.0.48.tar.gz
なぜだか、本来はこれでいいはずなのですけど、GZIP で圧縮されていないとのエラーが表示されてしまいました。ためしに tar xvf httpd-2.0.48.tar.gz としたらうまく展開できたので、もしうまくいかない場合はこうしてみるといいかもしれません。
つづいて、コンパイルとインストールです。
今回は WevDAV を利用したいので、configure にいくつかの引数を渡してあります。また、動的にモジュールを組み込める DSO 対応になるように、--enable-shared も付加しています。FrontPage からのアクセスも想定する場合は --enable-headers も付けておくと良いようです。
ついでに、SSL も使いたかったのでそれっぽいオプションもつけてみました。
./configure --enable-shared --enable-dav --enable-headers --enable-ssl --with-ssl=/usr/include/openssl
つづいて、コンパイルとインストールです。
make
make install
今回は、以前から使っていた Apache 2.0.39 の apache2/ ディレクトリを、念のためバックアップはしましたけど、そのまま上書きする感じでインストールを行いました。
ですので実際には、インストール前に /usr/local/apache2/bin/apachectl stop としてプロセスを停止し、インストール後に再度立ち上げる風にしています。
WebDAV を有効にする
WebDAV が使用するロックファイルを用意します。
今回は /var/httpd/dav.lock というファイルを用意してみることにします。このファイルは Apache が読み書きできる必要があるので、Apache を起動するプロセス、今回は Apache が書き込めるようにします。
mkdir /var/httpd
touch /var/httpd/dav.lock
chwon apache.apache /var/httpd/
chown apache.apache /var/httpd/dav.lock
ロックファイルの作成が完了したら、httpd.conf 内に次の行を追記して先ほどのロックファイルを使用するようにします。
DAVLockDB /var/httpd/dav.lock
続いて 「試しに」、WebDAV でアクセスできるようにサイトの設定を調整します。今回の自分の環境では、仮想ホスト設定で運用しているため、そのあたりに記述しています。
<VirtualHost *:80>
ServerName tmp.ez-net.jp
DocumentRoot /tmp/www
<Location />
DAV On
</Location>
これで Apache を再起動させれば、WebDAV が利用可能になります。
ためしに、Internet Explorer の 「ファイル」 メニューから 「開く」 を選択して URL を入力し、”Web フォルダとして開く" にチェックをいれると、通常のフォルダを開いたような、そんな画面が表示されると思います。
ただし、この状態だと誰もがアクセス出来てしまうので、アクセス制限をかけなくてはいけません。
認証を実装する
WebDAV を実装する以上、認証もいっしょに用意しないといけません。
Apache 標準の認証をつかうのが一番早いのですけど、パスワードを /etc/passwd で統一したかったので別のモジュールを組み込んでみることにしました。ただ /etc/passwd を認証に使うのは、セキュリティの面で危険とのことなので、使用する際は十分注意が必要です。
まずはソースファイルをダウンロードします。
Mod_Auth_External さまより、Apache 2 用の mod_auth_external-2.2.7.tar.gz をダウンロードします。それを次のようにして、展開してインストールします。
tar xvzf mod_auth_external-2.2.7.tar.gz
cd mod_auth_external-2.2.7
/usr/local/apache2/bin/apxs -c mod_auth_external.c
/usr/local/apache2/bin/apxs -i -a mod_auth_external.la
これでインストール完了です。httpd.conf に自動的に次の行が追加されています。
LoadModule external_auth_module modules/mod_auth_external.so
ClearModuleList というディレクティブがある場合には、さらに改めて次のようにモジュールが登録されているそうです。
AddModule mod_auth_external.c
続けて、pwauth のインストールを行います。
まず、Apache の起動ユーザが nobody でない場合は、pwauth/ ディレクトリの中の config.h を書き換える必要があります。たとえば、Apache が apache というアカウントで起動していて、その UID が 100 であるとするならば、次のような感じになります。
#define SERVER_UIDS 100 /* user "apache" */
編集が終わったらコンパイルとインストールを次のように行います。
make -C pwauth
mkdir /usr/local/libexec/
cp pwauth/pwauth /usr/local/libexec/
chmod u+s /usr/local/libexec/pwauth
これが終わったら httpd.conf に次の行を加えて、Apache を再起動します。
AddExternalAuth pwauth /usr/local/libexec/pwauth
SetExternalAuthMethod pwauth pipe
これに関してなのですけど、仮想ホストを利用している場合は <VirtualHost> ディレクティブの内部に記述する必要があるそうです。
SSL 環境も含めて、最後の VirtualHost ディレクティブに入っていればいいような説明書きがあったような気がするのですけど、やってみた感じでは、httpd.conf と ssl.conf の両方の、複数あるなら各 VirtualHost ディレクティブ内に入れておかないと認証に失敗するような感じがします。
なお、AddModule の記載は、httpd.conf の方にさえ書いておけば大丈夫でした。
そして、以下の内容の /etc/pam.d/pwauth ファイルを用意します。
auth required /lib/security/pam_pwdb.so shadow nullok
auth required /lib/security/pam_nologin.so
account required /lib/security/pam_pwdb.so
あとは自分で、目的のサイトに次のように認証関連の設定を行えば、認証が実装されます。
AuthType Basic
AuthExternal pwauth
AuthName "test authentication"
require user test
上記の例では test という名前のユーザに限定されています。valid-user にしてもいいかもしれないですけど、念のため最小限のアカウントにのみ許可をしたほうがいいかもしれません。
なお、これらの記載は <Location> や <Directory> ディレクティブ以外にも、 .htaccess ファイルでもいいようです。
WebDAV 制御の微調整
IIS の FrontPage Server Extensions のように、公開も管理も同一の URL で管理したいような場合は、次のようにするといいかもしれません。
<VirtualHost *:80>
ServerName tmp.ez-net.jp
DocumentRoot /tmp/www
AddExternalAuth pwauth /usr/local/libexec/pwauth
SetExternalAuthMethod pwauth pipe
<Location />
DAV On
<LimitExept GET POST HEAD OPTIONS>
AuthType Basic
AuthExternal pwauth
AuthName "test authentication"
require user test
</LimitExcept>
</Location>
上のようにすることで、通常の GET や POST といったメソッドは問題なくアクセスでき、WebDAV で使用するようなその他のメソッドの場合に初めてパスワードが聞かれるため、両立することが出来るようになると思います。
Web フォルダに書き込めない
さて、ひととおり設定も終わって使ってみたのですけど、Web サイトから自分のほうへはファイルをコピーできるものの、こちらからのアップロードをしようとすると書き込めないとのエラーが表示されてしまいました。
とりあえず、どのアカウントで書き込みを行おうとするかを調べようと、すべての権限でアクセスできるディレクトリを用意してみましたけど、それでも書き込みすることはできませんでした。
Apache のサイトログを調べてみると、エラーログのなかにロックファイルにアクセスできないことを示す表示がなされていました。
これの可能性が非常に大きいのでそのあたりのアクセス権限を調べてみると、あらかじめ作成した lock ファイルは apache が読み書きできるようにしてあったものの、それをおいてあるディレクトリは root のみとなっていました。
なのでそのディレクトリも Apache が書き込めるようにしてみたところ、無事、ファイルを書き込むことができました。その際、ロックファイルを置いてあるディレクトリには、"dav.lock.dir" と "dav.lock.pag" という2つが自動的に生成されていました。
さて、書き込んだファイルなのですけど、所有者の情報が Apache を動かしたアカウントの情報になっていました。
ある意味当たり前のことなのですけど、そうである以上、アップロード先のディレクトリは (すべて) Apache が書き込める必要があるようです。幸い、FTP などとは違って、ルートパスよりも上に行くことはできないので害は無いかもしれないですけど、少し注意する必要もあるかもしれないです。
なにはともあれ、グループに Apache のグループを割り当てて、すべてに g+w を設定してあげるのがいい感じではないでしょうか。
日本語環境に対応させる
WebDAV を日本語環境に対応させるモジュールがあったはずなので、それを組み込んでみることにします。
WebDAV Resources JP さまから、mod_encoding-20021209.tar.gz と mod_encoding.c.apache2.20020611a-2 をダウンロードします。そして次のような手順で、展開とインストールをおこないます。
tar xvzf mod_encoding-20021209.tar.gz
cd mod_encoding-20021209/lib/
./configure
make
make install
cd ..
./configure --with-apxs=/usr/local/apache2/bin/apxs
cp ../mod_encoding.c.apache2.20020611a-2 mod_encoding.c
/usr/local/apache2/bin/apxs -c mod_encoding.c
gcc -shared -o mod_encoding.la mod_encoding.o -Wc -Wall -L/usr/local/lib -Llib -liconv_hook
cp mod_encoding.la /usr/local/apache2/modules/
そして httpd.conf に次の行を追加します。
LoadModule encoding_module modules/mod_encoding.la
これで Apache を再起動すれば、とりあえずはモジュールがロードされるとおもったのですけど…、なにはら "libiconv_hook.so.1: cannot load shared object file: No such file or directory" というエラーが発生してしまいました。
どうやら libiconv_hook.so.1 というファイルが無いらいしです。調べてみると /usr/local/lib/libiconv_hook.so が見つかりました。どうやら httpd.conf に明示的に示す必要があるようです。
LoadFile /usr/local/lib/libiconv_hook.so
これを httpd.conf に書き加えて Apache を再起動してみると、無事起動することができるようになりました。なお、この行は "LoadModule encoding_module modules/mod_encoding.la" の行よりも前に書く必要があるようでした。
さて、モジュールが組み込めたらば、httpd.conf のグローバルセクションに次の設定を追加します。
<IfModule mod_encoding.c>
EncodingEngine on
NormalizeUsername on
SetServerEncoding UTF-8
DefaultClientEncoding JA-AUTO-SJIS-MS SJIS
AddClientEncoding "cadaver/" EUC-JP
</IfModule>
FrontPage 2003 の発行先に出来るようにするには…?
すべてがうまくいったようだったのですけど、いざ FrontPage 2003 を使って発行をしようとすると、認証までは行くものの、Share Point Server が無いなどといわれてしまってアップロードできませんでした。
調べてみると、ずばりこの事例というわけではないのですけど、なにやらそのままでは FrontPage Server Extensions と勘違いしてしまうとのことでした。
これを回避するためには、次の行を httpd.conf の該当するところ (DAV on あたり) に記述して、DAV であることを通知するヘッダを贈ってあげればいいそうです。
Header add MS-Author-Via "DAV"
この命令は mod_headers を組み込まないといけないので、組み込まれていない場合は httpd.conf にさらに次の行を追加しておきます。
AddModule mod_headers.c
ただ、この mod_headers はディフォルトでは使用することが出来ないようで、これを利用したい場合には、Apache のコンパイル作業にて、configure のオプションに --enable-headers をつけて改めてコンパイル、インストールする必要があります。
こうすることで、特に AddModule として明示しなくても Apache2 で Header add が使用できるようになるようでした。
けれど、それでも FrontPage 2003 から発行しようとすると同じようなエラーとなってしまいました。
何が悪いのか良くわからないながら、SSL の方に設定していたので、ためしに同じ設定を普通の HTTP の方に設定してみたところ…、あっさりとうまく行ってしまいました。さらに、SSL 設定の方の SSLEngine on の行をコメントアウトしてみると…、当然ながら普通の HTTP でのアクセスですけどうまくいってしまいます。
これは…、SSL だと FrontPage 2003 からはアクセスできない…、ということなのでしょうか。とりあえず Internet Explorer の Web フォルダ機能を使う分には、 SSL で平気なのですけどね…。
仕方ないので打開策が見つかるまで SSL なしで発行しようかと思いきや、なぜだか一覧は取得できるもののいざ発行の段階でアップロードすることが出来ませんでした。
いろいろと実験してみる
SSL であれなかれ、DAV サーバへ FrontPage でアップロードするのが目的でもあるので、改めていろいろと実験してみることにします。
上記では既存の Apache を使っていたためにむやみにいろいろとは実験できなかったので、今回は新たにまた Apache 2.0.48 を独立して立てての実験です。Apache のアカウントを apache-test、グループを apache として起動させることにします。これは httpd.conf の User: と Group: を編集することで変更可能です。
なお、apache-test アカウントの作成、および htdocs の所有者変更を次のようにして行いました。
useradd -d /usr/local/apache2/htdocs -s /bin/true -g apache apache-test
chown -R apache-test.apache /usr/local/apache2/htdocs
passwd apache-test
まずこの段階で Web サイトが普通に見れることを確認します。そうしたら、絶対に無理ですけど同じく Internet Explorer から DAV で接続できるかどうか確認しておきます。
ブラウズはできて、DAV が出来ないことが確認できたら、続いて DAV を有効にしてみます。
まずはロックファイルを置くディレクトリの用意です。
mkdir /var/httpd
chwon apache-test.apache /var/httpd/
そしてこれを利用できるように、httpd.conf に次の行を追加します。
DAVLockDB /var/httpd/dav.lock
同様に、httpd.conf の一番下あたりに次の行を追加して Apache を再起動します。
<Location />
DAV on
</Location>
この状態で、通常のブラウズと IE による Web フォルダを試してみて、両方できることを確認しました。Web フォルダでのファイルの操作も、読み込み、書き込みともにできました。
とりあえずこの状態で、FrontPage 2003 を使ってこのサイトを編集してみることにします。
URL を入力して開くと、WebDAV サイトはローカルディレクトリに作業領域を用意して編集、アップロードしないといけないとの事でした。なので C:\Temp\exp を作業ディレクトリとして開きます。開いたら導かれるまま、「リモートからローカル」 で発行、つまり作業ディレクトリへ既存の文書をダウンロードしてみます。
ここまではまったく問題を感じられませんでした。そして、いよいよ書き込みです。作業領域のファイルをひとつ編集して、「ローカルからリモート」 の方向で Web サイトの発行を行ってみました。
すると…、問題なくうまくいきました。
ではパスワードを設定するとどうなるかの実験をしてみます。上記で追加した <Location> ディレクティブ周りを、次のように設定してみました。
AddExternalAuth pwauth /usr/local/libexec/pwauth
SetExternalAuthMethod pwauth pipe
<Location />
AuthType Basic
AuthExternal pwauth
AuthName DAV
require user apache-test
</Location>
なお、このとき mod_auth_external を利用しているので、これもあらかじめインストールしておきました。あと、PAM も必要なのですけど、実験環境にはインストールされていなかったのでその辺りに少し触れておくことにします。
PAM は Index of -pub-linux-libs-pam-pre-library よりダウンロードすることが出来るようです。今回は Linux-PAM-0.77.tar.gz をダウンロードしてインストールしました。
tar xvzf Linux-PAM-0.77.tar.gz
cd Linux-PAM-0.77/
./configure
make
make install
そして…、思い当たりでてきとうにやってしまってなんなのですけど、/lib/security/ にいっぱいインストールされたものの /etc/pam.d/ は生成されなかったので、自分でつくってしまいました。
そしてそのなかに pwauth ファイルを用意したのですけど、どうも /lib/security/ には pam_pwdb.so が存在していないようだったので、それっぽい pam_unix_auth.so を利用するようにしてみました。
auth required /lib/security/pam_unix_auth.so shadow nullok
auth required /lib/security/pam_nologin.so
account required /lib/security/pam_unix_auth.so
こんなてきとうでうまくいくのか心配でしたけど、ちゃんと認証に成功すればサイトが見れるし、わざと間違えたパスワードを入れれば拒否されるし、なんだかうまくいったようです。
では、あらためて FrontPage 2003 を使って Web サイトの発行を行ってみます。
すると…、悩まされていたエラーが発生しました。念のため IE の Web フォルダで開いてみましたけど、それならば正常に開けるようです。これは、もしかすると認証方式か何かが問題になっているのかもしれませんね。
とりあえず、mod_auth_external ではなく mod_auth で Basic 認証を行ってみます。
# AddExternalAuth pwauth /usr/local/libexec/pwauth
# SetExternalAuthMethod pwauth pipe
<Location />
AuthType Basic
AuthUserFile /tmp/httpd.pwd
# AuthExternal pwauth
AuthName DAV
require user apache-test test
</Location>
pwauth 関連の行を念のためコメントアウトして、mod_auth に必要な AuthUserFile の行を追加しています。そして許可するユーザに "test" を追加しています。
なお、指定しているパスワードファイルは、実験中につき、とりあえず tmp/ ディレクトリ内に入れてみてます。また、このファイルは次のようにして作成しています。
/usr/local/apache2/bin/htpasswd -c /tmp/httpd.pwd test
これで実験してみましたけど、状況は mod_auth_external を利用していたときと同じようです。
Basic 認証のほかにダイジェスト認証もあるようで、もしかするとそれしか許可してない可能性も考えられたので、それも少し実験してみます。ダイジェスト認証を使用できるようにするには --enable-auth-digest をつけて Apache を再コンパイルする必要がありました。
既に利用できるかどうかは、/usr/local/apache2/bin/httpd -l を実行して、mod_auth_digest モジュールが組み込まれているかどうかで調べることが出来ます。
準備が出来たら、httpd.conf を次のように書き換えます。
<Location />
AuthType Digest
AuthDigestFile /tmp/httpd.digest
AuthName DAV
require user apache-test test
</Location>
書き換える箇所は、AuthType と AuthDigestFile の部分です。AuthUserFile は今回は不要なので削除しました。これらが書けたら Apache を再起動するとともに、次のようにしてダイジェスト認証用のファイルを作成します。
/usr/local/apache2/bin/htdigest -c /tmp/httpd.digest DAV test
上記で "realm" の部分は、認証の再に使用する文字列で、好きなものを指定できるようです。ただし、注意しなくてはいけないのは AuthName に指定したものと同じでないといけないとのことです。
実際、間違って別のものを設定してしまい認証に失敗してしまったので、設定の際には注意しましょう。余談ですけどダイジェスト認証にして、IE でサイトを参照してみると、Basic 認証のときよりは立派なダイアログボックスが表示されました。
さて、FrontPage 2003 ではどうなるでしょう…。Web の発行を行ってみると、やはり、Basic 認証のときと同様のエラーが発生してしまうのでした。
そういえば DAV の設定を見ていると、<Limit> にて特定のメソッドに対してパスワードを設定しているのを見かけます。
単純に、編集に関するものだけを除外しているのかと思っているのですけど、ここに何かヒントがあるかもしれないので実際にやってみることにします。認証はとりあえず mod_auth の Basic 認証に戻しておきます。
そのうえで、AuthType 関連の部分を次のようにして <Limit> 指定してみます。
<Location />
AuthType Basic
AuthUserFile /tmp/httpd.pwd
# AuthExternal pwauth
AuthName DAV
<Limit PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
require user apache-test test
</Limit>
</Location>
こうしてみましたけど、やっぱりエラーがでてしまいます。
そういえば、でているエラーを FrontPage で確認してみると、なぜだか 301 Moved Permanently なのでした。なにか Web のリストに狂いがあるのかもと思って更新もしてみましたけど効果は無いようです。
けれど、ためしにファイルを1つ選択してそれだけを発行してみると、なぜだか正常にファイルを発行することが出来るようです。複数を選択した場合もうまくいきました。
ここまでから、どうやら認証ありで 「発行」 の手続きをしようとすると 301 のエラーになってしまうようです。
Apache の書き出したアクセスログを見てみると…、思い当たるのは /images ディレクトリへの PROPFIND メソッドにて 301 があらわれている、くらいでしょうか。だからといって images/ ディレクトリが無いわけでもなく…。
PROPFIND で 301 が返ることが何か問題になっているのかも、と思って調べてみると、なかなか有力な説を発見しました。
ログでは /images という URI 要求がなされているのですけど、Apache は、最後に / がつかない場合はファイルとして認識するとのことなのです。そして 301 とともに、それは /images/ であるということを通知する…。
もしかすると、FrontPage はこの時点で /images はなかった、という結論を出してしまうのかもしれないです。でも、たぶんきっと本当に無い 401 の場合はちゃんとアップロードしてくれるのでしょう…。
ということで、サーバから images/ ディレクトリを削除して発行してみました。もうひとつ、_private/ というディレクトリもあったのでそれも削除して発行を行ってみると…、なんと正常に操作が完了しました。どうやら間違いないようです。
とはいえ、わざわざサーバのデータを消してからアップロードするわけにも行かないし…。ディレクトリの中身がちゃんとあればうまくいくかと考えてみたのですけど、それも無理でした。さらに、サーバ側のディレクトリを FrontPage から消そうとしても、同様に 301 エラーで操作不能でした。
これは、Apache の方で 301 を返さないようにしないといけません…。
これはどうやら、BrowserMatch "" redirect-carefully という行を追加することで対応できるようです。なので FrontPage が Web 発行で使用する UserAgent を調べてみることにします。
ログファイルに UserAgent を含めるため、"CustomLog logs/access_log common" の "common" だったところを、"combined" に変更します。combined というログの書式を含め、次のような感じです。
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog logs/access_log combined
こうして再び Web 発行を行ってみると、しっかりとログに UserAgent が記録されていました。それによると、FrontPage 2003 は次の UserAgent となっていました。
Mozilla/4.0 (compatible; MS FrontPage 6.0)
ということは、次のような BrowserMatch 行を追加すればいいことになるのでしょうか。
BrowserMatch "MS FrontPage" redirect-carefully
大まか過ぎて不安ですけど、とりあえずはこれでやってみることにします。いろいろな BrowserMatch が書かれているところへ上記を追加して Apache を再起動し、FrontPage で発行してみると、みごとアップロードすることができるようになりました。
なお、MacOS X 10.3 で WebDAV 接続した場合の UserAgent は "WebDAVFS/1.2.6 (01268000) Darwin/7.2.0 (Power Macintosh)" でした。Apache 2.0.48 のディフォルトでは次のものが登録されているようなので、もし無いようならこれらも登録しておくといいかもしれません。
#
# The following directives modify normal HTTP response behavior to
# handle known problems with browser implementations.
#
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
#
# The following directive disables redirects on non-GET requests for
# a directory that does not include the trailing slash. This fixes a
# problem with Microsoft WebFolders which does not appropriately handle
# redirects for folders with DAV methods.
# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
#
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-caref
ullyBrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
BrowserMatch "^gnome-vfs" redirect-carefully
これで一応、WebDAV による発行が問題なくできるようになりました。
ただ、元のサーバの SSL だと、やっぱり SharePoint Server がないとのエラーが帰ってきてしまうのでした。SSL だけを無効に設定すると平気なのですけどね。同様に Mac からも SSL には接続できなかったので、もしかすると仕組みがまた違ってくるのかもしれないです。
簡単にですけど調べてみると、MacOS X の Finder は SSL の WebDAV には対応していないとのことです。ということは、もしかすると FrontPage 2003 もそうなのかもしれないですね。根拠はないですけど…。