diff options
Diffstat (limited to 'net-mail/qmail/files/1.03-r12/bad-rcpt-noisy-patch')
-rw-r--r-- | net-mail/qmail/files/1.03-r12/bad-rcpt-noisy-patch | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/net-mail/qmail/files/1.03-r12/bad-rcpt-noisy-patch b/net-mail/qmail/files/1.03-r12/bad-rcpt-noisy-patch new file mode 100644 index 000000000000..576d6c410dcb --- /dev/null +++ b/net-mail/qmail/files/1.03-r12/bad-rcpt-noisy-patch @@ -0,0 +1,328 @@ +This is a noissy "badrcptto" patch for systems that have a lot +of addresses they want to reject, and want to log what happens + +Addresses to reject go in control/badrcptto and control/morebadrcptto, +one per line, just like badmailfrom. control/morebadrcptto is +compiled into control/morebadrcptto.cdb with the new program +qmail-newbrt. I'd suggest putting all of your bad addresses into +morebadrcptto since it's a lot faster to look something up in a CDB +than in a text file. + +Whenever qmail-smtp rejects a message or otherwise fails, it writes a +descriptive message to stderr, which if you're running under +daemontools should end up in the log file. The logging code is +adapted from an older anti-spam patch contributed to qmail.org. + +Unlike the previous badrcptto patch, this one does not reject the +message at RCPT TO time. Instead, it waits until the DATA command to +issue a 550 rejection. This has two effects: one is to deter +dictionary attackers which are perversely encouraged by RCPT TO +rejections. (If some of the addresses are bad, the rest must be +good.) The other is that if a message has a mixture of bad and good +addresses, the message will be rejected anyway. That's a feature, +since in my experience, any message addressed to a spam-only address +is spam even if it's also addressed to legit addresses. + +This version also does not let you list domains in the badrcptto +files. There's no point in doing so, since all domains not in +rcpthosts are rejected, anyway. + +This patch contains the entire new source file for qmail-newbrt.c as +a diff against an empty file. If patch gets mad at you, just create +the empty file. + +No warranty expressed or implied. If you find bugs, feel free to fix +them and please send me the fix. + +John Levine, johnl@iecc.com, 4/03 + + +diff -u qmail-1.03-dist/Makefile qmail-1.03/Makefile +--- qmail-1.03-dist/Makefile Mon Jun 15 06:53:16 1998 ++++ qmail-1.03/Makefile Wed Apr 9 01:30:20 2003 +@@ -803,7 +803,7 @@ + predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \ + qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ + qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ +-qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ ++qmail-smtpd sendmail tcp-env qmail-newmrh qmail-newbrt config config-fast dnscname \ + dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ + forward preline condredirect bouncesaying except maildirmake \ + maildir2mbox maildirwatch qail elq pinq idedit install-big install \ +@@ -1241,6 +1241,19 @@ + uint32.h substdio.h + ./compile qmail-newmrh.c + ++qmail-newbrt: \ ++load qmail-newbrt.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \ ++stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o ++ ./load qmail-newbrt cdbmss.o getln.a open.a cdbmake.a \ ++ seek.a case.a stralloc.a alloc.a strerr.a substdio.a \ ++ error.a str.a auto_qmail.o ++ ++qmail-newbrt.o: \ ++compile qmail-newbrt.c strerr.h stralloc.h gen_alloc.h substdio.h \ ++getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \ ++uint32.h substdio.h ++ ./compile qmail-newbrt.c ++ + qmail-newu: \ + load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \ + stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o +diff -u qmail-1.03-dist/qmail-newbrt.c qmail-1.03/qmail-newbrt.c +--- qmail-1.03-dist/qmail-newbrt.c Wed Apr 9 16:31:27 2003 ++++ qmail-1.03/qmail-newbrt.c Wed Apr 9 16:18:50 2003 +@@ -0,0 +1,70 @@ ++#include "strerr.h" ++#include "stralloc.h" ++#include "substdio.h" ++#include "getln.h" ++#include "exit.h" ++#include "readwrite.h" ++#include "open.h" ++#include "auto_qmail.h" ++#include "cdbmss.h" ++ ++#define FATAL "qmail-newbrt: fatal: " ++ ++void die_read() ++{ ++ strerr_die2sys(111,FATAL,"unable to read control/morebadrcptto: "); ++} ++void die_write() ++{ ++ strerr_die2sys(111,FATAL,"unable to write to control/morebadrcptto.tmp: "); ++} ++ ++char inbuf[1024]; ++substdio ssin; ++ ++int fd; ++int fdtemp; ++ ++struct cdbmss cdbmss; ++stralloc line = {0}; ++int match; ++ ++void main() ++{ ++ umask(033); ++ if (chdir(auto_qmail) == -1) ++ strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); ++ ++ fd = open_read("control/morebadrcptto"); ++ if (fd == -1) die_read(); ++ ++ substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf); ++ ++ fdtemp = open_trunc("control/morebadrcptto.tmp"); ++ if (fdtemp == -1) die_write(); ++ ++ if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write(); ++ ++ for (;;) { ++ if (getln(&ssin,&line,&match,'\n') != 0) die_read(); ++ case_lowerb(line.s,line.len); ++ while (line.len) { ++ if (line.s[line.len - 1] == ' ') { --line.len; continue; } ++ if (line.s[line.len - 1] == '\n') { --line.len; continue; } ++ if (line.s[line.len - 1] == '\t') { --line.len; continue; } ++ if (line.s[0] != '#') ++ if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1) ++ die_write(); ++ break; ++ } ++ if (!match) break; ++ } ++ ++ if (cdbmss_finish(&cdbmss) == -1) die_write(); ++ if (fsync(fdtemp) == -1) die_write(); ++ if (close(fdtemp) == -1) die_write(); /* NFS stupidity */ ++ if (rename("control/morebadrcptto.tmp","control/morebadrcptto.cdb") == -1) ++ strerr_die2sys(111,FATAL,"unable to move control/morebadrcpto.tmp to control/morebadrcptto.cdb"); ++ ++ _exit(0); ++} +diff -u qmail-1.03-dist/qmail-smtpd.c.orig qmail-1.03/qmail-smtpd.c +--- qmail-1.03-dist/qmail-smtpd.c.orig 2003-08-11 22:23:06.000000000 -0700 ++++ qmail-1.03/qmail-smtpd.c 2003-08-11 22:26:10.000000000 -0700 +@@ -25,12 +25,20 @@ + #include "commands.h" + #include "wait.h" + #include "fd.h" ++#include "cdb.h" + + #define AUTHCRAM + #define MAXHOPS 100 + unsigned int databytes = 0; + int timeout = 1200; + ++char *remoteip; ++char *remotehost; ++char *remoteinfo; ++char *local; ++char *relayclient; ++ ++ + const char *protocol = "SMTP"; + + #ifdef TLS +@@ -59,17 +67,50 @@ + char ssoutbuf[512]; + substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); + ++/* write errors to stderr */ ++char erroutbuf[512]; ++substdio errout = SUBSTDIO_FDBUF(safewrite,2,erroutbuf,sizeof erroutbuf); ++ + void flush() { substdio_flush(&ssout); } + void out(s) char *s; { substdio_puts(&ssout,s); } + ++void eflush() { substdio_flush(&errout); } ++void eout(s) char *s; { substdio_puts(&errout,s); } ++void enew() { substdio_puts(&errout,"qmail-smtpd: "); } ++ + void die_read() { _exit(1); } +-void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } +-void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } +-void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } +-void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); } +-void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } ++void die_alarm() ++{ ++ enew(); eout("Connection to "); eout(remoteip); eout(" timed out.\n"); ++ out("451 timeout (#4.4.2)\r\n"); flush(); eflush(); _exit(1); ++} ++void die_nomem() ++{ ++ enew(); eout("Out of memory while connected to "); eout(remoteip); eout("!\n"); ++ out("421 out of memory (#4.3.0)\r\n"); flush(); eflush(); _exit(1); ++} ++void die_control() ++{ ++ enew(); eout("Unable to read controls!\n"); ++ out("421 unable to read controls (#4.3.0)\r\n"); flush(); eflush(); ++ _exit(1); ++} ++void die_ipme() ++{ ++ enew(); eout("Unable to figure out my IP addresses!\n"); ++ out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); ++ eflush(); _exit(1); ++} ++void straynewline() ++{ ++ enew(); eout("Stray newline from "); eout(remoteip); eout(".\n"); ++ out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); ++ eflush(); _exit(1); ++} ++ + + void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } ++void err_brt() { out("550 sorry, this message is not deliverable (#5.7.1)\r\n"); } + #ifndef TLS + void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } + #else +@@ -115,12 +156,6 @@ + smtp_greet("221 "); out("\r\n"); flush(); _exit(0); + } + +-char *remoteip; +-char *remotehost; +-char *remoteinfo; +-char *local; +-char *relayclient; +- + stralloc helohost = {0}; + char *fakehelo; /* pointer into helohost, or 0 */ + +@@ -135,6 +170,10 @@ + int bmfok = 0; + stralloc bmf = {0}; + struct constmap mapbmf; ++int brtok = 0; ++stralloc brt = {0}; ++struct constmap mapbrt; ++int fdmbrt; + + void setup() + { +@@ -155,7 +194,16 @@ + if (bmfok == -1) die_control(); + if (bmfok) + if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); ++ ++ brtok = control_readfile(&brt,"control/badrcptto",0); ++ if (brtok == -1) die_control(); ++ if (brtok) ++ if (!constmap_init(&mapbrt,brt.s,brt.len,0)) die_nomem(); + ++ fdmbrt = open_read("control/morebadrcptto.cdb"); ++ if (fdmbrt == -1) if (errno != error_noent) die_control(); ++ ++ + if (control_readint(&databytes,"control/databytes") == -1) die_control(); + x = env_get("DATABYTES"); + if (x) { scan_ulong(x,&u); databytes = u; } +@@ -241,6 +289,14 @@ + return 1; + } + ++static void log_deny(m,f,t) char *m,*f,*t; ++{ ++ enew(); eout(m); eout(" check failed ("); eout(f); eout(") -> ("); ++ eout(t); eout(") ["); eout(remoteip); eout("] (HELO "); ++ eout(helohost.s); eout(")\n"); ++ eflush(); ++} ++ + int bmfcheck() + { + int j; +@@ -252,6 +308,19 @@ + return 0; + } + ++int brtcheck() ++{ ++ int j; ++ if (brtok) if (constmap(&mapbrt,addr.s,addr.len - 1)) return 1; ++ if (fdmbrt) { ++ uint32 dlen; ++ j = cdb_seek(fdmbrt, addr.s, addr.len - 1, &dlen); ++ if (j == -1) die_control(); ++ if (j) return j; ++ } ++ return 0; ++} ++ + int addrallowed() + { + int r; +@@ -281,6 +350,7 @@ + + int seenmail = 0; + int flagbarf; /* defined if seenmail */ ++int flagbrt; /* defined if any bad rcpts */ + stralloc mailfrom = {0}; + stralloc rcptto = {0}; + +@@ -333,6 +403,10 @@ + } + else + if (!addrallowed()) { err_nogateway(); return; } ++ if (!env_get("RELAYCLIENT") && brtcheck()) { ++ flagbrt = 1; ++ log_deny("BAD RCPT TO", mailfrom.s,addr.s); ++ } + if (!stralloc_cats(&rcptto,"T")) die_nomem(); + if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); + if (!stralloc_0(&rcptto)) die_nomem(); +@@ -452,6 +526,7 @@ + + if (!seenmail) { err_wantmail(); return; } + if (!rcptto.len) { err_wantrcpt(); return; } ++ if (flagbrt) { err_brt(); return; } + seenmail = 0; + if (databytes) bytestooverflow = databytes + 1; + if (qmail_open(&qqt) == -1) { err_qqt(); return; } |