diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2003-08-23 21:22:35 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2003-08-23 21:22:35 +0000 |
commit | 27f8d6fbc454e55e7f1127c642f342406d41b83c (patch) | |
tree | 8de51baab28e1dbf9e3f019a92eb2b8dfa079686 /libexec/spamd | |
parent | f60e4b727d6777f7d3a9fafa457c216b3323333f (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.8 | 27 | ||||
-rw-r--r-- | libexec/spamd/spamd.c | 97 |
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); |