\documentclass{acm_proc_article-sp} \begin{document} \title{Plan 9 Authentication in Linux} \numberofauthors{1} \author{ \alignauthor Ashwin Ganti \titlenote{ Ashwin Ganti was earlier with the Department of Computer Science, University of Illinois at Chicago, IL, USA where the current work has been done. He is now with Google Inc., Mountain View, CA 94043 USA.}\\ \affaddr{Google Inc.} \\ \email{aganti@google.com}} \maketitle \begin{abstract} In Linux, applications like \texttt{su} and \texttt{login} currently run as root in order to access authentication information and set or alter the identity of the process. In such cases, if the application is compromised while running as a privileged user, the entire system can become vulnerable. An alternative approach is taken by the Plan 9 operating system from Bell Labs, which runs such applications as a non-privileged user and relies on a kernel-based capability device working in coordination with an authentication server to provide the same services. This avoids the risk of an application vulnerability becoming a system vulnerability. This paper discusses the extension of Linux authentication mechanisms to allow the use of the Plan 9 approach with existing Linux applications in order to reduce the security risks mentioned earlier. It describes the port of the Plan 9 capability device as a character device driver for the Linux kernel. It also describes the port of the Plan 9 authentication server and the implementation of a PAM module which allows the use of these new facilities. \emph{It is now possible to restrain processes like login and su from the uncontrolled setuid bit and make them run on behalf of an unprivileged user in Linux.} \end{abstract} \category{D.4.6}{Operating Systems}{Security and Protection}[Authentication] \terms{Authentication} \section{Introduction} \emph{Authentication} is any process by which a system verifies that someone is who they claim to be. This usually involves a user name and password but it is also done using hardware tokens, biometrics etc. The anatomy of authentication involves two aspects, one is proving who you say you are and the other part is to change the owner of the process to the authenticated user. Historically, Linux authentication was based on the passwd and shadow files kept in \emph{/etc} which contained both a hashed password and various information about the user (such as her home directory and default shell). Applications heavily depended on these files which led to less extensible code. Moreover if a new authentication mechanism was introduced it required all the applications (like login, su etc.) that use the authentication information be rewritten to support it. \texttt{Pluggable Authentication Modules (PAM)} \cite{PAM} \cite{pamsrc} were created to provide more effective ways to authenticate users. PAM provides a generic framework enabling uniform authentication of user applications. It enables user applications to perform authentication without actually knowing the implementation details of the underlying mechanisms. It is usually done through a password based authentication mechanism but also supports a challenge response interaction. In order to use a particular authentication scheme (ex: Kerberos) to authenticate a user, an application can dynamically link a PAM module that implements that authentication scheme. Any PAM module which is written using the PAM framework exposes a generic set of API/functions to the applications. Applications simply call the functions defined in the module passing in the credentials of the user. The advantage of this framework is that any change that occurs in the authentication mechanism does not require the applications to be retrofitted to support it. While PAM is a convenient way of authenticating the users from the perspective of an application, it results in having the authentication code run in the same address space as the application and might be circumvented. Since it is just a library, an application using PAM must operate at the capability level which is necessary to provide the service. It does not have any increased level of privilege over the application using it and hence the onus of protecting the environment in which PAM operates is on the application. As mentioned earlier, the second part of authentication is the changing of the process ownership to the authenticated user. Historically, the ability to change the user id associated with a process was among a group of actions (such as mounting file systems, raw device access, or shutting down the system) which could only be performed by the super user. Applications (such as \texttt{login}, \texttt{ping}, and \texttt{mount}) which required these facilities used a special permission bit, named setuid, which would always execute the application with super user privileges even when started by a normal user. The danger in this approach was that flaws in these applications could enable privilege escalation which would allow normal users to become the super user or otherwise compromise the system. The Linux capability system was introduced to subdivide the actions typically associated with the super user to limit the security risk of applications which required a particular privileged operation. Instead of granting applications such as \texttt{ping} and \texttt{mount} super-user privileges via the set-uid bit, they are only given the capabilities they need to perform their function. This should prevent an application such as \texttt{ping}, which only requires the super user capability to directly access network devices, from being subverted to change the user identity of the process. However, this approach does not reduce the risk for applications such as \texttt{su} and \texttt{login} which require the capability to change the user identity. \emph{The existing capability system does not govern which users a process may change its identity to.} In other words, the same vulnerability described earlier exists for all applications involved with authentication such as \texttt{su} and \texttt{login}. Having an application run with the capability to change ownership to any user does not achieve necessary privilege separation \cite{privsep} and if the application has been compromised then an attacker can get super user access to the system. A new mechanism is required which isolates authentication from applications and provides more granular control over critical system capabilities such as the ability to set the user and group identity of a process. The Plan 9 research operating system from Bell Labs \cite{p9} solves most of the above security issues in a very graceful and modular way. Authentication in Plan 9 is centered around a per user agent called \emph{factotum} \cite{mit-security} following the lead of the SSH \emph{agent} \cite{ylonen}. \emph{Factotum} is a trusted process that holds the secure keys of the user and negotiates authentication protocols on behalf of the user. Factotum is implemented as a file server in Plan 9 and applications that need authentication services communicate with factotum using the usual file system calls (read, write etc.) The applications need not be compiled with the authentication or cryptographic code and can remain agnostic of the underlying mechanism which is understood by factotum. Moreover the applications need not be retrofitted for the changes in the authentication protocols. Isolating the privileged code to a single more trustworthy component makes it possible to run the applications at a weaker privilege level. Plan 9 avoids privilege escalation in applications such as \texttt{su} and \texttt{login} through a granular capability system which only provides the ability to switch identity to a specific user instead of granting these applications the ability to switch to any user. When a process such as the \texttt{login} program needs to change its identity it proves to the \emph{host owner's} factotum that it has the required credentials to run as that identity by running an authentication protocol. \emph{Host owner} is a user in Plan 9 that basically owns the local resources of a machine like the local disks, network interfaces, etc. The \emph{Host owner}'s factotum and the \texttt{login} program then interact with a kernel implemented capability system to authorize \texttt{login} to change its identity to the specific user authenticated by the protocol. Because the capability is specific to the authenticated identity, the \texttt{login} application can not be compromised to obtain super user (or even \emph{Host owner}) privileges. This is a more secure way of handling things when compared to Linux, which allows applications such as \texttt{login} to switch their identity to any user. Our effort here is to achieve similar results for Linux by adopting the authentication mechanisms and Plan 9 notion of capabilities. \emph{This work is going to be very useful in getting closer to a goal of getting a Linux machine to boot with no processes running as root}. There are numerous advantages: \begin{itemize} \item Applications like \texttt{su} and \texttt{login} need not run as the super user. \item The capability system is managed by the kernel which is inherently trusted and more secure. \item Capabilities to change identity are restricted to specific authenticated identities by the authentication system. \item Protocols used to communicate with the authentication server have been extensively researched and are proven to be more secure than the traditional protocols used for the communication of the authentication information. They are not subject to the "man in the middle" attacks that the other protocols suffer from. \item This is a cluster/networked solution in the sense that the same authentication mechanism which works for a stand alone machine can be scaled up to be used to perform authentication over a clustered environment. \end{itemize} We have implemented the Plan 9 capability device for the Linux kernel, porting the authentication server as part of this effort. We wrote a PAM module to perform the authentication with the host owner's factotum. The rest of the paper delineates the components needed for Linux to make use if this new mechanism while not being disruptive to the existing applications' code, explains the implementation details of the port and concludes by mentioning some future improvements and related work. % TODO: Add another section here entitled Plan auth primer ?? \section{Components needed in Linux} This section delineates the various components required to make the existing applications in Linux use the new authentication mechanism of Plan 9. The implementation details of each of the components needed is explained in Section 4. \subsection{Plan 9 authentication server for Linux } Each security domain in Plan 9 has a trusted authentication server where all the shared keys of the users are maintained. It also offers services for users and administrators to create and disable accounts, manage keys, etc. It is comprised of two services, \emph{authsrv} and \emph{keyfs}. \emph{authsrv} is a network service which is similar to the Key Distribution Center (KDC) in Kerberos. It brokers the network authentication sessions. The \emph{passwd} utility can be used to change account passwords on the authentication server. \emph{keyfs} is a user level file system that manages an encrypted database of user accounts. We have ported \emph{authsrv} and \emph{keyfs} for Linux using the pre-existing Plan 9 from User Space \cite{p9p} package which already included a Linux port of \emph{factotum}. We also ported \emph{changeuser} which is a utility to create and manage user accounts in the authentication server. A side effect of using these Plan 9 tools is that a copy of the user's account information must be maintained in the authentication server separate from the typical Linux locations, but this can be avoided in the future by building a Name Service Module configurable through \emph{nsswitch.conf} that retrieves the user's credentials from the Plan 9 authentication server. \subsection{Linux Capability Device} In Plan 9, a process that wants to change its identity authenticates with the host owner's factotum. The host owner's factotum on successful authentication creates a capability, gives a hash of it to the kernel and passes the capability to the process that requested the change of identity. Once the process receives the capability it proves to the kernel that it has a valid capability and the kernel changes the uid of the process. Further details on the semantics and working of the cap device for the Linux kernel can be found in Section 4.1. We have implemented the Plan 9 capability device for the Linux kernel as a character device driver. This is perhaps the most important part of the authentication scheme. The capability device managed by the kernel is used to allow factotum to grant permission to a process to change the user id. It exposes two device files which are used by the factotum to grant the capability and the process to use that capability. \subsection{Pluggable Authentication Module} We have implemented a Pluggable Authentication Module \\ \emph{(pam\_devcap)} that is an interface for the process to authenticate against the host owner's factotum. With regard to the security limitations of PAM discussed in the earlier sections, it should be noted that PAM does not perform the actual authentication. It is just used as an interface to interact with the factotum which performs the actual authentication. In this manner, all authentication code runs in a separate address space from the application instead of being linked in as a shared library. By using the PAM framework, the use of factotum to authenticate users is transparent to applications using the existing PAM API. The user process passes the target user's credentials to \\ \emph{pam\_devcap} which authenticates them against the host owner's factotum. \emph{pam\_devcap} uses the \emph{p9cr} authentication protocol to talk to the host owner's factotum. It gets back from the factotum a capability in the form of a string which it stores for later use. Whenever the user id needs to be changed, the application requests the PAM module to do so, which retrieves the stored capability and writes it to \texttt{/dev/capuse} after which the process runs on behalf of the new user. \begin{figure*} \begin{center} \includegraphics[keepaspectratio=true, scale=0.485]{overview} \end{center} \caption{Overview of the port} \label{overview} \end{figure*} \section{Overview of the port} Figure~\ref{overview} shows a sequence diagram of the overall flow between a user process that wants to change a user id, the PAM module and the host owner's factotum. The user process contacts \emph{pam\_devcap} initially to authenticate the target user's credentials. The PAM module contacts the host owner's factotum and talks to it using the \emph{p9cr} protocol. \emph{p9cr} is a textual challenge-response protocol which is typically done between a factotum and a local program and not between two factotums as in the case of other authentication protocols in Plan 9. The protocol with factotum is textual where in the client writes a user name, server responds with a challenge, client writes a response, server responds with \texttt{ok} or \texttt{bad}. Typically this information that is being exchanged is wrapped in other protocols like \emph{p9sk1} by the local programs before being sent over the network. The factotum using the information from the authentication server validates the target user's information. If the credentials (user name and password) are valid then it creates a capability, hashes it and writes it to {\texttt{/dev/caphash}} which is a write only file opened by the host owner's factotum at boot time. It also passes this back to the PAM module. Now the PAM module stores this capability for later use and sends back PAM\_SUCCESS to the user process informing the successful authentication of the target user. When the process wants to change the user id it contacts the PAM module again which basically writes the earlier saved capability to \texttt{/dev/capuse} and returns PAM\_SUCCESS. The application now runs on behalf of the target user. \section{Implementation} We shall now describe the implementation details of each of the components that are needed in Linux to use the Plan 9 authentication mechanisms. \subsection{Capability Device for Linux } Figure~\ref{capdevice} shows the flow of control in the cap device. \begin{figure*} \begin{center} \includegraphics[keepaspectratio=true, scale=0.53]{capdevice} \end{center} \caption{Flow of control in the cap device } \label{capdevice} \end{figure*} \begin{enumerate} \item A process running on behalf of \emph{user1} sends a message to the the host owner's factotum requesting a capability to change its user id from \emph{user1} to \emph{user2}. \item The host owner's factoum performs an authentication protocol(\emph{p9cr}) with the requesting process to authenticate the target user's credentials provided by the requesting process. \item Once the host owner's factotum knows that the requesting process gets the valid credentials of the \emph{user2} it creates a capability of the form \\\emph{user1@user2@randomString} and writes a HMAC SHA1 hash of it to \texttt{/dev/caphash}. \item The kernel internally maintains a linked list of these hashes written by the host owner's factotum. It adds the newly created hash to the list. \item The requesting process get the capability string and simply writes it to \texttt{/dev/capuse}. \item Once the capability is written to \texttt{/dev/capuse} the kernel checks whether the process requesting the uid change is actually running on behalf of \emph{user1}. If the process is not, then the kernel throws an error and the write operation fails. \item The kernel now splits the capability string and creates a HMAC SHA1 hash of \emph{user1@user2} with the \emph{randomString}. \item It does a linear search amongst the existing list of hashes for this hash and if it finds a match it changes the effective user id of the process to \emph{user2}. \item Once used the capability is discarded by the kernel, i.e. it is removed from the list of hashes. \item If there is no match found, or if there is a time out on the capability then the kernel returns an error and the write operation to \texttt{/dev/capuse} fails. \end{enumerate} \subsection{Authentication server} We have made minimal changes to the existing authentication server code in Plan 9 and ported it to Linux using the libraries provided by \emph{Plan 9 from User Space} in Linux. The authentication server, as of now, needs to be set up using xinetd or the like. This is only a temporary solution. We plan to avoid xinetd and setup the auth server in a more graceful manner in the future. \subsubsection{Steps to setup the authentication server under xinetd} \begin{enumerate} \item Create the /etc/xinetd.d/authsrv file containing the following: \begin{verbatim} service authsrv { socket_type = stream protocol = tcp wait = no user = root server = /usr/local/plan9/bin/authsrv server_args = -d } \end{verbatim} \item Create an entry in /etc/services \begin{verbatim} authsrv 567/tcp #Plan 9 auth server \end{verbatim} \item Make an entry in \$PLAN9/ndb/local for the auth server \begin{verbatim} authdomain = auth = port = 567 \end{verbatim} \item Make sure the \texttt{\$NAMESPACE} environment variable is set. This is essential for the authentication server to run. Typically it defaults to \texttt{/tmp/ns.\$USER.\$DISPLAY}. Set it manually if not set by default using the following command : \begin{verbatim} export NAMESPACE= \end{verbatim} \item Restart xinetd \begin{verbatim} sudo /etc/init.d/xinetd restart \end{verbatim} \end{enumerate} \subsubsection{User Account Setup} The authentication information of Linux users is generally handled by storing them in /etc/ files or some kind of naming service (configurable through \emph{nsswitch.conf}). But the authentication protocol(\emph{p9cr}) that happens between the host owner's factotum and the process is brokered by the authentication server. The authentication server in Plan 9 stores the shared keys of the users including the account information. Since the Plan 9 shared key protocols(\emph{p9cr}) are being used to authenticate the users to the host owner's factotum it is necessary for the existing user's accounts to be created again in the authentication server. We have ported the Plan 9 \emph{changeuser} utility to help add user accounts to the auth server. \begin{verbatim} changeuser \end{verbatim} Users are represented by integer uids in the Linux kernel unlike the Plan 9 case where the users are represented as string identifiers. The capability that is written to \texttt{/dev/caphash} and \texttt{/dev/capuse} is of the form \emph{user1@user2@randomstring} where \emph{user1} and \emph{user2} are the string values of the user identifiers in the case of Plan 9. NFS solves a similar problem by having a user space mapping daemon that is contacted by the kernel to get the integer user ids for the string names that are supplied. The easiest way to solve this problem in our case was to simply create the user names in the authentication server by the string equivalents of the uids (for example: \emph{changeuser 1000}). Now when the capability is created by host owner's factotum it would be the actual integer userids in string form that the kernel can understand. Whenever the capability is written to the kernel it is converted to an integer. Since the kernel understands the integer equivalent of this it simply changes the userid of the process to the target user id thereby avoiding the requirement of a user space mapping daemon. Please remember that this is a temporary solution. It would be preferable to have a user space mapping daemon in the long run. \subsection{Pluggable Authentication Module} The PAM module \emph{pam\_devcap} authenticates against the host owner's factotum, retrieves the capability and whenever the user space application wants to change the user credentials, writes the capability to \texttt{/dev/capuse}. \subsubsection{pam\_devcap configuration with PAM framework} \begin{enumerate} \item Copy the module's shared object file \texttt{pam\_devcap.so} to \texttt{/lib/security}. \item Include the following line in the beginning of the PAM configuration file for the application using this module - \texttt{su} in our example. \begin{verbatim} auth requisite pam_devcap.so \end{verbatim} \texttt{auth} signifies the PAM module's interface type. Modules with this interface type authenticate the user by a password. The module also can change the user's credentials such as Kerberos tickets or group memberships.\\ \\ \texttt{requisite} is the control flag for the \emph{pam\_devcap} module. It tells PAM what to do with the result of the module(pass/fail). Since PAM modules can be stacked in a particular order, control flags decide in what way does the result of the current module affect the final authentication outcome of the user. The \texttt{requisite} flag tells PAM that the module has to return success for the authentication to continue. The user is notified immediately if the module fails.\\ \\ \texttt{pam\_devcap.so} is the name of the module that implements the PAM interface. \item \texttt{pam\_devcap.so} implements the service module's equivalent methods for the \texttt{auth} interface type i.e. \\ \emph{pam\_sm\_authenticate()} and \emph{pam\_sm\_setcred()}. In \\ \emph{pam\_sm\_authenticate()} the PAM module authenticates against the host owner's factotum and retrieves the capability for the user. The capability is used to change the user id in \emph{pam\_sm\_setcred()}. \end{enumerate} \subsubsection{Logical Flow of authentication using PAM} Refer to Figure 1 for the overall flow. \renewcommand{\theenumi}{\arabic{enumi}} \renewcommand{\labelenumi}{\theenumi} \begin{enumerate} \item The application makes a call to the \emph{pam\_authenticate()} supplying the target user's credentials to the PAM module. \item The PAM framework internally routes it the service module's (i.e. \emph{pam\_devcap}) implementation of the \\ pam\_authenticate() method which is \\ \emph{pam\_sm\_authenticate()}. \item The authentication happens in the \emph{pam\_sm\_authenticate()} method of the PAM module. \item The target user's credentials are passed over to the host owner's factotum which validates them by contacting the authentication server. Upon successful authentication it returns the capability as a string to the PAM framework. \item The PAM module saves this capability using \\ \emph{pam\_set\_data()} and returns PAM\_SUCCESS to the user application. \item When the application wants to change the user id it makes a call to the \emph{pam\_setcred()} function. \item The service module equivalent of the \emph{pam\_setcred()} is the \emph{pam\_sm\_setcred()} function which is internally called by the PAM framework. The PAM module retrieves the capability that it saved earlier using the \emph{pam\_get\_data()} function. It writes this capability to \texttt{/dev/capuse} which results in the kernel changing the user id of the process to the target user id of the process. \end{enumerate} \subsubsection{Zero Application Code Change} While working on the PAM module we discovered that there might be no need to make \emph{any} changes to the application's code in order to use this new authentication mechanism. The application calls \emph{pam\_authenticate()} to authenticate the user and then does a \emph{setuid()} to the authenticated user. Since the purpose of this new authentication mechanism is to eliminate the need for applications to run as root and \emph{setuid()}, we might expect that at the minimum we need to modify the code to remove the \emph{setuid()} system calls. But we can avoid this and practically achieve a zero application code change. Basically \emph{pam\_authenticate()} uses the \emph{pam\_devcap} PAM module which internally writes to the cap device to change the user id. Hence, by the time \emph{pam\_authenticate()} returns the user is already running on the behalf of the new user. So the subsequent \emph{setuid()} call would effectively be a no-op. This means that it requires no code changes to user space applications to use the cap device as long as they use PAM to authenticate users. Unfortunately the PAM module's implementation is not complete at this point to demonstrate this. \section{Future Work} We focused on implementing the capability device to the Linux kernel and tried to demonstrate its use through the PAM framework. Additional improvements on the port could make it more secure and help applications to seamlessly use this authentication mechanism. \begin{itemize} \item The Plan 9 kernel starts a factotum at boottime which runs on behalf of the host owner. In order to do this the kernel needs a credential to start the factotum. In a similar case, the authentication server requires a credential in order to start. Plan 9 uses a secret password stored in nvram which the kernel prevents anyone from reading and uses it start the authentication server and the host owner's factotum. A similar mechanism needs to be developed for use with Linux in order to maximize security. \item The authentication server that is currently ported does not have the \emph{ndb} database file that implements the speaks-for relationship for the host id. If an application needs to use the speaks-for relation then it would be useful if ndb support is provided. \item The authentication server is currently setup to run with xinetd or the like. It would be useful to make it run as an independent service if more security is desired. \item If scalability is required then we recommend a user space mapping daemon that maps the string user names and the integer user ids. This daemon would be contacted by the kernel to resolve the user names it gets after parsing the capabilities written to the device files (by the process and the host owner's factotum). \item Linux uses Naming Services to retrieve the user's login information. Applications that are used to the \emph{getpwnam()} calls to retrieve the user account information might find an NSS module (configurable through nsswitch.conf) that contacts the Plan 9 authentication server useful. \end{itemize} \section{Related Work} Privilege separation by running a separate process for each user is widely used. \texttt{qmail} \cite{qmail} forks off a new process(and then does a setuid) for each user to deliver email. Linux implements the concept of Compartmented Mode Workstations that have split up root privileges into about 30 separate capabilities \cite{cmw}, including a \emph{setuid} capability. The programs do not run as root and assume privileges when needed and drop them when they don't thus implementing least privilege. SELinux \cite{selinux} provides protection by limiting the privileges of a process based on the user on behalf of which it runs and also the process's executable. In comparison to these methods the \emph{cap device} provides fine-grain one-time use capability to limit the setuid privileges further by allowing only the host owner's factotum to create the capability and managing the capability system in the kernel thereby providing better security. \section{Conclusion} Applications like \texttt{su} and \texttt{login} can now run on behalf of an unprivileged user instead of being setuid to root. This proves that the capability device for the Linux kernel is a very useful authentication mechanism considering the existing alternatives. Since these applications run as root, an attacker can get root access to the system by exploiting any kind of security flaw in the application (buffer overflows etc.). By implementing this new authentication mechanism, even if these applications are compromised we do not give away much when compared to the former case. This achieves better privilege separation thereby providing better security.\\ We have completed the implementation of the capability device for the kernel (about 300 lines of kernel code) and the port of the authentication server and Key File System of Plan 9 to Linux. Both the authentication server and keyfs use the framework provided by p9p (Plan 9 from User Space). We still need to complete the PAM module's implementation in order for it to be used by user space applications like \texttt{su}. We are currently in the process of debugging the module after which it will be made available at \cite{sources} We believe that the Plan 9 authentication and capability mechanisms can enhance the existing Linux security model, and hope that our prototype implementation can be used as a foundation for future improvements \newpage \section{Acknowledgments} We would like to thank \begin{itemize} \item \emph{Eric Van Hensbergen}\footnote{Research Staff Member in the Novel Systems Architecture group at IBM's Austin Research Lab} for his continual support throughout the entire work. \item my adviser \emph{Prof. Jon Solworth}\footnote{http://www.rites.uic.edu/$\sim$solworth/index.html} for providing invaluable guidance throughout this research. \item \emph{Latchesar Ionkov}\footnote{Technical Staff Member at Los Alamos National Laboratory} for giving me useful feedback and comments on the capability device driver's code. \end{itemize} This work was supported in part by the National Science Foundation under Grants No. 0627586 and 0551660. Any opinions, findings and conclusions or recommendations expressed in this paper are those of the author and do not necessarily reflect the views of the National Science Foundation. \bibliographystyle{abbrv} \bibliography{paper} \balancecolumns \end{document}