University of Illinois at Chicago

Strong Distributed Authentication Architecture for UNIX

by

Ashwin Ganti

A PROJECT SUBMITTED IN PARTIAL FULFILLMENT OF THE REQUIREMENTS FOR THE DEGREE

MASTER OF SCIENCE in SCIENCE

Approved, MASTERS PROJECT COMMITTEE

Jon Solworth, Adviser Associate Professor of Computer Science

V.N. Venkatakrishnan Assistant Professor of Computer Science

Chicago, Illinois December, 2007 This project is dedicated to my family. Acknowledgments

I would like to thank my adviser Jon Solworth for his invaluable guidance throughout the course of the research for this project and for having been most patient and supportive of me during the entire duration of my time in graduate school.

Ashwin

2 Contents

1 Introduction 7

2 Overview of the Frameworks used 9 2.1 PAM...... 10 2.2 Name Service Module ...... 11 2.3 IPSec ...... 12

3 System Design 12 3.1 Statics ...... 12 3.1.1 Modules of the system ...... 12 3.1.2 Relation between the Modules ...... 13 3.1.3 SayAnything Certificates Used ...... 13 3.1.4 Relation between certificates ...... 15 3.2 Dynamics - Logical Flow ...... 17

4 System Internals 18 4.1 pam sayAnything ...... 18 4.2 nss sayAnything ...... 18 4.2.1 getpwuid (uid t uid) ...... 19 4.2.2 getpwnam (char* name) ...... 20 4.2.3 setpwent (void) ...... 20 4.2.4 getpwent (void) ...... 20 4.2.5 endpwent (void) ...... 21 4.3 sayAnything Agent ...... 21 4.3.1 Overview ...... 22 4.3.2 Logical Flow ...... 22 4.4 Certificate Server ...... 24

3 4.4.1 Add Certificate ...... 24 4.4.2 Get Certificate ...... 24

5 System Administration 25 5.1 pam sayAnything ...... 25 5.1.1 Overview ...... 25 5.1.2 Configuration ...... 26 5.2 nss sayAnything ...... 27 5.2.1 Overview ...... 27 5.2.2 Configuration ...... 30 5.3 IPSEC ...... 30 5.3.1 Components that need to be setup ...... 31 5.3.2 Steps to setup ipsec on two test machines host1 and host2 ..... 31 5.3.3 The have a static ip ...... 32 5.3.4 Road-warrior scenario ...... 36

6 Conclusion 39

A Appendix 41 A.1 PAM...... 41 A.1.1 Framework Layer API’s ...... 41 A.2 Name Service Module ...... 42 A.2.1 NSS Module Nomenclature ...... 42 A.2.2 NSS Module Interface ...... 42 A.3 Feedback ...... 43

4 Summary

I have designed and implemented a Strong Distributed Authentication Architecture for as part of this Master’s Project. This document begins by giving an introduction to the current authentication mechanisms, the security issues faced with them and the motivation for implementing a new mechanism for distributed authentication. I then describe the design of the system, the modules that are part of it, how they are related to each other and the logical flow of the entire authentication process once a user types the name and password in the login screen. The report also covers the system internals that are specific to the implementation intended to be useful for the developers of applications that use this architecture. It finally ends with a section that intends to serve as a reference for the system administrators explaining the configuration details of the system.

5 Abstract

The Distributed Authentication Architecture described in this report is a novel way for authentication of users using Public Key Infrastructure. It uses sayAnything certifi- cates and cryptography (through IPSec) for the flow of the authentication information in the network. Host authentication is done through IPSec. The issue of a user logging into a client terminal (which may not be trusted) is considered as a context to explain the effectiveness of this authentication mechanism. As part of a login to the terminal, the user’s private key is obtained which is used to create new authentication tokens. The user is not required to type passwords for accessing every network service after the login. The authentication happens implicitly for each network service request within the system and is controlled by the kernel thus providing better security. Misuse of the authentication token that has been created at the client side by an attacker (if the client is compromised) is limited by reducing its lifetime (to the order of some hours). To prevent off-line attacks, this scheme only provides the password encrypted private-key to someone who has the password. If this assumption is violated the server might leak the encrypted private-key, but the attacker still needs to crack the password in an off-line attack. The keys are distributed as part of sayAnything certificates and are sent in the network over IPSec thereby providing confidentiality, integrity and non-repudiation (because of public key cryptography).

6 1 Introduction

Authentication is any process by which a system verifies that someone is who they claim to be. This section gives an overview of the current authentication mechanisms in UNIX. In earlier UNIX systems passwords were usually stored in the /etc/ (in a hashed form) which also keeps track of user information (such as the home directory and default shell). When a user types in a user name and password at login, a cryptographic hash of the password is generated and is compared with the existing hash in the file for that user. If the hashes match, then the system authenticates the user and the login scripts are executed. The problem with this approach is that the /etc/passwd file is world readable and anyone having access to the machine could retrieve the hashed passwords from the file. To address this vulnerability, the hashed passwords were stored in a separate file called /etc/shadow which is readable only by root. This might have solved the issue of the password hash being readable by an attacker but there were some problems that still remained:

• Applications heavily depended on these files leading to less extensible code. • This approach did not scale well to distributed systems due to the availability of data being static and lack of inherent support from the for running applications in a truly distributed way. • The password-based authentication over the network was subject to dictionary based attacks. • If a new authentication mechanism is introduced, it requires all the applications (like login, su etc.) that use the authentication information to be rewritten to support it.

In order to address these issues Pluggable Authentication Modules and Naming Services were introduced to provide more effective ways to authenticate users.

Pluggable Authentication Modules (PAM) [6] provide a generic framework enabling uniform authentication of user applications. PAM enables user applications to perform authentication without actually knowing the implementation details of the underlying authentication mechanisms. It is usually done through a password-based authentica- tion mechanism, but also supports a challenge-response interaction. An application can dynamically link a PAM module that implements a particular authentication scheme (ex: Kerberos). The advantage of PAM is that any change that occurs in the au- thentication mechanism does not require the applications to be retrofitted to support it. Naming services (NIS) store the information in central place which enables users ma- chines and applications to communicate across the network. The information can include user names, passwords, access permissions etc. Storing this information at a central place makes administration much easier.

