サーバーは、クライアントの資格を獲得できなければなりません。 例 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 は、コンテキストの起動元を示す構造体へのポインタまたはインデックスになることができます。また、各要求ごとにこの値を計算する代わりに、サーバーがコンテキスト作成時にこの値を計算します。このため、要求の処理時間が削減されます。