This example shows how UNIX authentication works on both the client and server sides.
To use UNIX authentication, the programmer first creates the Remote Procedure Call (RPC) client handle and then sets the authentication parameter.
The RPC client handle is created as follows:
clnt = clntudp_create (address, prognum, versnum, wait, sockp)
The UNIX authentication parameter is set as follows:
clnt->cl_auth = authunix_create_default();
Each remote procedure call associated with the client (clnt) then carries the following UNIX-style authentication credentials structure:
/* * UNIX style credentials. */ struct authunix_parms { u_long aup_time; /* credentials creation time */ char *aup_machname; /* host name where client is */ int aup_uid; /* client's UNIX effective uid */ int aup_gid; /* client's current group id */ u_int aup_len; /* element length of aup_gids */ int *aup_gids; /* array of groups user is in */ };
The authunix_create_default subroutine sets these fields by invoking the appropriate subroutines. The UNIX-style authentication is valid until destroyed with the following routine:
auth_destroy(clnt->cl_auth);
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; /* desired 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 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; } }