7 When a user types in a name and password on the login screen, the appropriate PAM module configured for the specific authentication scheme performs the authentication. Information about the user like default shell and home directory can be obtained with the help of calls (like getpwnam()) to the Naming Service Module. PAM and NIS have been leveraged by many authentication infrastructures, the most popular and widely used among them being Kerberos. Kerberos [4] is a network authentication protocol that allows users communicating over an insecure network to securely prove their identity to each other. When a user logs in, the user name is sent to the authentication server along with the name of the service that user wants to access (say the remote file system needs to be mounted and the user is authenticated for the file server). The authentication server constructs a ticket containing a session key that is randomly generated and encrypts the ticket with the secret key of the server that the user is trying to connect to (file server). This ticket is sent to the client. If the user typed in the correct password then the client can decrypt the session key, present the ticket to the file server and use the shared session key for further communication. The ticket generally is provided only for a small duration. Once it expires the user needs to type in the password again to get a fresh ticket. In practice, there is a separate ticket-granting server (TGS) whose job typically is to grant tickets for other services. The first service requested by the user is now the TGS which then grants tickets for other additional services. The authentication server and the ticket granting server are together called the Key Distri- bution center (KDC). The client or the server shares a secret key known only to itself and the KDC. The drawbacks of Kerberos are:

• It uses symmetric cryptography to encrypt the tickets. This has an inherent drawback of the key distribution and the problem of trust between the parties sharing the secret key.

• Single Point of failure : The effectiveness of the authentication scheme of Kerberos is contingent on the integrity of the KDC. Since KDC is the central place where all the keys are stored, compromise of the KDC would render the entire authentication mechanism useless.

• Non Repudiation is not possible as they are no certificates being used.

The current work is an attempt to achieve stronger authentication when compared to the mechanisms existing today. Consider the issue of logging into a distributed system. The distributed system is assumed to consist of unsecured clients (perhaps physically accessible to attackers) and a secured server. The goal is to limit the trust in each. The client is the weak link. There are two issues with the most popular type of system, a password system:

8 1. protecting the password from discovery and disclosure and 2. preventing misuse of authentication tokens.

(1) means preventing weak passwords and ensuring that passwords are not leaked while (2) means that the authentication token should not be disclosed. But these two requirements conflict with one another. If the password is disclosed to the server, it can check that the password is not weak but of course this discloses the passwords to the server. Otherwise, we must rely upon the client which is easily attacked. The distributed authentication architecture presented here solves (1) by using a zero knowl- edge proof for the password and providing the user with a password encrypted private key. It solves (2) by limiting the lifetime of the authentication token as mentioned earlier. Some of the features to be noted are:

• SayAnything certificate architecture is used for the certificates, that enables arbitrary statements to be made and provides separation of statements from the actions they engender. • User information (login shell, home directory etc.) is stored in the form of sayAny- thing certificates according to who can specify the information thus providing privilege separation. • Private/Public keys are also stored in sayAnything certificates thereby providing non repudiation. • Short term keys are created on the client side which are valid only for a small amount of time which reduce the time of the misuse by an attacker if the client machine is compromised. • IPSec is used for host authentication and for secure transmission of the information on the network.

2 Overview of the Frameworks used

This section essentially gives an overview of the following tools/frameworks that have been used in order to achieve strong distributed authentication:

• Pluggable Authentication Modules (PAM) • Naming Services (NIS) • IPSec

9 2.1 PAM

The core components of the PAM framework are the authentication library API (libpam), the authentication mechanism-specific modules (the backend), connected through the Service Provider Interface (SPI). Applications write to the PAM API, while the authentication- system (sayAnything) providers write to the PAM SPI and supply the back-end modules that are independent of the application. When an application uses the PAM API, it loads the appropriate authentication modules determined by the respective configuration file for that application in /etc/pam.d/. The request is forwarded to the underlying authentication module (for example, UNIX password, Kerberos, sayAnything) to perform the specified operation. The PAM layer then returns the response from the authentication module to the application. The PAM interfaces are divided into four areas of functionality namely authentication, ac- count management, session and password management. The area of interest to us in the case of sayAnything is the authentication interfaces. The authentication interfaces of the PAM API includes the following methods:

• pam authenticate() function to perform the authentication. • pam setcred() interface to set, refresh or destroy the user credentials.

For each of the above APIs there is a corresponding authentication-specific implementation version say password based authentication, Kerberos or in our case sayAnything. The following table shows the PAM methods called by the applications, their service module equivalents which are called by libpam and the purpose:

Application Application Function PAM Function Purpose 1. login pam authenticate() pam sm authenticate() authenticate the user 2. passwd pam setcred() pam sm setcred() change user creds

Note that the names of the module equivalent methods like pam sm authenticate() are not specific for any authentication mechanism which means that every authentication scheme be it password based, Kerberos or sayAnything would have an implementation with the same interface.

• pam sm authenticate() is the service module’s equivalent of the pam authenticate() method and is internally called by libpam. • pam sm setcred() is the module’s equivalent of the pam setcred() method called by libpam.

10 pam sayAnything is the sayAnything PAM module that provides the implementation of the above two methods. The authentication of the user resulting in the retrieval of the user’s private key is done in pam sm authenticate() and the change of the authentication token (the key) is performed in the pam sm setcred() function. The details of how this is actually done can be found in Section 3. A detailed explanation of the interfaces in PAM can be found in [6].

2.2 Name Service Module

PAM enables the user’s credentials that are supplied to be used for authentication. But after the user is authenticated, it is necessary to obtain other information like the default shell and the home directory so that the user’s environment can be set up after she logs in. This non- authentication information can be obtained by using Naming Services. Applications contact the Name Service Module by making calls like getpwnam() and getpwuid() to retrieve the user information. Depending on where and how the information is stored the calls are routed to the appropriate name service module that provides the implementation for these function calls and returns the user information. Naming services store information in a central place, which enables users, machines, and applications to communicate across the network. This information can include machine names and addresses, user names, passwords etc. Without a central naming service, each machine would have to maintain its own copy of this information. Naming service information can be stored in files, maps, or database tables. By centralizing all data, administration becomes easier. The following table shows the relation between the application level function calls, the NSS module equivalents and the purpose:

App Function Database Service NSS Function Purpose 1. getpwnam() passwd sayAnything nss sayAnything getpwnam r Retrieve the user info of the user name. 2. getpwuid() passwd sayAnything nss sayAnything getpwuid r Retrieve the user info of the user uid.

nss sayAnything is the Name service module implementing the API (getpwnam(), getpwuid() etc.) to access the user password database that contains the user’s information like home directory, default shell etc. All the information is stored in the form of sayAnything certifi- cates at the certificate server. The sayAnything module basically retrieves the certificates, parses the information out of them and returns the information to the user applications.

11 2.3 IPSec

