The Linux-PAM Module Writers' Guide Andrew G. Morgan morgan@kernel.org Thorsten Kukuk kukuk@thkukuk.de Version 0.99, 26. June 2006 This manual documents what a programmer needs to know in order to write a module that conforms to the Linux-PAM standard.It also discusses some security issues from the point of view of the module programmer. Introduction
Description Linux-PAM (Pluggable Authentication Modules for Linux) is a library that enables the local system administrator to choose how individual applications authenticate users. For an overview of the Linux-PAM library see the Linux-PAM System Administrators' Guide. A Linux-PAM module is a single executable binary file that can be loaded by the Linux-PAM interface library. This PAM library is configured locally with a system file, /etc/pam.conf, to authenticate a user request via the locally available authentication modules. The modules themselves will usually be located in the directory /lib/security (or /lib64/security, depending on the architecture) and take the form of dynamically loadable object files (see dlopen3 . Alternatively, the modules can be statically linked into the Linux-PAM library; this is mostly to allow Linux-PAM to be used on platforms without dynamic linking available, but this is a deprecated functionality. It is the Linux-PAM interface that is called by an application and it is the responsibility of the library to locate, load and call the appropriate functions in a Linux-PAM-module. Except for the immediate purpose of interacting with the user (entering a password etc..) the module should never call the application directly. This exception requires a "conversation mechanism" which is documented below.
Synopsis #include <security/pam_modules.h> gcc -fPIC -c pam_module.c gcc -shared -o pam_module.so pam_module.o -lpam
What can be expected by the module Here we list the interface that the conventions that all Linux-PAM modules must adhere to.
Getting and setting <emphasis>PAM_ITEM</emphasis>s and <emphasis>data</emphasis> First, we cover what the module should expect from the Linux-PAM library and a Linux-PAM aware application. Essesntially this is the libpam.* library.
Other functions provided by <filename>libpam</filename>
What is expected of a module The module must supply a sub-set of the six functions listed below. Together they define the function of a Linux-PAM module. Module developers are strongly urged to read the comments on security that follow this list.
Overview The six module functions are grouped into four independent management groups. These groups are as follows: authentication, account, session and password. To be properly defined, a module must define all functions within at least one of these groups. A single module may contain the necessary functions for all four groups.
Functional independence The independence of the four groups of service a module can offer means that the module should allow for the possibility that any one of these four services may legitimately be called in any order. Thus, the module writer should consider the appropriateness of performing a service without the prior success of some other part of the module. As an informative example, consider the possibility that an application applies to change a user's authentication token, without having first requested that Linux-PAM authenticate the user. In some cases this may be deemed appropriate: when root wants to change the authentication token of some lesser user. In other cases it may not be appropriate: when joe maliciously wants to reset alice's password; or when anyone other than the user themself wishes to reset their KERBEROS authentication token. A policy for this action should be defined by any reasonable authentication scheme, the module writer should consider this when implementing a given module.
Minimizing administration problems To avoid system administration problems and the poor construction of a /etc/pam.conf file, the module developer may define all six of the following functions. For those functions that would not be called, the module should return PAM_SERVICE_ERR and write an appropriate message to the system log. When this action is deemed inappropriate, the function would simply return PAM_IGNORE.
Arguments supplied to the module The flags argument of each of the following functions can be logically OR'd with PAM_SILENT, which is used to inform the module to not pass any text (errors or warnings) application. The argc and argv arguments are taken from the line appropriate to this module---that is, with the service_name matching that of the application---in the configuration file (see the Linux-PAM System Administrators' Guide). Together these two parameters provide the number of arguments and an array of pointers to the individual argument tokens. This will be familiar to C programmers as the ubiquitous method of passing command arguments to the function main(). Note, however, that the first argument (argv[0]) is a true argument and not the name of the module.
Authentication management To be correctly initialized, PAM_SM_AUTH must be #define'd prior to including <security/pam_modules.h>. This will ensure that the prototypes for static modules are properly declared.
Account management To be correctly initialized, PAM_SM_ACCOUNT must be #define'd prior to including <security/pam_modules.h>. This will ensure that the prototypes for static modules are properly declared.
Session management To be correctly initialized, PAM_SM_SESSION must be #define'd prior to including <security/pam_modules.h>. This will ensure that the prototypes for static modules are properly declared.
Authentication token management To be correctly initialized, PAM_SM_PASSWORD must be #define'd prior to including <security/pam_modules.h>. This will ensure that the prototypes for static modules are properly declared.
Generic optional arguments Here we list the generic arguments that all modules can expect to be passed. They are not mandatory, and their absence should be accepted without comment by the module. debug Use the pam_syslog3 call to log debugging information to the system log files. use_first_pass The module should not prompt the user for a password. Instead, it should obtain the previously typed password (by a call to pam_get_item() for the PAM_AUTHTOK item), and use that. If that doesn't work, then the user will not be authenticated. (This option is intended for auth and passwd modules only). See also The Linux-PAM System Administrators' Guide. The Linux-PAM Application Developers' Guide. The V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH PLUGGABLE AUTHENTICATION MODULES'', Open Software Foundation Request For Comments 86.0, October 1995. Author/acknowledgments This document was written by Andrew G. Morgan (morgan@kernel.org) with many contributions from Chris Adams, Peter Allgeyer, Tim Baverstock, Tim Berger, Craig S. Bell, Derrick J. Brashear, Ben Buxton, Seth Chaiklin, Oliver Crow, Chris Dent, Marc Ewing, Cristian Gafton, Emmanuel Galanos, Brad M. Garcia, Eric Hester, Roger Hu, Eric Jacksch, Michael K. Johnson, David Kinchlea, Olaf Kirch, Marcin Korzonek, Thorsten Kukuk, Stephen Langasek, Nicolai Langfeldt, Elliot Lee, Luke Kenneth Casson Leighton, Al Longyear, Ingo Luetkebohle, Marek Michalkiewicz, Robert Milkowski, Aleph One, Martin Pool, Sean Reifschneider, Jan Rekorajski, Erik Troan, Theodore Ts'o, Jeff Uphoff, Myles Uyema, Savochkin Andrey Vladimirovich, Ronald Wahl, David Wood, John Wilmes, Joseph S. D. Yao and Alex O. Yuriev. Thanks are also due to Sun Microsystems, especially to Vipin Samar and Charlie Lai for their advice. At an early stage in the development of Linux-PAM, Sun graciously made the documentation for their implementation of PAM available. This act greatly accelerated the development of Linux-PAM. Copyright information for this document Copyright (c) 2006 Thorsten Kukuk <kukuk@thkukuk.de> Copyright (c) 1996-2002 Andrew G. Morgan <morgan@kernel.org> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, and the entire permission notice in its entirety, including the disclaimer of warranties. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. Alternatively, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GNU GPL are required instead of the above restrictions. (This clause is necessary due to a potential bad interaction between the GNU GPL and the restrictions contained in a BSD-style copyright.) THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH