Secure NFS

In addition to the standard UNIX authentication system, the Network Information Service (NIS) and the Network File System (NFS) provide a means to authenticate users and machines in networks on a message-by-message basis. This additional authentication system uses Data Encryption Standard (DES) encryption and public key cryptography.

Secrecy

Throughout history, various groups of people have sought to communicate in such a way that only the sender and receiver know the contents of a given message. To achieve this secrecy, senders and receivers use a cipher, a scheme for converting a plaintext message into ciphertext and back again. Encryption is the process of converting plain text into cipher text, and decryption is the process of converting cipher text into plain text.

One of the earliest ciphers, the Caesar cipher, is attributed to Julius Caesar. In this cipher, one letter is substituted for another. For example, 'A' becomes 'C', 'B' becomes 'D', ..., 'Y' becomes 'A', and 'Z' becomes 'B'. So, the Caesar cipher encrypts the phrase ATTACK AT DAWN as CVVCEM CV FCYP.

If the Carthaginians could cryptanalyze the Caesar cipher and break it, the Roman cryptographers would have to invent an entirely new cipher. Since cipher development is an expensive process, the Romans might use a cipher key in order to get more use out of their cipher. For example, instead of specifying a letter-for-letter substitute, the Romans might specify a key K, where K indicates the number of positions to shift a letter. That is, if K = 2, then 'A' becomes 'C'. If K = 4, then 'A' becomes 'E', and so on. With this scheme, if the Carthaginians break the cipher, all the Romans must do is change the key. Of course, the Carthaginians might realize what algorithm the Italians were using, and exhaustively try every value of K from 1 to 26. If the Carthaginians had a computer, their task would be a trivial programming exercise.

Data Encryption Standard

Modern ciphers are designed to address the fact that computers can be powerful tools for an intruder attempting to break a cipher. In 1977, the U.S. government adopted a cipher as its Data Encryption Standard. This cipher is widely used in industry. DES is a highly complex algorithm which converts 64-bit blocks of plain text into 64-bit blocks of cipher text using a 56-bit key. Because of the complexity of the algorithm and the size of the cipher key, DES is essentially unbreakable. For example, if an intruder had a computer which could compute the DES algorithm at a rate of one key per microsecond, the computer would need over two thousand years to try every possible key.

Public Key Cryptography

A significant weakness in any encryption algorithm is the key used. If the sender and receiver are to communicate securely using a cipher, both the sender and receiver must know the key. They must agree upon a key either using a separate communications link, which itself must be secure, or in person.

To address this problem, two researchers (Diffie and Hellman) developed a technique by which the sender and receiver can exchange keys publicly without compromising the security of their communication. Their technique has three requirements:

Decipher( Encipher( plaintext, E ), D ) = plaintext

where E is the encryption key (known to the public), and D is the decryption key (known only by the receiver).

That is, Encipher and Decipher functions are inverses of each other. Therefore, if you take the encrypted text string returned by Encipher( plaintext, E), and use it along with the key D for the Decipher function, Decipher will return the original plain text.

An intruder cannot deduce Decipher() from Encipher().

Encipher() is unbreakable.

The following outline describes how a sender sends a secret message to a receiver.

The sender obtains the receiver's public encryption key.

The sender converts the plain text message into cipher text by computing the result:

ciphertext = Encipher( plaintext, E )

The sender sends the cipher text message to the receiver.

The receiver receives the cipher text message and converts it into plaintext by computing the result:

plaintext = Decipher( ciphertext, D )

Even if an intruder intercepts the message, the intruder will not be able to decipher it because the intruder does not have the receiver's decipher key. (For that matter, the sender cannot decipher the cipher text message either.)

Authentication

A primary application of secrecy is authentication. One common method of authentication (which is the standard UNIX method of authentication) uses a password. In other words, when a user wants to login, the operating system requires the user to provide a password known only by the operating system and the user. If the user provides the correct password, the operating system concludes that the user is who the user claims to be. Note that this method requires the operating system to store the user's password in a file on the system, although in encrypted form. This means that two different entities know a single password.

Public key cryptography provides an alternative to password authentication. Suppose a sender wants to send a message, and the receiver wants to be certain that the message is from the sender and not from an intruder pretending to be the sender. The authentication process will occur in the following manner:

First the sender enciphers a "request to send" message using the receiver's public key, and then sends the request.