IPSec is an extension to the IP protocol which provides security to the IP and the upper-layer protocols. IPSec uses two different protocols, AH and ESP, to ensure the authentication, integrity and confidentiality of the communication. It can protect either the entire IP datagram or only the upper-layer protocols. The appropriate modes are called tunnel mode and transport mode. In tunnel mode the IP datagram is fully encapsulated by a new IP datagram using the IPsec protocol. In transport mode only the payload of the IP datagram is handled by the IPsec protocol inserting the IPsec header between the IP header and the upper-layer protocol header. To protect the integrity, hashing is used, symmetric cryptography is used for confidentiality of information. IPSec uses a protocol called the Key Exchange protocol (IKE) to solve the problem of authentication of the hosts and the exchange of symmetric keys in the setup of secure communication. All the certificates are sent over IPSec in the network thereby achieving the above properties. Moreover IPSec can be configured in a way that the certificates given by the certificate server can be given only to a trusted peer. For example the long term private key certificate might have a very selective set of hosts that it provides the key to, whereas the public key might be given to a much larger set of hosts.

3 System Design

This section describes the detailed design of the system. In the first part I shall delineate the statics of the system describing the various certificates used by the components of the system i.e. the PAM, NSS modules, the sayAnything Agent and the relationship between the certificates. Then the dynamics of the system are described including the flow of control in the system after the user types in the user name and password on the login screen.

3.1 Statics

3.1.1 Modules of the system

The list of the modules in the system are described next. Their internals are covered in the Section 4.

1. pam sayAnything - Pluggable Authentication Module

12 nss_sayAnything

login app pam_sayAnything Certificate Server

sayAnything_agent

Kernel Sec Net

Figure 1: Relation between the components of the system

2. nss sayAnything - Name Service Module

3. sayAnything agent - Agent that contains the private keys of the users

4. certificate server - doles out the certificates (private key, public key etc.)

5. kernelsec net - responsible for the actual network authentication in the kernel.

3.1.2 Relation between the Modules

Figure 1 gives an overview of how the modules are related. Explanation of the internals of each of the modules is covered in the next section.

3.1.3 SayAnything Certificates Used

1. The admin initially creates a user. In this process he creates the following certificates and signs them.

13 (a) A long-term private key certificate containing the long term private key of the user encrypted with the admin assigned password (This is generated only to bootstrap the user). (b) A long-term public key certificate containing the long term public key of the user. (c) A User Info certificate containing the login name, home directory, user ID, group ID, default shell and gecos information.

Certificate login uID gID gecos home shell privKey pubKey sign √ √ 1. lt pvt Key Cert Admin √ √ 2. lt pub Key Cert Admin √ √ √ √ √ √ 3. userInfo Cert Admin

2. The user would specify the following certificates and sign them.

(a) Long-term private key certificate containing the new long term private key of the user encrypted by the user provided new password. (b) Long-term public key certificate containing the new long term public key of the user. (c) Short-term public key certificate containing the short term public key of the user. (d) Network Certificate that is used for network service requests. It uniquely identifies a single connection and is used by the sayAnything agent. Details on how this is used in network authentication can be found in Section 4.3

Note that (a) and (b) are performed only on the first login to replace the admin signed equivalent certificates. (c) and (d) are performed every time the user logs in or whenever a network service is accessed.

Certificate login uID gID gecos home shell privKey pubKey sign √ √ 1. lt pvt Key Cert User √ √ 2. lt pub Key Cert User √ √ 3. st pub Key Cert User

Certificate user rest srcip srcport dstip dstport pubkeysrc pubkeydst sign √ √ √ √ √ √ √ √ 1. net Cert User

14 3.1.4 Relation between certificates

1. Public Key Certificates : The public key certificates are ‘chained’ together

(a) The old long-term public key certificate signed by the admin contains the old long-term public key. (b) The new long-term public key certificate created by the user contains the new long-term public key created by the user. This is signed by the old long-term private key of the user (the one provided by the admin) and is verified with the help of the old long term public key obtained above in (a). (c) The new short-term public key certificate contains the new short term public key created by the user and is signed with the help of the new long-term private key of the user and is verified with the help of the new long-term public key obtained above in (b).

2. Private Key Certificates

(a) The admin initially assigns the password for the user when the user is created. She also creates the initial long-term public private key pair for the particular user. (b) The initial (old) long-term private key certificate (specified by the admin) contains the old long-term private key of the user. It is encrypted using the admin assigned password and signed by the admin’s private key. (c) The new long-term private key certificate contains the new long term private key specified by the user which is encrypted with the help of the new password specified by the user and signed using the same long-term private key of the user. (d) The short-term private key is used by the user and is used to sign authentication tokens which would be verified by the short-term public key of the user.

3. User Info Certificate

(a) The user info certificate containing the user login details is created by the admin and signed by him. This certificate is used by the NSS module for function calls like getpwnam etc. 4. Network Request Certificate

(a) The network request certificate contains the following fields • User Aspect (refer KernelSec [3] for details) • Restriction (refer KernelSec [3] for details) • Source IP Address • Source Port Number • Destination IP Address

15 login PAM NSS cert server agent

1 user name and password

2 fetch long term priv key

3 lt priv key encrypted with the password decrypt key 4 using password

5 generate short term key pair

6 send short term pub key

7 send < uid, short term priv key >

8 get the home dir

9 get the user info certificate

create the dir and 10 mount filesystem

11 Success

Figure 2: Logical Flow of the authentication

• Destination Port Number • Source Public Key • Destination Public Key (b) The certificate is used to authenticate the user for network services. (c) The network request uniquely identifies a network connection. (d) In addition to the normal TCP 4 tuple the public keys of the source and the destination also are made part of the tuple in order to uniquely identify the every network request.

16 3.2 Dynamics - Logical Flow

Refer Figure 2 for an overview of the authentication process after the user types in the name and password in the login application.

1. User logs in using the login name and password.

2. System requests the long-term private key certificate from the server by sending the login name of the user.

3. The Certificate Server sends back the password encrypted long-term private key cer- tificate.

4. The long-term private key is decrypted using the password provided by the user.

5. If the long-term private key certificate is signed by the administrator then:

(a) User is asked to change the password by entering a new one; a new private-public long-term key pair is generated. (b) User creates the following certificates and sends them to the Certificate Server: i. New long-term private key certificate encrypted with the new password and signed with the same new long-term private key. ii. New long-term public key certificate signed with the old long term private key retrieved from the Certificate Server (c) Server verifies the certificates sent by the user in the following way: i. The new long-term public key certificate is verified using the old long-term public key. ii. The new long-term private key certificate is verified using the new long-term public key. (d) Sometime after the verification: The old long-term public key certificate and the new long-term public key certificate are replaced by a single long-term public key certificate containing the new long-term public key of the user and signed by the admin. This may be delayed since the admin private key may not be stored on-line.

