Linux DevCenter    
 Published on Linux DevCenter (http://www.linuxdevcenter.com/)
 See this if you're having trouble printing code examples


Writing PAM Modules, Part One

by Jennifer Vesperman
05/16/2002

PAM stands for Pluggable Authentication Modules, and is a way of providing application independence for authentication. A PAM-enabled application calls a stack of PAM modules to run authentication, open and close sessions, and check account validity.

This is part one of a three part series on writing PAM modules. This part discusses the background information needed to write modules. Part two covers support code, and part three discusses the critical functions the module must supply.

Interactions

PAM modules provide the actual services that the application expects. The application calls PAM and requests service from one of the four module types (see next section). PAM checks the configuration file for that application, then calls the modules mentioned in the configuration file, in sequence, to provide the service.

The PAM library provides functions for both the application and the module. PAM expects a conversation function from the application, and at least one of a set of functions from the module. The requirements for modules are generally more strict than those for applications, because a module has to be able to provide some response (even just an error or a default success) to an application's request.

Module Types

PAM does more than authentication, though authentication is its primary purpose. It also provides for account and session management, and changing authentication tokens. A PAM configuration file groups these into four module types, and requires the system administrator to define what modules the system should call when each module type is required.

The four types are:

Account
Account management, most often determining whether a user has access at this time or on this console.

Auth
Authentication, the primary reason PAM exists. Establishes whether the user is who they claim to be, using the system administrator's choice of modules. It also covers setting credentials, such as group membership.

Password
Changing the authentication token, most often a password.

Session
Performs tasks done when a user starts or ends a session, such as displaying last login, whether they have mail, or mounting directories.

Stacking

PAM modules are stacked in a configuration file. This stacking provides PAM's greatest flexibility -- no module needs to "do it all"; each can be written to perform a single task. PAM extends the Unix ethos into authentication: small programs, each doing a single task and doing it well.

Write your module to do one specific task -- whether that task is as complex as performing Kerberos authentication or as simple as sounding a chime on login. If a system administrator wants to have that task done when the user starts or ends the application, they can add your module to the PAM stack.

A stack is the list of modules of this module-type for this application, in the sequence given in the configuration file.

If a stack succeeds, the application receives a PAM_SUCCESS response code and usually continues to its next task. If a stack fails, the application receives one of a number of failure codes and responds to it. A stack's success depends on the control flag the system administrator has given to each of the stack's modules. The simple versions of the control flags are:

required
Must succeed. If it fails, all other modules run but the stack returns a failure.

requisite
Must succeed. If it fails, no other module in this stack is executed. Failure is reported immediately. The failure code is that of the first module in the stack to fail.

sufficient
If this module succeeds, the whole stack succeeds. Later modules are not executed. Success is reported immediately. Failure does not prevent the stack from succeeding.

optional
Does not affect success or failure, so long as at least one non-optional module succeeds or fails.

For a more complete understanding of Linux-PAM stacks from a system administrator's point of view, see the Linux-PAM System Administrator's Guide.

What Modules Can Do

PAM modules are not limited to traditional authentication. Modules in the authentication category can authenticate by any means you can implement -- from just asking "are you foo? (Y/N)" to biometric tests. Authentication category modules can also perform tests or functions that might be useful for a system administrator to do while authentication is occurring; for example, the pam_env module sets or unsets environment variables during the authentication phase, and the pam_group module sets the user's group memberships.

Account modules are used to determine whether the user can access the account. pam_time and pam_nologin are typical account modules, and limit user access by time of day or week, or by the traditional "nologin" system.

The session module pam_lastlog logs the user's login and logout times to the var/log/lastlog file. Another commonly used module, pam_limits, restricts the user's use of system resources. Session modules usually manage tasks which are performed or triggered when a session is opened or closed.

An extremely useful password module is pam_cracklib, which provides a number of checks for too-easy passwords. It doesn't actually change the password, just tests for a bad one and then passes the tested password to the next module on the stack. Traditional Unix password management is performed by the pam_unix module.

The most important thing to realise about writing PAM modules is that they stack, so your module doesn't have to "do it all." If you think of something useful to do during standard Unix login or logout, you can write a small module to just do that one thing, then stack it next to pam_unix. You don't have to rewrite or hack pam_unix to get that one thing done.

Requirements

Function Independence

Most applications will call authentication first, then account, open the session, potentially change the authentication token with password, then close the session. This is not guaranteed, however. Modules must be able to be called independently, in any sequence.

The module must ensure that it behaves appropriately regardless of whether or not other sections have been run -- such as if password is called without authentication, or a session is opened without account management.

Module Completeness

It is perfectly acceptable to write a module which is only supposed to be called as one module type. However, for user friendliness, it can be a good idea to write functions that respond to requests for the other module types. These spurious functions should return either PAM_SERVICE_ERR or PAM_IGNORE.

Required Flags

The PAM_SILENT flag must be accepted by any module. It is passed in the flags parameter of all the functions. If the PAM_SILENT flag (which is logically ORed with any other flags) is on, the module must not pass any text errors or warnings to the application.

Argument Passing

PAM reads the configuration file for the application, parses the stack for the module type, parses the line for the specific module, and passes the appropriate arguments to the module. Each function has the parameters argc and argv, which are the count of the number of arguments and an array of pointers to the arguments, respectively.

These are similar to the parameters of the function main() in C, however, argv[0] is an argument and not the name of the module.

Generic Arguments

There are a number of arguments that all modules can expect they might be passed. A module should implement these modules (with one possible exception), but should not react to their absence.

debug
Send debug data to the system logs using syslog().

expose_account
If your module supports it, display appropriate information about user accounts, such as displaying the user's real name rather than the username in messages.

no_warn
Don't send warnings to the application.

try_first_pass
Retrieve a token from PAM_AUTHTOK and try it for this module. If it fails, ask the user for an authentication token.

use_first_pass
Retrieve a token from PAM_AUTHTOK and use it for this module. If it fails, the module fails.

use_mapped_pass
Applying this argument may cause you to break local laws regarding encryption. If so, Do not do it. No one wants anyone to get into legal trouble for writing code. If you can legally do so, the module should use the existing authentication token from the PAM_AUTHTOK item, and use it as a key to retrieve the authentication token for this module.

Learning the Korn Shell

Related Reading

Learning the Korn Shell
By Bill Rosenblatt, Arnold Robbins

Final Words

This is part one of a three-part series on writing PAM modules. Part two discusses managing a Linux-PAM environment, interacting with the user, and getting and setting module data. Part three discusses the functions a module is required to provide, security issues, and response codes.

Further Reading

Jennifer Vesperman is the author of Essential CVS. She writes for the O'Reilly Network, the Linux Documentation Project, and occasionally Linux.Com.


Return to the Linux DevCenter.

Copyright © 2009 O'Reilly Media, Inc.