GSS-API のプログラミング

server_establish_context()

server_establish_context() はコンテキスト確立ループの一部として gss_accept_sec_context() を呼び出します。


例 A–13 server_establish_context()


/*
 * 関数: server_establish_context
 *
 * 目的: 着信クライアントで指定されたサービスとして 
 * GSS-API コンテキストを確立し、コンテキストハンドルと
 * 関連するクライアント名を戻す。
 *
 * 引数:
 *
 *      s               (r) クライアントとの間で確立された TCP 接続
 *      service_creds   (r) gss_acquire_cred で取得したサーバーの資格
 *      context         (w) 確立された GSS-API コンテキスト
 *      client_name     (w) クライアントの ASCII 名
 *
 * 戻り値: 成功した場合は 0、失敗した場合は -1
 *
 * 効果:
 *
 * 有効なクライアント要求はすべて受け入れられる。コンテキストが
 * 確立された場合、そのハンドルが context に戻され、クライアント名が 
 * client_name に戻され、0 が戻される。失敗した場合、エラーメッセージが
 * 表示され、-1 が戻される。
 */
int server_establish_context(s, server_creds, context, client_name, ret_flags)
     int s;
     gss_cred_id_t server_creds;
     gss_ctx_id_t *context;
     gss_buffer_t client_name;
     OM_uint32 *ret_flags;
{
     gss_buffer_desc send_tok, recv_tok;
     gss_name_t client;
     gss_OID doid;
     OM_uint32 maj_stat, min_stat;
     gss_buffer_desc    oid_name;
        char *mechStr;

     *context = GSS_C_NO_CONTEXT;

     do {
          if (recv_token(s, &recv_tok) < 0)
               return -1;

          if (verbose && log) {
              fprintf(log, "Received token (size=%d): \n", recv_tok.length);
              print_token(&recv_tok);
          }

          maj_stat =
               gss_accept_sec_context(&min_stat,
                                      context,
                                      server_creds,
                                      &recv_tok,
                                      GSS_C_NO_CHANNEL_BINDINGS,
                                      &client,
                                      &doid,
                                      &send_tok,
                                      ret_flags,
                                      NULL,     /* time_rec を無視する */
                                      NULL);    /* del_cred_handle を無視する */

          if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
               display_status("accepting context", maj_stat, min_stat);
               (void) gss_release_buffer(&min_stat, &recv_tok);
               return -1;
          }

          (void) gss_release_buffer(&min_stat, &recv_tok);

          if (send_tok.length != 0) {
              if (verbose && log) {
                  fprintf(log,
                          "Sending accept_sec_context token (size=%d):\n",
                          send_tok.length);
                  print_token(&send_tok);
              }
               if (send_token(s, &send_tok) < 0) {
                    fprintf(log, "failure sending token\n");
                    return -1;
               }

               (void) gss_release_buffer(&min_stat, &send_tok);
          }
          if (verbose && log) {
              if (maj_stat == GSS_S_CONTINUE_NEEDED)
                  fprintf(log, "continue needed...\n");
              else
                  fprintf(log, "\n");
              fflush(log);
          }
     } while (maj_stat == GSS_S_CONTINUE_NEEDED);

     /* フラグを表示する */
     display_ctx_flags(*ret_flags);

     if (verbose && log) {
         maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name);
         if (maj_stat != GSS_S_COMPLETE) {
             display_status("converting oid->string", maj_stat, min_stat);
             return -1;
         }
                mechStr = (char *)__gss_oid_to_mech(doid);
         fprintf(log, "Accepted connection using mechanism OID %.*s (%s).\n",
                 (int) oid_name.length, (char *) oid_name.value,
                        (mechStr == NULL ? "NULL" : mechStr));
         (void) gss_release_buffer(&min_stat, &oid_name);
     }

     maj_stat = gss_display_name(&min_stat, client, client_name, &doid);
     if (maj_stat != GSS_S_COMPLETE) {
          display_status("displaying name", maj_stat, min_stat);
          return -1;
     }
     return 0;
}