6. A short-term public-private key pair is generated

7. Short-term public key certificate signed with the current long term private key.

8. The short-term public key certificate is sent to the certificate server.

9. Server verifies the short-term public key certificate using the current long-term public key.

17 10. A new agent request certificate is created that contains the user id and the short-term private key of the user and signed by the short term private key of the user.

11. The agent fetches the public key of the user from the Certificate Server and verifies the request. If the verification succeeds then all the future service requests made by the user are signed by the agent on behalf of the user using this private key.

12. All long-term private keys and the passwords are erased at the client side.

4 System Internals

Here we look at the implementation internals of each of the modules in the system.

4.1 pam sayAnything

The PAM module as mentioned earlier is responsible for the actual authentication of the user and retrieving the private key. This subsection gives some implementation details that would be useful to understand the module better, to enhance it and while writing applications to use this.

Authentication gets initiated at the pam sm authenticate method of the PAM module.

CryptoPP is used as the cryptography framework for encryption and decryption of the keys with the user’s password.

Certificates are generated and signed using the CDL parser API that generates sayAny- thing certificates.

Keys used (private and public) are 1024 bit RSA keys.

File System of the user on the remote machine is mounted once the user is authenticated. This is done with the help of curlftpfs [1] which is a user space file system based on curl and FUSE.

4.2 nss sayAnything

The NSS module simply implements the API to access the system user password database that is stored in the form of sayAnything certificates in the certificate server (the User Info certificate type). It implements the following methods :

18 1. struct passwd ∗ getpwuid (uid t uid); 2. struct passwd ∗ getpwnam (const char ∗name); 3. void setpwent (void); 4. void endpwent (void); 5. struct passwd ∗ getpwent (void);

The most important data structure here is struct passwd struct passwd { char ∗pw name; /∗ login name ∗/ uid t pw uid; /∗ user ID ∗/ gid t pw gid; /∗ group ID ∗/ char ∗pw gecos; /∗ Miscelleneous info ∗/ char ∗pw dir; /∗ Home directory ∗/ char ∗pw shell; /∗ Default shell ∗/ }

The above information is stored in the form of sayAnything certificates at the certificate server. The NSS module retrieves the appropriate certificate from the certificate server depending on the function call made, parses the certificate and returns a struct passwd datastructure for the applications. We next look into each of the methods’ implementation details. It should be noted that all the service module equivalent methods are re-entrant.

4.2.1 getpwuid (uid t uid)

This function returns a pointer to a statically-allocated structure containing information about the user whose user ID is uid. This structure may be overwritten on subsequent calls to getpwuid. A null pointer value indicates there is no user in the data base with user ID uid. The NSS module’s re-entrant function that corresponds to the above and that is called by the NSS frame work internally whenever the above function is called is : enum nss status nss sayAnything getpwuid r (uid t uid, struct passwd ∗result buf, char ∗buffer, size t buflen, int ∗errnop)

• The User Info certificate is fetched from the certificate server corresponding to the uid of the user.

• The certificate is verified whether it is signed by the admin using her public key.

19 • The certificate is parsed to retrieve the values of the passwd datastructure and the values are populated into result buf which is one of the return values for the function.

4.2.2 getpwnam (char* name)

The implementation for this function operates exactly the same way as getpwuid (uid t uid). The only difference is that the certificate is now searched by the user name passed in as the parameter instead of the uid. The module’s equivalent function is enum nss status nss sayAnything getpwuid r (const char∗ name, struct passwd ∗result buf, char ∗buffer, size t buflen, int ∗errnop)

4.2.3 setpwent (void)

This function initializes a stream which getpwent uses to read the user database. The service module’s equivalent method for this is enum nss status nss sayAnything setpwent (void)

The stream in the case of the is actually a file which contains the latest uid of the user whose information has been read by the getpwent() method.

• A file is created in /tmp with the name containing the pid of the process so that the file created is unique and that no conflicts arise.

• The value of -1 is written to the file to initialize the stream so that the first call for getpwent() actually fetches the next user’s record i.e. of uid zero.

4.2.4 getpwent (void)

The getpwent() function reads the next entry from the stream initialized by setpwent. It returns a pointer to the entry. The structure is statically allocated and is rewritten on subsequent calls to getpwent. The contents of the structure must be copied if the information is to be saved. A null pointer is returned when no more entries are available. The sayAnything module’s internal function that gets called is

20 enum nss status nss sayAnything getpwent r (struct passwd ∗result buf, char ∗buffer, size t buflen, int ∗errnop)

• The file that has been earlier created by the setpwent() function is opened and locked. File locking semantics ensure that the module’s equivalent of the getpwent() function is re-entrant.

• The value of the uid is read from the file

• A request for the next uid’s (in the stream) information is made to the certificate server.

• The server returns the User Info certificate of the next user in the stream after the current uid stored in the file.

• The certificate is verified to be signed by the admin by using the public key.

• The values of the user information like the default shell etc. are parsed from the certificate and the result buf parameter is populated with the values.

• Before returning the file is overwritten with the uid of the user whose information is currently read. This ensures that that the next call to getpwent() will return the next user’s information in line in the stream at the server side.

• Once the uid is written to the file it is unlocked and closed.

4.2.5 endpwent (void)

This function closes the internal stream used by getpwent(). It deletes the temporary file (if it exists) created by the setpwent() method thereby clearing out the state. void endpwent (void)

4.3 sayAnything Agent

The sayAnything agent similar to the ssh agent [7] is a trusted process holding the private keys of all the users in the system. It signs the certificates on behalf of the users.

21 4.3.1 Overview

The agent is consulted by three entities in the system namely the user processes, the kernel and peer sayAnything agents.

1. It listens on a netlink socket for certificate requests from kernelSec

2. It listens on a normal UDP socket for requests from the users to add the per user

3. It also listens to requests from peer sayAnything agents in order to verify the certificates that are sent to it.

The certificate used here is of the Network Request type the structure of which has been explained in Section 2.1

4.3.2 Logical Flow

The agent comes into the fore only after the user has successfully logged into the system and the short-term private key has been created. Once the private key is created the pair is added to the agent so that it can sign certificates on behalf of the user. Figure 3 shows the flow of control that contains when the user tries to connect to a network service. An explanation of the steps follows:

1. The user application makes a connect() system call specifying the location of the net- work server (say an FTP server, mail server etc.)

2. KernelSecNet intercepts the system call.

