[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

Communications Programming Concepts

RPC Authentication

The caller may not want to identify itself to the server, and the server may not require an ID from the caller. However, some network services, such as the Network File System (NFS), require stronger security. Remote Procedure Call (RPC) authentication provides a certain degree of security.

The following are part of RPC authentication:

RPC deals only with authentication and not with access control of individual services. Each service must implement its own access control policy and reflect this policy as return statuses in its protocol. The programmer can build additional security and access controls on top of the message authentication.

The authentication subsystem of the RPC package is open-ended. Different forms of authentication can be associated with RPC clients. That is, multiple types of authentication are easily supported at one time. Examples of authentication types include UNIX, DES, and NULL. The default authentication type is none (AUTH_NULL).

RPC Authentication Protocol

The RPC protocol provisions for authentication of the caller to the server, and vice versa, are provided as part of the RPC protocol. Every remote procedure call is authenticated by the RPC package on the server. Similarly, the RPC client package generates and sends authentication parameters. The call message has two authentication fields: credentials and verifier. The reply message has one authentication field: response verifier.

The following RPC protocol specification defines as an opaque data type the credentials of the call message and the verifiers of both the call and reply messages:

enum auth_flavor {
     AUTH_NULL    = 0,
     AUTH_UNIX    = 1,
     AUTH_SHORT   = 2,
     AUTH_DES     = 3
     /* and more to be defined */
struct opaque_auth {
     auth_flavor flavor;
     opaque body<400>;

Any opaque_auth structure is an auth_flavor enumeration followed by bytes that are opaque to the RPC protocol implementation. The interpretation and semantics of the data contained within the authentication fields are specified by individual, independent authentication protocol specifications.

If authentication parameters are rejected, response messages state the reasons. A server can support multiple types of authentication at one time.

NULL Authentication

Sometimes, the RPC caller does not know its own identity or the server does not need to know the caller's identity. In these cases, the AUTH_NULL authentication type can be used in both the call message and response messages. The bytes of the opaque_auth body are undefined. The opaque length should be 0.

UNIX Authentication

A process calling a remote procedure might need to identify itself as it is identified on the UNIX system. The value of the credential's discriminant of an RPC call message is AUTH_UNIX. The bytes of the credential's opaque body encode the following structure:

struct auth_unix {
     unsigned     stamp;
     string       machinename;
     unsigned     uid;
     unsigned     gid;
     unsigned     gids;

The parameters in the structure are defined as follows:

stamp Specifies the arbitrary ID generated by the caller's workstation.
machinename Specifies the name of the caller's workstation. The name must not exceed 255 bytes in length.
uid Specifies the caller's effective user ID.
gid Specifies the caller's effective group ID.
gids Specifies the counted array of group IDs that contain the caller as a member. A maximum of 10 groups is allowed.

The verifier accompanying the credentials should be AUTH_NULL.

The value of the discriminant in the response verifier of the reply message from the server is either AUTH_NULL or AUTH_SHORT. If the value is AUTH_SHORT, the bytes of the response verifier's string encode an opaque structure. The new opaque structure can then be passed to the server in place of the original AUTH_UNIX credentials. The server maintains a cache that maps shorthand opaque structures (passed back by way of an AUTH_SHORT-style response verifier) to the original credentials of the caller. The caller saves network bandwidth and server CPU time when the shorthand credentials are used.

Note: The server can eliminate, or flush, the shorthand opaque structures at any time. If this happens, the RPC message will be rejected due to an AUTH_REJECTEDCRED authentication error. The original AUTH_UNIX credentials can be used when this happens.

UNIX Authentication on the Client Side

When a caller creates a new RPC client handle, the authentication handle of the appropriate transport is set to the default by the authnone_create subroutine. The default for an RPC authentication handle is NULL. After creating the client handle, the client can select UNIX authentication with the authunix_create routine. This routine creates an authentication handle with operating system permissions and causes each remote procedure call associated with the handle to carry UNIX credentials.

Note: Authentication information can be destroyed with the auth_destroy subroutine. Authentication information should be destroyed if one is attempting to conserve memory.

For more information, see the Using UNIX Authentication Example.

UNIX Authentication on the Server Side

Dealing with authentication issues on the server side is more difficult than dealing with them on the client side. The caller's RPC package passes the service dispatch routine a request that has an arbitrary authentication style associated with it. The server must then determine which style of authentication the caller used and whether the style is supported by the RPC package.

If the authentication parameter type is not suitable for the calling service, the service dispatch routine calls the svcerr_weakauth routine to refuse the remote procedure call. It is not customary for the server to check the authentication parameters associated with procedure 0 (NULLPROC).

If the service does not have the requested protocol, the service dispatch returns a status for access denied. The svcerr_systemerr primitive is called to detect a system error that is not covered by a service protocol.

Data Encryption Standard (DES) Authentication

DES authentication offers more security features than UNIX authentication. For DES authentication to work, the keyserv daemon must be running on both the server and client machines. The users at these workstations need public keys assigned in the public key database by the person administering the network. Additionally, each user's secret key must be decrypted using their keylogin command password.

DES authentication can handle the following UNIX problems:

For more information, see the DES Authentication Example .

DES Authentication Naming Scheme

DES addresses the caller with a simple string of characters instead of an integer specific to a particular operating system. This string of characters is known as the caller's network name, or net name. The server is allowed to interpret the contents of the net name only to identify the caller. Therefore, net names should be unique for each caller in the network.

Each operating system is responsible for implementing DES authentication to generate unique net names for calling on remote servers. Because operating systems can already distinguish local users to their systems, extending this mechanism to the network is simple.

For example, a UNIX user at company xyz with a user ID of 515 might be assigned the following net name: unix.515@xyz.com. This net name contains three items that ensure uniqueness. First, only one naming domain in the Internet is called xyz.com. In this domain, there is only one UNIX user with user ID 515. Another user on another operating system, such as VMS, in the same naming domain can have the same user ID. However, two users are distinguished by the operating system name. In this example, one user is unix.515@xyz.com and the other is vms.515@xyz.com.

The first field is actually a naming method rather than an operating system name. Currently, a one-to-one correspondence between naming methods and operating systems exists. If a universal naming standard is agreed upon, the first field will become the name of that standard instead of an operating system name.

DES Authentication Verifiers

Unlike UNIX authentication, DES authentication has a verifier that permits the server to validate the client's credential and the client to validate the server's credential. The content of this verifier is primarily an encrypted time stamp. The time stamp is encrypted by the client and decrypted by the server. If the time stamp is close to real time, then the client encrypted it correctly. To encrypt the time stamp correctly, the client must have the conversation key of the RPC session. The client with the conversation key is the authentic client.

The conversation key is a DES key that the client generates and includes in its first remote procedure call to the server. The conversation key is encrypted using a public key scheme in the first transaction. The particular public key scheme used in DES authentication is the Diffie-Hellman system with 192-bit keys. For more information, see Diffie-Hellman Encryption .

For successful validation, both the client and the server need the same notion of current time. If network time synchronization cannot be guaranteed, the client can synchronize with the server before beginning the conversation, perhaps by consulting the Internet Time Server (TIME).

DES Authentication on the Server Side

The method for determining the validity of a client's time stamp depends on which transaction is under consideration. For the first transaction, the server checks only that the time stamp has not expired. For subsequent transactions, the server verifies that the time stamp is greater than the previous time stamp from the same client, and that the time stamp has not expired. A time stamp has expired if the server's time is later than the sum of the client's time stamp plus the client's window. The sum of the time stamp plus the client's window can be thought of as the lifetime of the credential.

DES Authentication on the Client Side

In the first transaction to the server, the client sends an encrypted item, the window verifier, that must equal the client's window minus one, as an added check. Otherwise, the client could successfully send random data instead of the time stamp. Other values for the credential are rejected by the server. If the window verifier is accepted by the server, the server returns to the client a verifier equal to the encrypted time stamp, minus one second. If the client receives a different time stamp from the server, the client rejects it.

For subsequent transactions, the client's time stamp is valid if it is greater than the previous time stamp, and has not expired. A time stamp has expired if the server's time is later than the sum of the client's time stamp plus the client's window. The sum of the time stamp plus the client window can be thought of as the lifetime of the credential.

To use DES authentication, the programmer must set the client authentication handle using the authdes_create subroutine. This subroutine requires the network name of the owner of the server process, a lifetime for the credential, the address of the host with which to synchronize, and the address of a DES encryption key to use for encrypting time stamps and data.


The server's DES authentication subsystem returns a nickname to the client in the verifier response to the first transaction. The nickname is an unsigned integer. The nickname is likely to be an index into a table on the server that stores each client's net name, decrypted DES key, and window. The client can use the nickname in all subsequent transactions instead of passing its net name, encrypted DES key, and window each time. The nickname is not required, but it saves time.

Clock Synchronization

Although the client and server clocks are originally synchronized, they can lose this synchronization. When this happens, the client RPC subsystem normally receives the RPC_AUTHERROR error message and should resynchronize.

A client can receive the RPC_AUTHERROR message even when the clocks are synchronized. The message indicates that the server's nickname table has been flushed either because of the table's size limitations or a server crash. To receive new nicknames, all clients must resend their original credentials to the server.

DES Authentication Protocol

DES authentication has the following form of eXternal Data Representation (XDR) enumeration:

enum authdes_namekind {
     ADN_FULLNAME = 0,
typedef opaque des_block[8];
const MAXNETNAMELEN = 255;

A credential is either a client's full network name or its nickname. For the first transaction with the server, the client must use its full name. For subsequent transactions, the client can use its nickname. DES authentication protocol includes a 64-bit block of encrypted DES data and specifies the maximum length of a network user's name.

The authdes_cred union provides a switch between the full-name and nickname forms, as follows:

union authdes_cred switch (authdes_namekind adc_namekind) {
     case ADN_FULLNAME:
          authdes_fullname adc_fullname;
     case ADN_NICKNAME:
          unsigned int adc_nickname;

The full name contains the network name of the client, an encrypted conversation key, and the window. The window is actually a lifetime for the credential. The server can terminate a client's time stamp and not grant the request if the time indicated by the verifier time stamp plus the window has expired. In the first transaction, the server confirms that the window verifier is one second less than the window. To ensure that requests are granted only once, the server can require time stamps in subsequent requests to be greater than the client's previous time stamps.

The structure for a credential using the client's full network name follows:

struct authdes_fullname {
    string name<MAXNETNAMELEN>; /* name of client              */
    des_block key;              /*PK encrypted conversation key*/
    unsigned int window;        /* encrypted window            */

A time stamp encodes the time since midnight, January 1, 1970. The structure for the time stamp follows:

struct timestamp {
     unsigned int seconds;      /* seconds           */
     unsigned int useconds;     /* and microseconds  */

The client verifier has the following structure:

struct {
     adv_timestamp;           /* one DES block          */
     adc_fullname.window;     /* one half DES block     */
     adv_winverf;             /* one half DES block     */

The window verifier is only used in the first transaction. In conjunction with the fullname credential, these items are packed into the structure shown previously before being encrypted.

This structure is encrypted using CBC mode encryption with an input vector of 0. All other time stamp encryptions use ECB mode encryption. The client's verifier has the following structure:

struct authdes_verf_clnt {
     timestamp adv_timestamp;     /* encrypted timestamp       */
     unsigned int adv_winverf;    /* encrypted window verifier */

The server returns the client's time stamp, minus one second, in an encrypted response verifier. This verifier also sends the client an unencrypted nickname to be used in future transactions. The verifier from the server has the following structure:

struct authdes_verf_svr {
     timestamp adv_timeverf;     /* encrypted verifier      */
     unsigned int adv_nickname;  /* new nickname for client */

Diffie-Hellman Encryption

The public key scheme used in DES authentication is Diffie-Hellman with 192-bit keys. The Diffie-Hellman encryption scheme includes two constants: BASE and MODULUS. Their values for these for the DES authentication protocol are:

const BASE = 3;
const MODULUS = "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; /* hex */

Two programmers, A and B, can send encrypted messages to each other in the following manner. First, programmers A and B independently generate secret keys at random, which can be represented as SK(A) and SK(B). Both programmers then publish their public keys PK(A) and PK(B) in a public directory. These public keys are computed from the secret keys as follows:

PK(A) = ( BASE ** SK(A) ) mod MODULUS
PK(B) = ( BASE ** SK(B) ) mod MODULUS

The ** (double asterisk) notation represents exponentiation. Programmers A and B can both arrive at the common key, represented here as CK(A, B), without revealing their secret keys.

Programmer A computes:

CK(A, B) = ( PK(B) ** SK(A)) mod MODULUS

while programmer B computes:

CK(A, B) = ( PK(A) ** SK(B)) mod MODULUS

These two can be shown to be equivalent:

(PK(B) ** SK(A)) mod MODULUS = (PK(A) ** SK(B)) mod MODULUS

If the mod MODULUS parameter is omitted, modulo arithmetic can simplify things as follows:

PK(B) ** SK(A) = PK(A) ** SK(B)

Then, if the result of the previous computation on B replaces PK(B) and the previous computation of A replaces PK(A), the equation is:

((BASE ** SK(B)) ** SK(A) = (BASE ** SK(A)) ** SK(B)

This equation can be simplified as follows:

BASE ** (SK(A) * SK(B)) = BASE ** (SK(A) * SK(B))

This produces a common key CK(A, B). This common key is not used directly to encrypt the time stamps used in the protocol. Instead, it is used to encrypt a conversation key that is then used to encrypt the time stamps. In this way, the common key is used as little as possible to prevent it from being broken. Breaking the conversation key usually has less serious consequences because conversations are relatively shortlived.

The conversation key is encrypted using 56-bit DES keys, while the common key is 192 bits. To reduce the number of bits, 56 bits are selected from the common key as follows. The middle eight bytes are selected from the common key and parity is added to the lower order bit of each byte, producing a 56-bit key with eight bits of parity.

[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]