summaryrefslogtreecommitdiff
path: root/libexec/spamd
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2003-08-23 21:22:35 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2003-08-23 21:22:35 +0000
commit27f8d6fbc454e55e7f1127c642f342406d41b83c (patch)
tree8de51baab28e1dbf9e3f019a92eb2b8dfa079686 /libexec/spamd
parentf60e4b727d6777f7d3a9fafa457c216b3323333f (diff)
add -s to specify stuttering delay, set receive buffer size to 1 byte
(causing a small TCP window size, tying up sender's resources), additional states: keep connection until ten body lines have been received, improved logging through syslog (envelope from/to, From:/To:/Subject: in header, first lines of body) at various levels. ok deraadt@
Diffstat (limited to 'libexec/spamd')
-rw-r--r--libexec/spamd/spamd.827
-rw-r--r--libexec/spamd/spamd.c97
2 files changed, 104 insertions, 20 deletions
diff --git a/libexec/spamd/spamd.8 b/libexec/spamd/spamd.8
index f716f4cab6a..3438e17d387 100644
--- a/libexec/spamd/spamd.8
+++ b/libexec/spamd/spamd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: spamd.8,v 1.35 2003/06/02 14:27:12 jmc Exp $
+.\" $OpenBSD: spamd.8,v 1.36 2003/08/23 21:22:34 dhartmei Exp $
.\"
.\" Copyright (c) 2002 Theo de Raadt. All rights reserved.
.\"
@@ -35,6 +35,7 @@
.Op Fl n Ar name
.Op Fl p Ar port
.Op Fl r Ar reply
+.Op Fl s Ar secs
.Sh DESCRIPTION
.Nm
is a fake
@@ -74,6 +75,10 @@ using
.It Fl r Ar reply
The SMTP error to return to the spammer, i.e. 450, 451, 550.
This defaults to 450.
+.It Fl s Ar secs
+Delay each character sent to the client by the specified
+amount of seconds.
+Defaults to 1.
.El
.Pp
.Nm
@@ -175,14 +180,32 @@ will reject mail by displaying all the messages from all blacklists in which
a connecting address is matched.
.Xr spamd-setup 8
is normally used to configure this information.
+.Sh LOGGING
+.Nm
+sends log messages to
+.Xr syslogd 8
+using
+.Em facility
+daemon and, with increasing verbosity,
+.Em level
+err, warn, info and debug.
+The following
+.Xr syslog.conf 5
+section can be used to log connection details to a dedicated file:
+.Bd -literal
+!spamd
+daemon.err;daemon.warn;daemon.info /var/log/spamd
+.Ed
.Sh FILES
/etc/spamd.conf
.Sh SEE ALSO
.Xr pf.conf 5 ,
.Xr services 5 ,
.Xr spamd.conf 5 ,
+.Xr syslog.conf 5 ,
.Xr pfctl 8 ,
-.Xr spamd-setup 8
+.Xr spamd-setup 8 ,
+.Xr syslogd 8
.Sh HISTORY
The
.Nm
diff --git a/libexec/spamd/spamd.c b/libexec/spamd/spamd.c
index 5c2dde1a86e..42c7dd2a33a 100644
--- a/libexec/spamd/spamd.c
+++ b/libexec/spamd/spamd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spamd.c,v 1.37 2003/08/23 20:36:44 itojun Exp $ */
+/* $OpenBSD: spamd.c,v 1.38 2003/08/23 21:22:34 dhartmei Exp $ */
/*
* Copyright (c) 2002 Theo de Raadt. All rights reserved.
@@ -77,6 +77,8 @@ struct con {
size_t osize;
char *op;
int ol;
+ int data_lines;
+ int data_body;
} *con;
void usage(void);
@@ -113,6 +115,7 @@ time_t t;
int maxcon = MAXCON;
int clients;
int debug;
+int stutter = 1;
#define MAXTIME 400
@@ -120,7 +123,8 @@ void
usage(void)
{
fprintf(stderr,
- "usage: spamd [-45d] [-c maxcon] [-n name] [-p port] [-r reply]\n");
+ "usage: spamd [-45d] [-c maxcon] [-n name] [-p port] [-r reply] "
+ "[-s secs]\n");
exit(1);
}
@@ -521,22 +525,23 @@ initcon(struct con *cp, int fd, struct sockaddr_in *sin)
hostname, spamd, ctime(&t));
cp->op = cp->obuf;
cp->ol = strlen(cp->op);
- cp->w = t + 1;
+ cp->w = t + stutter;
cp->s = t;
- strlcpy(cp->rend, "\n\r", sizeof cp->rend);
+ strlcpy(cp->rend, "\n", sizeof cp->rend);
clients++;
}
void
closecon(struct con *cp)
{
- if (debug > 0) {
- time_t t;
+ time_t t;
- time(&t);
+ time(&t);
+ syslog_r(LOG_INFO, &sdata, "%s disconnected after %ld seconds.",
+ cp->addr, (long)(t - cp->s));
+ if (debug > 0)
printf("%s connected for %ld seconds.\n", cp->addr,
(long)(t - cp->s));
- }
if (cp->lists != NULL) {
free(cp->lists);
cp->lists = NULL;
@@ -578,7 +583,7 @@ nextstate(struct con *cp)
cp->op = cp->obuf;
cp->ol = strlen(cp->op);
cp->state = 2;
- cp->w = t + 1;
+ cp->w = t + stutter;
break;
}
goto mail;
@@ -599,7 +604,7 @@ nextstate(struct con *cp)
cp->op = cp->obuf;
cp->ol = strlen(cp->op);
cp->state = 4;
- cp->w = t + 1;
+ cp->w = t + stutter;
break;
}
goto rcpt;
@@ -620,7 +625,10 @@ nextstate(struct con *cp)
cp->op = cp->obuf;
cp->ol = strlen(cp->op);
cp->state = 6;
- cp->w = t + 1;
+ cp->w = t + stutter;
+ if (cp->mail[0] && cp->rcpt[0])
+ syslog_r(LOG_INFO, &sdata, "%s: %s -> %s",
+ cp->addr, cp->mail, cp->rcpt);
break;
}
goto spam;
@@ -634,16 +642,49 @@ nextstate(struct con *cp)
spam:
case 50:
+ if (match(cp->ibuf, "DATA")) {
+ snprintf(cp->obuf, cp->osize,
+ "354 Enter spam, end with \".\" on a line by "
+ "itself\n");
+ cp->state = 60;
+ } else {
+ snprintf(cp->obuf, cp->osize,
+ "500 5.5.1 Command unrecognized\n");
+ }
+ cp->ip = cp->ibuf;
+ cp->il = sizeof(cp->ibuf) - 1;
+ cp->op = cp->obuf;
+ cp->ol = strlen(cp->op);
+ cp->w = t + stutter;
+ break;
+ case 60:
+ if (!strcmp(cp->ibuf, ".") ||
+ (cp->data_body && ++cp->data_lines >= 10)) {
+ cp->state = 98;
+ goto done;
+ }
+ if (!cp->data_body && !*cp->ibuf)
+ cp->data_body = 1;
+ if (cp->data_body && *cp->ibuf)
+ syslog_r(LOG_INFO, &sdata, "%s: Body: %s", cp->addr,
+ cp->ibuf);
+ else if (match(cp->ibuf, "FROM:") || match(cp->ibuf, "TO:") ||
+ match(cp->ibuf, "SUBJECT:"))
+ syslog_r(LOG_INFO, &sdata, "%s: %s", cp->addr,
+ cp->ibuf);
+ cp->ip = cp->ibuf;
+ cp->il = sizeof(cp->ibuf) - 1;
+ cp->r = t;
+ break;
+ done:
+ case 98:
cp->lists = strdup(doreply(cp));
cp->op = cp->obuf;
cp->ol = strlen(cp->op);
+ cp->w = t + stutter;
cp->state = 99;
- cp->w = t + 1;
break;
case 99:
- syslog_r(LOG_INFO, &sdata, "%s: %s -> %s %ldsec by lists:%s",
- cp->addr, cp->mail, cp->rcpt, (long)(t - cp->s),
- (cp->lists != NULL) ? cp->lists : "");
closecon(cp);
break;
default:
@@ -676,8 +717,13 @@ handler(struct con *cp)
}
}
if (end || cp->il == 0) {
+ while (cp->ip > cp->ibuf &&
+ (cp->ip[-1] == '\r' || cp->ip[-1] == '\n'))
+ cp->ip--;
*cp->ip = '\0';
cp->r = 0;
+ syslog_r(LOG_DEBUG, &sdata, "%s: says '%s'", cp->addr,
+ cp->ibuf);
nextstate(cp);
}
}
@@ -714,7 +760,7 @@ handlew(struct con *cp, int one)
}
}
handled:
- cp->w = t + 1;
+ cp->w = t + stutter;
if (cp->ol == 0) {
cp->w = 0;
nextstate(cp);
@@ -747,7 +793,7 @@ main(int argc, char *argv[])
if (gethostname(hostname, sizeof hostname) == -1)
err(1, "gethostname");
- while ((ch = getopt(argc, argv, "45c:p:dr:n:")) != -1) {
+ while ((ch = getopt(argc, argv, "45c:p:dr:s:n:")) != -1) {
switch (ch) {
case '4':
nreply = "450";
@@ -771,6 +817,11 @@ main(int argc, char *argv[])
case 'r':
reply = optarg;
break;
+ case 's':
+ i = atoi(optarg);
+ if (i < 0 || i > 10)
+ usage();
+ stutter = i;
case 'n':
spamd = optarg;
break;
@@ -807,6 +858,12 @@ main(int argc, char *argv[])
sizeof(one)) == -1)
return (-1);
+ one = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &one, sizeof(one)) == -1) {
+ syslog(LOG_ERR, "setsockopt: %s", strerror(errno));
+ return (-1);
+ }
+
conflisten = socket(AF_INET, SOCK_STREAM, 0);
if (conflisten == -1)
err(1, "socket");
@@ -861,6 +918,7 @@ main(int argc, char *argv[])
err(1, "fork");
} else
printf("listening for incoming connections.\n");
+ syslog_r(LOG_WARNING, &sdata, "listening for incoming connections.");
while (1) {
struct timeval tv, *tvp;
@@ -959,8 +1017,11 @@ main(int argc, char *argv[])
break;
if (i == maxcon)
close(s2);
- else
+ else {
initcon(&con[i], s2, &sin);
+ syslog_r(LOG_INFO, &sdata, "%s: connected (%d)",
+ con[i].addr, clients);
+ }
}
if (FD_ISSET(conflisten, fdsr)) {
sinlen = sizeof(lin);