The receiver receives the "request to send" message and deciphers it using the receiver's private key.

The receiver enciphers a "token" message using the sender's public key, and then sends the token.

The sender receives the token and deciphers it with the sender's private key. Now, when the sender sends messages to the receiver, the sender will begin each message with the token, signifying that the sender is, in fact, the sender. If an intruder attempts to send messages in the name of the sender, the receiver will reject them because the intruder does not know what the token is.

Note that, unlike password authentication, the receiver is able to authenticate the sender without knowing the sender's private key. For more information on authentication systems, see "Understanding RPC Authentication" in AIX Version 4.3 Communications Programming Concepts.

Secrecy in NFS and NIS

NFS and NIS use the DES algorithm for two purposes. First, NIS uses DES to encrypt private fields in NIS maps, such as the publickey NIS map. Second, NFS uses DES to encrypt a time stamp in the Remote Procedure Call (RPC) messages sent between NFS servers and clients. This encrypted time stamp authenticates machines just as the "token" authenticates the sender, as described in "Authentication".

Because NFS and NIS can authenticate every single RPC message exchanged between NFS clients and servers, this provides an additional, optional, level of security for each file system. By default, file systems are exported with the standard UNIX authentication. To take advantage of this additional level of security, you can specify the secure option when you export a file system.

Public Key Cryptography for Secure NFS

Both the user's public and the secret keys are stored and indexed by net name in the publickey.byname NIS map. The secret key is DES-encrypted with the user's login password. The keylogin command uses the encrypted secret key, decrypts it with the login password, then gives it to a secure local key server to save for use in future RPC transactions. Users are not aware of their public and secret keys because the yppasswd command, in addition to changing the login password, generates the public and secret keys automatically.

The keyserv daemon is an RPC service that runs on each NIS machine and executes the following three public key subroutines:

The key_setsecret subroutine tells the key server to store the user's secret key (SKA) for future use; it is normally called by the keylogin command. The client program calls the key_encryptsession subroutine to generate the encrypted conversation key, which is passed in the first RPC transaction to a server. The key server looks up the server public key and combines it with the client secret key (set up by a previous key_setsecret subroutine) to generate the common key. The server asks the key server to decrypt the conversation key by calling the key_decryptsession subroutine.

Implicit in these subroutine calls is the name of the caller, which must be authenticated in some manner. The key server cannot use DES authentication to do this, since it would create a deadlock. The key server solves this problem by storing the secret keys by the user ID (UID) and only granting requests to local root processes. The client process then executes a root user owned setuid subroutine which makes the request on the part of the client, telling the key server the real UID of the client.

Authentication Requirements

Secure NFS authentication is based on the ability of a sender to encrypt the current time, which the receiver can then decrypt and check against its own clock. This process has two requirements:

The two agents must agree on the current time.

The sender and receiver must be using the same DES encryption key.

Agreeing on the Current Time

If the network uses time synchronization, then the timed daemon will keep the client and server clocks in sync. If not, the client will compute the proper time stamps based on the server's clock. To do this, the client determines the server time before starting the RPC session, and then computes the time difference between its own clock and that of the server's. The client then adjusts its time stamp accordingly. If, during the course of an RPC session, the client and server clocks get out of sync to the point where the server begins rejecting the client's requests, the client will redetermine the server time.

Using the Same DES Key

The client and server compute the same DES encryption key by using public key cryptography. For any client A and server B, there is a key that only A and B can deduce. This key is called the common key. The client derives the common key by computing the following formula:

where K stands for the common Key, PK stands for Public Key, and SK stands for Secret Key, and each of these keys is a 128-bit number. The server derives the same common key by computing the following formula:

Only the server and client can calculate this common key since doing so requires knowing one secret key or the other. Because the common key has 128 bits, and DES uses a 56-bit key, the client and server extract 56 bits from the common key to form the DES key.

Authentication Process

When a client wants to talk to a server, it randomly generates a key used for encrypting the time stamps. This key is known as the conversation key (CK). The client encrypts the conversation key using the DES common key (described in "Authentication Requirements") and sends it to the server in the first RPC transaction. This process is shown in the Authentication Process illustration.

