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;
}
|