証明書検証時にパス構築を行うが、このときに
DN
のエンコード方式や格納さ れるデータが影響を与える。この部分に注目して各アプリケーションのソースコ ードを調査する。4.6.1 curl,w3m
サーバ証明書の検証には
SSL
接続のネゴシエート時に行われた検証結果を使用 している。SSL
接続を行う際にはサーバ側の証明書が必要になるため、openssl
ライブラリ内部でサーバ証明書を取得した際に検証動作が行われる。ただし、検証の結果不正であると判断されても、即時に通信を停止するという のはアプリケーションからみれば使いにくい実装であるので、アプリケーション に判断を委譲することができるようになっている。
curl
ではアプリケーションで証明書の有効期間などを取得するコードが書かれ ている。しかし、アプリケーションが取得した証明書の情報は画面表示に使用す るのみで一切チェックしていないため、証明書の検証動作には影響を与えていな い。証明書の検証は完全にopenssl
ライブラリに任せてあるため、検証ロジック はすべてopenssl
ライブラリに依存している。また、CRL
のチェックはcurl
、w3m
双方していない。openssl
が用いている検証ロジックについては後述する。4.6.2 lynx
lynx
でもcurl、w3m
と同様、SSL接続のネゴシエート時に行われた検証結果 を使用しているが、他と異なりlynx
ではネゴシエート途中でユーザーに確認を求 め、それ以降の処理を中止するかどうか決定している。しかし、それも証明書が不正であった場合の動作決定をいつおこなうかという 問題であり、証明書の検証動作に影響を与えるものではない。lynxでも検証自体 は
openssl
ライブラリに任せている。4.6.3 openca
openca
ではモジュールの内部でopenssl
コマンドを実行し、その結果を得ることで
S/MIME
メッセージの検証を行っている。署名検証動作の時に実際に起動される
openssl
コマンドは次のように生成され ており、このコマンドの実行結果によって検証結果を取得している。push(@command, "smime", "-verify");
push(@command, "-engine", $self->get̲param ("ENGINE", %params), "-keyform", "e")
if($self->get̲param ("ENGINE", %params));
push(@command, "-nointern") unless($params{USES̲EMBEDDED̲CERT});
push(@command, "-CAfile", $self->{ca̲certs̲file}) if($self->{ca̲certs̲file});
push(@command, "-certfile", $certfile) if($certfile);
push(@command, "-in", $self->{file}, "-out", $outfile,
"-signer", $signerfile);
openssl
コマンドでは-crl_fileオプションを使ってCRL
のチェックをすること ができるが、ここにそのオプションがない。このことからCRL
を参照していない 事がわかる。CRLを扱いたい場合、別の方法で検証しなければならない。4.6.4 apache
apache
の証明書を扱う部分は、他のアプリケーションと比べて格段に複雑な処理を行っている。しかし
SSL
クライアント認証時のクライアント証明書検証に限 った場合、検証のルールはopenssl
ライブラリ内部に隠蔽されており、他と同じ である。CRL
のチェックは行っているが、前述したとおりopenssl
のライブラリを利用 せず、アプリケーションで独自に実装している。ただし、独自に実装しているのは検証対象となる
CRL
をCRL
ストアから取得した後の動作であり、対象となる 証明書と同じissuer
をもつCRL
を取得する部分はopenssl
のX509̲STORE̲get̲by̲subject(&pStoreCtx, nType, pName, pObj);
関数をつかって実装されているため、
DN
の比較ルーチンとしてはopenssl
ライ ブラリに依存している事がわかる。このライブラリの中で
CRL
のストアからCRL
を取得する時、DNの比較をし ているが、DN比較では最終的にint X509̲NAME̲cmp(const X509̲NAME *a, const X509̲NAME *b)
関数が使用される。
4.6.5 openssl/smime(
コマンド)
openca
から呼び出されているopenssl/smime
コマンドの実装を調査した。CRL
チェックを有効にして呼び出せば、opensslライブラリの機能を利用してCRL
チェックを行う事ができる。証明書の検証は
X509_verify_cert()関数で行われる。導関数内において、最終的
にはX509_NAME_cmp()関数を使って比較が行われている。
4.6.6 openssl
ライブラリでの実装結局今回調査したアプリケーションでは証明書検証が必要な動作はすべて
openssl
ライブラリを使用して行っていることがわかった。openssl
ライブラリ内 でDN
を比較する処理を行っているのはX509_NAME_cmp()
関数であるため、こ の関数を調査すればopenssl
環境でのDN
比較ロジックが把握できる。if (na->value->type == V̲ASN1̲PRINTABLESTRING)
j=nocase̲spacenorm̲cmp(na->value, nb->value);
else if (na->value->type == V̲ASN1̲IA5STRING
&& OBJ̲obj2nid(na->object) == NID̲pkcs9̲emailAddress) j=nocase̲cmp(na->value, nb->value);
else {
j=na->value->length-nb->value->length;
if (j) return(j);
j=memcmp(na->value->data,nb->value->data, na->value->length);
}
X509_NAME_cmp()
関数の一部である。ここでna
、nb
は比較されるRDN
であ る。RDN
のエンコード方式がPrintableString
の場合は大文字、小文字の区別な し、前後の空白を無視、中間の連続した空白を一つの空白と置き換える比較を行 っている。それ以外の場合は
memcmp
によりデータの値を比較している。このコードに到達する以前に、エンコード方式が異なっている場合は比較する ことなく不一致としているため、