This figure shows client A connecting to server B. The term K(CK) means CK is encrypted with the DES common key K. In its first request, the client's RPC credential contains the client name (A), the conversation key (CK), and the variable called win (window) encrypted with CK. (The default window size is 30 minutes.) The client's verifier in the first request contains the encrypted time stamp and an encrypted verifier of the specified window, win + 1. The window verifier makes guessing the right credential much more difficult, and increases security.

After authenticating the client, the server stores the following items in a credential table:

Client name, A

Conversation key, CK

Window

Time stamp

The server only accepts time stamps that are chronologically greater than the last one seen, so any replayed transactions are guaranteed to be rejected. The server returns to the client in the verifier an index ID into the credential table, plus the client's time stamp minus one, encrypted by CK. The client knows that only the server could have sent such a verifier, since only the server knows what time stamp the client sent. The reason for subtracting one from the time stamp is to ensure that it is not valid and cannot be reused as a client verifier. After the first RPC transaction, the client sends just its ID and an encrypted time stamp to the server, and the server sends back the client's time stamp minus one, encrypted by CK.

Naming Network Entities for DES Authentication

DES authentication does its naming by using net names. A net name is a string of printable characters to authenticate. The public and secret keys are stored on a per-net-name rather than a per-user-name basis. The netid.byname NIS map maps the net name into a local UID and group-access list.

User names are unique within each domain. Net names are assigned by concatenating the operating system and user ID with the NIS and Internet domain names. A good convention for naming domains is to append the Internet domain name (com, edu, gov, mil) to the local domain name.

Network names are assigned to machines as well as to users. A net name of a machine is formed much like that of a user. For example, a machine named hal in the eng.ibm.com domain has the net name unix.hal@eng.ibm.com. Proper authentication of machines is important for diskless machines that need full access to their home directories over the network.

To authenticate users from any remote domain, you should make entries for them in two NIS databases. One is an entry for their public and secret keys; the other is for their local UID and group-access list mapping. Users in the remote domain can then access all of the local network services, such as the NFS and remote logins.

/etc/publickey File

The /etc/publickey file contains names and public keys, which NIS uses to create the publickey map. The publickey map is used for secure networking. Each entry in the file consists of a network user name (which may refer to either a user or a host name), followed by the user's public key (in hexadecimal notation), a colon, and the user's encrypted secret key (also in hexadecimal notation). By default, the only user in the /etc/publickey file is the user nobody.

Do not use a text editor to alter the /etc/publickey file because the file contains encryption keys. To alter the /etc/publickey file, use either the chkey or newkey commands.

Booting Considerations of Public Key Systems

When restarting a machine after a power failure, all of the stored secret keys are lost, and no process can access secure network services, such as mounting an NFS. Root processes could continue if there were someone to enter the password that decrypts the root user's secret key. The solution is to store the root user's decrypted secret key in a file that the key server can read.

Not all setuid subroutine calls operate as they should. For example, if a setuid subroutine is called by owner dave, who has not logged into the machine since it booted, the subroutine cannot access any secure network services as dave. However, most setuid subroutine calls are owned by the root user, and the root user's secret key is always stored at startup time.

Performance Considerations

Secure NFS affects system performance in two ways. First, both the client and server must compute the common key. The time it takes to compute the common key is about 1 second. As a result, it takes about 2 seconds to establish the initial RPC connection, since both client and server have to perform this operation. After the initial RPC connection, the key server caches the results of previous computations, and so it does not have to recompute the common key every time.

Second, each RPC transaction requires four DES encryption operations:

The client encrypts the request time stamp,

The server decrypts it,

The server encrypts the reply time stamp,

And finally, the client decrypts it.

Since system performance is reduced by secure NFS, you will have to weigh the benefits of increased security and your system's performance requirements.

Administering Secure NFS Checklist

The following is a checklist of items to help ensure that secure NFS operates properly:

When mounting a file system with the -secure option on a client, the server name must match the server host name in the /etc/hosts file. If a name server is being used for host name resolution, make sure the host information returned by the name server matches the entry in the /etc/hosts file. Authentication errors will result if these data do not match, because the net names for machines are based on the primary entries in the /etc/hosts file and keys in the publickey map are accessed by net name.

Do not mix secure and nonsecure exports and mounts. Otherwise, file access may be determined incorrectly. For example, if a client machine mounts a secure file system without the secure option or mounts an nonsecure system with the secure option, users have access as nobody, rather than as themselves. This condition also occurs if a user unknown to NIS attempts to create or modify files on a secure file system.

