diff options
Diffstat (limited to 'libexec/spamd/spamd.c')
-rw-r--r-- | libexec/spamd/spamd.c | 97 |
1 files changed, 79 insertions, 18 deletions
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); |