summaryrefslogtreecommitdiff
path: root/modules/pam_ftp
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2000-06-20 22:10:38 +0000
committerAndrew G. Morgan <morgan@kernel.org>2000-06-20 22:10:38 +0000
commitea488580c42e8918445a945484de3c8a5addc761 (patch)
treec992f3ba699caafedfadc16af38e6359c3c24698 /modules/pam_ftp
Initial revision
Diffstat (limited to 'modules/pam_ftp')
-rw-r--r--modules/pam_ftp/.cvsignore1
-rw-r--r--modules/pam_ftp/Makefile88
-rw-r--r--modules/pam_ftp/README18
-rw-r--r--modules/pam_ftp/pam_ftp.c299
4 files changed, 406 insertions, 0 deletions
diff --git a/modules/pam_ftp/.cvsignore b/modules/pam_ftp/.cvsignore
new file mode 100644
index 00000000..380a834a
--- /dev/null
+++ b/modules/pam_ftp/.cvsignore
@@ -0,0 +1 @@
+dynamic
diff --git a/modules/pam_ftp/Makefile b/modules/pam_ftp/Makefile
new file mode 100644
index 00000000..0ce77a7a
--- /dev/null
+++ b/modules/pam_ftp/Makefile
@@ -0,0 +1,88 @@
+#
+# $Id$
+#
+# This Makefile controls a build process of $(TITLE) module for
+# Linux-PAM. You should not modify this Makefile (unless you know
+# what you are doing!).
+#
+# Created by Andrew Morgan <morgan@linux.kernel.org> 1996/11/14
+#
+
+TITLE=pam_ftp
+
+#
+
+LIBSRC = $(TITLE).c
+LIBOBJ = $(TITLE).o
+LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
+LIBOBJS = $(addprefix static/,$(LIBOBJ))
+
+dynamic/%.o : %.c
+ $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
+
+static/%.o : %.c
+ $(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
+
+
+ifdef DYNAMIC
+LIBSHARED = $(TITLE).so
+endif
+
+ifdef STATIC
+LIBSTATIC = lib$(TITLE).o
+endif
+
+####################### don't edit below #######################
+
+dummy:
+
+ @echo "**** This is not a top-level Makefile "
+ exit
+
+all: dirs $(LIBSHARED) $(LIBSTATIC) register
+
+dirs:
+ifdef DYNAMIC
+ $(MKDIR) ./dynamic
+endif
+ifdef STATIC
+ $(MKDIR) ./static
+endif
+
+register:
+ifdef STATIC
+ ( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
+endif
+
+ifdef DYNAMIC
+$(LIBOBJD): $(LIBSRC)
+
+$(LIBSHARED): $(LIBOBJD)
+ $(LD_D) -o $@ $(LIBOBJD)
+endif
+
+ifdef STATIC
+$(LIBOBJS): $(LIBSRC)
+
+$(LIBSTATIC): $(LIBOBJS)
+ $(LD) -r -o $@ $(LIBOBJS)
+endif
+
+install: all
+ $(MKDIR) $(FAKEROOT)$(SECUREDIR)
+ifdef DYNAMIC
+ $(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
+endif
+
+remove:
+ rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
+
+clean:
+ rm -f $(LIBOBJD) $(LIBOBJS) core *~
+
+extraclean: clean
+ rm -f *.a *.o *.so *.bak dynamic/* static/*
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
diff --git a/modules/pam_ftp/README b/modules/pam_ftp/README
new file mode 100644
index 00000000..6d03330c
--- /dev/null
+++ b/modules/pam_ftp/README
@@ -0,0 +1,18 @@
+This is the README for pam_ftp
+------------------------------
+
+This module is an authentication module that does simple ftp
+authentication.
+
+Recognized arguments:
+
+ "debug" print debug messages
+ "users=" comma separated list of users which
+ could login only with email adress
+ "ignore" allow invalid email adresses
+
+Options for:
+auth: for authentication it provides pam_authenticate() and
+ pam_setcred() hooks.
+
+Thorsten Kukuk <kukuk@suse.de>, 17. June 1999
diff --git a/modules/pam_ftp/pam_ftp.c b/modules/pam_ftp/pam_ftp.c
new file mode 100644
index 00000000..eb2c3fd9
--- /dev/null
+++ b/modules/pam_ftp/pam_ftp.c
@@ -0,0 +1,299 @@
+/* pam_ftp module */
+
+/*
+ * $Id$
+ *
+ * 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"
+
+#define _GNU_SOURCE
+#define _BSD_SOURCE
+
+#include <features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <string.h>
+
+/*
+ * 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 <security/pam_modules.h>
+#include <security/_pam_macros.h>
+
+/* 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;
+ struct pam_conv *conv;
+
+ D(("begin to converse\n"));
+
+ retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
+ if ( retval == PAM_SUCCESS ) {
+
+ 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));
+ }
+
+ 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; i<MAX_L; ++i) {
+ if (!strcmp(l[i], name)) {
+ *_user = l[0];
+ anon = 1;
+ break;
+ }
+ }
+ }
+
+ return anon;
+}
+
+/* --- authentication management functions (only) --- */
+
+PAM_EXTERN
+int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
+ ,const char **argv)
+{
+ int retval, anon=0, ctrl;
+ const char *user;
+ char *users=NULL;
+
+ /*
+ * this module checks if the user name is ftp or annonymous. If
+ * this is the case, it can set the PAM_RUSER to the entered email
+ * address and SUCCEEDS, otherwise it FAILS.
+ */
+
+ ctrl = _pam_parse(argc, argv, &users);
+
+ retval = pam_get_user(pamh, &user, NULL);
+ if (retval != PAM_SUCCESS || user == NULL) {
+ _pam_log(LOG_ERR, "no user specified");
+ return PAM_USER_UNKNOWN;
+ }
+
+ if (!(ctrl & PAM_NO_ANON)) {
+ anon = lookup(user, users, &user);
+ }
+
+ if (anon) {
+ retval = pam_set_item(pamh, PAM_USER, (const void *)user);
+ if (retval != PAM_SUCCESS || user == NULL) {
+ _pam_log(LOG_ERR, "user resetting failed");
+ return PAM_USER_UNKNOWN;
+ }
+ }
+
+ /*
+ * OK. we require an email address for user or the user's password.
+ * - build conversation and get their input.
+ */
+
+ {
+ struct pam_message msg[1], *mesg[1];
+ struct pam_response *resp=NULL;
+ const char *token;
+ char *prompt=NULL;
+ int i=0;
+
+ if (!anon) {
+ prompt = malloc(strlen(PLEASE_ENTER_PASSWORD) + strlen(user));
+ if (prompt == NULL) {
+ D(("out of memory!?"));
+ return PAM_BUF_ERR;
+ } else {
+ sprintf(prompt, PLEASE_ENTER_PASSWORD, user);
+ msg[i].msg = prompt;
+ }
+ } else {
+ msg[i].msg = GUEST_LOGIN_PROMPT;
+ }
+
+ msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
+ mesg[i] = &msg[i];
+
+ retval = converse(pamh, ++i, mesg, &resp);
+ if (prompt) {
+ _pam_overwrite(prompt);
+ _pam_drop(prompt);
+ }
+
+ if (retval != PAM_SUCCESS) {
+ if (resp != NULL)
+ _pam_drop_reply(resp,i);
+ 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)) {
+ token = strtok(resp->resp, "@");
+ 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,int flags,int argc
+ ,const char **argv)
+{
+ 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 */