ピア間 (つまり、クライアントとサーバー間) でコンテキストが確立された後、メッセージは送信する前に保護できます。
コンテキストを確立しメッセージを送信するだけの場合、最も基本的な GSS-API 保護である「認証」が使用されます。認証を使用すると、受信側は、送信側であるべきと要求されているプリンシパルからのメッセージであるかどうかを知ることができます。使用される実際のセキュリティ機構によって異なりますが、GSS-API は次の 2 つの保護も提供します。
整合性。メッセージ整合性コード (MIC) をメッセージに添付します。MIC を使用すると、受信側は受信したメッセージが送信されたメッセージと同じであることをチェックできます。MIC を生成するのは、GSS-API の gss_get_mic() 関数です。
機密性。MIC の添付に加えて、メッセージを暗号化します。暗号化を実行するのは、GSS-API の gss_wrap() 関数です。
図 1–11 に、2 つの関数の違いを示します。
どちらの関数を使用するかは、ユーザーの必要性によって異なります。gss_wrap() は整合性サービスも含むため、多くのプログラムは gss_wrap() を使用します。機密性サービスを使用できるかどうかをテストするには、機密性サービスを付けて (または、付けずに) gss_wrap() を呼び出します。使用例は、データの送信(プログラムリストは call_server()) を参照してください。しかし、gss_get_mic() で保護されたメッセージは受信側がラップ解除する必要がないため、gss_wrap() を使用するときよりも CPU サイクルを節約できます。したがって、機密性が必要ないプログラムは gss_get_mic() でメッセージを保護する傾向にあります。
gss_get_mic() を使用すると、プログラムは暗号化 MIC をメッセージに追加できます。受信側は gss_verify_mic() を呼び出し、この MIC をチェックすることによって、受信したメッセージが送信されたメッセージと同じであるかどうかを調べることができます。次に、gss_get_mic() の形式を示します。
OM_uint32 gss_get_mic ( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t msg_token) |
実際の機構から戻される状態コード。
メッセージが送信されるコンテキスト。
要求する QOP (保護品質)。MIC を生成するときに使用される暗号化アルゴリズムです。移植性のためには、アプリケーションは可能な限りデフォルトの QOP を指定するべきです。つまり、この引数に GSS_C_QOP_DEFAULT
を設定します。デフォルト以外の QOP の指定については、付録 C を参照してください。
MIC をタグ付けするメッセージ。この引数は gss_buffer_desc オブジェクトの形式である必要があります (文字列および類似のデータを参照)。使用し終わったときには、gss_release_buffer() で解放する必要があります。
メッセージと MIC が入っているトークン。使用し終わったときには、gss_release_buffer() で解放する必要があります。
gss_get_mic() はメッセージと MIC を別々に出力します。これは、gss_wrap() とは異なります。gss_wrap() は両方を一緒にして出力します。このように別々に出力するということは、送信側アプリケーションがメッセージと MIC の両方を送信するためにアレンジを行う必要があるということを意味します。さらに重要なことは、受信側アプリケーションがメッセージと MIC を受信および区別できる必要があるということです。メッセージと MIC を適切に処理するには、次のような方法があります。
プログラム制御 (つまり、状態) を通じて。受信側アプリケーションは受信関数を 2 回呼び出す (つまり、1 回目はメッセージを取得するため、2 回目はメッセージの MIC を取得するため) ことをあらかじめ知ることができます。
フラグを通じて。送信と受信の関数はどの種類のトークンを含めるかをフラグで示すことができます。
メッセージと MIC の両方を入れることができるユーザー定義トークン構造体を通じて。
正常に終了した場合、gss_get_mic() は GSS_S_COMPLETE を戻します。指定した QOP が有効でなかった場合、gss_get_mic() は GSS_S_BAD_QOP を戻します。詳細は、gss_get_mic(3GSS) のマニュアルページを参照してください。
メッセージは gss_wrap() 関数で「ラップ」することも可能です。gss_get_mic() と同様に、gss_wrap() は MIC を提供します。機密性が要求される場合 (かつ、実際の機構で使用できる場合)、gss_wrap() はさらにメッセージを暗号化します。メッセージの受信側は gss_unwrap() でメッセージを「ラップ解除」します。次に、gss_wrap() の形式を示します。
OM_uint32 gss_wrap ( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req const gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer ) |
実際の機構から戻される状態コード。
このメッセージが送信されるコンテキスト。
機密性サービス (暗号化) を要求するためのフラグ。0 以外の場合、機密性と整合性の両方を要求します。0 の場合、整合性サービスだけを要求します。
要求する QOP (保護品質)。MIC を生成するときと暗号化を行うときに使用される暗号化アルゴリズムです。移植性のためには、アプリケーションは可能な限りデフォルトの QOP を指定するべきです。つまり、この引数に GSS_C_QOP_DEFAULT
を設定します。デフォルト以外の QOP の指定については、付録 C 「OID の指定」 を参照してください。
ラップするメッセージ。この引数は gss_buffer_desc オブジェクトの形式である必要があります (文字列および類似のデータを参照)。使用し終わったときには、gss_release_buffer() で解放する必要があります。
関数が戻ったときに、機密性が適用されたかどうかを示すフラグ。0 以外の場合、機密性、メッセージ起点認証、および整合性サービスが適用されたことを示します。0 の場合、メッセージ起点認証と整合性だけが適用されたことを示します。必要ない場合は、NULL を指定します。
ラップしたメッセージ用のバッファ。アプリケーションがメッセージを処理した後には、gss_release_buffer() で解放する必要があります。
gss_get_mic() とは違い、gss_wrap() はメッセージと MIC を一緒にラップし、1 つの出力メッセージにします。したがって、メッセージを転送する関数は 1 回呼び出すだけでかまいません。メッセージの受信側では、gss_unwrap() でメッセージを抽出します。なお、MIC はアプリケーションからは見えません。
メッセージが正常にラップされた場合、gss_wrap() は GSS_S_COMPLETE を戻します。要求した QOP が有効でなかった場合、gss_wrap() は GSS_S_BAD_QOP を戻します。gss_wrap() の使用例は、データの送信(プログラムリストは call_server()を参照してください。詳細は、gss_wrap(3GSS) のマニュアルページを参照してください。
gss_wrap() でメッセージをラップすると、メッセージのサイズが増加します。保護されたメッセージパケットは、転送プロトコルを通過できるぐらいのサイズである必要があります。したがって、GSS-API の gss_wrap_size_limit 関数を使用して、ラップしても転送プロトコルを通過できるメッセージの最大サイズを計算します。この最大サイズを超える場合、アプリケーションは gss_wrap() を呼び出す前にメッセージを分割できます。メッセージを実際にラップする前にはラップサイズの制限値をチェックするように習慣付けましょう。
サイズの増加量は次の 2 つの影響を受けます。
メッセージをラップするためにどの QOP (保護品質) アルゴリズムを使用するか。GSS-API の実装によってデフォルトの QOP が異なるため、デフォルトの QOP を指定した場合でも、ラップされたメッセージのサイズは異なる可能性があります。図 1–12 に、この様子を示します。
機密性を呼び出すかどうか。機密性を適用するかどうかに関わらず、gss_wrap() は転送されるメッセージに MIC を添付するため、メッセージのサイズは増加します。しかし、メッセージを暗号化すると (機密性を適用すると)、メッセージのサイズはさらに増加します。図 1–13 に、この様子を示します。
次に、gss_wrap_size_limit() の形式を示します。
OM_uint32 gss_wrap_size_limit ( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size, OM_uint32 *max_input_size) |
実際の機構から戻される状態コード。
データが転送されるコンテキスト。
機密性サービス (暗号化) を要求するためのフラグ。0 以外の場合、機密性と整合性の両方を要求します。0 の場合、整合性サービスだけを要求します。
要求する QOP (保護品質)。MIC を生成するときと暗号化を行うときに使用される暗号化アルゴリズムです。移植性のためには、アプリケーションは可能な限りデフォルトの QOP を指定するべきです。つまり、この引数に GSS_C_QOP_DEFAULT
を設定します。デフォルト以外の QOP の指定については、付録 C 「OID の指定」 を参照してください。
指定した転送プロトコルが処理できるデータ片の最大サイズ (型は int)。この情報は、ユーザーが自ら提供する必要があります。つまり、GSS-API はプロトコルに依存しないため、どのプロトコルが使用されるのかを知る方法がありません。
関数から戻される値。つまり、ラップしたときに req_output_size を超えないような、ラップしていないメッセージの最大サイズ。
正常に終了した場合、gss_wrap_size_limit() は GSS_S_COMPLETE を戻します。指定した QOP が有効でなかった場合、gss_wrap_size_limit() は GSS_S_BAD_QOP を戻します。gss_wrap_size_limit() でオリジナルのメッセージの最大サイズを求める例 (機密性を使用する場合と使用しない場合の両方) については、call_server()を参照してください。
この機能は gss_wrap() を呼び出した時点でのシステムリソースの可用性に依存するため、この呼び出しが正常に終了したとしても、必ずしも、gss_wrap() が max_input_size 以下のバイトの長さを持つメッセージを保護できるとは保証できません。詳細は、gss_wrap_size_limit(3GSS) のマニュアルページを参照してください。