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