3. It sends the following parameters to the sayAnythingAgent asking it to create a Net- work Request certificate containing them. It uses the netlink socket interface provided by the agent for communication with the kernel.

• User aspect • restriction • Source IP Address • Destination IP address • Source Port Number

22 application server

3 network certificate 1 connect() local agent remote agent 1 accept() 4 Ok

cert 2 params 5 Ok

6 SYN Kernel Sec Net Kernel Sec Net

7 SYN ACK

Figure 3: Network Authentication

• Destination Port Number

4. The agent on receiving the parameters does the following :

(a) It creates a network request certificate containing the parameters given to it by the kernel and signs it using the private key of the user. (b) It sends this certificate to the remote peer sayAnything agent that is running on the server. (c) The remote agent verifies the certificate using the user’s public key and replies back whether the user is allowed to access the service or not (d) Once the local agent receives the response as Ok from the peer agent it sends this result to KernelSecNet

5. If the kernel receives success from the agent it continues the intercepted connect() system and sends across the TCP SYN packet to the server.

6. The server by now already knows that the user is authenticated and it unblocks from the accept system call and forks a new process for the user if it is the first request from the user or hands it over to the already running user process at the server side. Details on how kernel sec net does this can be found in [2]

23 4.4 Certificate Server

The certificate server is responsible for storing all the certificates used in the system. It stores the following types of certificates :

1. Long-Term Private Key Certificate

2. Long-Term Public Key Certificate

3. Short-Term Public Key Certificate

4. User Info Certificate

The main job of the certificate server is to dole out the certificates to the clients. IPSec can be used here to decide as to what clients can get the private key certificates and who all can get the public key certificates. Currently it exposes two functionalities :

1. Add Certificate : Add/replace a certificate of a specific certificate type

2. Get Certificate : Fetch a certificate of a specific certificate type.

4.4.1 Add Certificate

The following actions are taken:

• The certificate is verified with the current public key of the user

• If the certificate is successfully verified then it is placed in the appropriate location depending on the certificate type. The certificate might be replaced in this process of addition.

• If the certificate is successfully added then the server returns success to the client that has sent in this request else failure is returned.

4.4.2 Get Certificate

The following actions are taken:

• If the certificate being requested is a User Info certificate as part of the getpwent() call on the client side then the next certificate that is stored in the sequence after the uid requested is returned to the client.

24 • For other certificate types the certificate is simply returned to the client depending on the type.

• As in the former case success or failure is returned to the client.

5 System Administration

The system administration details are described in this section for the PAM module, NSS module, the agent, certificate server and the file system.

5.1 pam sayAnything

This section describes the administration details of the PAM module. It initially gives an overview of the PAM configuration files and then describes the steps that need to be followed to setup the PAM module

5.1.1 Overview

The configuration for PAM basically requires the setup of the PAM configuration files that are typically stored in /etc/pam.d/ directory. Each service module has its own configuration file with the same name as the service.It needs to be in lower case. The PAM framework uses this configuration file to determine the module that needs to be used to authenticate the application. The configuration file is divided into four sections: authentication, account management, session management, and password management. A typical line may look like this: auth required /usr/lib/security/pam unix.so.1 try first pass

The individual fields are described below

Action field The first field denotes what action this particular service will perform. The valid values are ”auth” for authentication, ”account” for account management, ”ses- sion” for session management, and ”password” for password management.

Control Field The second field is known as the control field. It indicates the behavior of the PAM framework if the user should fail the authentication. There are two types of syntax for this control field: the simple one has a single simple keyword; the more complicated one involves a square-bracketed selection of value=action pairs. Valid control values in the former syntax are:

25 • required: failure of such a PAM will ultimately lead to the PAM-API returning failure but only after the remaining stacked modules (for this service and type) have been invoked. • requisite: like required, however, in the case that such a module returns a failure, control is directly returned to the application. • sufficient: success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module has failed the success of this one is ignored). • optional: the success or failure of this module is only important if it is the only module in the stack associated with this service+type. • include: include all lines of given type from the configuration file specified as an argument to this control. Path The third field is the path to the authentication module. The path can differ between systems. For example, the PAM modules are located in /usr/lib in the Linux-PAM implementation, while Solaris maintains the modules in /usr/lib/security. Arguments The fourth field is a space-separated list of module-dependent options, which are passed as arguments to the authentication module whenever it is invoked.

5.1.2 Configuration

Here are the steps that need to be followed to setup the PAM module.

1. Create the shared object file pam sayAnything.so using the Makefile in the sources. For example if the module written is say pam sayAnything.c here is how the shared object is created #include

gcc −fPIC −c pam sayAnything.c gcc −shared −o pam sayAnything.so pam sayAnything.o −lpam

2. Copy the module’s shared object file pam sayAnything.so to /lib/security. 3. Include the following line in the beginning of the PAM configuration file for the appli- cation using this module say login for example. auth requisite pam sayAnything.so

The file is usually found in the /etc/pam.d directory with the name of the application that is using the PAM module to authenticate the user. 4. pam sayAnything.so implements the service module’s equivalent methods i.e. pam sm authenticate() for the auth interface type

26 5.2 nss sayAnything

This section gives a brief overview of the configuration process of NSS and then describes the configuration details of the NSS module nss sayAnything.so.2

5.2.1 Overview

Configuration of nss sayAnything basically involves configuring the name service switch file. The name service switch is a file which is named, nsswitch.conf generally located in the /etc directory. The name service switch controls how a client machine or application obtains network information. The name service switch is used by client applications that call any of the getXbyY() interfaces such as gethostbyname(), getpwuid(), getpwnam() etc. Each machine has a switch file in its /etc directory. Each line of that file identifies a particular type of network information, such as host, password, and group, followed by one or more locations of that information. A client can obtain naming information from one or more of the switch’s sources. For example, an NIS+ client could obtain its hosts information from an NIS+ table and its password information from a local /etc file. In addition, the client could specify the conditions under which the switch must use each source

Format of the nsswitch.conf File : The nsswitch.conf file is essentially a list of types of information (databases) and the sources that getXXbyYY() routines (such as gethostbyname(), getpwuid()) search for that information. An example of the database name is passwd. The following provides a description of the kind of sources or services that can be listed in the switch file for the information types above.

Information Sources Description files A file stored in the client’s /etc directory. For example, /etc/passwd nisplus An NIS+ table. For example, the hosts table. nis An NIS map. For example, the hosts map. compat compat can be used for password and group information to support old-style + or - syntax /etc/passwd, /etc/shadow, and /etc/group files. dns Can be used to specify that host information be obtained from DNS.

