mod_encodingの罠

これはapacheでマルチバイト文字を含んだファイルを用いる場合に利用されるmod_encoding。
多くはWebDAV関連で知っているだろう。
これになかなかトラップがあるので、メモメモ。

mod_encodingはそもそも何をするモジュールかといえば、名前のとおりエンコードするモジュール。
マルチバイト文字には文字コードが付きまとう。
マルチバイト文字を含んだファイルをURIに含めると、クライアントサイドからのリクエスト文字コードとサーバでの文字コードが違うと、当然ファイルが見つからない状態になる。
この問題を解決するためのモジュールがこれということだ。

で、トラップその1。
Digest認証は基本的に使えないと思ったほうがいい。

Digest認証の流れをwikipediaからこぴぺ。

だいたいの流れは以下のようになる。

  1. クライアントは認証が必要なページをリクエストする。しかし、通常ここではユーザ名とパスワードを送っていない。なぜならばブラウザはそのページが認証を必要とするか否か知らないためである。
  2. サーバは401レスポンスコードを返し、認証領域 (realm) や認証方式(Digest)に関する情報をクライアントに返す。このとき、ランダムな文字列(nonce)も返される。
  3. ここでクライアントは、認証領域(通常は、アクセスしているサーバやシステムなどの簡単な説明)をユーザに提示して、ユーザ名とパスワードの入力を求める。ユーザはここでキャンセルすることもできる。
  4. ユーザ名とパスワードが入れられると、クライアントはnonceとは別のランダムな文字列(cnonce)を生成する。これよりユーザ名とパスワードと2つのランダムな文字列などを使ってハッシュ文字列(response)を生成する。
  5. クライアントはサーバから送られた認証に関する情報とともに、ユーザ名とresponseをサーバに送信する。
  6. サーバ側では、クライアントから送られてきたランダムな文字列(nonce、cnonce)などとサーバに格納されているハッシュ化されたパスワードから、正解のハッシュを計算する。
  7. この値と、クライアントから送られたresponseが一致する場合認証成功として、コンテンツを返す。失敗時は401レスポンスコードを返す。

ユーザ名とパスワードの具体的な計算は以下のようになる。なお、ここでは認証アルゴリズムMD5の時の計算方法を示す。

クライアントで計算するresponseは以下のようにして求められる:

A1 = ユーザ名 ":" realm ":" パスワード
A2 = HTTPのメソッド ":" コンテンツのURI
response = MD5( MD5(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" MD5(A2) )

サーバ側では、MD5(A1) を予め格納しておいてある。nonce,nc,cnonce,qopとHTTPのメソッド(GETなど)とコンテンツのURIはクライアントから送られるのでサーバ側で正解のresponseを計算できる。

A2のラインをみてほしい。
コンテンツのURIが計算に含まれている。
mod_encodingはURIのエンコードを行う。
すると、認証に用いるURIがクライアントとサーバで異なる値となるため、mod_encodingとDigest認証の組み合わせでは問題が発生することとなる。

トラップその2。
特定の文字を含んだURIにアクセスできなくなる。

とりあえず、この辺の文字は使わないほうがいい。

「#」、「=」、「&」、「%」、「?」、「!」、「*」、「,」、「/」、「」、「:」、「;」、「|」、「<」、「>」

!は使えたりするんで全部使えないわけじゃないけど大体使えない。
もともと使えないものも含まれてるんだけど、#と%を含むものが使えなくなるのは確認。
これはたぶん、Apache的にはエンコードしないでほしいのもエンコードしちゃってるからじゃないかとか思ってる。
実際のところはどうなのか知らない。

一応RFCの日本語訳から、URIに使用する文字について、非予約文字について。

2.3. 非予約文字

URI 内に含む事が認められており、予約目的のない文字は、予約されていない (unreserved) と呼ばれる。
これは、大文字と小文字のアルファベット、数字、ハイフン、ピリオド、アンダースコア、チルダが含まれる。

unreserved  = ALPHA / DIGIT / “-” / “.” / “_” / “~”

非予約文字を、対応するパーセントエンコードされた US-ASCII オクテットに置き換えている点が異なる URI は、等価である:
それらは同じリソースを識別する。
しかし、URI 比較を行う実装が常に比較の前に正規化を行うわけではない (Section 6 参照)。
整合性を持たせるため、URI の生成を行うものは ALPHA (%41-%5A と %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), tilde (%7E) の範囲におけるパーセントエンコードされたオクテットを生成すべきではないし、URI を発見した時に、URI 正規化によってそれらを対応する非予約文字にデコードすべきである。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>