上述の認証タイプ (AUTH_SYS、 AUTH_DES、 および AUTH_KERB) は、1 つの決まった見方で同じように扱うことができます。このため、新しいネットワーキング階層、Generic Security Standard API (汎用セキュリティ規格API)、すなわち GSS-API が追加されており、RPC プログラマが利用可能です。GSS-API のフレームワークでは、認証に加え次の 2 つの「サービス」が提供されています。 それは、完全性とプライバシです。
「完全性」一貫性サービスでは、GSS-API は下位層のメカニズムを使用してプログラム間で交換されるメッセージを認証します。暗号化チェックサムによって、以下が確立されます。
データの発信側から受信側への識別情報 (ID)
受信側から発信側への識別情報 (ID) (相互の認証が要求された場合)
伝送されたデータそのものの認証
「プライバシ」プライバシサービスには、完全性サービスが含まれています。これに加えて、伝送データも「暗号化」され傍受者から保護されます。
米国の輸出の規約により、プライバシサービスはすべてのユーザーが利用できるわけではありません。
現在、GSS–API はまだ発表されていません。ただし、特定の GSS-API 機能は RPCSEC_GSS の機能を通じて参照できます。詳細は、 『GSS-API のプログラミング』を参照してください。
RPCSEC_GSS API セキュリティタイプを使用すると、ONC RPC アプリケーションは、GSS-API の機能を最大に生かすことができます。RPCSEC_GSS は、次の図のように、GSS-API 階層の「最上部」に位置しています。
RPCSEC-GSS のプログラミングインタフェースを使用する場合は、ONC RPC アプリケーションは以下の項目を指定できます。
メカニズム — セキュリティのパラダイム。各種セキュリティメカニズムでは、1 つまたは複数レベルのデータ保護と同時に、それぞれ異なる種類のデータ保護を提供します。この場合、GSS-API によってサポートされる任意のセキュリティメカニズムを指定します (Kerberos v5、RSA 公開鍵など)。
セキュリティサービス — プライバシまたは完全性のいずれかを指定します (あるいはどちらも指定しない)。デフォルトは完全性です。この項目はメカニズムに依存しません。
QOP — 保護の質。QOP により、プライバシまたは完全性サービスを実現するために使用する暗号化アルゴリズムのタイプが指定されます。各セキュリティメカニズムには、それに関連する 1 つまたは複数の QOP があります。
アプリケーションは、RPCSEC_GSS によって提供される関数により、QOP およびメカニズムのリストを入手できます。その他の関数 を参照してください。 開発者は、メカニズムと QOP をハードコード化し、使用するアプリケーション内に埋め込むことは避けてください。そうすれば、新しい、または異なるメカニズムおよび QOP を使用するためにアプリケーションを修正する必要はありません。
これまでは、「セキュリティタイプ」と「認証タイプ」は同じものを表していました。RPCSEC_GSS の導入によって、「タイプ」は現在、多少異なる意味を持ちます。タイプには、認証とともにサービス (一貫性またはプライバシ) を含むことができるようになりました。ただし、現在のところは RPCSEC_GSS がそれに該当する唯一のタイプということになります。
RPCSEC_GSS を使用すると、ONC RPC アプリケーションは、他のタイプを使用して行う場合と同様に、ピアにセキュリティコンテキストを確立し、データを交換してこのコンテキストを破棄します。一度コンテキストが確立されると、アプリケーションは、送信したデータユニットごとに QOP およびサービスを変更できます。
RPCSEC_GSS データタイプを含む RPCSEC_GSS の詳細については、rpcsec_gss(3NSL) のマニュアルページを参照してください。
次の表は、RPCSEC_GSS コマンドを要約したものです。この表では、各関数の個別の説明ではなく、RPCSEC_GSS 関数の全般的な概要を示しています。各関数の詳細については、該当するマニュアルページを参照するか、RPCSEC_GSS データ構造のリストなどの概要が記載された、rpcsec_gss(3NSL) のマニュアルページを参照してください。
表 5–2 RPCSEC_GSS 関数処理 | 関数 | 入力 | 出力 |
---|---|---|---|
セキュリティコンテキストの作成 | rpc_gss_seccreate(3NSL) | クライアントのハンドル、主体名、メカニズム、QOP、サービスタイプ | AUTH ハンドル |
コンテキストの QOP とサービスタイプの変更 | rpc_gss_set_defaults(3NSL) | 古い QOP とサービス | 新しい QOP とサービス |
セキュリティの変換前に、データの最大サイズを示す | rpc_gss_max_data_length(3NSL) (クライアント側) | 伝送できる最大データサイズ | 変換前の最大データサイズ |
セキュリティの変換前に、データの最大サイズを示す | rpc_gss_svc_max_data_length(3NSL) (サーバー側) | 伝送できる最大データサイズ | 変換前の最大データサイズ |
表示するサーバーの主体名を設定する | rpc_gss_set_svc_name(3NSL) | 主体名 , RPC プログラム、バージョン番号 | 正常に完了した場合は TRUE |
呼び出し側 (クライアント) の資格を得る | rpc_gss_getcred(3NSL) | svc_req 構造体へのポインタ | UNIX 資格、RPCSEC_GSS 資格、cookie |
(ユーザーの作成した) コールバック関数を指定する | rpc_gss_set_callback(3NSL) | コールバック関数へのポインタ | 正常に完了した場合は TRUE |
固有のパラメータから主体名の RPCSEC_GSS 構造体を作成する | rpc_gss_get_principal_name(3NSL) | メカニズム、ユーザー名、マシン名、ドメイン名 | RPCSEC_GSS 主体名の構造体 |
RPCSEC_GSS ルーチンが失敗した場合にエラーコードを得る | rpc_gss_get_error(3NSL) |
| RPCSEC_GSS エラー番号、該当する場合には errno |
インストールされているメカニズムの文字列を入手する | rpc_gss_get_mechanisms(3NSL) |
| 有効なメカニズムのリスト |
有効な QOP 文字列を入手する | rpc_gss_get_mech_info(3NSL) | メカニズム | そのメカニズムの有効な QOP |
サポートされている RPCSEC_GSS の最大および最小のバージョン番号を得る | rpc_gss_get_versions(3NSL) |
| 最大および最小のバージョン番号 |
メカニズムが導入されているかどうかをチェックする | rpc_gss_is_installed(3NSL) | メカニズム | インストールされている場合は TRUE |
ASCII メカニズムを RPC オブジェクト識別子に変換する | rpc_gss_mech_to_oid(3NSL) | メカニズム (文字列で) | メカニズム (OID で) |
ASCII QOP を整数に変換する | rpc_gss_qop_to_num(3NSL) | QOP (文字列で) | QOP (整数で) |
コンテキストは、rpc_gss_seccreate() を使用して作成します。この関数では引数として次のものをとります。
クライアントハンドル(たとえば、clnt_create()によって戻されたもの)
サーバーの主体名 ( nfs@acme.com)
セッションのメカニズム (Kerberos V5 など)
セキュリティサービスタイプ (プライバシなど)
セッションの QOP
使用される場合は、ほとんど不透明( opaque )なまま使用される (つまり、プログラマが NULL 値を入れることができる) 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 はこのメカニズムのデフォルトに設定されます。これ以外の場合は、このメカニズムを使用して、rpc_gss_get_mechanisms() を指定したプログラムで有効な値を入手できます。詳細については、マニュアルページの rpc_gss_get_mechanisms(3NSL) を参照してください。
セキュリティサービスタイプ、rpc_gss_svc_integrity は、RPCSEC_GSS タイプの enum のひとつである rpc_gss_service_t です。rpc_gss_service_t のフォーマットは、次のようになります。
typedef enum { rpc_gss_svc_default = 0, rpc_gss_svc_none = 1, rpc_gss_svc_integrity = 2, rpc_gss_svc_privacy = 3 } rpc_gss_service_t;
デフォルトのセキュリティサービスは、完全性をマップするため、プログラマは指定された rpc_gss_svc_default を入手し、同じ結果を獲得することができます。
詳細については、rpc_gss_seccreate(3NSL) のマニュアルページを参照してください。
コンテキストが設定されると、アプリケーションは伝送される個々のデータユニットの QOP およびサービス値を変更する必要がある場合があります。たとえば、プログラムのパスワードは暗号化したいがログイン名は暗号化したくない場合。これは、次のように rpc_gss_set_defaults() を使用すると実行できます。
rpc_gss_set_defaults(clnt->clnt_auth, rpc_gss_svc_privacy, qop); . . . |
この場合、セキュリティサービスはプライバシに設定されます。 コンテキストの作成 を参照してください。 ここで、qop は新しい QOP の名前を表わす文字列へのポインタです。
コンテキストは、通常どおり、auth_destroy() を使用して破棄します。
QOP とサービスの変更に関する詳細は、 rpc_gss_set_defaults(3NSL) のマニュアルページを参照してください。
セキュリティコンテキストを確立し、保持するには、次の 2 つのタイプの主体名が必要です。
サーバーの主体名は、通常、「service@host」の形式の NULL で終わる ASCII 文字列で指定します。たとえば、 nfs@eng.acme.com のように指定します。
クライアントがセキュリティコンテキストを作成する時には、この形式でサーバーの主体名を指定します。 コンテキストの作成 を参照してください。 同様にサーバーは、表示する主体名を設定する必要がある場合は、rpc_gss_set_svc_name () を使用します。この関数は、引数としてこのフォーマットの主体名をとります。
サーバーが受信するクライアントの主体名は、rpc_gss_principal_t 構造の形式をとります。それは、使用するメカニズムによって決定される、特定の長さを持つ隠されたバイト列になります。この構造については、rpcsec_gss(3NSL) のマニュアルページを参照してください。
サーバーは、起動時に、そのサーバーを表わす主体名を指定する必要があります 。1 つのサーバーが、複数の主体として機能する場合もあります。次のプログラムで示すように、 rpc_gss_set_svc_name() を使用してサーバー主体名の設定をします。
char *principal, *mechanism; u_int req_time; principal = "nfs@eng.acme.com"; mechanism = "kerberos_v5"; req_time = 10000; /* 資格の有効時間 */ rpc_gss_set_svc_name(principal, mechanism, req_time, SERV_PROG, SERV_VERS);
Kerberos は、req_time パラメータを無視します。他の認証システムでは、このパラメータを使用する場合があります。
詳細については、rpc_gss_set_svc_name(3NSL) のマニュアルページを参照してください。
サーバーは、クライアントの主体名で稼動する必要があります。 たとえば、クライアントの主体名をアクセス制御リストと比較するため、またはクライアントの UNIX 資格が存在する場合にはそれを検出するために必要です。このような主体名は、rpc_gss_principal_t 構造体ポインタとして保存されます。 rpc_gss_principal_t についての詳細は、rpcsec_gss(3NSL) のマニュアルページを参照してください。 サーバーが、受信した主体名を既知のエンティティの名前と比較する必要がある場合、サーバーは、この形式で主体名を生成する必要があります。
次のプログラムで示すように、rpc_gss_get_principal_name() 呼び出しでは、ネットワーク上で個人を識別するパラメータをいくつか入力し、rpc_gss_principal_t 構造体ポインタとして主体名を生成します。
rpc_gss_principal_t *principal; rpc_gss_get_principal_name(principal, mechanism, name, node, domain); . . .
rpc_gss_get_principal_name() への引数は、次のとおりです。
「 principal 」には、設定された rpc_gss_principal_t 構造体へのポインタが入ります。
「mechanism 」は、使用されるセキュリティメカニズムです。生成される主体名は、メカニズムに依存します。
「 name 」には joeh または nfs などの個人名、またはサービス名が入ります。
「 node 」には、UNIX マシン名などが入ります。
「 domain 」には、たとえば、DNS、NIS、または NIS+ドメイン名、あるいは Kerberos の領域が入ります。
各セキュリティメカニズムには、別々の識別パラメータが必要です。たとえば、Kerberos V5 にはユーザー名が必ず必要です。また、オプションの場合に限り、修飾されたノード名とドメイン名が必要です (Kerberos 用語では、ホスト名と領域名)。
詳細については、rpc_gss_get_principal_name(3NSL) のマニュアルページを参照してください。
主体名は、free() ライブラリコールを使用して解放します。
サーバーは、クライアントの資格を獲得できなければなりません。 例 5–14 で示すように、 rpc_gss_getcred() 関数を使用すると、サーバーは UNIX 資格、または RPCSEC_GSS 資格のいずれか (またはこの両方) を検索できます。 これは、この関数が正常に終了した場合に設定された 2 つの引数によって実行されます。このうち1つは、呼び出し側の UNIX 資格が組み込まれた rpc_gss_ucred_t 構造体 (存在する場合) へのポインタになります。
typedef struct { uid_t uid; /* ユーザー ID */ gid_t gid; /* グループ ID */ short gidlen; git_t *gidlist; /* グループのリスト */ } rpc_gss_ucred_t; |
もう 1 つの引数は、次のような、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;
rpc_gss_rawcred_t にはクライアントとサーバーの両方の主体名が組み込まれているため、rpc_gss_getcred() は両方の名前を返します。 rpc_gss_principal_t 構造体の解説と作成方法については、クライアント主体名の作成 を参照してください。
次のプログラムは、単純なサーバー側のディスパッチ手続きの例です。サーバーは、呼び出し側の資格を入手しています。この手続きでは、呼び出し側の 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; } |
詳細については、rpc_gss_getcred(3NSL) のマニュアルページを参照してください。
例 5–14 では、rpc_gss_getcred () への最後の引数 (ここでは NULL になっている) は、ユーザー定義の cookie です。このコンテキストの作成時にサーバーによってどのような値が指定されていても、このユーザー定義の値が戻されます。この cookie は 4 バイトの値で、そのアプリケーションに適したあらゆる方法で使用されます。RPC はこれを解釈しません。たとえば、 cookie は、コンテキストの起動元を示す構造体へのポインタまたはインデックスになることができます。また、各要求ごとにこの値を計算する代わりに、サーバーがコンテキスト作成時にこの値を計算します。このため、要求の処理時間が削減されます。
これ以外に cookie が使用される場所は、コールバックです。サーバーは、rpc_gss_set_callback() 関数を使用することにより、ユーザー定義のコールバックを指定して、コンテキストが最初に使用された時を認知できます。コールバックは、コンテキストが指定されたプログラムとバージョン用に確立されたあとに、そのコンテキストがデータ交換に最初に使用された時に呼び出されます。
ユーザー定義のコールバックルーチンは、以下のような形式になります。
bool_t callback (struct svc_req *req, gss_cred_id_t deleg, gss_ctx_id_t gss_context rpc_gss_lock_t * lock void ** cookie);
2 番めと 3 番めの引数 deleg と gss_context は、GSS-API データタイプで、現在はまだ公開されていません。詳細については、『GSS-API のプログラミング』 を参照してください。 deleg は委譲されたピアを識別する情報になり、一方 gss_context は GSS-API コンテキストへのポインタになります。プログラムが GSS-API 処理をこのコンテキスト上で実行する必要がある場合、つまり受信条件のテストをする場合に、このポインタが必要となります。 cookie 引数については、すでに説明しました。
lock 引数は、以下のように rpc_gss_lock_t 構造体へのポインタです。
typedef struct { bool_t locked; rpc_gss_rawcred_t *raw_cred; } rpc_gss_lock_t; |
このパラメータを使用すると、サーバーはセッションに対し強制的に特定の QOP とサービスを実行できます。例 5–14 に記載したように、QOP とサービスは、rpc_gss_rawcred_t 構造体内で検出できます。サーバーは、サービスと QOP の値を変更する必要はありません。ユーザー定義のコールバックが呼び出されると、locked は FALSE に設定されます。サーバーが、locked を TRUE に設定すると、QOP とサービスの値が、rpc_gss_rawcred_t 構造体内の値と一致する要求だけが受理されます。
詳細は、rpc_gss_set_callback(3NSL) のマニュアルページを参照してください。
rpc_gss_max_data_length() と rpc_gss_svc_max_data_length() の 2 つの関数は、1 つのデータが、セキュリティ測度によって変換され「ワイヤを通じて」送信される前に、そのデータの大きさを判別する場合に便利です。つまり、暗号化などのセキュリティ変換により、通常、伝送される 1 つのデータのサイズは変更され、通常は大きくなります。データが使用できるサイズ以上に大きくならないよう に、これら 2 つの関数(前者はクライアント側バージョンで、後者はサーバー側バージョン) により、指定されたトランスポートの変換前の最大サイズが戻されます。
詳細については、rpc_gss_max_data_length(3NSL) のマニュアルページを参照してください。
関数の中には、導入されたセキュリティシステムに関する情報を入手する場合に使用できるものもあります。
rpc_gss_get_mechanisms(3NSL)() は、導入されたセキュリティメカニズムのリストを戻します。
rpc_gss_is_installed(3NSL)() は、指定したメカニズムがインストールされているかどうかを検査します。
rpc_gss_get_mech_info(3NSL)() は、指定されたメカニズムの有効な QOP を戻します。
これらの関数を使用することによって、プログラマは、アプリケーション内のセキュリティパラメータのハードコード化を避けることができます 。(RPCSEC_GSS 関数については、表 5–2 および rpcsec_gss(3NSL) マニュアルページを参照してください)。
RPCSEC_GSS は各種のファイルを使用して情報を保存します。
サーバーが要求に関連するクライアントの資格を検索すると、サーバーはクライアントの主体名 (rpc_gss_principal_t 構造体ポインタの形式)、またはクライアントのローカル UNIX 資格 (UID) のいずれかを入手できます。NFS 要求などのサービス では、アクセス検査に必要なローカル UNIX 資格が必要ですが、他の資格は必要ありません。これらのサービスでは、たとえば主体名は、 rpc_gss_principal_t 構造体として直接、独自のアクセス制御リスト内に格納できます。
クライアントのネットワーク資格 (その主体名) とローカルUNIX 資格間の対応は自動的に行われません。これは、ローカルのセキュリティ管理者が明示的に設定する必要があります。
gsscred ファイルには、クライアントの UNIX 資格とネットワーク(たとえば、Kerberos V5) 資格の両方が入っています。ネットワーク資格は、rpc_gss_principal_t 構造体が 16 進 ASCII 表現されています。gsscred ファイルは、XFN を通じてアクセスされます。したがって、このテーブルは、ファイル、NIS、NIS+、あるいは XFN によってサポートされる将来のネームサービス上に実装可能となります。XFN 階層では、このテーブルは this_org_unit/service/gsscred として表示されます。システム管理者は、ユーザーやマシンを追加したり削除したりできる gsscred ユーティリティを利用して、gsscred テーブルの保守管理を実行できます。
便宜上、RPCSEC_GSS では、メカニズムと保護の質 (QOP) パラメータを表示するためにリテラルの文字列を使用します。ただし、基本的なメカニズム自体では、メカニズムをオブジェクト識別子として、QOP は 32 ビット整数として表示する必要があります。また、各メカニズムごとに、そのメカニズムのサービスが実装された共有ライブラリを指定する必要があります。
/etc/gss/mech ファイルには、システム上に導入されたすべてのメカニズムに関する情報が保存されています。ASCII 形式によるメカニズム名、そのメカニズムの OID、このメカニズムによって提供されるサービスが実装された共有ライブラリ名、さらに、オプションとして、サービスが実装されたカーネルモジュール名です。次に例を示します。
kerberos_v5 1.2.840.113554.1.2.2 gl/mech_krb5.so gl_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() 関数を使用して、文字列ではない値で表現された、これらのパラメータを入手します。