(root)/
Linux-PAM-1.5.3/
libpam/
pam_start.c
       1  /* pam_start.c */
       2  
       3  /* Creator Marc Ewing
       4   * Maintained by AGM
       5   *
       6   * $Id$
       7   *
       8   */
       9  
      10  #include "pam_private.h"
      11  
      12  #include <ctype.h>
      13  #include <stdlib.h>
      14  #include <unistd.h>
      15  #include <string.h>
      16  #include <syslog.h>
      17  
      18  static int _pam_start_internal (
      19      const char *service_name,
      20      const char *user,
      21      const struct pam_conv *pam_conversation,
      22      const char *confdir,
      23      pam_handle_t **pamh)
      24  {
      25      D(("called pam_start: [%s] [%s] [%p] [%p]"
      26         ,service_name, user, pam_conversation, pamh));
      27  
      28      if (pamh == NULL) {
      29  	pam_syslog(NULL, LOG_CRIT,
      30  		   "pam_start: invalid argument: pamh == NULL");
      31  	return (PAM_SYSTEM_ERR);
      32      }
      33  
      34      if (service_name == NULL) {
      35  	pam_syslog(NULL, LOG_CRIT,
      36  		   "pam_start: invalid argument: service == NULL");
      37  	return (PAM_SYSTEM_ERR);
      38      }
      39  
      40      if (pam_conversation == NULL) {
      41  	pam_syslog(NULL, LOG_CRIT,
      42  		   "pam_start: invalid argument: conv == NULL");
      43  	return (PAM_SYSTEM_ERR);
      44      }
      45  
      46      if ((*pamh = calloc(1, sizeof(**pamh))) == NULL) {
      47  	pam_syslog(NULL, LOG_CRIT, "pam_start: calloc failed for *pamh");
      48  	return (PAM_BUF_ERR);
      49      }
      50  
      51      /* All service names should be files below /etc/pam.d and nothing
      52         else. Forbid paths. */
      53      if (strrchr(service_name, '/') != NULL)
      54  	service_name = strrchr(service_name, '/') + 1;
      55  
      56      /* Mark the caller as the application - permission to do certain
      57         things is limited to a module or an application */
      58  
      59      __PAM_TO_APP(*pamh);
      60  
      61      if (((*pamh)->service_name = _pam_strdup(service_name)) == NULL) {
      62  	pam_syslog(*pamh, LOG_CRIT,
      63  		   "pam_start: _pam_strdup failed for service name");
      64  	_pam_drop(*pamh);
      65  	return (PAM_BUF_ERR);
      66      } else {
      67  	char *tmp;
      68  
      69  	for (tmp=(*pamh)->service_name; *tmp; ++tmp)
      70  	    *tmp = tolower(*tmp);                   /* require lower case */
      71      }
      72  
      73      if (user) {
      74  	if (((*pamh)->user = _pam_strdup(user)) == NULL) {
      75  	    pam_syslog(*pamh, LOG_CRIT,
      76  		       "pam_start: _pam_strdup failed for user");
      77  	    _pam_drop((*pamh)->service_name);
      78  	    _pam_drop(*pamh);
      79  	    return (PAM_BUF_ERR);
      80  	}
      81      } else
      82  	(*pamh)->user = NULL;
      83  
      84      if (confdir) {
      85  	if (((*pamh)->confdir = _pam_strdup(confdir)) == NULL) {
      86  	    pam_syslog(*pamh, LOG_CRIT,
      87  		       "pam_start: _pam_strdup failed for confdir");
      88  	    _pam_drop((*pamh)->service_name);
      89  	    _pam_drop((*pamh)->user);
      90  	    _pam_drop(*pamh);
      91  	    return (PAM_BUF_ERR);
      92  	}
      93      } else
      94  	(*pamh)->confdir = NULL;
      95  
      96      (*pamh)->tty = NULL;
      97      (*pamh)->prompt = NULL;              /* prompt for pam_get_user() */
      98      (*pamh)->ruser = NULL;
      99      (*pamh)->rhost = NULL;
     100      (*pamh)->authtok = NULL;
     101      (*pamh)->oldauthtok = NULL;
     102      (*pamh)->fail_delay.delay_fn_ptr = NULL;
     103      (*pamh)->former.choice = PAM_NOT_STACKED;
     104      (*pamh)->former.substates = NULL;
     105  #ifdef HAVE_LIBAUDIT
     106      (*pamh)->audit_state = 0;
     107  #endif
     108      (*pamh)->xdisplay = NULL;
     109      (*pamh)->authtok_type = NULL;
     110      (*pamh)->authtok_verified = 0;
     111      memset (&((*pamh)->xauth), 0, sizeof ((*pamh)->xauth));
     112  
     113      if (((*pamh)->pam_conversation = (struct pam_conv *)
     114  	  malloc(sizeof(struct pam_conv))) == NULL) {
     115  	pam_syslog(*pamh, LOG_CRIT, "pam_start: malloc failed for pam_conv");
     116  	_pam_drop((*pamh)->service_name);
     117  	_pam_drop((*pamh)->user);
     118  	_pam_drop((*pamh)->confdir);
     119  	_pam_drop(*pamh);
     120  	return (PAM_BUF_ERR);
     121      } else {
     122  	memcpy((*pamh)->pam_conversation, pam_conversation,
     123  	       sizeof(struct pam_conv));
     124      }
     125  
     126      (*pamh)->data = NULL;
     127      if ( _pam_make_env(*pamh) != PAM_SUCCESS ) {
     128  	pam_syslog(*pamh,LOG_ERR,"pam_start: failed to initialize environment");
     129  	_pam_drop((*pamh)->pam_conversation);
     130  	_pam_drop((*pamh)->service_name);
     131  	_pam_drop((*pamh)->user);
     132  	_pam_drop((*pamh)->confdir);
     133  	_pam_drop(*pamh);
     134  	return PAM_ABORT;
     135      }
     136  
     137      _pam_reset_timer(*pamh);         /* initialize timer support */
     138  
     139      _pam_start_handlers(*pamh);                   /* cannot fail */
     140  
     141      /* According to the SunOS man pages, loading modules and resolving
     142       * symbols happens on the first call from the application. */
     143  
     144      if ( _pam_init_handlers(*pamh) != PAM_SUCCESS ) {
     145  	pam_syslog(*pamh, LOG_ERR, "pam_start: failed to initialize handlers");
     146  	_pam_drop_env(*pamh);                 /* purge the environment */
     147  	_pam_drop((*pamh)->pam_conversation);
     148  	_pam_drop((*pamh)->service_name);
     149  	_pam_drop((*pamh)->user);
     150  	_pam_drop((*pamh)->confdir);
     151  	_pam_drop(*pamh);
     152  	return PAM_ABORT;
     153      }
     154  
     155      D(("exiting pam_start successfully"));
     156  
     157      return PAM_SUCCESS;
     158  }
     159  
     160  int pam_start_confdir (
     161      const char *service_name,
     162      const char *user,
     163      const struct pam_conv *pam_conversation,
     164      const char *confdir,
     165      pam_handle_t **pamh)
     166  {
     167      return _pam_start_internal(service_name, user, pam_conversation,
     168  			       confdir, pamh);
     169  }
     170  
     171  int pam_start (
     172      const char *service_name,
     173      const char *user,
     174      const struct pam_conv *pam_conversation,
     175      pam_handle_t **pamh)
     176  {
     177      return _pam_start_internal(service_name, user, pam_conversation,
     178  			       NULL, pamh);
     179  }