コンテキストの確立におけるもう一つの仕事は、コンテキストの受け入れです。コンテキストの受け入れは gss_accept_sec_context() 関数で行います。通常、クライアントが (gss_init_sec_context() で) コンテキストを起動し、サーバーがそのコンテキストを受け入れます。
gss_accept_sec_context() は、起動側から送信された入力トークンを主な入力として使用します。gss_accept_sec_context() は、コンテキストハンドルと起動側に戻すべき出力トークンを戻します。しかし、gss_accept_sec_context() を呼び出す前に、サーバーはクライアントから要求されたサービスの資格を獲得しておく必要があります。サーバーはこのような資格を gss_acquire_cred() 関数で獲得します。あるいは、サーバーは資格を明示的に獲得するのではなく、gss_accept_sec_context() を呼び出すときにデフォルトの資格を指定する (GSS_C_NO_CREDENTIAL で示す) ことも可能です。
gss_accept_sec_context() を呼び出すとき、サーバーは次の引数値を渡します。
gss_acquire_cred() から戻された資格ハンドル。あるいは、GSS_C_NO_CREDENTIAL
を cred_handle 引数に渡して、デフォルトの資格を示します。
GSS_C_NO_CONTEXT
を context_handle 引数に渡して、初期コンテキストが NULL であることを示します。gss_init_sec_context() は通常ループ内で呼び出されるため、後続の呼び出しは以前の呼び出しで戻されたコンテキストハンドルを渡す必要があります。
クライアントから受け取ったコンテキストトークンを input_token 引数に渡します。
gss_accept_sec_context() 引数についての詳細は、以降の節で説明します。
セキュリティコンテキストを確立するためには、いくつかの「ハンドシェーク」が必要です。つまり、コンテキストが完全に確立されるまでに、起動側と受け入れ側は複数のコンテキスト情報を送信する必要があることがあります。したがって、移植性のため、コンテキストの受け入れは常に、コンテキストが完全に確立されたかどうかを検査するループの一部として行われる必要があります。コンテキストが完全に確立されていない場合、gss_accept_sec_context() はメジャー状態コードとして GSS_C_CONTINUE_NEEDED を戻します。したがって、ループは gss_accept_sec_context() の戻り値を使用して、受け入れループを継続するかどうかをテストする必要があります。
コンテキスト受け入れ側はコンテキスト情報をコンテキスト起動側に、gss_accept_sec_context() から戻された出力トークンの形式で渡します。その後、受け入れ側は以降の情報を起動側から入力トークンとして受け取ります。すると、後続の gss_accept_sec_context() の呼び出しに引数として渡すことができます。起動側に送信するトークンがなくなったとき、gss_accept_sec_context() は、length の値が 0 の出力トークンを戻します。したがって、gss_accept_sec_context() の戻り状態を検査することに加えて、ループは出力トークンの length を検査して、さらにトークンを送信するのかどうかを判断する必要があります。ループが始まる前には、出力トークンを GSS_C_NO_BUFFER
に設定するか、構造体の length フィールドを 0 に設定することによって、出力トークンの length を 0 に初期化する必要があります。
次に、このようなループの例を示します。かなり一般化されています。
context = GSS_C_NO_CONTEXT を入れる input_token = GSS_C_NO_BUFFER を入れる do { 起動側から input_token を受け取る gss_accept_sec_context(context, cred_handle, input_token, output_token, other args...) if (起動側に送信する output_token がある時) 起動側に output_token を送信 output_token を解放する if (GSS-API エラーがある時) context を削除する } while (context が完全になるまで) |
当然、実際のループはより複雑になります。たとえば、より多くのエラー検査が必要になるなどです。このようなコンテキスト受け入れループの実際の例については、コンテキストの受け入れ(プログラムリストは server_establish_context()) を参照してください。さらに、gss_accept_sec_context(3GSS) のマニュアルページにも、上記例ほど一般化されていない例があります。
繰り返しますが、GSS-API 自身はトークンを送受信しません。トークンの送受信はアプリケーションが処理する必要があります。トークン転送関数の例については、send_token() と recv_token()を参照してください。
次に、gss_accept_sec_context() の形式を示します。詳細は、gss_accept_sec_context(3GSS) のマニュアルページを参照してください。
OM_uint32 gss_accept_sec_context ( OM_uint32 *minor_status, gss_ctx_id_t *context_handle, const gss_cred_id_t acceptor_cred_handle, const gss_buffer_t input_token_buffer, const gss_channel_bindings_t input_chan_bindings, const gss_name_t *src_name, gss_OID *mech_type, gss_buffer_t output_token, OM_uint32 *ret_flags, OM_uint32 *time_req, gss_cred_id_t *delegated_cred_handle) |
実際の機構から戻される状態コード。
起動側に戻すべきコンテキストハンドル。ループが始まる前には、GSS_C_NO_CONTEXT
に設定する必要があります。
受け入れ側が (通常は、gss_acquire_cred() で) 獲得した資格のハンドル。GSS_C_NO_CREDENTIAL
に初期化すると、デフォルトの資格を使用することを示すことができます。デフォルトの資格が定義されていない場合、GSS_C_NO_CRED を戻します。
(注: プリンシパル名として GSS_C_NO_NAME
が渡された場合、gss_acquire_cred() は gss_accept_sec_context() がデフォルトの資格として扱うような資格を生成します。)
コンテキスト起動側から受け取ったトークン。
セキュリティコンテキストに接続された特定のピアツーピアチャネル識別情報。チャネルバインディングについての詳細は、チャネルバインディングを参照してください。チャネルバインディングを使用しない場合は、GSS_C_NO_CHANNEL_BINDINGS
に設定します。
起動しているプリンシパルの名前。たとえば、nfs@machinename などです。プリンシパルの名前が重要でない場合は、NULL に設定します。
使用されるセキュリティ機構。どの機構が使用されるかが重要でない場合は、NULL に設定します。
起動側に送信すべきトークン。関数が呼び出される前に、GSS_C_NO_BUFFER
に初期化する (あるいは、長さフィールドを 0 に設定する) 必要があります。長さが 0 の場合、送信する必要のあるトークンはありません。
このコンテキストで要求された追加のサービスまたはパラメータを示すフラグ。ret_flags フラグは次のようにビット論理積をとって、戻されたビットマスク値をテストする必要があります。
if (ret_flags & GSS_C_CONF_FLAG) confidentiality = TRUE; |
起動側の資格が delegated_cred_handle 引数経由で委託できることを示します。委託を参照してください。
相互認証が使用できることを示します。相互認証を参照してください。
繰り返しメッセージの検出が有効であることを示します。誤順序の検出とリプレイの検出を参照してください。
誤順序メッセージの検出が有効であることを示します。誤順序の検出とリプレイの検出を参照してください。
真の場合、転送されるメッセージに機密性サービスを適用できます。つまり、メッセージを暗号化できます。機密性が許可されない場合、データ起点認証と (GSS_C_INTEG_FLAG が偽でなければ) 整合性サービスだけを適用できます。
真の場合、メッセージに整合性サービスを適用できます。つまり、メッセージに MIC (Message Integrity Code) を付けて有効性を保証できます。
コンテキスト起動側が匿名のままであることを示します。匿名認証を参照してください。
コンテキストの確立に時間がかかる場合、コンテキストが完全に確立されていない場合でも、受け入れ側がコンテキスト関連のデータを処理できるように、クライアントは起動パスに十分な情報を送信できます。このような状況では、受け入れ側は情報がどのように保護されているかを (もしあれば) 知る必要があります。
GSS_C_PROT_READY_FLAG が真の場合、GSS_C_CONF_FLAG と GSS_C_INTEG_FLAG が示す保護サービスを指定します。すると、受け入れ側は希望の保護サービスに適切なデータ受け入れ関数 (gss_unwrap() または gss_verify_mic()) を呼び出すことができます。
(さらに、コンテキスト起動側と同様に、受け入れ側はこれらのフラグを使用して、起動側に送信したいデータをバッファに格納しておいて、コンテキストが完全に確立された後で、バッファに格納しておいたデータを送信できます。)
GSS_C_PROT_READY_FLAG が偽の場合、受け入れ側はデータ保護を仮定できず、コンテキストの確立が完了するまで (つまり、gss_accept_sec_context() が GSS_S_COMPLETE を戻すまで) 待機する必要があります。
GSS-API の以前のバージョンは GSS_C_PROT_READY_FLAG 引数をサポートしていません。したがって、移植性を最大限にしたい開発者は、コンテキストの確立が完了した後で GSS_C_CONF_FLAG と GSS_C_INTEG_FLAG フラグを調べて、どのメッセージ毎サービスを使用できるかを判断する必要があります。
真の場合、このコンテキストがエクスポートできることを示します。コンテキストのインポートとエクスポートについての詳細は、コンテキストのエクスポートとインポートを参照してください。
コンテキストが有効である時間 (秒)。時間が重要でない場合は、NULL に設定します。
コンテキスト起動側から受け取った資格 (つまり、クライアントの資格) の資格ハンドル。受け入れ側がプロクシとして動作するように起動側が要求した場合だけ、つまり、ret_flags 引数に GSS_C_DELEG_FLAG が含まれている場合だけ有効です。委託についての詳細は、委託を参照してください。
正常に終了した場合、gss_accept_sec_context() は GSS_S_COMPLETE を戻します。コンテキストが完全に確立されていない場合、gss_accept_sec_context() は GSS_S_CONTINUE_NEEDED を戻します。エラーが発生した場合、gss_accept_sec_context() はエラーコードを戻します。エラーコードについては、gss_accept_sec_context(3GSS) のマニュアルページを参照してください。