サーバーはクライアントの資格を取り出せる必要があります。rpc_gss_getcred() 関数 (例 8-5 を参照) を使用すると、サーバーは UNIX 資格または RPCSEC_GSS 資格のどちらか (あるいは、両方) を取り出すことができます。関数が成功した場合、これらの資格は次の 2 つの引数に設定されます。1 つは、rpc_gss_ucred_t 構造体へのポインタで、呼び出し側の UNIX 資格が (存在すれば) 入ります。
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_principal_t() 構造体とその作成方法については、「クライアントプリンシパル名の生成」を参照してください。rpc_gss_rawcred_t にはクライアントとサーバーの両方のプリンシパル名が入っているため、rpc_gss_getcred() はこれら両方を戻すことができます。
例 8-5 は、サーバー側のディスパッチ手順の簡単な例です。この例では、サーバーが呼び出し側の資格を取得しています。この手順は、呼び出し側の UNIX 資格を取得します。そして、rpc_gss_rcred_t 引数中の機構、QOP、およびサービスのタイプを使用して、ユーザーの識別情報を確認します。
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);
/*
* 自分の config ファイルを参照して、受信した
* セキュリティパラメータによるアクセスがユーザーに
* 許可されているかどうかを確認する。
*/
if (!authenticate_user(ucred->uid, rcred->mechanism,
rcred->qop, rcred->service)) {
svcerr_weakauth(xprt);
return;
}
break; /* ユーザーに許可する。 */
default:
svcerr_weakauth(xprt);
return;
} /* switch 文の終了 */
switch (rqstp->rq_proq) {
case SERV_PROC1:
. . .
}
/* 通常の要求処理。応答を送信するなど。 */
return;
}
|
詳細は、rpc_gss_getcred(3N) のマニュアルページを参照してください。
例 8-5 では、rpc_gss_getcred() への最後の引数 (ここでは NULL) はユーザーが定義した cookie です。この値は、戻り時、サーバーがコンテキストを作成したときに指定した値になります。この cookie は 4 バイトの値であり、アプリケーションに適切な方法で使用できます (RPC ではこの値を使用しません)。たとえば、cookie をコンテキストインジケータを表す構造体へのポインタ (または、インデックス) とすることも可能です。つまり、サーバーは要求ごとにこの値を計算するのではなく、コンテキスト作成時にこの値を計算します。したがって、要求処理時間を短縮できます。