These names are simply strings which the NSS code uses to find the implicitly addressed functions. Visible to the user are the modules which implement an individual service.

27 Assume the service sayAnything shall be used for a lookup. The code for this ser- vice is implemented in a module called libnss sayAnything. On a system support- ing shared libraries this is in fact a shared library with the name (for example) lib- nss sayAnything.so.2. The number at the end is the currently used version of the interface which will not change frequently. Normally the user need not be cognizant of these files since they should be placed in a directory where they are found automatically. Only the names of all available services are important.

Switch Status Messages : If a routine finds the information, the routine returns a success status message. If the routine does not find the information, the routine returns one of three error status messages. Possible status messages are as follows:

Status Message Meaning SUCCESS The requested entry was found in the speci- fied source. UNAVAIL The source is either unresponsive or unavail- able. NOTFOUND The source responded with ”No such entry”. In other words, a NIS+ table, an NIS map, or a /etc file was accessed but the needed information was not found. TRYAGAIN The source is busy. The source might re- spond next time. In other words, the table, map, or file was found, but could not respond to the query.

Switch Action Options : You can instruct the switch to respond to status messages with either of the following actions:

Action Meaning return Stop looking for the infor- mation. continue Try the next source

Default Search Criteria : The combination of nsswitch.conf file status message and action option determines what the routine does at each step. The combination of status and action make up the search criteria. Action items are placed between two service names and are written within brackets. The general form is

28 [ ( !? status = action )+ ] where status => success | notfound | unavail | tryagain action => return | continue

The switch’s default search criteria are the same for every source. As described in terms of the status messages listed above, see the following.

• SUCCESS=return : Stop looking for the information. Proceed using the infor- mation that has been found. • UNAVAIL=continue : Go to the next nsswitch.conf file source and continue searching. • NOTFOUND=continue : Go to the next nsswitch.conf file source and continue searching. • TRYAGAIN=continue : Go to the next nsswitch.conf file source and continue searching.

You can change default search criteria by explicitly specifying some other criteria by using the STATUS=action syntax shown above. For example, the default action for a NOTFOUND condition is to continue the search to the next source. For example, to specify for networks, the search should stop in a NOTFOUND condition, edit the networks line of the switch file. The line would read as follows : networks : nis [NOTFOUND=return] files

This line specifies a non-default criterion for the NOTFOUND status. Non-default criteria are delimited by square brackets. In this example, the search routine behaves as follows:

• If the networks map is available, and contains the needed information, the routine returns with a SUCCESS status message • If the networks map is not available, the routine returns with an UNAVAIL status message. By default, the routine continues to search the appropriate /etc file • If the networks map is available and found, but the map does not contain the needed information, the routine returns with a NOTFOUND message. But, in- stead of continuing on to search the appropriate /etc file, which would be the default behavior, the routine stops searching • If the networks map is busy, the routine returns with an TRYAGAIN status message and by default continues on to search the appropriate /etc file

29 5.2.2 Configuration

The configuration process of the name service module consists of

Module shared object creation linking to the right libraries and placement in a location where the NSS framework can find the module. Each module is designed following a specific interface specification. For now the version is 2 and this manifests in the version number of the shared library object of the NSS modules: they have the extension .2. If the interface changes again in an incompatible way, this number will be increased. Modules using the old interface will still be usable. Developers of a new service will have to make sure that their module is created using the correct interface number. This means the file itself must have the correct name and on ELF systems, the soname (Shared Object Name) must also have this number.

Building a module from a bunch of object files on an ELF system using GNU CC could be done like this: gcc −shared −o libnss sayAnything.so.2 −Wl,−soname,libnss sayAnything.so.2 OBJECTS

To use the new module the library must be able to find it. This can be achieved by using options for the dynamic linker so that it will search the directory where the binary is placed. For an ELF system this could be done by adding the wanted directory to the value of LD LIBRARY PATH. But this is not always possible since some programs (those which run under IDs which do not belong to the user) ignore this variable. Therefore the stable version of the module should be placed into a directory which is searched by the dynamic linker. Normally this should be the directory $prefix/lib, where $prefix corresponds to the value given to configure using the --prefix option. nsswitch.conf file configuration for the specific module. In the nsswitch.conf file which is generally found in /etc add sayAnything [NOTFOUND=return] as the first entry to look for the passwd database. As an example the line might look like this after the change depending on the actual setup in the machine passwd: sayAnything [NOTFOUND=return] db files nis

5.3 IPSEC

This section describes how to setup ipsec between pairs of hosts. It describes

30 1. how to configure when both the hosts have a static IP address assigned 2. how to configure the hosts when one of them has a dynamic IP assigned (possibly NATed) and the other has a static IP assigned to it.

5.3.1 Components that need to be setup

The following components need to be setup in either of the cases mentioned above :

1. Public and private keys for each of the hosts 2. Configuration of racoon.conf 3. Populate the Security Policy Database using setkey to identify packets needing IPSec operations.

5.3.2 Steps to setup ipsec on two test machines host1 and host2

1. Install ipsec-tools on both the machines. 2. Make sure the kernel has got IPSec enabled. This can be verified from the kernel config file. 3. Create the public and private keys for the hosts (host1 and host2 ) using the following command : On host1 : plainrsa-gen -b 2048 -f host1.keys On host2 : plainrsa-gen -b 2048 -f host2.keys 4. The file created contains both the private key and the public key. Separate the public key part of the file by copying the line beginning with “#pubkey” to a new file host1.pub on host1. Do the same on host2 to create host2.pub 5. Once the public key files are created on both the hosts rename host1.keys to host1.priv and host2.keys to host2.priv. The public key portion of the file (which is commented) can be safely removed. Note that these files have the private keys of the host machines and should be safely guarded. 6. Copy the file host2.pub from host2 to host1 7. Copy the file host1.pub from host1 to host2 8. Place all the keys in one directory (/home/ashwin in the current example) so that the location can be specified in racoon.conf

31 9. Make changes to racoon.conf on both the machines. Refer to the subsequent sections for sample configuration files for static-ip case and road-warrior scenario.

10. Add the security policies for the machines (see the sample scripts in the subsequent sections).

11. Restart racoon : /etc/init.d/racoon restart

12. Ping the server machine from the client and check the output of tcpdump to confirm that ipsec is being used to send packets.

5.3.3 The hosts have a static ip

Machine Configuration :

