伺服器必須能夠提取一個客戶端的證書。範例 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 可以是代表上下文指標結構的一個指標或索引;伺服器不會為每個要求計算此數值,反而會依照建立上下文的時間來計算它(因此而節省處理要求的時間)。