For more information, see the rpc_gss_getcred(3NSL) man page.
Cookies
In Example 5-14, the last argument to rpc_gss_getcred() (here, a NULL) is a user-defined cookie, with a value on return of whatever was specified by the server when the context was created. This cookie, a 4-byte value, can be used in any way appropriate for the application. RPC does not interpret the cookie. For example, the cookie can be a pointer or index to a structure that represents the context initiator. Instead of computing this value for every request, the server computes it at context-creation time, saving on request-processing time.
Callbacks
Another opportunity to use cookies is with callbacks. By using the rpc_gss_set_callback() function, a server can specify a user-defined callback so that it knows when a context first gets used. The callback is invoked the first time a context is used for data exchanges, after the context is established for the specified program and version.
The user-defined callback routine takes the following form:
bool_t callback (struct svc_req *req, gss_cred_id_t deleg, gss_ctx_id_t gss_context rpc_gss_lock_t * lock void ** cookie); |
The second and third arguments, deleg and gss_context, are GSS-API data types and are currently exposed. See the GSS-API Programming Guide for more information. Note that deleg is the identity of any delegated peer, while gss_context is a pointer to the GSS-API context. This pointer is necessary in case the program needs to perform GSS-API operations on the context, that is, to test for acceptance criteria. You have already seen the cookie argument.
The lock argument is a pointer to a rpc_gss_lock_t structure:
typedef struct { bool_t locked; rpc_gss_rawcred_t *raw_cred; } rpc_gss_lock_t; |
This parameter enables a server to enforce a particular QOP and service for the session. QOP and service are found in the rpc_gss_rawcred_t structure described in Example 5-14. A server should not change the values for service and QOP. When the user-defined callback is invoked, the locked field is set to FALSE. If the server sets locked to TRUE, only requests with QOP and service values that match the QOP and service values in the rpc_gss_rawcred_t structure are accepted.
For more information, see the rpc_gss_set_callback(3NSL) man page.
Maximum Data Size
Two functions, rpc_gss_max_data_length() on the client side, and rpc_gss_svc_max_data_length() on the server side, are useful in determining how large a piece of data can be before it is transformed by security measures and sent "over the wire." A security transformation such as encryption usually changes the size of a piece of transmitted data, most often enlarging it. To make sure that data won't be enlarged past a usable size, these two functions return the maximum pre-transformation size for a given transport.
For more information, see the rpc_gss_max_data_length(3NSL) man page.
Miscellaneous Functions
You can use several functions for getting information about the installed security system.
rpc_gss_get_mechanisms(3NSL)() returns a list of installed security mechanisms.
rpc_gss_is_installed(3NSL)() checks if a specified mechanism is installed.
rpc_gss_get_mech_info(3NSL)() returns valid QOPs for a given mechanism.
Using these functions gives the programmer latitude in avoiding hard-coding security parameters in applications. (See Table 5-2 and the rpcsec_gss(3NSL) man page for a list of all RPCSEC_GSS functions.)
Associated Files
RPCSEC_GSS makes use of certain files to store information.
gsscred Table
When a server retrieves the client credentials associated with a request, the server can get either the client's principal name in the form of a rpc_gss_principal_t structure pointer or local UNIX credentials (UID) for that client. Services such as NFS require a local UNIX credential for access checking, but others might not. Those services can, for example, store the principal name directly in their own access control lists as a rpc_gss_principal_t structure.
Note - The correspondence between a client's network credential (its principal name) and any local UNIX credential is not automatic. The local security administrator must be set up explicitly.
The gsscred file contains both the client's UNIX and network (for example, Kerberos V5) credentials. The network credential is the Hex-ASCII representation of the rpc_gss_principal_t structure. The gsscred file is accessed through XFN. Thus, this table can be implemented over files, NIS, or NIS+, or any future name service supported by XFN. In the XFN hierarchy, this table appears as this_org_unit/service/gsscred. Administrators can maintain the gsscred table with the use of the gsscred utility, which enables adding and deleting of users and mechanisms.
/etc/gss/qop and /etc/gss/mech
For convenience, RPCSEC_GSS uses string literals for representing mechanisms and quality of protection (QOP) parameters. The underlying mechanisms themselves, however, require mechanisms to be represented as object identifiers and QOPs as 32-bit integers. Additionally, for each mechanism, you need to specify the shared library that implements the services for that mechanism.
The /etc/gss/mech file stores the following information on all installed mechanisms on a system: the mechanism name, in ASCII; the mechanism's OID; the shared library implementing the services provided by this mechanism; and, optionally, the kernel module implementing the service. A sample line might look like this:
kerberos_v5 1.2.840.113554.1.2.2 gl/mech_krb5.so gl_kmech_krb5 |
For all mechanisms installed, the /etc/gss/qop file stores all the QOPs supported by each mechanism, both as an ASCII string and as its corresponding 32-bit integer.
Both /etc/gss/mech and /etc/gss/qop are created when security mechanisms are first installed on a given system.
Many of the in-kernel RPC routines use non-string values to represent mechanism and QOP. Therefore, applications can use the rpc_gss_mech_to_oid() and rpc_gss_qop_to_num() functions to get the non-string equivalents for these parameters, should they need to maximize use of those in-kernel routines.
Using Port Monitors
RPC servers can be started by port monitors such as inetd and listen. Port monitors listen for requests and spawn servers in response. The forked server process is passed the file descriptor 0 on which the request has been accepted. For inetd, when the server is done, it can exit immediately or wait a given interval for another service request. See also Appendix F, Writing a Port Monitor With the Service Access Facility (SAF).
For listen, servers should exit immediately after replying because listen() always spawns a new process. The following function call creates a SVCXPRT handle to be used by the services started by port monitors.
transp = svc_tli_create(0, nconf, (struct t_bind *)NULL, 0, 0) |
nconf is the netconfig structure of the transport from which the request is received.
Because the port monitors have already registered the service with rpcbind, the service does not need to register with rpcbind. The service must call svc_reg() to register the service procedure.
svc_reg(transp, PROGNUM, VERSNUM, dispatch,(struct netconfig *)NULL) |
The netconfig structure is NULL to prevent svc_reg() from registering the service with rpcbind.
For connection-oriented transports, the following routine provides a lower level interface:
transp = svc_fd_create(0, recvsize, sendsize); |
A 0 file descriptor is the first argument. You can set the value of recvsize and sendsize to any appropriate buffer size. A 0 for either argument causes a system default size to be chosen. Application servers that do not do any listening of their own use svc_fd_create().
Using inetd
Entries in /etc/inet/inetd.conf have different formats for socket-based, TLI-based, and RPC services. The format of inetd.conf entries for RPC services follows.
Service | Description |
---|---|
rpc_prog/vers | The name of an RPC program followed by a / and the version number or a range of version numbers. |
endpoint_type | One of dgram (for connectionless sockets), stream (for connection mode sockets), or tli (for TLI endpoints). |
proto | May be * (for all supported transports), a net type, a net ID, or a comma separated list of net type and net ID. |
flags | Either wait or nowait. |
user | Must exist in the effective passwd database. |
pathname | Full path name of the server daemon. |
args | Arguments to be passed to the daemon on invocation. |
For example:
rquotad/1 tli rpc/udp wait root /usr/lib/nfs/rquotad rquotad |
For more information, see the inetd.conf(4) man page.
Using the Listener
Use pmadm to add RPC services:
pmadm -a -p pm_tag -s svctag -i id -v vers \ -m `nlsadmin -c command -D -R prog:vers` |
The arguments are:
The command is given root permissions, installed in version 4 of the listener database file, and is made available over TCP transports. Because of the complexity of the arguments and options to pmadm, use a command script or the menu system to add RPC services. To use the menu system, type sysadm ports and choose the -port_services option.
After adding a service, the listener must be re-initialized before the service is available. To do this, stop and restart the listener, as follows. rpcbind must be running.
# sacadm -k -p pmtag # sacadm -s -p pmtag |
For more information, such as how to set up the listener process, see the listen(1M), pmadm(1M), and sacadm(1M) man pages. Also see "How the TCP/IP Protocols Handle Data Communications" in System Administration Guide: IP Services.