上述の認証タイプ (AUTH_SYS、AUTH_DES、AUTH_KERB) は、1 つの決まった見方で同じように扱うことができます。このため、新しいネットワーキング階層、Generic Security Standard API (汎用セキュリティ規格 API)、すなわち GSS-API が追加されています。GSS-API のフレームワークでは、認証に加え次の 2 つの「サービス」が提供されています。
「完全性」
一貫性サービスでは、GSS-API は下位層のメカニズムを使用してプログラム間で交換されるメッセージを認証します。暗号化チェックサムによって、以下が確立されます。
データの発信側から受信側への識別情報 (ID)
受信側から発信側への識別情報 (ID) (相互の認証が要求された場合)
伝送されたデータそのものの認証
「プライバシ」
プライバシサービスには、完全性サービスが含まれています。これに加えて、伝送データも「暗号化」され傍受者から保護されます。
また、GSS-API を使用すると、それがサポートする kerberos V 5、RSA 公開鍵、Diffie-Hellman 公開鍵、CSM や将来サポートされるメカニズムをアプリケーションから使用することができます。 [現在、GSS-API はまだ発表されていません。ただし、特定の GSS-API 機能は RPCSEC_GSS の機能 (この機能は「不透明な」(内部の見えない) 形で扱うことができます) を通じて参照できます。プログラマはこれらの値に直接かかわる必要はありません。]
RPCSEC_GSS セキュリティタイプを使用すると、ONC RPC アプリケーションは GSS-API の機能の利点を利用することができます。RPCSEC_GSS は、次のように GSS-API 階層の「最上部」に位置します。
RPCSEC-GSS のプログラミングインタフェースを使用する場合は、ONC RPC アプリケーションは以下の項目を指定できます。
セキュリティのパラダイム。各種セキュリティメカニズムでは、1 つまたは複数レベルのデータ保護と同時に、それぞれ異なる種類のデータ保護を提供します。この場合、GSS-API によってサポートされる任意のセキュリティメカニズムを指定します (Kerberos v5、RSA 公開鍵など)。
プライバシまたは完全性のいずれかを指定します (あるいはどちらも指定しない)。この項目はメカニズムに依存しません。
QOP (Quality of Protection) は、保護の質を意味します。QOP により、プライバシまたは完全性サービスとともに使用する暗号化アルゴリズムのタイプが指定されます。各セキュリティメカニズムには、それに関連する 1 つまたは複数の QOP があります。
アプリケーションは、構成ファイル (/etc/gss/qop と /etc/gss/mech) またはネームサービスから、有効な QOP とメカニズムを入手できます。開発者は、メカニズムと QOP をハードコード化し、使用するアプリケーション内に埋め込むことは避けてください。そうすれば、新しい、または異なるメカニズムおよび QOP を使用するためにアプリケーションを修正する必要はありません。
これまでは、「セキュリティタイプ」と「認証タイプ」は同じものを表していました。RPCSEC_GSS の導入によって、「タイプ」は現在、多少異なる意味を持ちます。タイプには、認証とともにサービス (一貫性またはプライバシ) を含むことができますが、現在は RPCSEC_GSS が、これを実行できる唯一のタイプです。
RPCSEC_GSS を使用すると、ONC RPC アプリケーションは、他のタイプを使用して行う場合と同様に、ピアにセキュリティコンテキストを確立し、データを交換し、そしてこのコンテキストを破壊します。一度コンテキストが確立されると、アプリケーションは、送信したデータユニットごとに QOP およびサービスを変更できます。
RPCSEC_GSS データタイプを含む RPCSEC_GSS の詳細については、rpcsec_gss(3N) のマニュアルページを参照してください。
表 4-8 は、RPCSEC_GSS コマンドを要約したものです。この表では、各関数の個別の説明ではなく、RPCSEC_GSS 関数の全般的な概要を示しています。詳細については、各関数のマニュアルページを参照してください。
表 4-8 RPCSEC_GSS Functions関数 | 目的 | 入力 | 出力 | 注 |
---|---|---|---|---|
rpc_gss_seccreate() | セキュリティコンテキストの作成 | クライアントのハンドル、主体名、メカニズム、QOP、サービスタイプ | AUTH ハンドル | |
rpc_gss_set_defaults() | コンテキストの QOP とサービスタイプの変更 | 古い QOP とサービス | 新しい QOP とサービス | クライアント側 |
rpc_gss_max_data_length() | セキュリティの変換前に、データの最大サイズを示す | 伝送できる最大データサイズ | 変換前の最大データサイズ | クライアント側 |
rpc_gss_svc_max_data_length() | セキュリティの変換前に、データの最大サイズを示す | 伝送できる最大データサイズ | 変換前の最大データサイズ | サーバー側 |
rpc_gss_set_svc_name() | 表示するサーバーの主体名を設定する | 主体名 , RPC プログラム、バージョン番号 | 正常に完了した場合は TRUE | サーバー側 |
rpc_gss_getcred() | 呼び出し元 (クライアント) の資格を得る | svc_req 構造へのポインタ | UNIX 資格、RPCSEC_GSS 資格、cookie | |
rpc_gss_set_callback() | (ユーザーの作成した) コールバック関数を指定する | コールバック関数へのポインタ | 正常に完了した場合は TRUE | |
rpc_gss_get_principal_name() | 固有のパラメータから主体名の RPCSEC_GSS 構造を作成する | メカニズム、ユーザー名、マシン名、ドメイン名 | RPCSEC_GSS 主体名の構造 | |
rpc_gss_get_error() | RPCSEC_GSS ルーチンが失敗した場合にエラーコードを得る |
| RPCSEC_GSS エラー番号、該当する場合には errno | |
rpc_gss_get_mechanisms() | インストールされているメカニズムの文字列を入手する |
| 有効なメカニズムのリスト | |
rpc_gss_get_mech_info() | 有効な QOP 文字列を入手する | メカニズム | そのメカニズムの有効な QOP | |
rpc_gss_get_versions() | サポートされている RPCSEC_GSS の最大および最小のバージョン番号を得る |
| 最大および最小のバージョン番号 | |
rpc_gss_is_installed() | メカニズムが導入されているかどうかをチェックする | メカニズム | インストールされている場合は TRUE | |
rpc_gss_mech_to_oid() | ASCII メカニズムを RPC オブジェクト識別子に変換する | メカニズム (文字列で) | メカニズム (OID で) | |
rpc_gss_qop_to_num() | ASCII QOP を整数に変換する | QOP (文字列で) | QOP (整数で) |
コンテキストは、rpc_gss_seccreate() 呼び出しを使用して作成します。この関数では引数として、セッションの、クライアントハンドル (たとえば clnt_create() によって戻されたもの) , サーバーの主体名 (nfs@machine.eng.company.com)、メカニズム、サービスタイプ、および QOPと、使用される場合はほとんどの場合不透明なまま使用される 2 つの GSS-API パラメータをとります。この関数で、AUTH 認証ハンドルを返します。以下のコードフラグメントは、Kerberos v5 セキュリティメカニズムと完全性サービスを使用したコンテキストを作成する場合、rpc_gss_seccreate() がどのように使用されるかを示しています。
CLIENT *clnt; /* クライアントハンドル */ char server_host[] = "foo"; char service_name[] = "nfs@machine.eng.company.com"; char mech[] = "kerberosv5"; clnt = clnt_create(server_host, SERVER_PROG, SERV_VERS, "netpath"); clnt->clnt_auth = rpc_gss_seccreate(clnt, service_name, mech, ¥ rpc_gss_svc_integrity, NULL, NULL, NULL); . . . |
この例では、注意する点が数カ所あります。まず、メカニズムは明示的に宣言してありますが (読みやすくするために)、通常は、rpc_gss_get_mechanisms() 用いて、使用できるメカニズムの表から入手します。QOP にも同様のことが言えます。 ここでは、最初の NULL を渡しています。これは、QOP をこのメカニズムのデフォルトに設定するものです。次に、サービスタイプは、RPCSEC_GSS タイプの enum のひとつである rpc_gss_service_t です。最後に、末尾の 2 つの NULL 引数は、不透明な GSS-API オプション用で、プログラマは安全に NULL を値として渡すことができます。
コンテキストが設定されると、アプリケーションは伝送される個々のデータユニットの QOP およびービス値を変更できます。たとえば、パスワードは暗号化したいがログイン名は暗号化したくない場合。これは、次のように rpc_gss_set_defaults() を使用すると実行できます。
rpc_gss_set_defaults(clnt->clnt_auth, rpc_gss_svc_privacy, qop); . . . |
コンテキストは、通常どおり、auth_destroy() を使用して破棄します。
セキュリティコンテキストを確立し、保持するには、次の 2 つのタイプの主体名が必要です。
「サーバー」主体名
サーバーの主体名は、通常、「service@host」の形式の NULL で終わる ASCII 文字列で指定します。たとえば、 nfs@dalkey.eng.company.com のように指定します。
クライアントが rpc_gss_seccreate() でセキュリティコンテキストを作成する時に、この方法でサーバーの主体名を指定します。同様にサーバーは、表示する主体名を設定する必要がある場合は、引数としてこのフォーマットの主体名をとる rpc_gss_set_svc_name() を使用します。
「クライアント」主体名
サーバーが受信するクライアントの主体名は、rpc_gss_principal_t 構造の形式 (使用するメカニズムによって決定される、不透明で長さを暗示したバイト列) をとります。
サーバーは、起動時に、そのサーバーを表わす主体名を指定する必要があります。1 つのサーバーが複数の主体として機能する場合もあります。サーバー主体名の設定には、rpc_gss_set_svc_name() を使用します。
char *principal, *mechanism; u_int req_time; principal = "nfs@engineering.company.com"; mechanism = "kerberosv5"; req_time = 10000; /* 資格の有効時間 */ rpc_gss_set_svc_name(principal, mechanism, req_time, SERV_PROG, SERV_VERS); |
サーバーは、クライアントの主体名で稼動できなければなりません。たとえば、クライアントの主体名をアクセス制御リストと比較するため、またはクライアントの UNIX 資格を検出するため (このような資格が存在する場合) に必要です。サーバーが、受信した主体名を既知のエンティティの名前と比較する必要がある場合、サーバーは、既知のエンティティ用に rpc_gss_principal_t 主体名を生成できなければなりません。 rpc_gss_get_principal_name() 呼び出しでは、ネットワーク上で個人を識別するパラメータをいくつか入力し、rpc_gss_principal_t 構造ポインタの形式で主体名を設定します。
rpc_gss_principal_t *principal; rpc_gss_get_principal_name(principal, mechanism, name, node, domain); . . . |
主体名は、free() ライブラリコールを使用して解放します。
サーバーは、クライアントの資格を獲得できなければなりません。 rpc_gss_getcred() 関数を使用すると、サーバーは UNIX 資格または RPCSEC_GSS 資格のいずれか (またはこの両方) を検索できます。これは、この関数が正常に終了した場合に設定された 2 つの引数によって実行されます。最初の引数は、呼び出し元の UNIX 資格 (uid とgid) が組み込まれた rpc_gss_ucred_t 構造 (存在する場合) へのポインタになります。2 番めの引数は rpc_gss_raw_cred_t 構造へのポインタです。
typedef struct { u_int version; /* RPCSEC_GSS プログラムバージョン */ char *mechanism; char *qop; rpc_gss_principal_t *client_principal; /* クライアント主体名 */ char *svc_principal; /* サーバー主体名 */ rpc_gss_service_t service; /* プライバシ、完全性 enum */ } rpc_gss_rawcred_t; |
例 4-29 は 1 つのサーバー側のディスパッチプロシージャの例です。これにより、サーバーは呼び出し元の資格を入手します。このプロシージャでは、呼び出し元の UNIX 資格を入手してから、次に rpc_gss_rcred_t 引数内で検出された、メカニズム、QOP、サービスタイプを使用してユーザーの識別情報 (ID) を確認します。
static void server_prog(struct svc_req *rqstp, SVCXPRT *xprt) { rpc_gss_ucred_t *ucred; rpc_gss_rawcred_t *rcred; if (rqst->rq_proq == NULLPROC) { svc_sendreply(xprt, xdr_void, NULL); return; } /* * 他の全ての要求を認証する */ */ switch (rqstp->rq_cred.oa_flavor) { case RPCSEC_GSS: /* * 資格情報を取得する */ rpc_gss_getcred(rqstp, &rcred, &ucred, NULL); /* * 認証ファイルを参照してセキュリティパラメータを * 使用することでユーザーにアクセスが許可されている * ことを確認する */ if (!authenticate_user(ucred->uid, rcred->mechanism, rcred->qop, rcred->service)) { svcerr_weakauth(xprt); return; } break; /* ユーザーに許可する */ default: svcerr_weakauth(xprt); return; } /* スイッチの終り */ switch (rqstp->rq_proq) { case SERV_PROC1: . . . } /* 通常の要求処理 ; 応答を送る ... */ return; } |
例 4-29 では、 rpc_gss_getcred()への最後の引数は、ユーザー定義の cookie です。このコンテキストの作成時にサーバーによってどのような値が指定されていても、このユーザー定義の値が戻されます。この cookie は 4 バイトの値で、そのアプリケーションに適したあらゆる方法で使用されます。RPC はこれを解釈しません。たとえば、 cookie は、コンテキストの起動元を示す構造へのポインタまたはインデックスになることができます。また、各要求ごとにこの値を計算する代わりに、サーバーがコンテキスト作成時にこの値を計算します。このため、要求の処理時間が削減されます。
これ以外に cookie が使用される場所は、コールバックです。サーバーは、rpc_gss_set_callback() 関数を使用することにより、(ユーザー定義の) コールバックを指定してコンテキストが最初に使用された時を認知できます。コールバックは、コンテキストが指定されたプログラムとバージョン用に確立されたあとに、そのコンテキストがデータ交換に最初に使用された時に呼び出されます。
ユーザー定義のコールバックルーチンは、以下のような形式になります。
2 番めと 3 番めの引数は、GSS-API データタイプで、現在はまだ公開されていません。そのため、コールバック関数はこれらを無視します。簡単に説明すると、プログラムが GSS-API オペレーションをこのコンテキスト上で実行する必要がある場合、すなわち受信条件のテストをする場合、deleg は代表されるピアの識別情報になり、一方 gss_context は GSS-API コンテキストへのポインタになります。cookie 引数については、すでに説明しました。
lock 引数は、以下のように rpc_gss_lock_t 構造へのポインタです。
typedef struct { bool_t locked; rpc_gss_rawcred_t *raw_cred; } rpc_gss_lock_t; |
rpc_gss_max_data_length() と rpc_gss_svc_max_data_length() の 2 つの関数は、1 つのデータが、セキュリティ測度によって変換され「ワイヤを通じて」送信される前に、そのデータの大きさを判別する場合に便利です。つまり、暗号化などのセキュリティ変換により、通常、伝送される 1 つのデータのサイズは変更されます (通常は、大きくなる)。データが使用できるサイズ以上に大きくならないように、これら 2 つの関数 (前者はクライアント側バージョンで、後者はサーバー側バージョン) により、指定されたトランスポートの変換前の最大サイズが戻されます。
関数の中には、導入されたセキュリティシステムに関する情報を入手する場合に使用できるものもあります。rpc_gss_get_mechanisms() は、導入されたセキュリティメカニズムのリストを戻します。一方、rpc_gss_is_installed() は、指定したメカニズムがインストールされているかどうかを検査します。rpc_gss_get_mech_info() は、指定されたメカニズムの有効な QOP を戻します。これらの関数を使用することによって、プログラマは、アプリケーション内のセキュリティパラメータのハードコード化を避けることができます。RPCSEC_GSS 関数については、表 4-8 と rpcsec_gss(3N) マニュアルページを参照してください。
サーバーが要求に関連するクライアントの資格を検索すると、サーバーはクライアントの主体名 (rpc_gss_principal_t 構造ポインタの形式)、またはクライアントのローカル UNIX 資格 (UID) のいずれかを入手できます。NFS 要求などのサービス では、アクセス検査に必要なローカル UNIX 資格が必要ですが、他の資格は必要ありません。つまり、これらのサービスでは、たとえば主体名は、rpc_gss_principal_t 構造として直接、独自のアクセス制御リスト内に格納できるからです。
クライアントのネットワーク資格 (その主体名) とローカル UNIX 資格間の対応は自動的に行われません。これは、ローカルのセキュリティ管理者が明示的に設定する必要があります。
gsscred ファイルには、クライアントの UNIX 資格とネットワーク資格の両方が入っています。後者は、rpc_gss_principal_t 構造の Hex-ASCII 表示です。これには、XFN を通じてアクセスするため、このテーブルは、ファイル、NIS、NIS+、あるいは XFN によってサポートされる将来のネームサービス上に導入できます。XFN 階層では、このテーブルは this_org_unit/service/gsscred として表示されます。 gsscred テーブルは、gsscred ユーティリティとともに保持されます。このユーティリティを使用すると、管理者はユーザーやメカニズムの追加および削除が行えます。
便宜上、RPCSEC_GSS では、メカニズムと保護の質 (QOP) パラメータを表示するためにリテラルの文字列を使用します。ただし、基本的なメカニズム自体では、メカニズムをオブジェクト識別子として、QOP は 32 ビット整数として表示する必要があります。また、各メカニズムごとに、そのメカニズムのサービスを実現する共有ライブラリを指定する必要があります。
/etc/gss/mech ファイルには、システム上に導入されたすべてのメカニズムに関する情報、メカニズム名 (ASCII 形式)、メカニズムの ODI、サービスを実現する共有ライブラリとカーネルモジュールが格納されます。次に例を示します。
kerberosv5 1.2.840.113554.1.2.2 mech_krb5.so kmech_krb5 |
/etc/gss/qop ファイルには、導入されたすべてのメカニズム用に、各メカニズムがサポートするすべての QOP が、ASCII 文字列とそれに対応する 32 ビット整数の両方で格納されます。
/etc/gss/mech と /etc/gss/qop は、両方とも指定されたシステムにセキュリティメカニズムが最初に導入されたときに作成されます。
カーネル内 RPC ルーチンは、通常、文字列にない値を使用してメカニズムと QOP を表すため、アプリケーションは、これらのカーネル内ルーチンを利用したい場合には、rpc_gss_mech_to_oid() と rpc_gss_qop_to_num() 関数を使用してこれらのパラメータと同等の文字列にない値を入手します。