ExtendedKeyUsageとブラウザの挙動

2005/1/31作成
2005/2/12更新



ある日、凝りもせずopensslとApacheでmod_sslの実験をしていたときです。
この組み合わせでの実験はだいぶ慣れてきたのでいつものように設定を入れてApacheを起動させたのですが、どうもアクセスでエラーになってしまいます。
原因を調べてみたら意外なことがわかりました。

■原因調査

○Apacheの挙動
Apache2.0.52のopenssl-0.9.7で問題なく起動しています。
プロセスも立ち上がっていましたし、'netstat -an'でも80と443のポートが開いていました。
○InternetExplorerの挙動
httpでは問題なくアクセスできました。
httpsでアクセスするとまず最初にプライベートCAで発行した証明書だったので、「信頼された認証局から発行されていません」のメッセージが出てきました。
実験だったので「OK」を押すと、「サーバに問題があります」のページが出ます。(サーバが落ちているときに出るメッセージです)
○Apacheのログ
いっさい残っていません。
○opensslのクライアントモードで試してみる
opensslにはクライアントモードというのがあります。
SSL/TLSセッションを張ってしまえばtelnetで80番にアクセスしたときと同様のことができるようになります。
% openssl s_client -connect localhost:443 -no_tls1 -state -debug
GET / HTTP/1.0
意外にも、この方法ではちゃんとアクセスできます。
opensslを使った場合、デフォルトではTLS1.0を使ってしまうので使わないように指定しました。

普段ならこのまま泥沼にはまるところですが、なぜかその日は冴えていたようですぐに原因が分かりました。
その日はopenssl.cnfの設定に次のようなくだりを書いて実験をしていました。

#extendedKeyUsage = serverAuth, clientAuth, msSGC, nsSGC
extendedKeyUsage = clientAuth, emailProtection, msSmartcardLogin

これはサーバ証明書とクライアント証明書でExtendedKeyUsageを使い分けるために用意したものです。
上記のようにクライアント証明書側に設定をしておいて、サーバ証明書を発行していたのです。

つまり、ExtendedKeyUsageにserverAuthが無いものをサーバ証明書として使った場合、

という動作をすることになります。

■RFC的には?

それではどっちが正しいのかということになりますが、RFC2459によると次のように解釈されています。
RFC2459 4.2.1.13 Extended key usage fieldより抜粋
This extension may, at the option of the certificate issuer, be either critical or non-critical.

If the extension is flagged critical, then the certificate MUST be used only for one of the purposes indicated.

If the extension is flagged non-critical, then it indicates the intended purpose or purposes of the key, and may be used in finding the correct key/certificate of an entity that has multiple keys/certificates. It is an advisory field and does not imply that usage of the key is restricted by the certification authority to the purpose indicated. Certificate using applications may nevertheless require that a particular purpose be indicated in order for the certificate to be acceptable to that application.
要約すると、ExtendKeyUsageがcriticalに設定されている場合はその用途にのみ使用しなければいけないけど、non-criticalの場合は認証局がこんな風に使って欲しいなという希望なんだよ。
non-criticalに設定されている場合でも、その目的にのみ利用したいというのであれば、アプリケーションで任意に決めてくれてもいいよ。
と読みとれます。
今回の設定では特にcriticalには設定していなかったので、non-criticalになるわけですが、RFC的にはどっちも正解ということですかね。
別に白黒つけたいわけではありませんが、なんか釈然としない結果になってしまいました。

■それではcriticalにしてみましょう

ということで、試しにcriticalに設定してみました。
extendedKeyUsage = critical, clientAuth, emailProtection, msSmartcardLogin
これの設定でサーバ証明書を発行し、Apacheに組み込みます。
そして、前述の原因調査と同様にアクセスしてみました。
結果は・・
opensslでアクセスできてしまうのはちょっと意外でした。
でも、冷静に考えると、opensslのクライアントモードはhttpsのブラウザではなく、SSL/TLSのクライアントツールなんですよね。
SMTPのSSLとかLDAPのSSLなんてのもあるわけなので、その上で走っているプロトコルなんて気にする必要はないのでしょう。
それより問題なのはApacheが動いている方ではないでしょうか。
RFCを律儀に守るのであれば、この証明書をサーバ証明書として使っちゃダメですよ。

openssl側の実装ミスと思われがちですが、この件に関してはApache側がどうにかする問題でしょうね。
openssl側でアプリがチェックするための便利なインタフェースなんかが用意されるといいかもしれません。

もどる