さてさて、なんとかWindows Server 2008 R2とADとCentOS 5.7とApache 2.2.3とmod_auth_kerbでKerberos認証を行うところまではいった。後は本番で使うために404や401用の専用ページを作る。Apacheの設定でErrorDocumentディレクティブを用いて独自のエラーページを表示させるわけだ。
ところがである。401のエラーページをCGIにすると、Kerberos認証が効かなくなったのだ。

正確には以下のような状況である。Apacheのけろけろすの設定は

<Location "/needsauth/">
    AuthType Kerberos
    KrbAuthRealms EXAMPLE.COM
    KrbServiceName HTTP/centos.example.com
    Krb5Keytab conf.d/centos.keytab
    KrbMethodNegotiate on
    KrbMethodK5Passwd on
    require valid-user
</Location>

つまり、Kerberosによる統合Windows認証を試行し、ダメだったらBASIC手順でユーザー名とパスワードを入力させてそいつをKerberosで確認する設定だ。この時に

ErrorDocument 401 /cgi-bin/error401.cgi

というのを同時に指定するとWebブラウザーが統合Windows認証もBASIC手順も行わずにすぐ諦めるようになりくさった。IE8でもFirefox8でも同じだ。例によってWiresharkの出番。すると、http://centos.example.com/needsauthにアクセスした時、ErrorDocumentが無い場合は

WWW-Authenticate: Negotiate\r\n
WWW-Authenticate: Basic realm="hogehoge"\r\n

と、WWW-AuthenticateというHTTPレスポンスヘッダーを2行で返すが、ErrorDocumentにCGIを設定した場合は

WWW-Authenticate: Negotiate, Basic realm="hogehoge"

と、カンマ区切りで2つ並べて返している。httpd.confで

ErrorDocument "hogehoge"

という風に文言だけ返すようにした場合と、

ErrorDocument /error/error404.html

という風に静的HTMLを返すようにした場合は起こらない。CGIが悪さをしていると思われる。より正確に言うとCGIが結果をApacheに返した後、Apache(mod_cgi?)がHTTPレスポンスヘッダーを再構築するタイミングでこの意図しないHTTPレスポンスヘッダーのマージが行われているようだ。ApacheのソースとAPRのソースを見てみたがよく分からんかった。apr_table_tというのでヘッダーを管理しているようだが。

なので、mod_auth_kerbが統合Windows認証とBASIC手順によるユーザー名の取得を両方とも有効にしていて、かつ401のエラードキュメントをCGIに転送している場合にのみ発生すると結論付けた。今回構築中のこれは本番ではBASIC手順によるユーザー名の取得は行わないため、これ以上の調査は面倒だし断念する事と相成った。

追記:上を書いた後こんな事(mod_auth_kerb+401CGI)しとる奴居らんやろ~ネットで散々っぱら探しても全く見当たらんしわしが世界で最初ちゃうんバグ報告なんかしちゃったら「おうおうJapのくせにやるじゃねえか」とか言われるんやろうかうひひひひひ、と意気揚々とApache HTTPDのBugzillaに登録しに行ったらすでにあった・・・・。ASF Bugzilla – Bug 50891(2.2.16用の様だが)パッチまで用意されとるがね。ただ、今回の件に限って言えば要らんし独自にパッチを当てたプログラムを動かした時に問題が起きたら責任取れんし何もせん事に決定。