/* pam_ftp module */ /* * $Id$ * * Written by Andrew Morgan 1996/3/11 * */ #define PLEASE_ENTER_PASSWORD "Password required for %s." #define GUEST_LOGIN_PROMPT "Guest login ok, " \ "send your complete e-mail address as password." /* the following is a password that "can't be correct" */ #define BLOCK_PASSWORD "\177BAD PASSWPRD\177" #include "config.h" #include #include #include #include #include #include /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module * but strongly encouraged generally) it is used to instruct the * modules include file to define the function prototypes. */ #define PAM_SM_AUTH #include #include /* some syslogging */ static void _pam_log(int err, const char *format, ...) { va_list args; va_start(args, format); openlog("PAM-ftp", LOG_CONS|LOG_PID, LOG_AUTH); vsyslog(err, format, args); va_end(args); closelog(); } static int converse(pam_handle_t *pamh, int nargs , struct pam_message **message , struct pam_response **response) { int retval; const void *void_conv; const struct pam_conv *conv; D(("begin to converse\n")); retval = pam_get_item(pamh, PAM_CONV, &void_conv); conv = (const struct pam_conv *)void_conv; if ( retval == PAM_SUCCESS && conv ) { retval = conv->conv(nargs, ( const struct pam_message ** ) message , response, conv->appdata_ptr); D(("returned from application's conversation function\n")); if ((retval != PAM_SUCCESS) && (retval != PAM_CONV_AGAIN)) { _pam_log(LOG_DEBUG, "conversation failure [%s]" , pam_strerror(pamh, retval)); } } else { _pam_log(LOG_ERR, "couldn't obtain coversation function [%s]" , pam_strerror(pamh, retval)); if (retval == PAM_SUCCESS) retval = PAM_BAD_ITEM; /* conv was NULL */ } D(("ready to return from module conversation\n")); return retval; /* propagate error status */ } /* argument parsing */ #define PAM_DEBUG_ARG 01 #define PAM_IGNORE_EMAIL 02 #define PAM_NO_ANON 04 static int _pam_parse(int argc, const char **argv, char **users) { int ctrl=0; /* step through arguments */ for (ctrl=0; argc-- > 0; ++argv) { /* generic options */ if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"users=",6)) { *users = x_strdup(6+*argv); if (*users == NULL) { ctrl |= PAM_NO_ANON; _pam_log(LOG_CRIT, "failed to duplicate user list - anon off"); } } else if (!strcmp(*argv,"ignore")) { ctrl |= PAM_IGNORE_EMAIL; } else { _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv); } } return ctrl; } /* * check if name is in list or default list. place users name in *_user * return 1 if listed 0 if not. */ static int lookup(const char *name, char *list, const char **_user) { int anon = 0; *_user = name; /* this is the default */ if (list) { const char *l; char *x; x = list; while ((l = strtok(x, ","))) { x = NULL; if (!strcmp(name, l)) { *_user = list; anon = 1; } } } else { #define MAX_L 2 static const char *l[MAX_L] = { "ftp", "anonymous" }; int i; for (i=0; iresp, "@"); retval = pam_set_item(pamh, PAM_RUSER, token); if ((token) && (retval == PAM_SUCCESS)) { token = strtok(NULL, "@"); retval = pam_set_item(pamh, PAM_RHOST, token); } } /* we are happy to grant annonymous access to the user */ retval = PAM_SUCCESS; } else { /* * we have a password so set AUTHTOK */ (void) pam_set_item(pamh, PAM_AUTHTOK, resp->resp); /* * this module failed, but the next one might succeed with * this password. */ retval = PAM_AUTH_ERR; } if (resp) { /* clean up */ _pam_drop_reply(resp, i); } /* success or failure */ return retval; } } PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED, int argc UNUSED, const char **argv UNUSED) { return PAM_IGNORE; } #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_ftp_modstruct = { "pam_ftp", pam_sm_authenticate, pam_sm_setcred, NULL, NULL, NULL, NULL, }; #endif /* end of module definition */