This example illustrates how Data Encryption Standard (DES) authentication works on both the client side and the server side.
To use DES authentication, the client first sets its authentication handle as follows:
cl->cl_auth = authdes_create(servername, 60, &server_addr, NULL);
The first argument (servername) to the authdes_create routine is the network name, or net name, of the owner of the server process. Typically, server processes are root processes. The net name can be derived using the following call:
char servername[MAXNETNAMELEN];
host2netname(servername, rhostname, NULL);
The rhostname parameter is the host name of the machine on which the server process is running. The host2netname routine supplies the servername that will contain this net name for the root process. If the server process is run by a regular user, the user2netname routine can be called instead.
The following example illustrates a server process with the same user ID as the client:
char servername[MAXNETNAMELEN];
user2netname(servername, getuid(), NULL);
The user2netname and host2netname routines identify the naming domain at the server location. The NULL parameter in this example means that the local domain name should be used.
The second argument (60) to the authdes_create routine identifies the lifetime of the credential, which is 60 seconds. This means the credential has 60 seconds until expiration. The server Remote Procedure Call (RPC) subsystem does not grant either a second request within the 60-second lifetime or requests made after the credential has expired.
The third argument (&server_addr) to the authdes_create routine is the address of the host with which to synchronize. DES authentication requires that the server and client agree on the time. The time is determined by the server when it receives the address. If the server and client times are already synchronized, the argument can be set to null.
The final argument (NULL) to the authdes_create routine is the address of a DES encryption key that is used to encrypt time stamps and data. Because this argument is null, a random key is chosen. The programmer can get the encryption key from the ah_key field of the authentication handle.
The following example illustrates DES authentication on the server side. The server side is simpler than the client side. This example uses AUTH_DES instead of AUTH_UNIX:
#include <sys/time.h> #include <rpc/auth_des.h> ... ... nuser(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp; { struct authdes_cred *des_cred; int uid; int gid; int gidlen; int gidlist[10]; /* * we don't care about authentication for null proc */
if (rqstp->rq_proc == NULLPROC) { /* same as before */ }
/* * now get the uid */ switch (rqstp->rq_cred.oa_flavor) { case AUTH_DES: des_cred = (struct authdes_cred *) rqstp->rq_clntcred; if (! netname2user(des_cred->adc_fullname.name, &uid, &gid, &gidlen, gidlist)) { fprintf(stderr, "unknown user: %s\n", des_cred->adc_fullname.name); svcerr_systemerr(transp); return; } break; case AUTH_NULL: default: svcerr_weakauth(transp); return; }
/* * The rest is the same as UNIX-style authentication */ 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; } }
Note: The netname2user routine, which is the inverse of the user2netname routine, converts a network ID to a user ID. The netname2user routine also supplies group IDs, which are not used in this example but may be useful in other programs.