123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /*
- * pam_ftp module
- *
- * Written by Andrew Morgan <morgan@linux.kernel.org> 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 <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <syslog.h>
- #include <stdarg.h>
- #include <string.h>
- #include <security/pam_modules.h>
- #include <security/_pam_macros.h>
- #include <security/pam_ext.h>
- #include "pam_inline.h"
- /* argument parsing */
- #define PAM_DEBUG_ARG 01
- #define PAM_IGNORE_EMAIL 02
- #define PAM_NO_ANON 04
- static int
- _pam_parse(pam_handle_t *pamh, int argc, const char **argv, const char **users)
- {
- int ctrl=0;
- /* step through arguments */
- for (ctrl=0; argc-- > 0; ++argv) {
- const char *str;
- /* generic options */
- if (!strcmp(*argv,"debug"))
- ctrl |= PAM_DEBUG_ARG;
- else if (!strcmp(*argv,"ignore"))
- ctrl |= PAM_IGNORE_EMAIL;
- else if ((str = pam_str_skip_prefix(*argv, "users=")) != NULL)
- *users = str;
- else
- pam_syslog(pamh, LOG_ERR, "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, const char *list, char **_user)
- {
- int anon = 0;
- if (list && *list) {
- const char *l;
- char *list_copy, *x;
- char *sptr = NULL;
- list_copy = strdup(list);
- x = list_copy;
- while (list_copy && (l = strtok_r(x, ",", &sptr))) {
- x = NULL;
- if (!strcmp(name, l)) {
- *_user = list_copy;
- anon = 1;
- break;
- }
- }
- if (*_user != list_copy) {
- free(list_copy);
- }
- } else {
- #define MAX_L 2
- static const char *l[MAX_L] = { "ftp", "anonymous" };
- int i;
- for (i=0; i<MAX_L; ++i) {
- if (!strcmp(l[i], name)) {
- *_user = strdup(l[0]);
- anon = 1;
- break;
- }
- }
- }
- return anon;
- }
- /* --- authentication management functions (only) --- */
- int
- pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
- {
- int retval, anon=0, ctrl;
- const char *user;
- char *anon_user = NULL;
- const char *users = NULL;
- /*
- * this module checks if the user name is ftp or anonymous. If
- * this is the case, it can set the PAM_RUSER to the entered email
- * address and SUCCEEDS, otherwise it FAILS.
- */
- ctrl = _pam_parse(pamh, argc, argv, &users);
- retval = pam_get_user(pamh, &user, NULL);
- if (retval != PAM_SUCCESS) {
- pam_syslog(pamh, LOG_NOTICE, "cannot determine user name: %s",
- pam_strerror(pamh, retval));
- return PAM_USER_UNKNOWN;
- }
- if (!(ctrl & PAM_NO_ANON)) {
- anon = lookup(user, users, &anon_user);
- }
- if (anon) {
- retval = pam_set_item(pamh, PAM_USER, (const void *)anon_user);
- if (retval != PAM_SUCCESS || anon_user == NULL) {
- pam_syslog(pamh, LOG_ERR, "user resetting failed");
- free(anon_user);
- return PAM_USER_UNKNOWN;
- }
- free(anon_user);
- }
- /*
- * OK. we require an email address for user or the user's password.
- * - build conversation and get their input.
- */
- {
- char *resp = NULL;
- const char *token;
- if (!anon)
- retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
- PLEASE_ENTER_PASSWORD, user);
- else
- retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
- GUEST_LOGIN_PROMPT);
- if (retval != PAM_SUCCESS) {
- _pam_overwrite (resp);
- _pam_drop (resp);
- return ((retval == PAM_CONV_AGAIN)
- ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
- }
- if (anon) {
- /* XXX: Some effort should be made to verify this email address! */
- if (!(ctrl & PAM_IGNORE_EMAIL)) {
- char *sptr = NULL;
- token = strtok_r(resp, "@", &sptr);
- retval = pam_set_item(pamh, PAM_RUSER, token);
- if ((token) && (retval == PAM_SUCCESS)) {
- token = strtok_r(NULL, "@", &sptr);
- retval = pam_set_item(pamh, PAM_RHOST, token);
- }
- }
- /* we are happy to grant anonymous access to the user */
- retval = PAM_SUCCESS;
- } else {
- /*
- * we have a password so set AUTHTOK
- */
- pam_set_item(pamh, PAM_AUTHTOK, resp);
- /*
- * this module failed, but the next one might succeed with
- * this password.
- */
- retval = PAM_AUTH_ERR;
- }
- /* clean up */
- _pam_overwrite(resp);
- _pam_drop(resp);
- /* success or failure */
- return retval;
- }
- }
- int
- pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
- int argc UNUSED, const char **argv UNUSED)
- {
- return PAM_IGNORE;
- }
- /* end of module definition */
|