伺服器必須能夠提取一個客戶端的證書。範例 8-5 中所示的 rpc_gss_getcred() 函數允許伺服器擷取 UNIX 證書或是 RPCSEC_GSS 證書(或兩者皆是)。它會藉由函數成功之後被設定的兩個引數來達到此目的。其中一個是 rpc_gss_ucred_t 結構的指標,其中包含呼叫者的 UNIX 證書,如果存在的話﹕
typedef struct {
uid_t uid; /* user ID */
gid_t gid; /* group ID */
short gidlen;
git_t *gidlist; /* list of groups */
} rpc_gss_ucred_t;
另一個引數則是 rpc_gss_raw_cred_t 結構的指標,此引數如下所示﹕
typedef struct {
u_int version; /* RPCSEC_GSS program version */
char *mechanism;
char *qop;
rpc_gss_principal_t client_principal; /* client principal name */
char *svc_principal; /* server principal name */
rpc_gss_service_t service; /* privacy, integrity enum */
} rpc_gss_rawcred_t;
(請參見 "生成客戶端主管名稱" 中有關 rpc_gss_principal_t 結構與如何建立的說明。)因為 rpc_gss_rawcred_t 同時包含客戶端及伺服器的主管名稱,rpc_gss_getcred() 便可以將它們兩個傳回。
範例 8-5 是一種簡單的伺服端配送程序的範例,其中伺服器取得呼叫者的證書。程序取得呼叫者的 UNIX 證書,然後確認使用者的身份,使用機制 QOP 以及 rpc_gss_rcred_t 引數中找到的服務類型。
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;
}
/*
* authenticate all other requests */
*/
switch (rqstp->rq_cred.oa_flavor) {
case RPCSEC_GSS:
/*
* get credential information
*/
rpc_gss_getcred(rqstp, &rcred, &ucred, NULL);
/*
* verify that the user is allowed to access
* using received security parameters by
* peeking into my config file
*/
if (!authenticate_user(ucred->uid, rcred->mechanism,
rcred->qop, rcred->service)) {
svcerr_weakauth(xprt);
return;
}
break; /* allow the user in */
default:
svcerr_weakauth(xprt);
return;
} /* end switch */
switch (rqstp->rq_proq) {
case SERV_PROC1:
. . .
}
/* usual request processing; send response ... */
return;
}
|
如需更詳細的資訊,請參見 rpc_gss_getcred(3N) 線上援助頁。
在 範例 8-5 中,rpc_gss_getcred()(此處是一個 NULL)的最後一個引數是一個使用者定義的 cookie,伺服器將在建立上下文時指定其傳回數值。您可以採用任何適於應用程式的方法來使用一個四位元組數值的 cookie - RPC 並不會將它解譯。例如 cookie 可以是代表上下文指標結構的一個指標或索引;伺服器不會為每個要求計算此數值,反而會依照建立上下文的時間來計算它(因此而節省處理要求的時間)。