Because NIS must propagate a new map after each use of the chkey and newkey commands, only use these commands when the network is lightly loaded.

Do not delete the /etc/keystore file or the /etc/.rootkey file. If you reinstall, move, or upgrade a machine, save the /etc/keystore and /etc/.rootkey files.

Instruct your users to use the yppasswd command rather than the passwd command to change passwords. Doing so will keep passwords and private keys synchronized.

Because the login command does not retrieve keys out of the publickey map for the keyserv daemon, the user must execute the keylogin command. You may want to place the keylogin command in each user's profile file to execute the command automatically during login. Note that the keylogin command requires the user to enter his or her password again.

When you generate keys for the root user at each host with either the newkey -h or chkey command, you must execute the keylogin command to pass the new keys to the keyserv daemon. The keys are stored in the /etc/.rootkey file, which is read by the keyserv daemon each time the daemon is started.

Periodically verify that the yppasswdd and ypupdated daemons are running on the NIS master server. These daemons are necessary for maintaining the publickey map.

Periodically verify that that the keyserv daemon is running on all machines using secure NFS.

Configuring Secure NFS

To configure secure NFS on NIS master and slave servers, use the Web-based System Manager Network application or use the following procedure:

On the NIS master server, create an entry for each user in the NIS /etc/publickey file using the newkey command. This command has two options. For a regular user, enter:

smit newkey

OR

newkey -u username

For a root user on a host machine, enter:

newkey -h hostname

Alternatively, users can establish their own public keys using the chkey or newkey commands.

Create the NIS publickey map by following the instructions in "Changing an NIS Map". The corresponding NIS publickey.byname map should reside only on the NIS servers.

Exporting a File System Using Secure NFS

You can export a secure NFS using the Web-based System Manager Network application or by using one of the following procedures.

To export a secure NFS file system using SMIT:

Verify that NFS is already be running by executing the command lssrc -g nfs. The output should indicate that the nfsd and the rpc.mountd daemons are active. If they are not, start NFS using the instructions in "Starting the NFS Daemons".

Verify that the publickey map exists and that the keyserv daemon is running. See "Configuring Secure NFS" for more information.

Execute the smitmknfsexp fast path.

Specify the appropriate values for the PATHNAME of directory to export, MODE to export directory, and EXPORT directory now, system restart or both fields. Specify yes for the Use SECURE option field.

Specify any other optional characteristics you wish, or simply accept the default values by leaving the remaining fields as they are.

Exit SMIT. If the /etc/exports file does not exist, then it will be created.

Repeat steps 3 through 6 for each directory you wish to export.

To export a secure NFS file system using a text editor:

Open the /etc/exports file with your favorite text editor.

Create an entry for each directory to be exported, using the full path name of the directory. List each directory to be exported starting in the left margin. No directory should include any other directory that is already exported. See the /etc/exports file documentation for a description of the full syntax for entries in the /etc/exports file, including how to specify the secure option.

Save and close the /etc/exports file.

If NFS is currently running, enter:

/usr/sbin/exportfs -a

The -a option tells the exportfs command to send all information in the /etc/exports file to the kernel. If NFS is not running, start NFS using the instructions in "Start the NFS Daemons".

To export an NFS file system temporarily (that is, without changing the /etc/exports file):

Enter:

exportfs -i -o secure /dirname

where dirname is the name of the file system you want to export. The exportfs -i command specifies that the /etc/exports file is not to be checked for the specified directory, and all options are taken directly from the command line.

Mounting a File System Using Secure NFS

To mount a secure NFS directory explicitly:

Verify that the NFS server has exported the directory. Do this by executing the command:

showmount -e ServerName

where ServerName is the name of the NFS server. This command displays the names of the directories currently exported from the NFS server. If the directory you want to mount is not listed, export the directory from the server.

Establish the local mount point using the mkdir command. For NFS to complete a mount successfully, a directory that acts as the mount point (or place holder) of an NFS mount must be present. This directory should be empty. This mount point can be created like any other directory, and no special attributes are needed for this directory.

Verify that the publickey map exists and that the keyserv daemon is running. See "Configuring Secure NFS" for more information.

Enter:

mount -o secure ServerName:/remote/directory/local/directory

where ServerName is the name of the NFS server, /remote/directory is the directory on the NFS server you want to mount, and /local/directory is the mount point on the NFS client.