(root)/
Linux-PAM-1.5.3/
modules/
pam_shells/
pam_shells.c
       1  /*
       2   * pam_shells module
       3   *
       4   * by Erik Troan <ewt@redhat.com>, Red Hat Software.
       5   * August 5, 1996.
       6   * This code shamelessly ripped from the pam_securetty module.
       7   */
       8  
       9  #include "config.h"
      10  
      11  #include <pwd.h>
      12  #include <stdarg.h>
      13  #include <string.h>
      14  #include <stdio.h>
      15  #include <stdlib.h>
      16  #include <stdbool.h>
      17  #include <sys/stat.h>
      18  #include <syslog.h>
      19  #include <unistd.h>
      20  #if defined (USE_ECONF)	&& defined (VENDORDIR)
      21  #include <libeconf.h>
      22  #endif
      23  
      24  #include <security/pam_modules.h>
      25  #include <security/pam_modutil.h>
      26  #include <security/pam_ext.h>
      27  
      28  #define SHELL_FILE "/etc/shells"
      29  #define SHELLS "shells"
      30  #define ETCDIR "/etc"
      31  #define DEFAULT_SHELL "/bin/sh"
      32  
      33  static bool check_file(const char *filename, const void *pamh)
      34  {
      35      struct stat sb;
      36  
      37      if (stat(filename, &sb)) {
      38  	pam_syslog(pamh, LOG_ERR, "Cannot stat %s: %m", filename);
      39  	return false;		/* must have /etc/shells */
      40      }
      41  
      42      if ((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) {
      43  	pam_syslog(pamh, LOG_ERR,
      44  		   "%s is either world writable or not a normal file",
      45  		   filename);
      46  	return false;
      47      }
      48      return true;
      49  }
      50  
      51  static int perform_check(pam_handle_t *pamh)
      52  {
      53      int retval = PAM_AUTH_ERR;
      54      const char *userName;
      55      const char *userShell;
      56      struct passwd * pw;
      57  
      58      retval = pam_get_user(pamh, &userName, NULL);
      59      if (retval != PAM_SUCCESS) {
      60  	return PAM_SERVICE_ERR;
      61      }
      62  
      63      pw = pam_modutil_getpwnam(pamh, userName);
      64      if (pw == NULL || pw->pw_shell == NULL) {
      65  	return PAM_AUTH_ERR;		/* user doesn't exist */
      66      }
      67      userShell = pw->pw_shell;
      68      if (userShell[0] == '\0')
      69  	userShell = DEFAULT_SHELL;
      70  
      71  #if defined (USE_ECONF)	&& defined (VENDORDIR)
      72      size_t size = 0;
      73      econf_err error;
      74      char **keys;
      75      econf_file *key_file;
      76  
      77      error = econf_readDirsWithCallback(&key_file,
      78  				       VENDORDIR,
      79  				       ETCDIR,
      80  				       SHELLS,
      81  				       NULL,
      82  				       "", /* key only */
      83  				       "#", /* comment */
      84  				       check_file, pamh);
      85      if (error) {
      86  	pam_syslog(pamh, LOG_ERR,
      87  		   "Cannot parse shell files: %s",
      88  		   econf_errString(error));
      89  	return PAM_AUTH_ERR;
      90      }
      91  
      92      error = econf_getKeys(key_file, NULL, &size, &keys);
      93      if (error) {
      94  	pam_syslog(pamh, LOG_ERR,
      95  		   "Cannot evaluate entries in shell files: %s",
      96  		   econf_errString(error));
      97  	econf_free (key_file);
      98  	return PAM_AUTH_ERR;
      99      }
     100  
     101      retval = 1;
     102      for (size_t i = 0; i < size; i++) {
     103  	retval = strcmp(keys[i], userShell);
     104          if (!retval)
     105  	   break;
     106      }
     107      econf_free (key_file);
     108  #else
     109      char shellFileLine[256];
     110      FILE * shellFile;
     111  
     112      if (!check_file(SHELL_FILE, pamh))
     113          return PAM_AUTH_ERR;
     114  
     115      shellFile = fopen(SHELL_FILE,"r");
     116      if (shellFile == NULL) {       /* Check that we opened it successfully */
     117  	pam_syslog(pamh, LOG_ERR, "Error opening %s: %m", SHELL_FILE);
     118  	return PAM_SERVICE_ERR;
     119      }
     120  
     121      retval = 1;
     122  
     123      while(retval && (fgets(shellFileLine, 255, shellFile) != NULL)) {
     124  	if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
     125  	    shellFileLine[strlen(shellFileLine) - 1] = '\0';
     126  	retval = strcmp(shellFileLine, userShell);
     127      }
     128  
     129      fclose(shellFile);
     130   #endif
     131  
     132      if (retval) {
     133  	return PAM_AUTH_ERR;
     134      } else {
     135  	return PAM_SUCCESS;
     136      }
     137  }
     138  
     139  /* --- authentication management functions (only) --- */
     140  
     141  int pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
     142  		        int argc UNUSED, const char **argv UNUSED)
     143  {
     144      return perform_check(pamh);
     145  }
     146  
     147  int pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
     148  		   int argc UNUSED, const char **argv UNUSED)
     149  {
     150       return PAM_SUCCESS;
     151  }
     152  
     153  /* --- account management functions (only) --- */
     154  
     155  int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
     156  		     int argc UNUSED, const char **argv UNUSED)
     157  {
     158      return perform_check(pamh);
     159  }
     160  
     161  /* end of module definition */