1. Test Machine 1 (a) Hostname : host1 (b) IP Address : 131.193.36.46 (c) OS : Linux Ubuntu Feisty Fawn. Kernel version : 2.6.20-15 (d) Version of ipsec-tools : 0.6.6 2. Test Machine 2 (a) Hostname : host2 (b) IP Address : 131.193.36.48 (c) OS : Linux Ubuntu Feisty Fawn. Kernel version : 2.6.20-15 (d) Version of ipsec-tools : 0.6.6

Configuration of racoon - Test Machine 1 :

# Racoon will look for a keyfile in this directory . path certificate ”/home/ashwin”;

# Specifying ”anonymous” here instructs racoon to accept # connections from anywhere remote anonymous { exchange mode main;

# A unique identifier for the current host. my identifier user fqdn ”[email protected]”;

# List of the identifiers of peers who the host is # willing to accept connections from.

32 peers identifier user fqdn ”[email protected]”;

# The private key file of the current host. certificate type plain rsa ”/home/ashwin/host1.priv”;

# The list of the public keys from which the host is # willing to accept connections. peers certfile plain rsa ”/home/ashwin/host2.pub”;

proposal check obey;

proposal { # Use AES (Rijndael) encryption encryption algorithm aes;

hash algorithm sha1;

#Use plain rsa as the authentication method authentication method rsasig;

dh group 2; } }

# This specifies the parameters which may be used for the setup # of the security associations . sainfo anonymous { pfs group 2; lifetime time 12 hour;

# Use AES (Rijndael) encryption encryption algorithm aes;

authentication algorithm hmac sha1, hmac md5; compression algorithm deflate; }

Configuration of racoon - Test Machine 2 :

# Racoon will look for a keyfile in this directory . path certificate ”/home/ashwin” ;

# Specifying ”anonymous” here instructs racoon to accept # connections from anywhere remote anonymous { exchange mode main;

33 # A unique identifier for the current host. my identifier user fqdn ”[email protected]”;

# List of the identifiers of peers who the host is # willing to accept connections from. peers identifier user fqdn ”[email protected]”;

# The private key file of the current host. certificate type plain rsa ”/home/ashwin/host2.priv”;

# The list of the public keys from which the host is # willing to accept connections. peers certfile plain rsa ”/home/ashwin/host1.pub”;

proposal check obey;

proposal { # Use AES (Rijndael) encryption encryption algorithm aes; hash algorithm sha1;

# Use plain rsa as the authentication method authentication method rsasig;

dh group 2; } }

# This specifies the parameters which may be used for the setup # of the security associations . sainfo anonymous { pfs group 2; lifetime time 12 hour;

# Use AES (Rijndael) encryption encryption algorithm aes;

authentication algorithm hmac sha1, hmac md5; compression algorithm deflate; }

Scripts :

1. Script to retrieve the local IP address of the machine Make sure this script is placed in the same directory as that of the security policy script. #!/bin/sh

#Name of the Script : ipScript

34 #Parameters : None #Purpose : This script retrieves the ip address of the local machine.

# Get OS name OS=‘uname‘ case $OS in Linux) IP=‘ifconfig | grep ’ inet addr:’ | grep −v ’127.0.0.1 ’ | cut −d: −f2 | awk ’{ print $1}’ ‘;; FreeBSD|OpenBSD) IP=‘ifconfig | grep −E ’inet.[0−9]’ | grep −v ’127.0.0.1 ’ | awk ’{ print $2}’‘ ;; SunOS) IP=‘ifconfig −a | grep inet | grep −v ’127.0.0.1 ’ | awk ’{ print $2} ’‘ ;; ∗) IP=”Unknown”;; esac echo ”$IP”

2. Script to add the security policies to SPD #!/bin/sh

#Name of the Script : spScript #Parameters : Remote IP address #Purpose : This script is used to populate the SPD

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

echo ‘sudo setkey −PDF‘

LOCAL IP=$(echo ‘$PWD/ipScript‘)

echo ”The local ip address is : $LOCAL IP”

REMOTE IP=$1

echo ”The remote ip address is : $REMOTE IP”

#Security policies echo ” spdadd $LOCAL IP $REMOTE IP any −P out ipsec esp/tunnel/$LOCAL IP−$REMOTE IP/require; spdadd $REMOTE IP $LOCAL IP any −P in ipsec esp/tunnel/$REMOTE IP−$LOCAL IP/require; ” | setkey −c

3. Test Machine 1 Execute the above security policy script with the ip address of the remote machine (131.193.36.48 in this example) as a parameter. 4. Test Machine 2 Execute the above security policy script with the ip address of the remote machine (131.193.36.46 in this example) as a parameter.

35 5.3.4 Road-warrior scenario

Machine configuration :

1. Test Machine 1 (client)- This machine is behind NAT (a) HostName : dhcpclient (b) IP Address : 192.168.1.100 (c) OS : Linux Ubuntu Feisty Fawn. Kernel version : 2.6.20-15 (d) Version of ipsec-tools : 0.6.6 2. Test Machine 2 (server) - This machine is on a static ip. (a) HostName : host2 (b) IP Address : 131.193.36.48 (c) OS : Linux Ubuntu Feisty Fawn. Kernel version : 2.6.20-15 (d) Version of ipsec-tools : 0.6.6

Configuration of racoon - Test Machine 1 (client) :

# Racoon will look for a keyfile in this directory . path certificate ”/home/ashwin”;

# This specifies the configuration for a specific # remote host that the client wants to connect to. # Add as many ’remote’ sections as there are remote hosts.

remote 131.193.36.48 { exchange mode main;

# When nat traversal is set to on this host will use # NAT traversal as soon as a NAT device is deteced on the path. nat traversal on;

ike frag on; passive off ;

# A unique identifier for the current host. my identifier user fqdn ”[email protected]”;

# A unique identifier for the remote host. peers identifier user fqdn ”[email protected]”;

# The private key file of the current host. certificate type plain rsa ”/home/ashwin/host1.priv”;

# The public key file of the remote host. peers certfile plain rsa ”/home/ashwin/host2.pub”;

36 proposal check obey;

proposal { # Use AES (Rijndael) encryption encryption algorithm aes;

hash algorithm sha1;

#Use plain rsa as the authentication method authentication method rsasig;

dh group 2; } }

# This specifies the parameters which may be used for the setup # of the security associations .

sainfo anonymous { pfs group 2; lifetime time 12 hour;

# Use AES (Rijndael) encryption encryption algorithm aes;

authentication algorithm hmac sha1, hmac md5; compression algorithm deflate; }

Configuration of racoon - Test Machine 2 (server) :

# Racoon will look for a keyfile in this directory . path certificate ”/home/ashwin” ;

