2007/01/20
この記事では Windows クライアントの WebDAV の実装に関する問題が扱われている。Windows クライアントの WebDAV に関しては膨大な記事がネット上に存在するが、殆どは Apache の設定などのハウツーに関するもので、プロトコルレベルの議論は見つからない。ここではプロトコルレベルで発生している問題を扱い、そのためにサーバが何をしなくてはならないのかを解説する。
記事のスタイルはブログ風である。従ってどのような試行錯誤の中で問題を解決していったか、またその途中でどのような現象が発生したかがよく分かると思う。
なおサーバは Pegasus であるが、記事の内容は普遍的なものである。Pegasus に関しては「Pegasus 2.4, CGI/1.1 and WebDAV」を参考にしてほしい。
実験対象のクライアントのバージョンは 5.1(SP2)
図1. WinXP のバージョン情報
この画面はウィンドウの HELP の「バージョン情報」で得られる。
2007/01/14
support.microsoft.com の情報(2003年7月)によると WebClient サービスにはバグがあって、認証が働かないらしい。一旦サービスを停止させ、ウェブフォルダが作成されたら、また動作させよとのこと。この情報は現在も有効なのか否かは不明。(有効であれば3年間も放置されていることになる!)
現在の到達点。認証を外した上で
net use * http://pc/dav
を発行。結果は「システムエラー 67 」(ネットワーク名が見つからない)
ここに "pc" は筆者の実験中のサーバ名で、このように名前で指定できるためには
Windows/system32/drivers/etc/hosts
に "pc" と その IP アドレスを登録しなくてはならない。また "/dav" は、サーバ上に設定されている DAV ようのディレクトリである。なお net コマンドに関しては、例えば
http://www.atmarkit.co.jp/fwin2k/win2ktips/258netcommand/netcommand.html
に解説されている。
サーバのログは
OPTIONS / HTTP/1.1 translate: f User-Agent: Microsoft-WebDAV-MiniRedir/5.1.2600 Host: pc Content-Length: 0 Connection: Keep-Alive
となっている。
なお WinXP のユーザエイジェントは
になっているらしい。WebClient が動作しているか否かはサーバのログを見なくても、WinXP で
の順に辿れば WebClient の状態が分かる。
Win-XP クライアントはこの結論を出す前に
PROPFIND /dav/ HTTP/1.1
を試している。サーバの応答(認証は外してあるので、プロパティの応答はしている)に何らかの問題があったと考えられる。(後に見るように、この推測は正しくない。)
なお筆者のサーバの応答ヘッダには
MS-Author-Via: DAV
は含まれている。
2007/01/14
WebClient サービスの簡便な停止の方法が
http://ulihansen.kicks-ass.net/aero/webdav/
に載っている。このサイトには WinXP 問題に関する詳しい説明と解決法が載っている。それによると Web フォルダーの作成の入力欄に次の2つのいずれかを使うと良いらしい。
http://pc:80/dav
http://pc/dav#
また Google によるネットの情報では
http://pc/dav?
も解決策とされている。
net use コマンドではいずれもダメであった。net use コマンドを使う第2の方法では
ユーザ名とパスワードの入力を促されたが(サーバは認証を要求していないのに...)
「システムエラー 5 が発生しました。アクセスが拒否されました」と言われた。
原因は net コマンドが、 dav# を "dav%23" としてサーバにリクエストを送ったためである。つまり "#" をパス名の一部と解釈したのである。これは net use コマンドのバグかも知れない。また第1と第3ではそもそもサーバにアクセスに行かない!
007/01/14
net コマンドではうまく行かない。しかし「マイネットワーク」の「ネットワークプレースを追加する」で
http://pc/dav?
とすると確かに「pc上のdav」が追加された。
図1. WinXP のネットワークプレース
そしてサーバのログでは User-Agent が "Microsoft Data Access Internet Publishing Provider DAV" に変わった。確かに WebClient サービスが停止されたのである。
サーバを認証なしに設定していると net コマンドは依然として「67」エラーであるが、ダイジェスト認証に設定し
net use * http://pc/dav
を実行すると、ユーザ名とパスワードの入力を求められるようになり、ユーザ名
arisawa@pc
にして
「システムエラー1219」
「同じユーザによる、サーバまたは共有リソースへの複数のユーザ名での複数の接続は許可されません。サーバまたは共有リソースへの以前の接続をすべて切断してから、再試行してください。」と言われる。(しかし同じ事をやっても別のメッセージがでる事もある。)
WinXP はネットワーク資源のアクセスに関しては "arisawa" のような、ネットワーク情報の付加されないユーザ名を拒否する。従ってサーバ側でユーザ名を、次のいずれかに設定しなくてはならない。
arisawa@pc
pc\arisawa
ここに "pc" は筆者が実験中のサーバ名である。「\」を使うのは Win 臭くて嫌なので、筆者は "arisawa@pc" に設定している。(後に見るように、これでもよろしい。)
ホスト名が要求されるのは「ネットワークプレイスの追加」の時だけらしい。
従って
arisawa@pc
arisawa
の 2 つのユーザ名を許すように設定すれば、ウェブフォルダーの作成に成功した後は "arisawa" でやっていける。
なお、「ネットワークプレイスの追加」の時のホスト名が
http://ar.aichi-u.ac.hp/dav?
のようなフルアドレスの場合でも、追加の際に要求されるユーザ名は
arisawa@ar
のようにホスト名だけを追加したもので構わない。
2007/01/16
なお、WinXP は SP2 以降、通信路が暗号化されていない場合の基本認証を禁止している(文献)。
次に示すのは
net use * http://pc/dav
によるログである。(これはユーザ認証を求められた後に「67」エラー)
OPTIONS / HTTP/1.1 translate: f User-Agent: Microsoft-WebDAV-MiniRedir/5.1.2600 Host: pc Content-Length: 0 Connection: Keep-Alive PROPFIND /dav HTTP/1.1 Depth: 0 translate: f User-Agent: Microsoft-WebDAV-MiniRedir/5.1.2600 Host: pc Content-Length: 0 Connection: Keep-Alive # redirect to /dav/ PROPFIND /dav/ HTTP/1.1 Depth: 0 translate: f User-Agent: Microsoft-WebDAV-MiniRedir/5.1.2600 Host: pc Content-Length: 0 Connection: Keep-Alive
ここでダイジェスト認証を求めらる。しかし WinXP は、ここでアクセスを止める。サーバには認証情報を送っていない。
"#" で始まる行は、サーバからクライアントへの指示。(ログから得られた筆者のコメント)
次に示すのはウェブフォルダをクリックした場合のログ。
PROPFIND /dav HTTP/1.1 Content-Language: en-us Accept-Language: ja, en-us;q=0.2 Content-Type: text/xml Translate: f Depth: 0 Content-Length: 0 User-Agent: Microsoft Data Access Internet Publishing Provider DAV Host: pc Connection: Keep-Alive # redirect to /dav/ PROPFIND /dav HTTP/1.1 Content-Language: en-us Accept-Language: ja, en-us;q=0.2 Content-Type: text/xml Translate: f Depth: 1 Content-Length: 489 User-Agent: Microsoft Data Access Internet Publishing Provider DAV Host: pc Connection: Keep-Alive
Redirection の指示が無視されている!
(PROPFIND に関しては "/" を付ける必要はないかも知れないが...)
構わず
Depth: 1
が実行される。つまり、サーバの応答を無視している!
そして期待される結果が得られないので、さらに続いて OPTION をトライする。
OPTIONS / HTTP/1.1 Translate: f User-Agent: Microsoft Data Access Internet Publishing Provider Protocol Discovery Host: pc Content-Length: 0 Connection: Keep-Alive OPTIONS /dav HTTP/1.1 Translate: f User-Agent: Microsoft Data Access Internet Publishing Provider Protocol Discovery Host: pc Content-Length: 0 Connection: Keep-Alive # redirect to /dav/ OPTIONS /dav/ HTTP/1.1 Translate: f User-Agent: Microsoft Data Access Internet Publishing Provider Protocol Discovery Host: pc Content-Length: 0 Connection: Keep-Alive # Reply: 401 Unauthorized
WinXP はサーバの認証要求に応えない(パスワード入力画面が現れない)。もちろんクライアントはマウントに失敗する。
やんちゃな WinXP クライアントにつきあうか? その場合には
の(いずれか、あるいは両方の)改造を加えなくてはならなくなる。サーバコードがくちゃくちゃする!
2007/01/16
ウェブフォルダをクリックした場合のログからは対策の方向が見えてくる。PROPFIND でのリダイレクションを WinXP は捕えない(Mac/OSX は捕えている)。たぶん WinXP の DAV クライアントは、まさかリダイレクションの指示が返ってくるとは思っていないのであろう。相手は DAV サーバであり、単なる http サーバではないのだから... と。
http サーバの場合にはクライアントから
http://host/foo
のようなリクエストがあり、"foo" がディレクトリであれば、クライアントにそのことを知らせるために
http://host/foo/
でアクセスするように求める。これによってクライアントは "foo" がディレクトリである事を認識する。
多分どのサーバでも Pegasus と同様な手順を踏むと思うのだが、Pegasus はリクエストされているファイルを完全に確定してから、アクセス制限のチェックや認証を求め、さらにそれに合格したリクエストに関してのみ、(その対象が CGI であれば) CGI プログラムを実行する。つまりリダイレクションは CGI である webdav にリクエストが渡る前に行われる。Pegasus 自身は GET, HEAD, POST, OPTION 以外のメソッドを知らないのだ。
しかし WebDAV は PROPFIND を持っている。これを使えばリダイレクションをしなくてもクライアントは "foo" がディレクトリてある事が分かる。従って WinXP 対策としては、WebDAV に特徴的なメソッドに対してはリダイレクションをしない事が考えられる。しかしこの方向はサーバのプログラムコードを複雑にするから嫌だ。
筆者にとっては WebDAV はあくまで Pegasus の CGI の一つである。WebDAV に固有なコードは一行だって入れたくはないのである。そこで次のように考えてみた。"foo" と言うディレクトリが存在するからリダイレクションを指示することになるのだと...
そこで "/doc/dav" を作らない事にした。その代わりハンドラの内容を(とりあえず)次のようにしてみた*。
/dav - + /bin/webdav /dav /doc/dav1
/dav/* - + /bin/webdav /dav /doc/dav1
この意味は
http://pc/dav/foo
のようなリクエストに対して
/bin/webdav /dav /doc/dav1
を実行する事を指示する。webdav はリクエストの内容 "/dav/foo" を環境変数 $request から知る事ができる。そこで、webdav に与えられた2つの引数 "/dav" と "/doc/dav1" を参照して "/doc/dav1/foo" を構成し、実際の処理対象のディレクトリを "/doc/dav1" にすり替えるようと言う訳である。
注意 *: 現在はこの仕様は変わっている。第3フィールドは WebDAV の場合には "+" ではなく、"*" を指定する。(2007/01/19)
この考えで webdav に(引数が与えられるように)手を加えたところ、今度はうまく WinXP クライアントを騙せた。
WinXP クライアントによる "http://pc/dav" のマウント
めでたしめでたし。
筆者は Microsoft は嫌いである。だから悪口を書く事が多いが、ここでは WebDAV のサポートに当たって Microsoft が考えたであろう事を肯定的に述べてみたい。
WebDAV はどのような目的で使われるのか? 次の2つが考えられる。
第1の場合には、ファイルの実態をドキュメントルートの下に置くのは好ましくない。従ってクライアントとのインターフェースが
http://pc/dav
であっても、実際にファイルが置かれる場所は "/doc/dav" ではなく、ドキュメントルート "/doc" の外にあるディレクトリになるであろう。
第2の場合には、ユーザはマウントされたディレクトリの中にドキュメントルート以下のファイルを全て見たいのである。従って "/doc" が編集の対象となるディレクトリに指定されなくてはならない。この場合のハンドラの設定は
/dav - + /bin/webdav /dav /doc
/dav/* - + /bin/webdav /dav /doc
となる*。この場合、ユーザの誤操作を防ぐ意味でも、マウントされたディレクトリの中に "/dav" が含まれない方が好ましい。
つまり、よく考えてみると Microsoft の考え方に合理性があるのである。
注意 *: 現在はこの仕様は変わっている。第3フィールドは WebDAV の場合には "+" ではなく、"*" を指定する。(2007/01/19)
マウントされた HTML ファイルをダブルクリックすると IE が起動し、そして認証が求められた。なぜ認証が求められるか不思議に思いサーバのログを調べるとリクエストは次のようになっている。
GET /dav/memo.html HTTP/1.1 Accept: */* Accept-Language: ja Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) Host: pc Connection: Keep-Alive
何と IE が直接アクセスしているのである! だからもう一度認証のやり直しである。ちゃんとファイルシステムとして実装されていない、とりあえず見かけ上なんとかファイルシステムに見えればよいだなんてあんまりだ。
2007/02/04
WinXP クライアントからは
Pegasus 側では
Win2000 は既にリリースされて 7 年を経ており、その間に多くの修正が加えられている。従って実験中の OS バージョンをはっきりさせておく必要があろう。筆者のは
OS 名 Microsoft Windows 2000 Professional
バージョン 5.0.2195 Service Pack 4 ビルド 2195
である。
システテム情報
この画面は、「コントロールパネル」→「管理ツール」を辿って得られる。
同じ情報は WinXP と同様に、ウィンドウの「HELP」からも得られる。
2007/01/14
Win-2000 をクライアントにした場合に観測される様々な User-Agent
SP3 以降では、他に次のようなものが観測される
不思議な事にメソッドによって使い分けているようである。
サーバのログを見ると
GET /_vti_inf.html HTTP/1.1
POST /_vti_bin/shtml.exe/_vti_rpc HTTP/1.1
が見える。これは何故か? POST がクライアントから自動的に行われる事に危うさを感じるが...
この問題に対する microsoft による情報は
http://support.microsoft.com/kb/828909/ja
ネットの記事によるとサーバが次のヘッダを持っていれば
MS-Author-Via: DAV
Win クライアントは _vti_inf.html を要求しないらしい*。
2007/01/19
さて WinXP はクリアしたので、今日は Win2000 に再度アタックする。
「ネットワークプレイスの追加ウイザード」から
http://pc/dav
で追加を試みるも、「入力したフォルダは有効ではない」と言われる。サーバは次のように反応している。(このサーバは WinXP をマウントできる。)
OPTIONS / HTTP/1.1 Translate: f User-Agent: Microsoft Data Access Internet Publishing Provider Protocol Discovery Host: pc Content-Length: 0 Connection: Keep-Alive OPTIONS /dav HTTP/1.1 Translate: f User-Agent: Microsoft Data Access Internet Publishing Provider Protocol Discovery Host: pc Content-Length: 0 Connection: Keep-Alive # Reply: 401 Unauthorized OPTIONS / HTTP/1.1 User-Agent: Microsoft Data Access Internet Publishing Provider Cache Manager Host: pc Content-Length: 0 Connection: Keep-Alive OPTIONS /dav HTTP/1.1 Accept-Language: ja, en-us;q=0.2 User-Agent: Microsoft Data Access Internet Publishing Provider DAV 1.1 Host: pc Content-Length: 0 Connection: Keep-Alive # Reply: 401 Unauthorized GET /_vti_inf.html HTTP/1.1 Date: Fri, 19 Jan 2007 13:26:25 GMT MIME-Version: 1.0 Accept: */* User-Agent: Mozilla/2.0 (compatible; MS FrontPage 4.0) Host: pc Accept: auth/sicily Content-Length: 0 Connection: Keep-Alive Cache-Control: no-cache # Reply: 404 Not Found POST /_vti_bin/shtml.exe/_vti_rpc HTTP/1.1 Date: Fri, 19 Jan 2007 13:26:25 GMT MIME-Version: 1.0 User-Agent: MSFrontPage/4.0 Host: pc Accept: auth/sicily Content-Length: 41 Content-Type: application/x-www-form-urlencoded X-Vermeer-Content-Type: application/x-www-form-urlencoded Connection: Keep-Alive Cache-Control: no-cache # unallowed: POST /_vti_rpc
WinXP でやったように
http://pc/dav?
とやっても、やはりフェブフォルダは作成されない。(同じメッセージ)
サーバが認証情報を要求しているのに、無視している。
そこで、サーバのパスワードを外して
http://pc/dav
でウェブフォルダの作成を試みると成功。作成されたウェブフォルダをダブルクリックするとマウントされているのが確認できる。
この時のサーバのログは次の通り:
OPTIONS / HTTP/1.1 User-Agent: Microsoft Data Access Internet Publishing Provider Cache Manager Host: pc Content-Length: 0 Connection: Keep-Alive OPTIONS /dav HTTP/1.1 Accept-Language: ja, en-us;q=0.2 User-Agent: Microsoft Data Access Internet Publishing Provider DAV 1.1 Host: pc Content-Length: 0 Connection: Keep-Alive PROPFIND /dav HTTP/1.1 Accept-Language: ja, en-us;q=0.2 Content-Type: text/xml Translate: f Content-Length: 0 Depth: 0 User-Agent: Microsoft Data Access Internet Publishing Provider DAV 1.1 Host: pc Connection: Keep-Alive OPTIONS /dav HTTP/1.1 User-Agent: Microsoft Data Access Internet Publishing Provider Cache Manager Host: pc Content-Length: 0 Connection: Keep-Alive PROPFIND /dav HTTP/1.1 Accept-Language: ja, en-us;q=0.2 Content-Type: text/xml Translate: f Content-Length: 380 Depth: 1 User-Agent: Microsoft Data Access Internet Publishing Provider DAV 1.1 Host: pc Connection: Keep-Alive
どうやら Win2000 をサポートするには、OPTIONS に対して認証を要求してはならないらしい。
(ウェブフォルダが作成されたら、後は認証を要求しても大丈夫かと試したが、「予期しないエラー」でダメである。)
2007/01/20
認証なしの OPTIONS を許してみる。
しかし
Win2000 のエラーメッセージ
表示されているファイルの中のメッセージは
You can't POST on <a href="/_vti_bin/shtml.exe/_vti_rpc"> here
である。
この問題は OPTIONS への応答ヘッダに
MS-Author-Via: DAV
を含める事によって解決した。
Win2000 にパスワード入力画面が現れて、必要な情報を入れてやった。今度はエラーにはならない。しかしダメ。マウントはされたように見えるが、そこにファイルの一覧が見えない。
サーバのログを調べると
PROPFIND /dav HTTP/1.1
にまで進んだ事を示している。サーバはここで認証を要求する。
クライアントは確かにダイジェスト認証で応えてはいるが、サーバのログは認証エラーを示している。Win2000 はダイジェストの計算を間違えている! そしてまたもや、サーバからの応答メッセージを捕えていない。
でも不思議だねー。Win2000 クライアントは、その後、パスワード入力画面を示さない。再起動しても、ウェブフォルダーを作り直してもである! どうやら一回入力したパスワードが記憶されていて、それが使われているらしい。こういうのは実に嫌だ。
パスワード入力画面の問題は「ゴミ箱」を空にしたら解決した。さらに認証されなかった問題も同時に解決。
Win2000 の WebDAV のマウント画面
2007/02/04
日本の文字を含むファイルやディレクトリにアクセスできない事に気づいた。
サーバのログを見て、あっと驚く。
Win2000 クライアントは RFC の規則を守っていない!
これでは Win2000 の場合には日本文字を含むファイルのサポートをあきらめるしかないであろう。
(文字コードを解析して Win2000 のための特殊パッチを充てる程の価値はないと思う)
NB: この記事は正確ではない。これは IE5.0 を使用していたからである。IE6.0 をインストールしたら、日本の文字を含むファイル名のファイルにアクセスできた。
こういう問題が IE と絡んでいるところが Win らしい。
(2007/02/08)
2007/02/04
クライアント側から見た WinXP との違いをまとめる。
Win2000 の認証画面
2007/01/20
Pegasus は Win2000 クライアントをマウントするするようになったものの、これを正式の仕様にするのは嫌だ。そのためには OPTIONS を認証なしにどのディレクトリに対しても許さなくてはならない。この場合、OPTIONS の応答に CGI が使われれば、セキュリティ上の弱点になる。他方 Pegasus の本体で処理すれば、OPTIONS の本来の趣旨に反し、ディレクトリが何であれ一律に全てのメソッドをサポートしているかのような応答をせざるを得なくなる。(今回の筆者が採用した方法は後者であり、また Windows IIS も後者ではないかと思われる。)
さらに
MS-Author-Via: DAV
を Pegasus の(CGI にではなく)本体に組み込むのも嫌である。
結局 WIn2000 のサポートのためのコードは Pegasus の全体の論理構造を崩し、単なる Win2000 のためのダーティトリックである。従って Win2000 はコンパイラオプションによって許すことにしようと思う。