summaryrefslogtreecommitdiff
path: root/usr.sbin/popa3d/pop_root.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/popa3d/pop_root.c')
-rw-r--r--usr.sbin/popa3d/pop_root.c99
1 files changed, 71 insertions, 28 deletions
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;