サーバーはクライアントの資格を取り出せる必要があります。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 をコンテキストインジケータを表す構造体へのポインタ (または、インデックス) とすることも可能です。つまり、サーバーは要求ごとにこの値を計算するのではなく、コンテキスト作成時にこの値を計算します。したがって、要求処理時間を短縮できます。