summaryrefslogtreecommitdiff
path: root/usr.sbin/popa3d
diff options
context:
space:
mode:
authorCamiel Dobbelaar <camield@cvs.openbsd.org>2001-09-21 20:22:07 +0000
committerCamiel Dobbelaar <camield@cvs.openbsd.org>2001-09-21 20:22:07 +0000
commitf2234427fb48ac1ddff2888d88175a676f349d57 (patch)
treeafeb388eb8d1d7da514b1395ecb5fe6502adc2aa /usr.sbin/popa3d
parentfa205f9135d5a17814a8cee8cd9022324337f970 (diff)
update to 0.4.9.4:
- stand-alone or inetd selectable from command-line (-D = daemon mode) - logging priorities more accurate - chroots to empty dir - tcp wrappers support
Diffstat (limited to 'usr.sbin/popa3d')
-rw-r--r--usr.sbin/popa3d/Makefile14
-rw-r--r--usr.sbin/popa3d/auth_passwd.c8
-rw-r--r--usr.sbin/popa3d/mailbox.c49
-rw-r--r--usr.sbin/popa3d/mailbox.h6
-rw-r--r--usr.sbin/popa3d/params.h62
-rw-r--r--usr.sbin/popa3d/pop_auth.c20
-rw-r--r--usr.sbin/popa3d/pop_auth.h7
-rw-r--r--usr.sbin/popa3d/pop_root.c99
-rw-r--r--usr.sbin/popa3d/pop_trans.c54
-rw-r--r--usr.sbin/popa3d/protocol.c19
-rw-r--r--usr.sbin/popa3d/protocol.h7
-rw-r--r--usr.sbin/popa3d/standalone.c56
-rw-r--r--usr.sbin/popa3d/startup.c66
-rw-r--r--usr.sbin/popa3d/virtual.c18
-rw-r--r--usr.sbin/popa3d/virtual.h8
15 files changed, 358 insertions, 135 deletions
diff --git a/usr.sbin/popa3d/Makefile b/usr.sbin/popa3d/Makefile
index f1e0a6da594..9f8c7e85a53 100644
--- a/usr.sbin/popa3d/Makefile
+++ b/usr.sbin/popa3d/Makefile
@@ -1,10 +1,16 @@
-# $OpenBSD: Makefile,v 1.1 2001/08/19 13:05:57 deraadt Exp $
+# $OpenBSD: Makefile,v 1.2 2001/09/21 20:22:06 camield Exp $
PROG= popa3d
-
+MAN= popa3d.8
SRCS= auth_passwd.c database.c mailbox.c misc.c pop_auth.c pop_root.c \
- pop_trans.c protocol.c standalone.c virtual.c
+ pop_trans.c protocol.c standalone.c startup.c virtual.c
-MAN= popa3d.8
+CFLAGS+=-Wall -Werror -DHAVE_PROGNAME
.include <bsd.prog.mk>
+
+.if (${TCP_WRAPPERS:L} == "yes")
+CFLAGS+= -DLIBWRAP
+LDADD+= -lwrap
+DPADD+= ${LIBWRAP}
+.endif
diff --git a/usr.sbin/popa3d/auth_passwd.c b/usr.sbin/popa3d/auth_passwd.c
index 924fc03981d..d0503ac7aa7 100644
--- a/usr.sbin/popa3d/auth_passwd.c
+++ b/usr.sbin/popa3d/auth_passwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth_passwd.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: auth_passwd.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* The /etc/passwd authentication routine.
@@ -8,7 +8,7 @@
#if AUTH_PASSWD && !VIRTUAL_ONLY
-#define _XOPEN_SOURCE
+#define _XOPEN_SOURCE 4
#define _XOPEN_SOURCE_EXTENDED
#define _XOPEN_VERSION 4
#define _XPG4_2
@@ -17,11 +17,11 @@
#include <pwd.h>
#include <sys/types.h>
-struct passwd *auth_userpass(char *user, char *pass, char **mailbox)
+struct passwd *auth_userpass(char *user, char *pass, int *known)
{
struct passwd *pw, *result;
- if ((pw = getpwnam(user))) *mailbox = user;
+ *known = (pw = getpwnam(user)) != NULL;
endpwent();
result = NULL;
diff --git a/usr.sbin/popa3d/mailbox.c b/usr.sbin/popa3d/mailbox.c
index 3316ed26b4a..b67f2655838 100644
--- a/usr.sbin/popa3d/mailbox.c
+++ b/usr.sbin/popa3d/mailbox.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mailbox.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: mailbox.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* Mailbox access.
@@ -50,14 +50,14 @@ static int db_compare(struct db_message *msg)
/*
* Checks if the buffer pointed to by s1, of n1 chars, starts with the
- * string s2.
+ * string s2, of n2 chars.
*/
-static int linecmp(char *s1, char *s2, int n1)
+#ifdef __GNUC__
+inline
+#endif
+static int linecmp(char *s1, int n1, char *s2, int n2)
{
- int n2;
-
- if (s1[0] != s2[0]) return 1;
- if (n1 < (n2 = strlen(s2))) return 1;
+ if (s1[0] != s2[0] || n1 < n2) return 1;
return memcmp(s1, s2, n2);
}
@@ -217,12 +217,12 @@ static int mailbox_parse(int init)
/* Check for a new message if we've just seen a blank line */
if (blank && start)
- if (!linecmp(line, "From ", length)) {
+ if (!linecmp(line, length, "From ", 5)) {
/* Process the previous one first, if exists */
if (offset) {
if (!header && !body) break;
msg.raw_size = offset - msg.raw_offset;
- msg.data_size = offset - msg.data_offset;
+ msg.data_size = offset - 1 - msg.data_offset;
MD5Final(msg.hash, &hash);
if (db_op(&msg)) break;
}
@@ -255,10 +255,10 @@ static int mailbox_parse(int init)
/* Some header lines are known to remain fixed over MUA runs */
if (header && start)
- if (!linecmp(line, "Received:", length) ||
- !linecmp(line, "Date:", length) ||
- !linecmp(line, "Message-Id:", length) ||
- !linecmp(line, "Subject:", length))
+ if (!linecmp(line, length, "Received:", 9) ||
+ !linecmp(line, length, "Date:", 5) ||
+ !linecmp(line, length, "Message-Id:", 11) ||
+ !linecmp(line, length, "Subject:", 8))
fixed = 1;
/* We can hash all fragments of those lines (until "end"), for UIDL */
@@ -275,7 +275,7 @@ static int mailbox_parse(int init)
if (offset != mailbox_size) return 1;
if (!header && !body) return 1;
msg.raw_size = offset - msg.raw_offset;
- msg.data_size = offset - msg.data_offset;
+ msg.data_size = offset - blank - msg.data_offset;
MD5Final(msg.hash, &hash);
if (db_op(&msg)) return 1;
@@ -303,12 +303,17 @@ int mailbox_open(char *spool, char *mailbox)
return errno != ENOENT;
}
+ if (!S_ISREG(stat.st_mode)) {
+ free(pathname);
+ return 1;
+ }
+
if (!stat.st_size) {
free(pathname);
return 0;
}
- mailbox_fd = open(pathname, O_RDWR);
+ mailbox_fd = open(pathname, O_RDWR | O_NOCTTY);
free(pathname);
@@ -349,14 +354,18 @@ static int mailbox_changed(void)
int mailbox_get(struct db_message *msg, int lines)
{
- if (mailbox_changed()) return 1;
+ if (mailbox_changed()) return POP_CRASH_SERVER;
+
+ if (lseek(mailbox_fd, msg->data_offset, SEEK_SET) < 0)
+ return POP_CRASH_SERVER;
+ if (pop_reply_multiline(mailbox_fd, msg->data_size, lines))
+ return POP_CRASH_NETFAIL;
- if (lseek(mailbox_fd, msg->data_offset, SEEK_SET) < 0) return 1;
- if (pop_reply_multiline(mailbox_fd, msg->data_size, lines)) return 1;
+ if (mailbox_changed()) return POP_CRASH_SERVER;
- if (mailbox_changed()) return 1;
+ if (pop_reply_terminate()) return POP_CRASH_NETFAIL;
- return pop_reply_terminate();
+ return POP_OK;
}
static int mailbox_write(char *buffer)
diff --git a/usr.sbin/popa3d/mailbox.h b/usr.sbin/popa3d/mailbox.h
index ba6fc7ad0b0..102774ec97f 100644
--- a/usr.sbin/popa3d/mailbox.h
+++ b/usr.sbin/popa3d/mailbox.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mailbox.h,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: mailbox.h,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* Mailbox access.
@@ -14,8 +14,8 @@
extern int mailbox_open(char *spool, char *mailbox);
/*
- * Sends (first lines of) a message to the POP client. Returns a non-zero
- * value on error; the POP session then has to crash.
+ * Sends (first lines of) a message to the POP client. Returns one of the
+ * POP_* event codes.
*/
extern int mailbox_get(struct db_message *msg, int lines);
diff --git a/usr.sbin/popa3d/params.h b/usr.sbin/popa3d/params.h
index 717a3aa77b8..5d4e7db370b 100644
--- a/usr.sbin/popa3d/params.h
+++ b/usr.sbin/popa3d/params.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: params.h,v 1.4 2001/08/25 15:35:09 camield Exp $ */
+/* $OpenBSD: params.h,v 1.5 2001/09/21 20:22:06 camield Exp $ */
/*
* Global POP daemon parameters.
@@ -8,6 +8,11 @@
#define _POP_PARAMS_H
/*
+ * Our name to use when talking to various interfaces.
+ */
+#define POP_SERVER "popa3d"
+
+/*
* Are we going to be a standalone server or start via an inetd clone?
*/
#define POP_STANDALONE 1
@@ -15,12 +20,40 @@
#if POP_STANDALONE
/*
+ * Should the command line options be supported?
+ * If enabled, popa3d will default to inetd mode and will require a -D
+ * to actually enable the standalone mode.
+ */
+#define POP_OPTIONS 1
+
+/*
* The address and port to listen on.
*/
#define DAEMON_ADDR "0.0.0.0" /* INADDR_ANY */
#define DAEMON_PORT 110
/*
+ * Should libwrap be used?
+ *
+ * This may make things slower and also adds to code running as root,
+ * so it is recommended that you use a packet filter instead. This
+ * option is provided primarily as a way to meet conventions of certain
+ * systems where all services obey libwrap access controls.
+ */
+#ifdef LIBWRAP
+#define DAEMON_LIBWRAP 1
+#else
+#define DAEMON_LIBWRAP 0
+#endif
+
+#if DAEMON_LIBWRAP
+/*
+ * How do we talk to libwrap?
+ */
+#define DAEMON_LIBWRAP_IDENT POP_SERVER
+#endif
+
+/*
* Limit the number of POP sessions we can handle at a time to reduce
* the impact of connection flood DoS attacks.
*/
@@ -69,10 +102,16 @@
#endif
/*
- * An unprivileged dummy user to run as before authentication. The user
- * and its UID must not be used for any other purpose.
+ * A pseudo-user to run as before authentication. The user and its UID
+ * must not be used for any other purpose.
+ */
+#define POP_USER POP_SERVER
+
+/*
+ * An empty directory to chroot to before authentication. The directory
+ * and its parent directories must not be writable by anyone but root.
*/
-#define POP_USER "popa3d"
+#define POP_CHROOT "/usr/share/empty"
/*
* Sessions will be closed if idle for longer than POP_TIMEOUT seconds.
@@ -133,9 +172,18 @@
/*
* Your mail spool directory. Note: only local (non-NFS) mode 775 mail
* spools are currently supported.
+ *
+ * #undef this for qmail-style $HOME/Mailbox mailboxes.
*/
#define MAIL_SPOOL_PATH "/var/mail"
+#ifndef MAIL_SPOOL_PATH
+/*
+ * The mailbox file name relative to the user's home directory.
+ */
+#define HOME_MAILBOX_NAME "Mailbox"
+#endif
+
#endif
/*
@@ -148,10 +196,12 @@
/*
* How do we talk to syslogd? These should be fine for most systems.
*/
-#define SYSLOG_IDENT "popa3d"
+#define SYSLOG_IDENT POP_SERVER
#define SYSLOG_OPTIONS LOG_PID
#define SYSLOG_FACILITY LOG_DAEMON
-#define SYSLOG_PRIORITY LOG_INFO
+#define SYSLOG_PRI_LO LOG_INFO
+#define SYSLOG_PRI_HI LOG_NOTICE
+#define SYSLOG_PRI_ERROR LOG_CRIT
/*
* There's probably no reason to touch anything below this comment.
diff --git a/usr.sbin/popa3d/pop_auth.c b/usr.sbin/popa3d/pop_auth.c
index 65ea612d0bc..cbec928bc1d 100644
--- a/usr.sbin/popa3d/pop_auth.c
+++ b/usr.sbin/popa3d/pop_auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pop_auth.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: pop_auth.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* AUTHORIZATION state handling.
@@ -31,14 +31,14 @@ static int pop_auth_user(char *params)
user = pop_get_param(&params);
if (!user || pop_user || params) return POP_ERROR;
- if (!(pop_user = strdup(user))) return POP_CRASH;
+ if (!(pop_user = strdup(user))) return POP_CRASH_SERVER;
return POP_OK;
}
static int pop_auth_pass(char *params)
{
if (!params || !pop_user) return POP_ERROR;
- if (!(pop_pass = strdup(params))) return POP_CRASH;
+ if (!(pop_pass = strdup(params))) return POP_CRASH_SERVER;
return POP_STATE;
}
@@ -67,23 +67,25 @@ int do_pop_auth(int channel)
return 0;
}
-void log_pop_auth(int result, char *mailbox)
+void log_pop_auth(int result, char *user)
{
if (result == AUTH_NONE) {
- syslog(SYSLOG_PRIORITY, "Didn't attempt authentication");
+ syslog(SYSLOG_PRI_LO, "Didn't attempt authentication");
return;
}
#if POP_VIRTUAL
if (virtual_domain) {
- syslog(SYSLOG_PRIORITY, "Authentication %s for %s@%s",
+ syslog(result == AUTH_OK ? SYSLOG_PRI_LO : SYSLOG_PRI_HI,
+ "Authentication %s for %s@%s",
result == AUTH_OK ? "passed" : "failed",
- mailbox ? mailbox : "UNKNOWN",
+ user ? user : "UNKNOWN USER",
virtual_domain);
return;
}
#endif
- syslog(SYSLOG_PRIORITY, "Authentication %s for %s",
+ syslog(result == AUTH_OK ? SYSLOG_PRI_LO : SYSLOG_PRI_HI,
+ "Authentication %s for %s",
result == AUTH_OK ? "passed" : "failed",
- mailbox ? mailbox : "UNKNOWN");
+ user ? user : "UNKNOWN USER");
}
diff --git a/usr.sbin/popa3d/pop_auth.h b/usr.sbin/popa3d/pop_auth.h
index 4352552f133..2708dcd6058 100644
--- a/usr.sbin/popa3d/pop_auth.h
+++ b/usr.sbin/popa3d/pop_auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pop_auth.h,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: pop_auth.h,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* AUTHORIZATION state handling.
@@ -21,9 +21,8 @@
extern int do_pop_auth(int channel);
/*
- * Logs an authentication attempt for mailbox (or NULL if the requested
- * mailbox doesn't exist).
+ * Logs an authentication attempt for user, use NULL for non-existent.
*/
-extern void log_pop_auth(int result, char *mailbox);
+extern void log_pop_auth(int result, char *user);
#endif
diff --git a/usr.sbin/popa3d/pop_root.c b/usr.sbin/popa3d/pop_root.c
index 194de4a19e4..d7509b133fd 100644
--- a/usr.sbin/popa3d/pop_root.c
+++ b/usr.sbin/popa3d/pop_root.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pop_root.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: pop_root.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* Main daemon code: invokes the actual POP handling routines. Most calls
@@ -6,6 +6,7 @@
* POP_USER or the authenticated user). Depending on compile-time options
* in params.h, the following files may contain code executed as root:
*
+ * startup.c if supporting command line options (POP_OPTIONS)
* standalone.c if not running via an inetd clone (POP_STANDALONE)
* virtual.c if supporting virtual domains (POP_VIRTUAL)
* auth_passwd.c if using passwd or *BSD (AUTH_PASSWD && !VIRTUAL_ONLY)
@@ -17,6 +18,7 @@
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
+#include <time.h>
#include <grp.h>
#include <pwd.h>
#include <sys/stat.h>
@@ -32,15 +34,19 @@
#endif
#if !VIRTUAL_ONLY
-extern struct passwd *auth_userpass(char *user, char *pass, char **mailbox);
+extern struct passwd *auth_userpass(char *user, char *pass, int *known);
#endif
+/* POP_USER's pw_uid and pw_gid, other fields may not be valid */
static struct passwd pop_pw;
-static char *mailbox;
+
+static int known;
+static char *user;
+static char *spool, *mailbox;
int log_error(char *s)
{
- syslog(SYSLOG_PRIORITY, "%s: %m", s);
+ syslog(SYSLOG_PRI_ERROR, "%s: %m", s);
return 1;
}
@@ -58,6 +64,17 @@ static int set_user(struct passwd *pw)
return 0;
}
+static int drop_root(void)
+{
+ tzset();
+ openlog(SYSLOG_IDENT, SYSLOG_OPTIONS | LOG_NDELAY, SYSLOG_FACILITY);
+
+ if (chroot(POP_CHROOT)) return log_error("chroot");
+ if (chdir("/")) return log_error("chdir");
+
+ return set_user(&pop_pw);
+}
+
/*
* Attempts to read until EOF, and returns the number of bytes read.
* We don't expect any signals, so even EINTR is considered an error.
@@ -89,10 +106,10 @@ static int read_loop(int fd, char *buffer, int count)
static int do_root_auth(int channel)
{
static char auth[AUTH_BUFFER_SIZE + 2];
- char *user, *pass;
+ char *pass;
struct passwd *pw;
- mailbox = NULL;
+ known = 0;
#if POP_VIRTUAL
virtual_domain = NULL;
#endif
@@ -104,30 +121,56 @@ static int do_root_auth(int channel)
sizeof(pop_buffer)) return AUTH_NONE;
/* Now, the authentication data. */
- memset(auth, 0, sizeof(auth)); /* Ensure the NUL termination */
- if (read_loop(channel, auth, AUTH_BUFFER_SIZE) < 0) return AUTH_NONE;
+ memset(auth, 0, sizeof(auth)); /* Ensure NUL termination */
+ if (read_loop(channel, auth, AUTH_BUFFER_SIZE) < 0) {
+ memset(auth, 0, sizeof(auth));
+ return AUTH_NONE;
+ }
user = auth;
pass = &user[strlen(user) + 1];
pw = NULL;
#if POP_VIRTUAL
- if (!(pw = virtual_userpass(user, pass, &mailbox)) && virtual_domain)
+ if (!(pw = virtual_userpass(user, pass, &known)) && virtual_domain) {
+ memset(pass, 0, strlen(pass));
return AUTH_FAILED;
+ }
#endif
#if VIRTUAL_ONLY
- if (!pw)
+ if (!pw) {
+ memset(pass, 0, strlen(pass));
return AUTH_FAILED;
+ }
#else
- if (!pw && !(pw = auth_userpass(user, pass, &mailbox)))
+ if (!pw && !(pw = auth_userpass(user, pass, &known))) {
+ memset(pass, 0, strlen(pass));
return AUTH_FAILED;
+ }
#endif
- if (!*user || !*pass) return AUTH_FAILED;
-
+ if (!*pass) return AUTH_FAILED;
memset(pass, 0, strlen(pass));
+ if (!*user) return AUTH_FAILED;
if (set_user(pw)) return AUTH_FAILED;
+#if POP_VIRTUAL
+ if (virtual_domain) {
+ spool = virtual_spool;
+ mailbox = user;
+
+ return AUTH_OK;
+ }
+#endif
+
+#ifdef MAIL_SPOOL_PATH
+ spool = MAIL_SPOOL_PATH;
+ mailbox = user;
+#else
+ spool = pw->pw_dir;
+ mailbox = HOME_MAILBOX_NAME;
+#endif
+
return AUTH_OK;
}
@@ -142,11 +185,14 @@ int do_pop_startup(void)
errno = 0;
if (!(pw = getpwnam(POP_USER))) {
- syslog(SYSLOG_PRIORITY, "getpwnam(\"" POP_USER "\"): %s",
+ syslog(SYSLOG_PRI_ERROR, "getpwnam(\"" POP_USER "\"): %s",
errno ? strerror(errno) : "No such user");
return 1;
}
- memcpy(&pop_pw, pw, sizeof(pop_pw));
+ memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
+ endpwent();
+ pop_pw.pw_uid = pw->pw_uid;
+ pop_pw.pw_gid = pw->pw_gid;
#if POP_VIRTUAL
if (virtual_startup()) return 1;
@@ -160,7 +206,10 @@ int do_pop_session(void)
int channel[2];
int result, status;
- signal(SIGCHLD, SIG_IGN);
+/* For SIGCHLD, default action is to ignore the signal. {SIGCHLD, SIG_IGN}
+ * may be invalid (POSIX) or may enable a different behavior (SUSv2), none
+ * of which are any good for us. */
+ signal(SIGCHLD, SIG_DFL);
if (pipe(channel)) return log_error("pipe");
@@ -170,7 +219,7 @@ int do_pop_session(void)
case 0:
if (close(channel[0])) return log_error("close");
- if (set_user(&pop_pw)) return 1;
+ if (drop_root()) return 1;
return do_pop_auth(channel[1]);
}
@@ -189,18 +238,12 @@ int do_pop_session(void)
if (result == AUTH_OK) {
if (close(channel[0])) return log_error("close");
- log_pop_auth(result, mailbox);
-#if POP_VIRTUAL
- if (virtual_domain)
- return do_pop_trans(virtual_spool, mailbox);
-#endif
-#if !VIRTUAL_ONLY
- return do_pop_trans(MAIL_SPOOL_PATH, mailbox);
-#endif
+ log_pop_auth(result, user);
+ return do_pop_trans(spool, mailbox);
}
- if (set_user(&pop_pw)) return 1;
- log_pop_auth(result, mailbox);
+ if (drop_root()) return 1;
+ log_pop_auth(result, known ? user : NULL);
#ifdef AUTH_FAILED_MESSAGE
if (result == AUTH_FAILED) pop_reply("-ERR %s", AUTH_FAILED_MESSAGE);
@@ -211,7 +254,7 @@ int do_pop_session(void)
return status;
}
-#if !POP_STANDALONE
+#if !POP_STANDALONE && !POP_OPTIONS
int main(void)
{
if (do_pop_startup()) return 1;
diff --git a/usr.sbin/popa3d/pop_trans.c b/usr.sbin/popa3d/pop_trans.c
index 05ecbec76a3..59155066ce8 100644
--- a/usr.sbin/popa3d/pop_trans.c
+++ b/usr.sbin/popa3d/pop_trans.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pop_trans.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: pop_trans.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* TRANSACTION state handling.
@@ -28,7 +28,7 @@ static int pop_trans_stat(char *params)
{
if (params) return POP_ERROR;
if (pop_reply("+OK %d %ld", db.visible_count, db.visible_size))
- return POP_CRASH;
+ return POP_CRASH_NETFAIL;
return POP_QUIET;
}
@@ -51,14 +51,14 @@ static int pop_trans_list_or_uidl(char *params, int uidl)
msg->hash[1], msg->hash[0],
msg->hash[7], msg->hash[6],
msg->hash[5], msg->hash[4]))
- return POP_CRASH;
+ return POP_CRASH_NETFAIL;
} else
if (pop_reply("+OK %d %ld", number, msg->size))
- return POP_CRASH;
+ return POP_CRASH_NETFAIL;
return POP_QUIET;
}
- if (pop_reply_ok()) return POP_CRASH;
+ if (pop_reply_ok()) return POP_CRASH_NETFAIL;
for (number = 1; number <= db.total_count; number++) {
msg = db.array[number - 1];
if (msg->flags & MSG_DELETED) continue;
@@ -70,12 +70,12 @@ static int pop_trans_list_or_uidl(char *params, int uidl)
msg->hash[1], msg->hash[0],
msg->hash[7], msg->hash[6],
msg->hash[5], msg->hash[4]))
- return POP_CRASH;
+ return POP_CRASH_NETFAIL;
} else
if (pop_reply("%d %ld", number, msg->size))
- return POP_CRASH;
+ return POP_CRASH_NETFAIL;
}
- if (pop_reply_terminate()) return POP_CRASH;
+ if (pop_reply_terminate()) return POP_CRASH_NETFAIL;
return POP_QUIET;
}
@@ -94,12 +94,13 @@ static int pop_trans_retr(char *params)
{
int number;
struct db_message *msg;
+ int event;
number = pop_get_int(&params);
if (number < 1 || number > db.total_count || params) return POP_ERROR;
msg = db.array[number - 1];
if (msg->flags & MSG_DELETED) return POP_ERROR;
- if (mailbox_get(msg, -1)) return POP_CRASH;
+ if ((event = mailbox_get(msg, -1)) != POP_OK) return event;
#if POP_SUPPORT_LAST
if (number > db.last) db.last = number;
#endif
@@ -110,6 +111,7 @@ static int pop_trans_top(char *params)
{
int number, lines;
struct db_message *msg;
+ int event;
number = pop_get_int(&params);
if (number < 1 || number > db.total_count) return POP_ERROR;
@@ -117,7 +119,7 @@ static int pop_trans_top(char *params)
if (lines < 0 || params) return POP_ERROR;
msg = db.array[number - 1];
if (msg->flags & MSG_DELETED) return POP_ERROR;
- if (mailbox_get(msg, lines)) return POP_CRASH;
+ if ((event = mailbox_get(msg, lines)) != POP_OK) return event;
return POP_QUIET;
}
@@ -161,7 +163,7 @@ static int pop_trans_rset(char *params)
static int pop_trans_last(char *params)
{
if (params) return POP_ERROR;
- if (pop_reply("+OK %d", db.last)) return POP_CRASH;
+ if (pop_reply("+OK %d", db.last)) return POP_CRASH_NETFAIL;
return POP_QUIET;
}
#endif
@@ -203,28 +205,32 @@ int do_pop_trans(char *spool, char *mailbox)
if (!pop_sane()) return 1;
if (db_load(spool, mailbox)) {
- syslog(SYSLOG_PRIORITY, "Failed to open mailbox");
+ syslog(SYSLOG_PRI_HI,
+ "Failed or refused to load %s/%s",
+ spool, mailbox);
pop_reply_error();
return 0;
}
- syslog(SYSLOG_PRIORITY, "%d message%s (%ld byte%s) loaded",
+ syslog(SYSLOG_PRI_LO, "%d message%s (%ld byte%s) loaded",
db.total_count, db.total_count == 1 ? "" : "s",
db.total_size, db.total_size == 1 ? "" : "s");
if (pop_reply_ok())
- result = POP_CRASH;
+ result = POP_CRASH_NETFAIL;
else
switch ((result = pop_handle_state(pop_trans_commands))) {
case POP_STATE:
if (mailbox_update()) {
if (db.flags & DB_STALE) break;
- syslog(SYSLOG_PRIORITY, "Failed to update mailbox");
+ syslog(SYSLOG_PRI_ERROR,
+ "Failed to update %s/%s",
+ spool, mailbox);
pop_reply_error();
break;
}
- syslog(SYSLOG_PRIORITY, "%d (%ld) deleted, %d (%ld) left",
+ syslog(SYSLOG_PRI_LO, "%d (%ld) deleted, %d (%ld) left",
db.total_count - db.visible_count,
db.total_size - db.visible_size,
db.visible_count,
@@ -232,15 +238,21 @@ int do_pop_trans(char *spool, char *mailbox)
pop_reply_ok();
break;
- case POP_TIMED_OUT:
- syslog(SYSLOG_PRIORITY, "Connection timed out");
+ case POP_CRASH_NETFAIL:
+ syslog(SYSLOG_PRI_LO, "Premature disconnect");
+ break;
+
+ case POP_CRASH_NETTIME:
+ syslog(SYSLOG_PRI_LO, "Connection timed out");
}
if (db.flags & DB_STALE)
- syslog(SYSLOG_PRIORITY, "Another MUA active, giving up");
+ syslog(SYSLOG_PRI_LO, "Another MUA active, giving up");
else
- if (result == POP_CRASH)
- syslog(SYSLOG_PRIORITY, "Session crashed");
+ if (result == POP_CRASH_SERVER)
+ syslog(SYSLOG_PRI_ERROR,
+ "Server failure accessing %s/%s",
+ spool, mailbox);
mailbox_close();
diff --git a/usr.sbin/popa3d/protocol.c b/usr.sbin/popa3d/protocol.c
index cbe5aa41b19..4ff40f97769 100644
--- a/usr.sbin/popa3d/protocol.c
+++ b/usr.sbin/popa3d/protocol.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: protocol.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: protocol.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* POP protocol handling.
@@ -17,7 +17,7 @@
#include "protocol.h"
struct pop_buffer pop_buffer;
-static jmp_buf pop_timed_out;
+static sigjmp_buf pop_timed_out;
void pop_init(void)
{
@@ -41,7 +41,7 @@ int pop_sane(void)
static void pop_timeout(int signum)
{
signal(SIGALRM, SIG_DFL);
- longjmp(pop_timed_out, 1);
+ siglongjmp(pop_timed_out, 1);
}
static int pop_fetch(void)
@@ -103,7 +103,7 @@ int pop_handle_state(struct pop_command *commands)
struct pop_command *command;
int response;
- if (setjmp(pop_timed_out)) return POP_TIMED_OUT;
+ if (sigsetjmp(pop_timed_out, 1)) return POP_CRASH_NETTIME;
while (pop_get_line(line, sizeof(line))) {
if ((params = strchr(line, ' '))) {
@@ -120,24 +120,24 @@ int pop_handle_state(struct pop_command *commands)
switch (response) {
case POP_OK:
- if (pop_reply_ok()) return POP_CRASH;
+ if (pop_reply_ok()) return POP_CRASH_NETFAIL;
break;
case POP_ERROR:
- if (pop_reply_error()) return POP_CRASH;
+ if (pop_reply_error()) return POP_CRASH_NETFAIL;
case POP_QUIET:
break;
case POP_LEAVE:
- if (pop_reply_ok()) return POP_CRASH;
+ if (pop_reply_ok()) return POP_CRASH_NETFAIL;
default:
return response;
}
}
- return POP_CRASH;
+ return POP_CRASH_NETFAIL;
}
char *pop_get_param(char **params)
@@ -207,8 +207,7 @@ int pop_reply_error(void)
int pop_reply_multiline(int fd, long size, int lines)
{
- char *in_buffer;
- char *out_buffer;
+ char *in_buffer, *out_buffer;
char *in, *out;
int in_block, out_block;
int start, body;
diff --git a/usr.sbin/popa3d/protocol.h b/usr.sbin/popa3d/protocol.h
index 05cacace937..8f2863184d3 100644
--- a/usr.sbin/popa3d/protocol.h
+++ b/usr.sbin/popa3d/protocol.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: protocol.h,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: protocol.h,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* POP protocol handling.
@@ -15,8 +15,9 @@
#define POP_QUIET 2 /* We've already replied */
#define POP_LEAVE 3 /* Leave the session */
#define POP_STATE 4 /* Advance the state */
-#define POP_CRASH 5 /* Session crashed */
-#define POP_TIMED_OUT 6 /* Connection timed out */
+#define POP_CRASH_NETFAIL 5 /* Network failure */
+#define POP_CRASH_NETTIME 6 /* Network timeout */
+#define POP_CRASH_SERVER 7 /* POP server failure */
/*
* POP command description.
diff --git a/usr.sbin/popa3d/standalone.c b/usr.sbin/popa3d/standalone.c
index 0f374e01ce3..da8d60f19f7 100644
--- a/usr.sbin/popa3d/standalone.c
+++ b/usr.sbin/popa3d/standalone.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: standalone.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: standalone.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* Standalone POP server: accepts connections, checks the anti-flood limits,
@@ -24,6 +24,12 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#if DAEMON_LIBWRAP
+#include <tcpd.h>
+int allow_severity = SYSLOG_PRI_LO;
+int deny_severity = SYSLOG_PRI_HI;
+#endif
+
/*
* These are defined in pop_root.c.
*/
@@ -31,6 +37,9 @@ extern int log_error(char *s);
extern int do_pop_startup(void);
extern int do_pop_session(void);
+typedef sig_atomic_t a_int;
+typedef volatile a_int va_int;
+
/*
* Active POP sessions. Those that were started within the last MIN_DELAY
* seconds are also considered active (regardless of their actual state),
@@ -39,13 +48,13 @@ extern int do_pop_session(void);
*/
static struct {
struct in_addr addr; /* Source IP address */
- int pid; /* PID of the server, or 0 for none */
+ a_int pid; /* PID of the server, or 0 for none */
clock_t start; /* When the server was started */
clock_t log; /* When we've last logged a failure */
} sessions[MAX_SESSIONS];
-static volatile int child_blocked; /* We use blocking to avoid races */
-static volatile int child_pending; /* Are any dead children waiting? */
+static va_int child_blocked; /* We use blocking to avoid races */
+static va_int child_pending; /* Are any dead children waiting? */
/*
* SIGCHLD handler; can also be called directly with a zero signum.
@@ -76,7 +85,31 @@ static void handle_child(int signum)
errno = saved_errno;
}
+#if DAEMON_LIBWRAP
+static void check_access(int sock)
+{
+ struct request_info request;
+
+ request_init(&request,
+ RQ_DAEMON, DAEMON_LIBWRAP_IDENT,
+ RQ_FILE, sock,
+ 0);
+ fromhost(&request);
+
+ if (!hosts_access(&request)) {
+/* refuse() shouldn't return... */
+ refuse(&request);
+/* ...but just in case */
+ exit(1);
+ }
+}
+#endif
+
+#if POP_OPTIONS
+int do_standalone(void)
+#else
int main(void)
+#endif
{
int true = 1;
int sock, new;
@@ -169,7 +202,7 @@ int main(void)
if (!sessions[i].log ||
now < sessions[i].log ||
now - sessions[i].log >= MIN_DELAY * CLK_TCK) {
- syslog(SYSLOG_PRIORITY,
+ syslog(SYSLOG_PRI_HI,
"%s: per source limit reached",
inet_ntoa(addr.sin_addr));
sessions[i].log = now;
@@ -178,21 +211,24 @@ int main(void)
}
if (j < 0) {
- syslog(SYSLOG_PRIORITY, "%s: sessions limit reached",
+ syslog(SYSLOG_PRI_HI, "%s: sessions limit reached",
inet_ntoa(addr.sin_addr));
continue;
}
switch ((pid = fork())) {
case -1:
- syslog(SYSLOG_PRIORITY, "%s: fork: %m",
+ syslog(SYSLOG_PRI_ERROR, "%s: fork: %m",
inet_ntoa(addr.sin_addr));
break;
case 0:
- syslog(SYSLOG_PRIORITY, "Session from %s",
- inet_ntoa(addr.sin_addr));
if (close(sock)) return log_error("close");
+#if DAEMON_LIBWRAP
+ check_access(new);
+#endif
+ syslog(SYSLOG_PRI_LO, "Session from %s",
+ inet_ntoa(addr.sin_addr));
if (dup2(new, 0) < 0) return log_error("dup2");
if (dup2(new, 1) < 0) return log_error("dup2");
if (dup2(new, 2) < 0) return log_error("dup2");
@@ -201,7 +237,7 @@ int main(void)
default:
sessions[j].addr = addr.sin_addr;
- (volatile int)sessions[j].pid = pid;
+ (va_int)sessions[j].pid = pid;
sessions[j].start = now;
sessions[j].log = 0;
}
diff --git a/usr.sbin/popa3d/startup.c b/usr.sbin/popa3d/startup.c
new file mode 100644
index 00000000000..d554fbe992e
--- /dev/null
+++ b/usr.sbin/popa3d/startup.c
@@ -0,0 +1,66 @@
+/* $OpenBSD: startup.c,v 1.1 2001/09/21 20:22:06 camield Exp $ */
+
+/*
+ * Command line option parsing.
+ */
+
+#include "params.h"
+
+#if POP_OPTIONS
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* pop_root.c */
+extern int do_pop_startup(void);
+extern int do_pop_session(void);
+
+/* standalone.c */
+extern int do_standalone(void);
+
+#ifdef HAVE_PROGNAME
+extern char *__progname;
+#define progname __progname
+#else
+static char *progname;
+#endif
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: %s [-D]\n", progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int standalone = 0;
+
+#ifndef HAVE_PROGNAME
+ if (!(progname = argv[0]))
+ progname = POP_SERVER;
+#endif
+
+ while ((c = getopt(argc, argv, "D")) != -1) {
+ switch (c) {
+ case 'D':
+ standalone++;
+ break;
+
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc)
+ usage();
+
+ if (standalone)
+ return do_standalone();
+
+ if (do_pop_startup()) return 1;
+ return do_pop_session();
+}
+
+#endif
diff --git a/usr.sbin/popa3d/virtual.c b/usr.sbin/popa3d/virtual.c
index c11975d7a5d..2202f8409f3 100644
--- a/usr.sbin/popa3d/virtual.c
+++ b/usr.sbin/popa3d/virtual.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: virtual.c,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: virtual.c,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* Virtual domain support.
@@ -8,7 +8,7 @@
#if POP_VIRTUAL
-#define _XOPEN_SOURCE
+#define _XOPEN_SOURCE 4
#define _XOPEN_SOURCE_EXTENDED
#define _XOPEN_VERSION 4
#define _XPG4_2
@@ -52,7 +52,7 @@ static char *lookup(void)
return inet_ntoa(sin.sin_addr);
}
-static int isvaliduser(char *user)
+static int is_valid_user(char *user)
{
unsigned char *p;
@@ -66,7 +66,7 @@ static int isvaliduser(char *user)
return 1;
}
-struct passwd *virtual_userpass(char *user, char *pass, char **mailbox)
+struct passwd *virtual_userpass(char *user, char *pass, int *known)
{
struct passwd *pw, *result;
struct stat stat;
@@ -76,6 +76,8 @@ struct passwd *virtual_userpass(char *user, char *pass, char **mailbox)
int fail;
int fd, size;
+ *known = 0;
+
/* Make sure we don't try to authenticate globally if something fails
* before we find out whether the virtual domain is known to us */
virtual_domain = "UNKNOWN";
@@ -90,7 +92,7 @@ struct passwd *virtual_userpass(char *user, char *pass, char **mailbox)
}
fail = 0;
- if (!isvaliduser(user)) {
+ if (!is_valid_user(user)) {
user = "INVALID";
fail = 1;
}
@@ -138,7 +140,7 @@ struct passwd *virtual_userpass(char *user, char *pass, char **mailbox)
size = 0;
if (fd >= 0) {
- if (!fail) *mailbox = user;
+ *known = !fail;
if ((size = read(fd, auth, sizeof(auth))) < 0) {
log_error("read");
@@ -167,10 +169,8 @@ struct passwd *virtual_userpass(char *user, char *pass, char **mailbox)
}
if (!strtok(NULL, ":")) fail = 1;
- if ((pw = getpwnam(template))) {
+ if ((pw = getpwnam(template)))
memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
- pw->pw_passwd = "*";
- }
endpwent();
result = NULL;
diff --git a/usr.sbin/popa3d/virtual.h b/usr.sbin/popa3d/virtual.h
index 312e7c99743..baa8e3b6d8d 100644
--- a/usr.sbin/popa3d/virtual.h
+++ b/usr.sbin/popa3d/virtual.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: virtual.h,v 1.1 2001/08/19 13:05:57 deraadt Exp $ */
+/* $OpenBSD: virtual.h,v 1.2 2001/09/21 20:22:06 camield Exp $ */
/*
* Virtual domain support.
@@ -28,9 +28,9 @@ extern int virtual_startup(void);
* indicated either by the connected IP address (the socket is available
* on fd 0), or as a part of the username. If the virtual domain is known,
* virtual_domain and virtual_spool are set appropriately. If the username
- * is known as well, mailbox is set to the username. Returns the template
- * user to run as if the authentication is successful, or NULL otherwise.
+ * is known as well, known is set. Returns the template user to run as if
+ * authentication is succeeds, or NULL otherwise.
*/
-extern struct passwd *virtual_userpass(char *user, char *pass, char **mailbox);
+extern struct passwd *virtual_userpass(char *user, char *pass, int *known);
#endif