summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/popa3d/popa3d.813
-rw-r--r--usr.sbin/popa3d/standalone.c269
-rw-r--r--usr.sbin/popa3d/startup.c18
3 files changed, 101 insertions, 199 deletions
diff --git a/usr.sbin/popa3d/popa3d.8 b/usr.sbin/popa3d/popa3d.8
index 6d70b7023f2..61389528de9 100644
--- a/usr.sbin/popa3d/popa3d.8
+++ b/usr.sbin/popa3d/popa3d.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: popa3d.8,v 1.10 2004/06/26 10:46:55 jmc Exp $
+.\" $OpenBSD: popa3d.8,v 1.11 2004/07/17 20:54:24 brad Exp $
.\"
.\" Copyright (c) 2001-2003 Camiel Dobbelaar (cd@sentia.nl)
.\" All rights reserved.
@@ -32,7 +32,7 @@
.Nd "Post Office Protocol (POP3) server"
.Sh SYNOPSIS
.Nm
-.Op Fl 46DV
+.Op Fl D | V
.Sh DESCRIPTION
.Nm
is a POP3 server.
@@ -60,14 +60,6 @@ To send mail, the SMTP protocol is commonly used; see
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl 4
-In standalone mode
-.Pq Fl D ,
-listen to IPv4 only.
-.It Fl 6
-In standalone mode
-.Pq Fl D ,
-listen to IPv6 only.
.It Fl D
With this option set,
.Nm
@@ -85,6 +77,7 @@ also does quite a few checks to significantly reduce the impact of
connection flood attacks.
.It Fl V
Show version information and exit.
+.Pp
.El
.Pp
Alternatively,
diff --git a/usr.sbin/popa3d/standalone.c b/usr.sbin/popa3d/standalone.c
index 009373718ee..2d146dd5b84 100644
--- a/usr.sbin/popa3d/standalone.c
+++ b/usr.sbin/popa3d/standalone.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: standalone.c,v 1.6 2004/06/20 20:46:27 itojun Exp $ */
+/* $OpenBSD: standalone.c,v 1.7 2004/07/17 20:54:24 brad Exp $ */
/*
* Standalone POP server: accepts connections, checks the anti-flood limits,
@@ -17,8 +17,6 @@
#include <syslog.h>
#include <time.h>
#include <errno.h>
-#include <netdb.h>
-#include <poll.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -38,7 +36,6 @@ int deny_severity = SYSLOG_PRI_HI;
extern int log_error(char *s);
extern int do_pop_startup(void);
extern int do_pop_session(void);
-extern int af;
typedef volatile sig_atomic_t va_int;
@@ -49,7 +46,7 @@ typedef volatile sig_atomic_t va_int;
* information about sessions that we could have allowed to proceed.
*/
static struct {
- char addr[NI_MAXHOST]; /* Source IP address */
+ struct in_addr addr; /* Source IP address */
volatile 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 */
@@ -58,15 +55,13 @@ static struct {
static va_int child_blocked; /* We use blocking to avoid races */
static va_int child_pending; /* Are any dead children waiting? */
-int handle(int);
-
/*
* SIGCHLD handler.
*/
static void handle_child(int signum)
{
int saved_errno;
- int pid;
+ pid_t pid;
int i;
saved_errno = errno;
@@ -77,11 +72,11 @@ static void handle_child(int signum)
child_pending = 0;
while ((pid = waitpid(0, NULL, WNOHANG)) > 0)
- for (i = 0; i < MAX_SESSIONS; i++)
- if (sessions[i].pid == pid) {
- sessions[i].pid = 0;
- break;
- }
+ for (i = 0; i < MAX_SESSIONS; i++)
+ if (sessions[i].pid == pid) {
+ sessions[i].pid = 0;
+ break;
+ }
}
signal(SIGCHLD, handle_child);
@@ -116,75 +111,32 @@ int main(void)
#endif
{
int true = 1;
- int *fds, new, sock;
- struct pollfd *pfds;
- int i, n;
- struct addrinfo hints, *res, *res0;
- char sbuf[NI_MAXSERV];
- int error;
+ int sock, new;
+ struct sockaddr_in addr;
+ socklen_t addrlen;
+ pid_t pid;
+ struct tms buf;
+ clock_t now, log;
+ int i, j, n;
if (do_pop_startup()) return 1;
- snprintf(sbuf, sizeof(sbuf), "%u", DAEMON_PORT);
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = af;
- hints.ai_flags = AI_PASSIVE;
- error = getaddrinfo(NULL, sbuf, &hints, &res0);
- if (error)
- return log_error("getaddrinfo");
-
- i = 0;
- for (res = res0; res; res = res->ai_next)
- i++;
-
- fds = malloc(i * sizeof(fds[0]));
- if (!fds)
- return log_error("malloc");
- pfds = malloc(i * sizeof(pfds[0]));
- if (!pfds)
- return log_error("malloc");
-
- i = 0;
- for (res = res0; res; res = res->ai_next) {
- if ((fds[i] = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol)) < 0)
- continue;
-
- if (setsockopt(fds[i], SOL_SOCKET, SO_REUSEADDR,
- (void *)&true, sizeof(true))) {
- close(fds[i]);
- continue;
- }
-
-#ifdef IPV6_V6ONLY
- if (res->ai_family == AF_INET6)
- (void)setsockopt(fds[i], IPPROTO_IPV6, IPV6_V6ONLY,
- (void *)&true, sizeof(true));
-#endif
-
- if (bind(fds[i], res->ai_addr, res->ai_addrlen)) {
- close(fds[i]);
- continue;
- }
-
- if (listen(fds[i], MAX_BACKLOG)) {
- close(fds[i]);
- continue;
- }
-
- memset(&pfds[i], 0, sizeof(pfds[i]));
- pfds[i].fd = fds[i];
- pfds[i].events = POLLIN;
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ return log_error("socket");
- i++;
- }
- freeaddrinfo(res0);
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&true, sizeof(true)))
+ return log_error("setsockopt");
- if (i == 0)
- return log_error("socket");
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(DAEMON_ADDR);
+ addr.sin_port = htons(DAEMON_PORT);
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
+ return log_error("bind");
- n = i;
+ if (listen(sock, MAX_BACKLOG))
+ return log_error("listen");
chdir("/");
setsid();
@@ -207,49 +159,19 @@ int main(void)
signal(SIGCHLD, handle_child);
memset((void *)sessions, 0, sizeof(sessions));
+ log = 0;
new = 0;
while (1) {
child_blocked = 0;
- if (child_pending)
- raise(SIGCHLD);
-
- i = poll(pfds, n, INFTIM);
-
- if (i < 0)
- log_error("poll");
-
- sock = -1;
- for (i = 0; i < n; i++)
- if (pfds[i].revents & POLLIN)
- handle(pfds[i].fd);
- }
-}
-
-int
-handle(int sock)
-{
- clock_t now, log;
- int new;
- char hbuf[NI_MAXHOST];
- struct sockaddr_storage addr;
- int addrlen;
- int pid;
- struct tms buf;
- int error;
- int j, n, i;
-
- log = 0;
- new = 0;
+ if (child_pending) raise(SIGCHLD);
- addrlen = sizeof(addr);
- new = accept(sock, (struct sockaddr *)&addr, &addrlen);
+ if (new > 0)
+ if (close(new)) return log_error("close");
- error = getnameinfo((struct sockaddr *)&addr, addrlen,
- hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
- if (error)
- ; /* XXX */
+ addrlen = sizeof(addr);
+ new = accept(sock, (struct sockaddr *)&addr, &addrlen);
/*
* I wish there was a portable way to classify errno's... In this case,
@@ -257,76 +179,75 @@ handle(int sock)
* rather than risk terminating the entire service because of a minor
* temporary error having to do with one particular connection attempt.
*/
- if (new < 0)
- return 0;
-
- now = times(&buf);
- if (!now)
- now = 1;
-
- child_blocked = 1;
-
- j = -1;
- n = 0;
- for (i = 0; i < MAX_SESSIONS; i++) {
- if (sessions[i].start > now)
- sessions[i].start = 0;
- if (sessions[i].pid ||
- (sessions[i].start &&
- now - sessions[i].start < MIN_DELAY * CLK_TCK)) {
- if (strcmp(sessions[i].addr, hbuf) == 0)
- if (++n >= MAX_SESSIONS_PER_SOURCE)
- break;
- } else if (j < 0)
- j = i;
- }
+ if (new < 0) continue;
+
+ now = times(&buf);
+ if (!now) now = 1;
+
+ child_blocked = 1;
+
+ j = -1; n = 0;
+ for (i = 0; i < MAX_SESSIONS; i++) {
+ if (sessions[i].start > now)
+ sessions[i].start = 0;
+ if (sessions[i].pid ||
+ (sessions[i].start &&
+ now - sessions[i].start < MIN_DELAY * CLK_TCK)) {
+ if (sessions[i].addr.s_addr ==
+ addr.sin_addr.s_addr)
+ if (++n >= MAX_SESSIONS_PER_SOURCE) break;
+ } else
+ if (j < 0) j = i;
+ }
- if (n >= MAX_SESSIONS_PER_SOURCE) {
- if (!sessions[i].log ||
- now < sessions[i].log ||
- now - sessions[i].log >= MIN_DELAY * CLK_TCK) {
- syslog(SYSLOG_PRI_HI,
- "%s: per source limit reached",
- hbuf);
- sessions[i].log = now;
+ if (n >= MAX_SESSIONS_PER_SOURCE) {
+ if (!sessions[i].log ||
+ now < sessions[i].log ||
+ now - sessions[i].log >= MIN_DELAY * CLK_TCK) {
+ syslog(SYSLOG_PRI_HI,
+ "%s: per source limit reached",
+ inet_ntoa(addr.sin_addr));
+ sessions[i].log = now;
+ }
+ continue;
}
- return 0;
- }
- if (j < 0) {
- if (!log ||
- now < log || now - log >= MIN_DELAY * CLK_TCK) {
- syslog(SYSLOG_PRI_HI,
- "%s: sessions limit reached", hbuf);
- log = now;
+ if (j < 0) {
+ if (!log ||
+ now < log || now - log >= MIN_DELAY * CLK_TCK) {
+ syslog(SYSLOG_PRI_HI,
+ "%s: sessions limit reached",
+ inet_ntoa(addr.sin_addr));
+ log = now;
+ }
+ continue;
}
- return 0;
- }
- switch ((pid = fork())) {
- case -1:
- syslog(SYSLOG_PRI_ERROR, "%s: fork: %m", hbuf);
- break;
+ switch ((pid = fork())) {
+ case -1:
+ syslog(SYSLOG_PRI_ERROR, "%s: fork: %m",
+ inet_ntoa(addr.sin_addr));
+ break;
- case 0:
- if (close(sock)) return log_error("close");
+ case 0:
+ if (close(sock)) return log_error("close");
#if DAEMON_LIBWRAP
- check_access(new);
+ check_access(new);
#endif
- syslog(SYSLOG_PRI_LO, "Session from %s",
- hbuf);
- 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");
- if (close(new)) return log_error("close");
- return do_pop_session();
-
- default:
- strlcpy(sessions[j].addr, hbuf,
- sizeof(sessions[j].addr));
- (va_int)sessions[j].pid = pid;
- sessions[j].start = now;
- sessions[j].log = 0;
+ 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");
+ if (close(new)) return log_error("close");
+ return do_pop_session();
+
+ default:
+ sessions[j].addr = addr.sin_addr;
+ 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
index 206fd41f955..fc25a777b3b 100644
--- a/usr.sbin/popa3d/startup.c
+++ b/usr.sbin/popa3d/startup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: startup.c,v 1.4 2004/06/26 10:46:55 jmc Exp $ */
+/* $OpenBSD: startup.c,v 1.5 2004/07/17 20:54:24 brad Exp $ */
/*
* Command line option parsing.
@@ -8,8 +8,6 @@
#if POP_OPTIONS
-#include <sys/types.h>
-#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -32,11 +30,9 @@ extern char *__progname;
static char *progname;
#endif
-int af = PF_UNSPEC;
-
static void usage(void)
{
- fprintf(stderr, "Usage: %s [-46DV]\n", progname);
+ fprintf(stderr, "Usage: %s [-D] [-V]\n", progname);
exit(1);
}
@@ -56,20 +52,12 @@ int main(int argc, char **argv)
progname = POP_SERVER;
#endif
- while ((c = getopt(argc, argv, "DV46")) != -1) {
+ while ((c = getopt(argc, argv, "DV")) != -1) {
switch (c) {
case 'D':
standalone++;
break;
- case '4':
- af = AF_INET;
- break;
-
- case '6':
- af = AF_INET6;
- break;
-
case 'V':
version();