サーバー SSL | SChannel クライアント証明書の失効

SSLOptions.VerifyCertificateをTrueに設定すると、サーバーは接続してくるクライアントごとに証明書を要求し、提示されたチェーンを検証します。この検証によって、クライアントのチェーンが信頼できることが確認されます。しかし、そのクライアント証明書が発行後に失効させられたかどうかについては何も分かりません。

このギャップは、証明書そのものが認証情報となる場面で重要になります。ノートパソコンを紛失したり従業員が退職したりして、その相手に発行された証明書を失効させても、有効期限が切れる日までは依然としてサーバー上でセッションを開始できてしまいます。失効の照会は、SSLOptions.SChannel_Options.Revocationを通じて明示的に要求した場合にのみ行われます。

失効に関する設定は、クライアント証明書の検証中に読み取られます。そのため、そもそもサーバーにクライアント証明書を要求させるSSLOptions.VerifyCertificateがTrueでなければ、これらの設定は何も行いません。証明書をまったく提示しないクライアントを拒否するか通過させるかは別の判断であり、SSLOptions.VerifyCertificate_Options.FailIfNoCertificateが決定します。


oServer.SSL := True;
oServer.SSLOptions.IOHandler := iohSChannel;
oServer.SSLOptions.VerifyCertificate := True;
oServer.SSLOptions.VerifyCertificate_Options.FailIfNoCertificate := True;
oServer.SSLOptions.SChannel_Options.Revocation.Check := scrcChainExcludeRoot;

失効状態は証明書チェーンの構築中に取得されます。つまり、クライアント証明書に指定されたCRL配布ポイントまたはOCSPレスポンダーには、ハンドシェイク中にアクセスが行われます。チェックがデフォルトで無効になっているのはこのためです。有効にすると、サーバーが受け付けるすべての接続の経路に外向きのリクエストが加わります。

Check

クライアントチェーンのどの範囲まで失効状態を照会するかを選択します。

scrcDisabled デフォルト。失効状態は取得されず、必須でもありません。
scrcEndCertificate クライアント証明書自体のみをチェックします。最も負荷の低いオプションで、接続ごとに1回の照会で済みます。
scrcChainExcludeRoot クライアント証明書とそれを発行した中間証明書をチェックし、ルート証明書はチェックしません。クライアント証明書を発行するCAのルート証明書が自身のCRLを公開することはほとんどないため、通常はこれを選択します。
scrcChain ルート証明書を含むチェーン全体。

Timeout

失効情報の取得全体に許可されるミリ秒数です。URLごとではないため、応答しないレスポンダーをサーバーが待ち続けてハンドシェイクが停滞することはありません。デフォルトは5000です。値をゼロにするとWindowsのデフォルトが適用され、これはかなり長くなる場合があります。

CacheOnly

Trueの場合、Windowsが既にキャッシュしている失効データのみが使用され、ハンドシェイクがネットワークにアクセスすることはないため、受信接続がレスポンダーによって遅延することもありません。ただしキャッシュが空の場合は状態が不明のままとなり、その扱いはIgnoreNoRevocationCheckが決定します。デフォルトはFalseです。

IgnoreRevocationOffline

レスポンダーに到達できなかった場合の動作を決定します。デフォルトはTrueで、クライアント証明書を受け入れます。これはソフトフェイルの動作です。代わりに拒否するにはFalseに設定します。拒否する方が厳格ですが、新しい接続すべてがサーバーからレスポンダーへ到達できることに依存することになるため、レスポンダーの障害がすべてのクライアントの障害になります。

IgnoreNoRevocationCheck

クライアント証明書がCRL配布ポイントもOCSPレスポンダーもまったく公開しておらず、その状態を確定できない場合の動作を決定します。デフォルトはTrueで、受け入れます。内部のCAが発行した証明書は失効情報を持たないことが多いため、クライアントに渡すすべての証明書が失効情報を公開していると確認できてから、これをFalseに設定してください。

どちらのIgnoreプロパティも、失効が確認された証明書を受け入れることはありません。この結果は常に拒否され、ハンドシェイクは失敗します。

報告されるステータス

チェーンのチェックによってクライアントが拒否された場合、その理由は次のいずれかです:

ecCryptRevoked クライアント証明書が発行者によって失効させられています。常に拒否されます。
ecCryptRevocationOffline レスポンダーに到達できませんでした。IgnoreRevocationOfflineがFalseの場合にのみ拒否されます。
ecCryptNoRevocationCheck クライアント証明書が失効情報を公開していません。IgnoreNoRevocationCheckがFalseの場合にのみ拒否されます。

安全なデフォルト

SSLOptions.PresettlspSecureDefaultsに設定すると、クライアント側で同じプリセットが既に適用していた内容に合わせて、サーバーでもチェックがscrcChainExcludeRootとして有効になります。2つのソフトフェイル設定はそのまま維持されるため、これまで受け入れられていたクライアントは引き続き受け入れられます。プリセットを適用する前に自分で選択した範囲は変更されません。


oServer.SSLOptions.Preset := tlspSecureDefaults;

注意