Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
5.  Advanced RPC Programming Techniques Batching  Previous   Contents   Next 
   
 

Authentication

Just as you can use different transports when creating RPC clients and servers, you can associate different "flavors" of authentication with RPC clients. The authentication subsystem of RPC is open ended. So, RPC can support many flavors of authentication. Appendix B, RPC Protocol and Language Specification further defines the authentication protocols.

Sun RPC currently supports the authentication flavors shown in the following table.

Table 5-1 Authentication Methods Supported by Sun RPC

Method

Description

AUTH_NONE

Default. No authentication performed.

AUTH_SYS

An authentication flavor based on the process permissions authentication in the UNIX operating system.

AUTH_SHORT

An alternate flavor of AUTH_SYS used by some servers for efficiency. Client programs using AUTH_SYS authentication can receive AUTH_SHORT response verifiers from some servers. See Appendix B, RPC Protocol and Language Specification for details.

AUTH_DES

An authentication flavor based on DES encryption techniques.

AUTH_KERB

Version 5 Kerberos authentication based on DES framework.

When a caller creates a new RPC client handle as in:

clnt = clnt_create(host, prognum, versnum, nettype);

the appropriate client-creation routine sets the associated authentication handle to:

clnt->cl_auth = authnone_create();

If you create a new instance of authentication, you must destroy it with auth_destroy(clnt->cl_auth). This destruction conserves memory.

On the server side, the RPC package passes a request that has an arbitrary authentication style associated with it to the service-dispatch routine. The request handle passed to a service-dispatch routine contains the structure rq_cred. This structure is opaque, except for one field: the flavor of the authentication credentials.

/*
 * Authentication data
 */
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 */
};

The RPC package guarantees the following structural requirements to the service-dispatch routine:

  • The rq_cred field in the svc_req structure is well formed. You can check rq_cred.oa_flavor to get the flavor of authentication. You can also check the other fields of rq_cred if RPC does not support the flavor.

  • The rq_clntcred field that is passed to service procedures is either NULL or points to a well-formed structure that corresponds to a supported flavor of authentication credential. No authentication data exists for the AUTH_NONE flavor. rq_clntcred can be cast only as a pointer to an authsys_parms, short_hand_verf, authkerb_cred, or authdes_cred structure.

AUTH_SYS Authentication

The client can use AUTH_SYS style authentication (called AUTH_UNIX in previous releases) by setting clnt->cl_auth after creating the RPC client handle:

clnt->cl_auth = authsys_create_default();

This setting causes each RPC call associated with clnt to carry with it the following credentials-authentication structure shown in the following example:


Example 5-7 AUTH_SYS Credential Structure

/*
 * AUTH_SYS flavor credentials.
 */
struct authsys_parms {
	u_long aup_time;			 /* credentials creation time */
	char *aup_machname;		 /* client's host name */
	uid_t aup_uid;				 /* client's effective uid */
	gid_t aup_gid;				 /* client's current group id */
	u_int aup_len;				 /* element length of aup_gids*/
	gid_t *aup_gids;			 /* array of groups user is in */
};

rpc.broadcast defaults to AUTH_SYS authentication.

The following example shows a server, with procedure RUSERPROC_1(), that returns the number of users on the network. As an example of authentication, the server checks AUTH_SYS credentials and does not service requests from callers with a uid of 16.


Example 5-8 Authentication Server

nuser(rqstp, transp)
	struct svc_req *rqstp;
	SVCXPRT *transp;
{
	struct authsys_parms *sys_cred;
	uid_t uid;
	unsigned int nusers;

	/* NULLPROC should never be authenticated */
	if (rqstp->rq_proc == NULLPROC) {
		if (!svc_sendreply( transp, xdr_void, (caddr_t) NULL))
			fprintf(stderr, "can't reply to RPC call\n");
		return;
	}

	/* now get the uid */
	switch(rqstp->rq_cred.oa_flavor) {
		case AUTH_SYS:
			sys_cred = (struct authsys_parms *) rqstp->rq_clntcred;
			uid = sys_cred->aup_uid;
			break;
		default:
			svcerr_weakauth(transp);
			return;
	}
	switch(rqstp->rq_proc) {
		case RUSERSPROC_1:
			/* 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_int, &nusers))
				fprintf(stderr, "can't reply to RPC call\n");
			return;
		default:
			svcerr_noproc(transp);
			return;
	}
}

Note the following points about the example:

  • The authentication parameters associated with the NULLPROC (procedure number zero) are usually not checked.

  • The server calls svcerr_weakauth() if the authentication parameter's flavor is too weak. In this case, there is no way to get the list of authentication flavors the server requires.

  • The service protocol should return status for access denied. In the examples, the protocol instead calls the service primitive svcerr_systemerr().

The last point underscores the relation between the RPC authentication package and the services: RPC deals only with authentication and not with an individual service's access control. The services must establish access-control policies and reflect these policies as return statuses in their protocols.

 
 
 
  Previous   Contents   Next