Oracle Solaris セキュリティーサービス開発ガイド

GSS-API データ型

ここでは、主な GSS-API データ型について説明します。すべての GSS-API データ型を確認するには、「GSS-API データ型と値」を参照してください。

GSS-API の整数

int のサイズはプラットフォームによって異なるため、GSS-API は次の整数型を提供します。OM_uint32。これは、32 ビットの符号なし整数です。

GSS-API の文字列とそれに類するデータ

GSS-API はすべてのデータを内部形式で処理するため、文字列も、GSS-API 形式に変換したあとで GSS-API 関数に渡す必要があります。GSS-API は、gss_buffer_desc 構造体を使って文字列を処理します。

typedef struct gss_buffer_desc_struct {
     size_t     length;
     void       *value;
}  gss_buffer_desc *gss_buffer_t;

gss_buffer_t は、そうした構造体へのポインタです。文字列は、GSS-API 関数に渡す前に gss_buffer_desc 構造体に変換しておく必要があります。次の例では、汎用的な GSS-API 関数を使って、送信前のメッセージに保護を適用しています。


例 4–1 GSS-API における文字列の使用法

char *message_string;
gss_buffer_desc input_msg_buffer;

input_msg_buffer.value = message_string;
input_msg_buffer.length = strlen(input_msg_buffer.value) + 1;

gss_generic_function(arg1, &input_msg_buffer, arg2...);

gss_release_buffer(input_msg_buffer);

ここで、input_msg_buffer は、終了時に gss_release_buffer() を使って解放する必要がある点に注意してください。

gss_buffer_desc オブジェクトは文字列だけに使用されるわけではありません。たとえば、トークンも gss_buffer_desc オブジェクトとして処理されます。詳細は、「GSS-API トークン」を参照してください。

GSS-API における名前

「名前」は主体を指します。ネットワークセキュリティーの用語では、「主体」とは、ユーザー、プログラム、またはマシンを指します。主体はクライアントまたはサーバーのどちらにでもなり得ます。主体の例を、次にいくつか挙げます。

GSS-API では、名前は gss_name_t オブジェクトとして格納されます。このオブジェクトはアプリケーションに対して不透明です。名前を gss_buffer_t オブジェクトから gss_name_t 形式に変換するには、gss_import_name() 関数を使用します。インポートされたすべての名前には関連する「名前型」が割り当てられます。名前型とは、その名前の形式を示すものです。名前型については、「GSS-API の OID」を参照してください。有効な名前型の一覧については、「名前型」を参照してください。

gss_import_name() の構文は次のとおりです。

OM_uint32 gss_import_name (
       OM_uint32          *minor-status,
       const gss_buffer_t input-name-buffer,
       const gss_OID      input-name-type,
       gss_name_t         *output-name)
minor-status

実際の機構から戻される状態コード。「GSS-API 状態コード」を参照してください。

input-name-buffer

インポートされた名前が格納される gss_buffer_desc 構造体。この構造体は、アプリケーション側で明示的に割り当てる必要があります。「GSS-API の文字列とそれに類するデータ」および例 4–2 を参照してください。この引数は、アプリケーションでの使用終了後、gss_release_buffer() を使って解放する必要があります。

input-name-type

input-name-buffer の形式を示す gss_OID「GSS-API における名前型」を参照してください。また、「名前型」に、有効な名前型の一覧表があります。

output-name

名前を受け取る gss_name_t 構造体。

次に示すのは、例 4–1 の汎用例に若干の変更を加えたものであり、gss_import_name() の使用法を示しています。まず、通常の文字列が gss_buffer_desc 構造体に挿入されています。次に、その文字列が、gss_import_name () によって gss_name_t 構造体内に格納されています。


例 4–2 gss_import_name()() の使用例

char *name_string;
gss_buffer_desc input_name_buffer;
gss_name_t      output_name_buffer;

input_name_buffer.value = name_string;
input_name_buffer.length = strlen(input_name_buffer.value) + 1;

gss_import_name(&minor_status, input_name_buffer, 
                    GSS_C_NT_HOSTBASED_SERVICE, &output_name);

gss_release_buffer(input_name_buffer);

インポートされた名前は、人間が読める形式で表示できるように、元の gss_buffer_t オブジェクトに戻すことが可能です。それには、gss_display_name() を使用します。ただし、gss_display_name() は、結果の文字列が元と同じであることを保証しません。その原因は、実際の機構が名前を格納する方法にあります。GSS-API にはほかにも名前を処理する関数があります。「GSS-API 関数」を参照してください。

gss_name_t 構造体には、単一の名前の複数のバージョンを格納できます。GSS-API によってサポートされている機構ごとに、1 つのバージョンが生成されます。つまり、user@companygss_name_t 構造体には、Kerberos v5 から提供されたその名前の 1 つのバージョンと、別の機構から提供された別のバージョンが含まれる可能性があります。関数 gss_canonicalize_name() は、入力として内部名と機構を受け取ります。また、gss_canonicalize_name() は、出力としてその機構に固有の単一バージョン名だけを含む別の内部名を返します。

