Book Image

Pluggable Authentication Modules: The Definitive Guide to PAM for Linux SysAdmins and C Developers

By : Kenneth Geisshirt
Book Image

Pluggable Authentication Modules: The Definitive Guide to PAM for Linux SysAdmins and C Developers

By: Kenneth Geisshirt

Overview of this book

<p>PAM-aware applications reduce the complexity of authentication. With PAM you can use the same user database for every login process. PAM also supports different authentication processes as required. Moreover, PAM is a well-defined API, and PAM-aware applications will not break if you change the underlying authentication configuration.<br /><br />The PAM framework is widely used by most Linux distributions for authentication purposes. Originating from Solaris 2.6 ten years ago, PAM is used today by most proprietary and free UNIX operating systems including GNU/Linux, FreeBSD, and Solaris, following both the design concept and the practical details. PAM is thus a unifying technology for authentication mechanisms in UNIX. <br /><br />PAM is a modular and flexible authentication management layer that sits between Linux applications and the native underlying authentication system. PAM can be implemented with various applications without having to recompile the applications to specifically support PAM.</p>
Table of Contents (13 chapters)

The ssh_tunnels Module


The example of a small PAM module is the ssh_tunnels module. The module initiates a number of SSH tunnels for the user when he or she logs in. SSH tunnels tend to close when they are not used for a while, and the autossh program wraps the SSH client in order to prevent this (or more precisely—autossh will reconnect). The module use the autossh program instead of the plain SSH client.

/* pam_tunnels module */

/*
 * based on the pam_deny module (Linux PAM)
 */


#define PAM_SM_SESSION

#include <security/pam_modules.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>
#include <syslog.h>

/* --- session management --- */

PAM_EXTERN int
pam_sm_open_session(pam_handle_t *pamh, int flags,
                    int argc, const char **argv)
{

  FILE *conffile;
  char *conffilename;
  const char *username = NULL;
  char *lport, *rport, *host;
  char cmdline[256], line[256];
  struct passwd *pwd = malloc(sizeof(struct passwd));

  if (pam_get_user(pamh, &username, NULL) != PAM_SUCCESS) {
    syslog(LOG_ERR, "cannot determine user name");
    return PAM_USER_UNKNOWN;
  }
  pwd = getpwnam(username);
  conffilename = calloc(sizeof(char), strlen(pwd->pw_dir)+20);
  sprintf(conffilename, "%s/.pam_tunnels.conf", pwd->pw_dir);
  conffile = fopen(conffilename, "r");
  while ((fscanf(conffile, "%s\n", line)) != EOF) {
    lport = strtok(line, ":");
    host = strtok(NULL, ":");
    rport = strtok(NULL, ":");
    sprintf(cmdline, "autossh -f -N -L %s:%s:%s %s", lport, host, rport, host);
    system(cmdline);
  }
  fclose(conffile);
  free(conffilename);
  return PAM_SUCCESS;
}
PAM_EXTERN int
pam_sm_close_session(pam_handle_t *pamh, int flags,
                    int argc, const char **argv)
{
  return PAM_SUCCESS;
}


/* end of module definition */

/* static module data */
#ifdef PAM_STATIC
struct pam_module _pam_deny_modstruct = {
    "pam_deny",
    NULL,
    NULL,
    NULL,
    pam_sm_open_session,
    pam_sm_close_session,
    NULL
};
#endif