(root)/
Linux-PAM-1.5.3/
modules/
pam_ftp/
pam_ftp.c
       1  /*
       2   * pam_ftp module
       3   *
       4   * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
       5   */
       6  
       7  #define PLEASE_ENTER_PASSWORD "Password required for %s."
       8  #define GUEST_LOGIN_PROMPT "Guest login ok, " \
       9  "send your complete e-mail address as password."
      10  
      11  /* the following is a password that "can't be correct" */
      12  #define BLOCK_PASSWORD "\177BAD PASSWPRD\177"
      13  
      14  #include "config.h"
      15  
      16  #include <stdio.h>
      17  #include <stdlib.h>
      18  #include <unistd.h>
      19  #include <syslog.h>
      20  #include <stdarg.h>
      21  #include <string.h>
      22  
      23  #include <security/pam_modules.h>
      24  #include <security/_pam_macros.h>
      25  #include <security/pam_ext.h>
      26  #include "pam_inline.h"
      27  
      28  /* argument parsing */
      29  
      30  #define PAM_DEBUG_ARG       01
      31  #define PAM_IGNORE_EMAIL    02
      32  #define PAM_NO_ANON         04
      33  
      34  static int
      35  _pam_parse(pam_handle_t *pamh, int argc, const char **argv, const char **users)
      36  {
      37      int ctrl=0;
      38  
      39      /* step through arguments */
      40      for (ctrl=0; argc-- > 0; ++argv) {
      41  	const char *str;
      42  
      43  	/* generic options */
      44  
      45  	if (!strcmp(*argv,"debug"))
      46  	    ctrl |= PAM_DEBUG_ARG;
      47  	else if (!strcmp(*argv,"ignore"))
      48  	    ctrl |= PAM_IGNORE_EMAIL;
      49  	else if ((str = pam_str_skip_prefix(*argv, "users=")) != NULL)
      50  	    *users = str;
      51  	else
      52  	    pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
      53      }
      54  
      55      return ctrl;
      56  }
      57  
      58  /*
      59   * check if name is in list or default list. place users name in *_user
      60   * return 1 if listed 0 if not.
      61   */
      62  
      63  static int lookup(const char *name, const char *list, char **_user)
      64  {
      65      int anon = 0;
      66  
      67      if (list && *list) {
      68  	const char *l;
      69  	char *list_copy, *x;
      70  	char *sptr = NULL;
      71  
      72  	list_copy = strdup(list);
      73  	x = list_copy;
      74  	while (list_copy && (l = strtok_r(x, ",", &sptr))) {
      75  	    x = NULL;
      76  	    if (!strcmp(name, l)) {
      77  		*_user = list_copy;
      78  		anon = 1;
      79  		break;
      80  	    }
      81  	}
      82  	if (*_user != list_copy) {
      83  	    free(list_copy);
      84  	}
      85      } else {
      86  #define MAX_L 2
      87  	static const char *l[MAX_L] = { "ftp", "anonymous" };
      88  	int i;
      89  
      90  	for (i=0; i<MAX_L; ++i) {
      91  	    if (!strcmp(l[i], name)) {
      92  		*_user = strdup(l[0]);
      93  		anon = 1;
      94  		break;
      95  	    }
      96  	}
      97      }
      98  
      99      return anon;
     100  }
     101  
     102  /* --- authentication management functions (only) --- */
     103  
     104  int
     105  pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
     106  		     int argc, const char **argv)
     107  {
     108      int retval, anon=0, ctrl;
     109      const char *user;
     110      char *anon_user = NULL;
     111      const char *users = NULL;
     112  
     113      /*
     114       * this module checks if the user name is ftp or anonymous. If
     115       * this is the case, it can set the PAM_RUSER to the entered email
     116       * address and SUCCEEDS, otherwise it FAILS.
     117       */
     118  
     119      ctrl = _pam_parse(pamh, argc, argv, &users);
     120  
     121      retval = pam_get_user(pamh, &user, NULL);
     122      if (retval != PAM_SUCCESS) {
     123  	pam_syslog(pamh, LOG_NOTICE, "cannot determine user name: %s",
     124  		   pam_strerror(pamh, retval));
     125  	return PAM_USER_UNKNOWN;
     126      }
     127  
     128      if (!(ctrl & PAM_NO_ANON)) {
     129  	anon = lookup(user, users, &anon_user);
     130      }
     131  
     132      if (anon) {
     133  	retval = pam_set_item(pamh, PAM_USER, (const void *)anon_user);
     134  	if (retval != PAM_SUCCESS || anon_user == NULL) {
     135  	    pam_syslog(pamh, LOG_ERR, "user resetting failed");
     136  	    free(anon_user);
     137  
     138  	    return PAM_USER_UNKNOWN;
     139  	}
     140  	free(anon_user);
     141      }
     142  
     143      /*
     144       * OK. we require an email address for user or the user's password.
     145       * - build conversation and get their input.
     146       */
     147  
     148      {
     149  	char *resp = NULL;
     150  	const char *token;
     151  
     152  	if (!anon)
     153  	  retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
     154  			       PLEASE_ENTER_PASSWORD, user);
     155  	else
     156  	  retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
     157  			       GUEST_LOGIN_PROMPT);
     158  
     159  	if (retval != PAM_SUCCESS) {
     160  	    pam_overwrite_string (resp);
     161  	    _pam_drop (resp);
     162  	    return ((retval == PAM_CONV_AGAIN)
     163  		    ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
     164  	}
     165  
     166  	if (anon) {
     167  	  /* XXX: Some effort should be made to verify this email address! */
     168  
     169  	    if (!(ctrl & PAM_IGNORE_EMAIL)) {
     170  		char *sptr = NULL;
     171  		token = strtok_r(resp, "@", &sptr);
     172  		retval = pam_set_item(pamh, PAM_RUSER, token);
     173  
     174  		if ((token) && (retval == PAM_SUCCESS)) {
     175  		    token = strtok_r(NULL, "@", &sptr);
     176  		    retval = pam_set_item(pamh, PAM_RHOST, token);
     177  		}
     178  	    }
     179  
     180  	    /* we are happy to grant anonymous access to the user */
     181  	    retval = PAM_SUCCESS;
     182  
     183  	} else {
     184  	    /*
     185  	     * we have a password so set AUTHTOK
     186  	     */
     187  
     188  	    pam_set_item(pamh, PAM_AUTHTOK, resp);
     189  
     190  	    /*
     191  	     * this module failed, but the next one might succeed with
     192  	     * this password.
     193  	     */
     194  
     195  	    retval = PAM_AUTH_ERR;
     196  	}
     197  
     198  	/* clean up */
     199  	pam_overwrite_string(resp);
     200  	_pam_drop(resp);
     201  
     202  	/* success or failure */
     203  
     204  	return retval;
     205      }
     206  }
     207  
     208  int
     209  pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
     210  		int argc UNUSED, const char **argv UNUSED)
     211  {
     212       return PAM_IGNORE;
     213  }
     214  
     215  /* end of module definition */