UNIX Authentication on the Server Side
This example shows how to use UNIX authorization on the server side.
The following is a structure definition of a request handle passed
to a service dispatch routine at the server:
/*
* An RPC Service request
*/
struct svc_req {
u_long rq_prog; /* service program number */
u_long rq_vers; /* service protocol vers num */
u_long rq_proc; /* required procedure number */
struct opaque_auth rq_cred; /* raw credentials from wire */
caddr_t rq_clntcred; /* credentials (read only) */
};
Except for the style or flavor of authentication credentials, the rq_cred routine
is opaque.
/*
* Authentication info. Mostly opaque to the programmer.
*/
struct opaque_auth {
enum_t oa_flavor; /* style of credentials */
caddr_t oa_base; /* address of more auth stuff */
u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
};
Before passing a request to the service dispatch routine, RPC guarantees:
- The request's rq_cred field is in an acceptable form. Therefore, the service implementor may inspect the request's rq_cred.oa_flavor to determine which style of authentication the caller used. The service implementor may also wish to inspect the other rq_cred fields if the authentication style is not one of the styles supported by the RPC package.
- The request's rq_clntcred field is either null or points to a well-formed structure that corresponds to a supported style of authentication credentials. The rq_clntcred field can currently be set as a pointer to an authunix_parms structure for UNIX-style authentication. If rq_clntcred is null, the service implementor can inspect the other opaque fields of the rq_cred credential for any new types of authentication that may be unknown to the RPC package.
The following example uses UNIX authentication
on the server side. Here, the remote users service example is extended
so that it computes results for all users except user ID (UID) 16:
nuser(rqstp, transp)
struct svc_req *rqstp;
SVCXPRT *transp;
{
struct authunix_parms *unix_cred;
int uid;
unsigned long nusers;
/*
* we don't care about authentication for null proc
*/
if (rqstp->rq_proc == NULLPROC) {
if (!svc_sendreply(transp, xdr_void, 0)) {
fprintf(stderr, "can't reply to RPC call\n");
return (1);
}
return;
}
/*
* now get the uid
*/
switch (rqstp->rq_cred.oa_flavor) {
case AUTH_UNIX:
unix_cred =
(struct authunix_parms *)rqstp->rq_clntcred;
uid = unix_cred->aup_uid;
break;
case AUTH_NULL:
default:
svcerr_weakauth(transp);
return;
}
switch (rqstp->rq_proc) {
case RUSERSPROC_NUM:
/*
* make sure caller is allowed to call this proc
*/
if (uid == 16) {
svcerr_systemerr(transp);
return;
}
/*
* Code here to compute the number of users
* and assign it to the variable nusers
*/
if (!svc_sendreply(transp, xdr_u_long, &nusers)) {
fprintf(stderr, "can't reply to RPC call\n");
return (1);
}
return;
default:
svcerr_noproc(transp);
return;
}
}