summaryrefslogtreecommitdiffstats
path: root/libexec/ftpd
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>1999-09-19 22:05:32 +0000
committermarkm <markm@FreeBSD.org>1999-09-19 22:05:32 +0000
commit0b2fe68756570c146bda89ff69a3d209aac9f8be (patch)
tree8d4295813f9b149f83950d8b50c74d07c35aa987 /libexec/ftpd
parentfc84b1a733b5c4774a2dcd8035e4f71948716a55 (diff)
downloadFreeBSD-src-0b2fe68756570c146bda89ff69a3d209aac9f8be.zip
FreeBSD-src-0b2fe68756570c146bda89ff69a3d209aac9f8be.tar.gz
Fix for new Kerberos4. Make a fist cut at PAM-ising while I'm here.
Diffstat (limited to 'libexec/ftpd')
-rw-r--r--libexec/ftpd/Makefile12
-rw-r--r--libexec/ftpd/ftpd.c160
2 files changed, 145 insertions, 27 deletions
diff --git a/libexec/ftpd/Makefile b/libexec/ftpd/Makefile
index bd5453f..ad5d142 100644
--- a/libexec/ftpd/Makefile
+++ b/libexec/ftpd/Makefile
@@ -17,13 +17,11 @@ LSDIR= ../../bin/ls
SRCS+= ls.c cmp.c print.c stat_flags.c util.c
CFLAGS+=-DINTERNAL_LS -Dmain=ls_main -I${.CURDIR}/${LSDIR}
-.if exists(${DESTDIR}/usr/lib/libkrb.a) && defined(MAKE_KERBEROS4)
-.PATH: ${.CURDIR}/../../lib/libpam/modules/pam_kerberosIV
-SRCS+= klogin.c
-LDADD+= -lkrb -ldes -lcom_err
-DPADD+= ${LIBKRB} ${LIBDES} ${LIBCOM_ERR}
-CFLAGS+=-DKERBEROS
-DISTRIBUTION= krb
+.if defined(NOPAM)
+CFLAGS+=-DNOPAM
+.else
+DPADD+= ${LIBPAM}
+LDADD+= ${MINUSLPAM}
.endif
.include <bsd.prog.mk>
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 52321ef..0f9d20c 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -94,6 +94,10 @@ static const char rcsid[] =
#include <skey.h>
#endif
+#if !defined(NOPAM)
+#include <security/pam_appl.h>
+#endif
+
#include "pathnames.h"
#include "extern.h"
@@ -168,19 +172,13 @@ char *ident = NULL;
static char ttyline[20];
char *tty = ttyline; /* for klogin */
-#ifdef KERBEROS
-int klogin __P((struct passwd *, char *, char *, char *));
+#if !defined(NOPAM)
+static int auth_pam __P((struct passwd**, const char*));
#endif
struct in_addr bind_address;
char *pid_file = NULL;
-#if defined(KERBEROS)
-int notickets = 1;
-int noticketsdontcomplain = 1;
-char *krbtkfile_env = NULL;
-#endif
-
/*
* Timeout intervals for retrying connections
* to hosts that don't accept PORT cmds. This
@@ -914,6 +912,132 @@ end_login()
dochroot = 0;
}
+#if !defined(NOPAM)
+
+/*
+ * the following code is stolen from imap-uw PAM authentication module and
+ * login.c
+ */
+#define COPY_STRING(s) (s ? strdup(s) : NULL)
+
+struct cred_t {
+ const char *uname; /* user name */
+ const char *pass; /* password */
+};
+typedef struct cred_t cred_t;
+
+static int
+auth_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata)
+{
+ int i;
+ cred_t *cred = (cred_t *) appdata;
+ struct pam_response *reply =
+ malloc(sizeof(struct pam_response) * num_msg);
+
+ for (i = 0; i < num_msg; i++) {
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_ON: /* assume want user name */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = COPY_STRING(cred->uname);
+ /* PAM frees resp. */
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* assume want password */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = COPY_STRING(cred->pass);
+ /* PAM frees resp. */
+ break;
+ case PAM_TEXT_INFO:
+ case PAM_ERROR_MSG:
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = NULL;
+ break;
+ default: /* unknown message style */
+ free(reply);
+ return PAM_CONV_ERR;
+ }
+ }
+
+ *resp = reply;
+ return PAM_SUCCESS;
+}
+
+/*
+ * Attempt to authenticate the user using PAM. Returns 0 if the user is
+ * authenticated, or 1 if not authenticated. If some sort of PAM system
+ * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
+ * function returns -1. This can be used as an indication that we should
+ * fall back to a different authentication mechanism.
+ */
+static int
+auth_pam(struct passwd **ppw, const char *pass)
+{
+ pam_handle_t *pamh = NULL;
+ const char *tmpl_user;
+ const void *item;
+ int rval;
+ int e;
+ cred_t auth_cred = { (*ppw)->pw_name, pass };
+ struct pam_conv conv = { &auth_conv, &auth_cred };
+
+ e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
+ if (e != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
+ return -1;
+ }
+
+ e = pam_authenticate(pamh, 0);
+ switch (e) {
+ case PAM_SUCCESS:
+ /*
+ * With PAM we support the concept of a "template"
+ * user. The user enters a login name which is
+ * authenticated by PAM, usually via a remote service
+ * such as RADIUS or TACACS+. If authentication
+ * succeeds, a different but related "template" name
+ * is used for setting the credentials, shell, and
+ * home directory. The name the user enters need only
+ * exist on the remote authentication server, but the
+ * template name must be present in the local password
+ * database.
+ *
+ * This is supported by two various mechanisms in the
+ * individual modules. However, from the application's
+ * point of view, the template user is always passed
+ * back as a changed value of the PAM_USER item.
+ */
+ if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
+ PAM_SUCCESS) {
+ tmpl_user = (const char *) item;
+ if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
+ *ppw = getpwnam(tmpl_user);
+ } else
+ syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
+ pam_strerror(pamh, e));
+ rval = 0;
+ break;
+
+ case PAM_AUTH_ERR:
+ case PAM_USER_UNKNOWN:
+ case PAM_MAXTRIES:
+ rval = 1;
+ break;
+
+ default:
+ syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
+ rval = -1;
+ break;
+ }
+
+ if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
+ rval = -1;
+ }
+ return rval;
+}
+
+#endif /* !defined(NOPAM) */
+
void
pass(passwd)
char *passwd;
@@ -934,9 +1058,9 @@ pass(passwd)
rval = 1; /* failure below */
goto skip;
}
-#if defined(KERBEROS)
- rval = klogin(pw, "", hostname, passwd);
- if (rval == 0)
+#if !defined(NOPAM)
+ rval = auth_pam(&pw, passwd);
+ if (rval >= 0)
goto skip;
#endif
#ifdef SKEY
@@ -953,7 +1077,7 @@ pass(passwd)
skip:
/*
* If rval == 1, the user failed the authentication check
- * above. If rval == 0, either Kerberos or local authentication
+ * above. If rval == 0, either PAM or local authentication
* succeeded.
*/
if (rval) {
@@ -1085,14 +1209,14 @@ skip:
if (thishost != firsthost)
snprintf(proctitle, sizeof(proctitle),
"%s: anonymous(%s)/%.*s", remotehost, hostname,
- sizeof(proctitle) - sizeof(remotehost) -
- sizeof(": anonymous/"), passwd);
+ (int)(sizeof(proctitle) - sizeof(remotehost) -
+ sizeof(": anonymous/")), passwd);
else
#endif
snprintf(proctitle, sizeof(proctitle),
"%s: anonymous/%.*s", remotehost,
- sizeof(proctitle) - sizeof(remotehost) -
- sizeof(": anonymous/"), passwd);
+ (int)(sizeof(proctitle) - sizeof(remotehost) -
+ sizeof(": anonymous/")), passwd);
setproctitle("%s", proctitle);
#endif /* SETPROCTITLE */
if (logging)
@@ -1937,10 +2061,6 @@ dologout(status)
if (logged_in) {
(void) seteuid((uid_t)0);
ftpd_logwtmp(ttyline, "", "");
-#if defined(KERBEROS)
- if (!notickets && krbtkfile_env)
- unlink(krbtkfile_env);
-#endif
}
/* beware of flushing buffers after a SIGPIPE */
_exit(status);
OpenPOWER on IntegriCloud