UNIX Authentication and Pluggable-authentication Modules (PAMs)

—A Presentation (slides)

Russell Bateman

Description of UNIX authentication, PAM authentication and configuration, how to make an application “PAM aware,” how to write a PAM (sample code), comprehensive notes and bibliography.

UNIX Authentication

Enter PAM!

PAM eliminates mess by enabling programs to authenticate transparently, regardless of scheme employed.

PAM Authentication

Pictorial of PAM Framework

(graphics) applications telnet ftp login PAM API UNIX Smart-card Kerberos mechanisms

PAM Configuration

PAM schemes across operating systems...

PAM Stacking

PAM Defaults: the “other” File

Potential Uses of PAM

Programming

Writing PAM-aware applications and PAMs

Making an Application “PAMaware”

Sample Application Code

	/*
	** pam_demo.c
	** Loop checking user/password pairs until "q"...
	**
	** Note: An application consuming pluggable-authentication module(s) (PAMs)
	** links libpam.a and libdl.a and, in this case, at least, a
	** helper library, libpam_misc.a.
	*/
	#include <stdio.h>
	#include <string.h>
	#include <security/pam_misc.h>
	#include <security/pam_appl.h>

	#define TRUE 1
	#define FALSE 0

	struct pam_conv gConv =
	{
	   misc_conv,      // convenient helper from pam_misc.h
	   ( void * ) NULL // appdata_ptr
	};

Sample Application Code

	int main( void )
	{
	   int          err;
	   pam_handle_t *pamh;

	   while( TRUE ) // loop until "q" typed...
	   {
	      char user[ 128 ];

	      printf( "Enter log-in name: " );
	      gets( user );

	      if( stricmp( user, "q" ) == 0 )
	         break;

	      if( err = pam_start( "check_user", user, &gConv, &pamh ) != PAM_SUCCESS )
	      {
	         printf( "Authentication service failed to initialize...\n" );
	         exit( err );
	      }

	      err = pam_authenticate( pamh, 0 ); // bonafide user?

	      if( err == PAM_SUCCESS )
	         err = pam_acct_mgmt( pamh, 0 ); // ...with access?

	      printf( ( err )
	               ? "Authentication failed for %s...\n"
	               : "Authentication succeeded for %s...\n", user );

	      if( err = pam_end( pamh, err ) )
	      {
	         printf( "Authentication service shutdown failed...\n" );
	         exit( err );
	      }
	   }

	   return ( err == PAM_SUCCESS ) ? 0 : err;
	}

Making a PAM

Sample Code

	/* pam_checkuser.c
	**
	** A pluggable-authentication module (PAM) is a single executable
	** binary file that can be loaded by the PAM interface library.
	** This library is configured locally using a system file, either
	** /etc/pam.conf or files off /etc/pam.d. The binary is stored on
	** the path /usr/lib/security as a “special object” module (.so).
	**
	** Except for interacting with the user (entering a password, etc.),
	** the PAM should not call the application directly. Instead, the
	** documented "conversation mechanism" should be used.
	*/
	#include <stdio.h>
	#include <security/pam_modules.h>


	int pam_sm_authenticate
	(
	   pam_handle_t *pamh,
	   int          flags,
	   int          argc,
	   const char   **argv
	)
	{
	#pragma unused( flags, argc, argv )
	   int        err;
	   const char *user;

	   // our caller doesn’t tell us what this is, but PAM will...
	   err = pam_get_user( pamh, &user, NULL );

	   if( err != PAM_SUCCESS )
	   {
	      printf( "pam_get_user: %s", pam_strerror( pamh, err ) );
	      return err;
	   }

	   if( !user || !*user )
	   {
	      printf( "User name unknown--will not supply a default...\n" );
	      return PAM_USER_UNKNOWN;
	   }

	   return PAM_SUCCESS;
	}

	int pam_sm_acct_mgmt
	(
	   pam_handle_t *pamh,
	   int          flags,
	   int          argc,
	   const char   **argv )
	{
	#pragma unused( pamh, flags, argc, argv )
	   /*
	   ** It’s not yet abundantly clear what to do here in support of
	   ** pam_demo.c. We would have to call into a UNIX authentication
	   ** piece, or Kerberos, eDirectory, etc. depending on what we
	   ** were trying to do.
	   */
	   return PAM_SUCCESS;
	}

	/* -------------------------------------------------------------------
	** The remainder of this code does nothing except satisfy the caution
	** that all six functions be supplied so that if called, they are
	** extant. They are all, therefore, mere stubs that return success.
	** -------------------------------------------------------------------
	*/
	int pam_sm_setcred
	(
	   pam_handle_t *pamh,
	   int          flags,
	   int          argc,
	   const char   **argv )
	{
	   #pragma unused( pamh, flags, argc, argv )
	   return PAM_IGNORE;
	}

likewise...

	int pam_sm_chauthtok()
	int pam_sm_open_session()
	int pam_sm_close_session()

Bibliography (Webography)

Notes on PAM

Notes recorded in presentation for use in writing a how-to or introductory document on PAM use.

PAM Types

The short of it...

In more detail...

What goes on in screensavers (for example)...

PAM Control

Module Path

Module Arguments

PAM Implementation Differences

MD5...

...takes a message of arbitrary length and produces a 128-bit “fingerprint” or “message digest” of the input. The conjecture is that it is computationally infeasible to produce two messages with the same message digest, or to produce any message having a given prespecified target message digest. Intended for digital signature applications where a large file is “compressed” in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA.

Kerberos...

...is a network authentication protocol for client/server applications using secret-key cryptography. See summary here. A free implementation is available from MIT.