# Specifying ”anonymous” here instructs racoon to accept # connections from anywhere remote anonymous { exchange mode main; proposal check claim;

# This option instructs racoon to create the appropriate policy # when a new connection is initiated. generate policy on;

# When nat traversal is set to on this host will use # NAT traversal as soon as a NAT device is deteced on the path. nat traversal on;

37 dpd delay 20; ike frag on;

# A unique identifier for the current host. my identifier user fqdn ”[email protected]”;

# A unique identifier for the remote host. peers identifier user fqdn ”[email protected]”;

# The private key file of the current host. certificate type plain rsa ”/home/ashwin/host2.priv”;

# The public key file of the remote host. peers certfile plain rsa ”/home/ashwin/host1.pub”;

proposal { # Use AES (Rijndael) encryption encryption algorithm aes;

hash algorithm sha1;

#Use plain rsa as the authentication method authentication method rsasig;

dh group 2; } }

# This specifies the parameters which may be used for the setup # of the security associations . sainfo anonymous { pfs group 2; lifetime time 12 hour;

# Use AES (Rijndael) encryption encryption algorithm aes;

authentication algorithm hmac sha1, hmac md5; compression algorithm deflate; }

Scripts : The scripts are the same as that of the static ip case mentioned in the earlier sections

Test Machine 1 (client) Invoke the security policy script with the ip address of the remote machine or the server (131.193.36.48 in this example) as a parameter.

38 Test Machine 2 (server) The racoon.conf file on this machine has got ’gener- ate policy’ on which automatically takes care of creating the security policy for the server. There is no need for a manual creation in this case.

6 Conclusion

The current distributed authentication mechanism is more secure when compared to most of the authentication mechanisms currently designed for UNIX. Exisitng Password based au- thentication mechanism are inherently weak with either passwords not being very strongly selected or by being sent unencrypted on the network. The advantages of the current au- thentication mechanism in terms of providing better security are:

• Public Key Infrastructure is used to avoid the need to send the passwords over the network. A zero knowledge proof is used to prove to the server that the user has got the right authentication token.

• Ephemeral Keys (short-term) are used in order to reduce the window during which the attacker can misuse the authentication token. The keys created are valid only for a small amount of time and even if the client’s machine is compromised the time gap is reduced.

• IPSec ensures that all the data that is being sent on the network in the encrypted form. It also performs host authentication. The certificate server can be configured to send the certificates only to trusted hosts.

• The name server certificates are partitioned according to who is allowed to provide the information (user or system admin) providing privilege separation [5]

• No password is ever sent on the network directly.

39 References

[1] Curlftpfs. http://curlftpfs.sourceforge.net.

[2] Kernel sec net. http://www.rites.uic.edu/~solworth/securityPapers.html.

[3] Kernelsec. http://kernelsec.org.

[4] J. Kohl and B. Neuman. The kerberos network authentication service. Technical report, 1991.

[5] Niels Provos, Markus Friedl, and Peter Honeyman. Preventing privilege escalation. 12th USENIX Security Symposium, August 2002.

[6] Vipin Samar. Unified login with pluggable authentication modules(pam). In CCS ’96: Proceedings of the 3rd ACM conference on Computer and communications security, pages 1–10, New York, NY, USA, 1996. ACM Press.

[7] T. Ylonen. SSH - secure login connections over the internet. Proceedings of the 6th Security Symposium) (USENIX Association: Berkeley, CA):37, 1996.

40 A Appendix

A.1 PAM

A.1.1 Framework Layer API’s

Apart from the methods mentioned earlier the PAM framework API set further includes the following functions which are of interest to us. These functions are again called by the applications that would like to use the PAM module i.e. pam sayAnything.

pam start() is called to initiate an authentication transaction. int pam start (char ∗service name, char ∗user, struct pam conv ∗pam conversation, pam handle t ∗∗pamh);

‘pam start()’ takes as arguments the name of the service, the name of the user to be authenticated, the address of the conversation structure. ‘pamh’ is later used as a handle for subsequent calls to the PAM library. The PAM modules do not communicate directly with the user; instead they rely on the application to perform all such interaction. The application needs to provide the conversation functions, ‘conv()’, and associated application data pointers through a ‘pam conv’ structure when it initiates an authentication transaction. The module uses the ‘conv()’ function to prompt the user for data, display error messages, or text information. In pam sayAnything this function is used to request the password from the user (it also blinds the password on the screen) pam end() is called to terminate the PAM transaction as specified by ‘pamh’, and to free any storage area allocated by the PAM modules. int pam end(pam handle t ∗pamh,int pam status);

Apart from these methods there also functions like pam get item()’ and ‘pam set item()’ that allow the parameters specified in the initial call to ‘pam start()’ to be read and updated and functions like ‘pam set data()’, ‘pam get data()’ that are used to store module specific data. But these are not currently used in the sayAnything module due to the lack of necessity.

41 A.2 Name Service Module

A.2.1 NSS Module Nomenclature

The name of each function in the module consist of various parts: nss service function

“service” corresponds to the name of the module this function is found in. The function part is derived from the interface function in the C library itself. If the user calls the function gethostbyname and the service used is files the function nss files gethostbyname r

in the module libnss files .so.2

is used. The NSS modules only contain reentrant versions of the lookup functions. I.e., if the user would call the gethostbyname r function this also would end in the above function. For all user interface functions the C library maps this call to a call to the reentrant function. For reentrant functions this is trivial since the interface is (nearly) the same. For the non- reentrant version The library keeps internal buffers which are used to replace the user supplied buffer. I.e., the reentrant functions can have counterparts. No service module is forced to have functions for all databases and all kinds to access them. If a function is not available it is simply treated as if the function would return UNAVAIL

A.2.2 NSS Module Interface

The prototypes for the non-reentrant and reentrant versions of the example function geth- ostbyname() are: struct hostent ∗gethostbyname (const char ∗name) int gethostbyname r (const char ∗name, struct hostent ∗result buf , char ∗buf, size t buflen, struct hostent ∗∗result, int ∗h errnop)

The actual prototype of the function in the NSS modules in this case is enum nss status nss files gethostbyname r (

42 const char ∗name, struct hostent ∗result buf , char ∗buf, size t buflen, int ∗errnop, int ∗h errnop)

The interface function is in fact the reentrant function with the change of the return value and the omission of the result parameter. While the user-level function returns a pointer to the result the reentrant function return an enum nss status value: In case the interface function has to return an error it is important that the correct error code is stored in *errnop. Some return status value have only one associated error code, others have more.

A.3 Feedback

For comments and suggestions please send an email to the author at [email protected]

43