そうした機構に固有な名前のことを「機構名 (Mechanism Name、MN)」と呼びます。機構名とは、特定の機構の名前ではなく、特定の機構によって生成された主体の名前です。このプロセスを示したのが次の図です。

図 4–3 内部名と機構名 (MN)

機構名が派生するプロセスを示しています。

GSS-API における名前の比較

サーバーがクライアントからある名前を受け取り、その名前をアクセス制御リスト内で検索する必要がある場合を考えます。「アクセス制御リスト (Access Control List、ACL)」とは、特定のアクセス権を持つ主体のリストのことです。そうした検索を行うには、次のような方法が考えられます。

  1. gss_import_name() で、クライアント名を GSS-API 内部形式にインポートします (まだインポートされていない場合)。

    場合によっては、サーバーは名前を内部形式で受け取ります。その場合、この手順は必要ありません。たとえば、サーバーはクライアント自身の名前を検索する可能性があります。コンテキストの起動中、クライアント自身の名前は内部形式で渡されます。

  2. gss_import_name() で、各 ACL 名を インポートします。

  3. gss_compare_name() で、インポートした各 ACL 名をインポートしたクライアント名と比較します。

次の図に、このプロセスを示します。ここでは手順 1 が必要であると仮定します。

図 4–4 名前の比較 (遅い)

gss_compare_name 関数を使用して内部クライアント名を比較する方法を示しています。

名前の数が少ない場合は、名前を個別に比較する上記の方法でも問題ありません。名前の数が非常に多い場合は、gss_canonicalize_name() 関数を使用するほうが効率的です。この方法の実行手順を次に示します。

  1. gss_import_name() で、クライアント名をインポートします (まだインポートされていない場合)。

    名前を比較する前述の方法と同様に、名前がすでに内部形式である場合には、この手順は必要ありません。

  2. gss_canonicalize_name() を使用してクライアント名の機構名バージョンを生成します。

  3. gss_export_name() を使用してエクスポート名を生成します。エクスポート名は、連続した文字列としてのクライアント名です。

  4. memcmp() を使用してエクスポートされたクライアント名を ACL 内の個々の名前と比較します。これは、高速で動作するオーバーヘッドの少ない関数です。

次の図に、このプロセスを示します。ここでも、サーバーがクライアントから受信した名前をインポートする必要があると仮定します。

図 4–5 名前の比較 (速い)

memcmp 関数を使用して内部クライアント名を比較する方法を示しています。

gss_export_name() は機構名 (MN) を期待するため、先にクライアント名に対して gss_canonicalize_name() を実行する必要があります。

詳細は、gss_export_name(3GSS)gss_import_name(3GSS)、および gss_canonicalize_name(3GSS) を参照してください。

GSS-API の OID

オブジェクト識別子 (Object Identifier、OID) は、次のようなデータを格納するときに使用します。

OID は、GSS-API の gss_OID_desc 構造体に格納されます。次の例のように、GSS-API はその構造体へのポインタ gss_OID を提供します。


例 4–3 OID の構造体

typedef struct gss_OID_desc_struct {
        OM_uint32   length;
        void        *elements;
     } gss_OID_desc, *gss_OID;

さらに、1 つ以上の OID を gss_OID_set_desc 構造体に格納することもできます。


例 4–4 OID セットの構造体

typedef struct gss_OID_set_desc_struct {
        size_t    count;
        gss_OID   elements;
     } gss_OID_set_desc, *gss_OID_set;


注意 – 注意 –

アプリケーションは free() で OID を解放するべきではありません。


GSS-API における機構と QOP

GSS-API では、使用するセキュリティー機構をアプリケーションが選択できるようになっていますが、GSS-API が選択したデフォルトの機構をできる限り使用する必要があります。同様に、GSS-API では、データ保護の保護品質レベルをアプリケーションが指定できるようになっていますが、デフォルトの QOP をできる限り使用する必要があります。デフォルトの機構を受け入れることを示すには、機構または QOP を期待する関数に値 GSS_C_NULL_OID を引数として渡します。


注意 – 注意 –

セキュリティー機構または QOP を明示的に指定することは、GSS-API の使用目的に反します。そうした特定の選択は、アプリケーションの移植性を制限します。ほかの GSS-API 実装は、その QOP または機構を意図した方法でサポートしていない可能性があります。ただし、付録 C OID の指定では、利用可能な機構や QOP を知る方法と、それらの選択方法について、簡単に説明しています。


GSS-API における名前型

QOP とセキュリティー機構のほかに、名前型を示すためにも OID が使用されます。名前型とは、関連する名前の形式を示すものです。たとえば、gss_import_name() 関数は主体の名前を文字列から gss_name_t 型に変換しますが、この関数は変換すべき文字列の形式を引数の 1 つとして受け取ります。たとえば、名前型が GSS_C_NT_HOSTBASED_SERVICE である場合、この関数は、入力された名前が service@host 形式であると判断します。名前型が GSS_C_NT_EXPORT_NAME である場合、この関数は GSS-API エクスポート名を期待します。アプリケーションは gss_inquire_names_for_mech() 関数を使用すると、指定した機構で使用できる名前型を知ることができます。GSS-API によって使用される名前型の一覧については、「名前型」を参照してください。