client_establish_context() は gss_init_sec_context() を呼び出して、サーバーとのコンテキストを確立します。
/* * 関数: client_establish_context * * 目的: 指定されたサービスとの GSS-API コンテキストを確立し、 * コンテキストハンドルを戻す * * 引数: * * s (r) サーバーとの間で確立された TCP 接続 * service_name (r) サービスの ASCII 名 * context (w) 確立された GSS-API コンテキスト * ret_flags (w) init_sec_context から戻されたフラグ * * 戻り値: 成功した場合は 0、失敗した場合は -1 * * 効果: * * service_name が GSS-API 名としてインポートされ、 * 対応するサービスとの間で GSS-API コンテキストが確立される。 * サービスは TCP 接続 s 上で応答待ちする。デフォルトの * GSS-API 機構が使用され、相互認証とリプレイの検出が * 要求される。 * * 成功した場合、コンテキストハンドルが context に戻される。 * 失敗した場合、GSS-API エラーメッセージが stderr に表示され、 * -1 が戻される。 */ int client_establish_context(s, service_name, deleg_flag, oid, gss_context, ret_flags) int s; char *service_name; gss_OID oid; OM_uint32 deleg_flag; gss_ctx_id_t *gss_context; OM_uint32 *ret_flags; { gss_buffer_desc send_tok, recv_tok, *token_ptr; gss_name_t target_name; OM_uint32 maj_stat, min_stat; /* * 名前を target_name にインポートする。send_tok で * ローカル変数空間を保存する。 */ send_tok.value = service_name; send_tok.length = strlen(service_name) + 1; maj_stat = gss_import_name(&min_stat, &send_tok, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &target_name); if (maj_stat != GSS_S_COMPLETE) { display_status("parsing name", maj_stat, min_stat); return -1; } /* * コンテキスト確立ループを実行する。 * * ループを通過するごとに、token_ptr はサーバーに送信される * トークンに設定される (最初に通過するときは GSS_C_NO_BUFFER)。 * 生成された各トークンは send_tok に格納され、サーバーに送信される。 * 受信された各トークンは recv_tok に格納され、token_ptr は次の * gss_init_sec_context の呼び出しで処理されるトークンに * 設定される。 * * GSS-API は、以下の 2 つのことを保証する。 * 1.サーバーがクライアントからこれ以上トークンを期待していない場合のみ、 * send_tok の length の値が 0 になる。 * 2.サーバーにクライアントへ送るトークンが存在する場合のみ、 * gss_init_sec_context が GSS_S_CONTINUE_NEEDED を戻す。 */ token_ptr = GSS_C_NO_BUFFER; *gss_context = GSS_C_NO_CONTEXT; do { maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, gss_context, target_name, oid, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | deleg_flag, 0, NULL, /* チャネルバインディングなし */ token_ptr, NULL, /* 機構の型を無視する */ &send_tok, ret_flags, NULL); /* time_rec を無視する */ if (gss_context == NULL){ printf("Cannot create context\n"); return GSS_S_NO_CONTEXT; } if (token_ptr != GSS_C_NO_BUFFER) (void) gss_release_buffer(&min_stat, &recv_tok); if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) { display_status("initializing context", maj_stat, min_stat); (void) gss_release_name(&min_stat, &target_name); return -1; } if (send_tok.length != 0) { fprintf(stdout, "Sending init_sec_context token (size=%ld)...", send_tok.length); if (send_token(s, &send_tok) < 0) { (void) gss_release_buffer(&min_stat, &send_tok); (void) gss_release_name(&min_stat, &target_name); return -1; } } (void) gss_release_buffer(&min_stat, &send_tok); if (maj_stat == GSS_S_CONTINUE_NEEDED) { fprintf(stdout, "continue needed..."); if (recv_token(s, &recv_tok) < 0) { (void) gss_release_name(&min_stat, &target_name); return -1; } token_ptr = &recv_tok; } printf("\n"); } while (maj_stat == GSS_S_CONTINUE_NEEDED); (void) gss_release_name(&min_stat, &target_name); return 0; } |