diff -d -p -P -U 3 -r -N qmail-1.03/Makefile qmail-1.03-bgs/Makefile --- qmail-1.03/Makefile 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/Makefile 2003-04-14 18:05:59.000000000 +0200 @@ -800,8 +800,8 @@ ipalloc.h ip.h gen_alloc.h exit.h it: \ qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \ qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \ -predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \ -qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ +predate datemail mailsubj qmail-upq qmail-showctl qmail-BGSshowctl qmail-newu \ +qmail-pw2u qmail-qread qmail-qstat qmail-BGSqstat 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 \ dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ @@ -1414,6 +1414,11 @@ warn-auto.sh qmail-qstat.sh conf-qmail c > qmail-qstat chmod 755 qmail-qstat +qmail-BGSqstat: \ +qmail-BGSqstat + chmod 755 qmail-BGSqstat + + qmail-qstat.0: \ qmail-qstat.8 nroff -man qmail-qstat.8 > qmail-qstat.0 @@ -1520,6 +1525,16 @@ auto_patrn.o auto_spawn.o auto_split.o auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \ auto_split.o +qmail-BGSshowctl: \ +load qmail-BGSshowctl.o auto_uids.o control.o open.a getln.a stralloc.a \ +alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \ +auto_patrn.o auto_spawn.o auto_split.o + ./load qmail-BGSshowctl auto_uids.o control.o open.a getln.a \ + stralloc.a alloc.a substdio.a error.a str.a fs.a \ + auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \ + auto_split.o + + qmail-showctl.0: \ qmail-showctl.8 nroff -man qmail-showctl.8 > qmail-showctl.0 @@ -1531,17 +1546,25 @@ auto_uids.h auto_qmail.h auto_break.h au auto_split.h ./compile qmail-showctl.c +qmail-BGSshowctl.o: \ +compile qmail-BGSshowctl.c substdio.h subfd.h substdio.h exit.h fmt.h \ +str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \ +auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \ +auto_split.h + ./compile qmail-BGSshowctl.c + + qmail-smtpd: \ load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \ -open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \ +open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a\ fs.a auto_qmail.o socket.lib ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \ received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ datetime.a getln.a open.a sig.a case.a env.a stralloc.a \ - alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ + alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ socket.lib` qmail-smtpd.0: \ @@ -1776,7 +1799,7 @@ qreceipt.1 splogger.8 tcp-env.1 config.s qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \ qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \ qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \ -qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \ +qmail-qread.c qmail-qstat.sh qmail-BGSqstat qmail-queue.c qmail-remote.c \ qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \ qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \ dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \ diff -d -p -P -U 3 -r -N qmail-1.03/README.DELE_access qmail-1.03-bgs/README.DELE_access --- qmail-1.03/README.DELE_access 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03-bgs/README.DELE_access 2003-04-14 17:37:09.000000000 +0200 @@ -0,0 +1,27 @@ + + + The DELE_access patch is a very simple patch that allows you some +control on users deleting mails. This can be useful in some cases +when more than one user is accessing the mailboxes. + + The usage is very simple. qmail-pop3d checks for the DELE_NOTIFY +and DELE_DENY environment variables. If DELE_NOTIFY is set every +DELE command will be logged with syslog() with LOG_ALERT with the IP +of the client. If DELE_DENY is set, all DELE commands are denied +and the attempt is logged like in the DELE_NOTIFY case. In addition +the contents of the DELE_DENY is returned with the ERR line. + + You can set these parameters through a tcp wrapper like tcpserver. +With selective tcp settings you can allow for example a single user +to remove mail from the common mailboxes. + + This can also be useful with some mail archive systems like 'march' +(check http://bgslinux.info). + +This patch is under the GPL license. You can freely use it for non +profit purposes. If you use it, please drop me a line. + + + +Author: Bgs +Keywords: qmail dele pop3 deny notify diff -d -p -P -U 3 -r -N qmail-1.03/README.bgs_bundle qmail-1.03-bgs/README.bgs_bundle --- qmail-1.03/README.bgs_bundle 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03-bgs/README.bgs_bundle 2003-04-14 18:03:47.000000000 +0200 @@ -0,0 +1,63 @@ + +bgs_bundle patch 0.1d +2003.04.14. +bgs@bgslinux.info +http://bgslinux.info + + + The bgs_bundle patch includes several patches joined to form a +usefull general patch for a reliable and secure smtp server. Some +of the patches are my own, some are gathered from the net or are +other's patches modified by me. (For faster scanning I use the +following notation: * my patch, & other's patch, + other's patch +modified by me). In addition there are a few little pre-tunings +listed after the patches. + + Here is the list of patches: + + +* DELE_access.patch: Read README.DELE_access + +* qmail-BGSshowctl.patch: A simple patch to an alternative showctl. + (It also shows the newly added controls.) + ++ tarpit.patch: A tarpitting patch by Chris Johnson + modified by me. The modification + is about a NOTARPIT environtment variable. If set tarpitting is + disabled regardless of the tarpitcount/tarpitdelay control files. + Usefull for defense, but still allowing some hosts to send bunchmail. + + ++ high_injection_rate.patch: A patch by UNKOWN to limit + qmail-send's queue rescan overhead with high injection rate. My + modification is the use of control/minqueuedelay to override the default + 5 second setting. + +& logrelay.patch: Patch by UNKNOWN to log failed relay attempts. + + + +Tunings: + + - queuelifetime default value changed to 172800 (2 days). In most cases + a week without problem notification is way too long. Two days seems + more adequate. (If network is down for more than a day on either sender + or recipient side you have bigger problems. A one week delay before + knowing that you mail didn't get there is a much more irritating and + more frequent problem). + +Scripts : +(some of the scripts use zsh!) + + * qmail-BGSqstat: alternative qmail-qstat script. + + & qmail-reinject: from UNKNOWN move a message from state 5 to + state 4 ie. from preprocessed to queued stat useful when a message is + "stuck" in the wrong queue (local or remote) or to force a delivery + retry usage: + + qmail-reinject [-v] inode + + reinjects the message int ~qmail/queue/mess/xx/inode + + \ No newline at end of file diff -d -p -P -U 3 -r -N qmail-1.03/README.qmail-reinject qmail-1.03-bgs/README.qmail-reinject --- qmail-1.03/README.qmail-reinject 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03-bgs/README.qmail-reinject 2003-04-14 17:37:09.000000000 +0200 @@ -0,0 +1,8 @@ +Taken from the script: + + qmail-reinject: move a message from state 5 to state 4 + ie from preprocessed to queued stat + useful when a message is "stuck" in the wrong queue + (local or remote) or to force a delivery retry + usage: qmail-reinject [-v] inode + reinjects the message int ~qmail/queue/mess/xx/inode diff -d -p -P -U 3 -r -N qmail-1.03/qmail-BGSqstat qmail-1.03-bgs/qmail-BGSqstat --- qmail-1.03/qmail-BGSqstat 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03-bgs/qmail-BGSqstat 2003-04-14 18:02:42.000000000 +0200 @@ -0,0 +1,28 @@ +#!/bin/zsh + +QUEUE=/var/qmail/queue + +messfiles=$(find $QUEUE/mess/ -type f) +todofiles=$(find $QUEUE/todo/ -type f) + + +[[ ! -z $messfiles ]] && { + messsize=$(du -cs $(echo $messfiles) | tail -1) + messsize=$messsize[(w)1]; +} || { + messsize=0 +} + + +[[ ! -z $todofiles ]] && { + todosize=$(du -cs $(echo $todofiles) | tail -1) + todosize=$todosize[(w)1]; +} || { + todosize=0 +} + + +echo "number of messages in queue:\t\t\t\t$(($(echo $messfiles|wc -w)))" +echo "total size of messages in queue (kB):\t\t\t$messsize" +echo "number of unprocessed messages in queue:\t\t$(($(echo $todofiles| wc -w)))" +echo "total size of unprocessed messages in queue (kB):\t$todosize" \ No newline at end of file Binary files qmail-1.03/qmail-BGSshowctl and qmail-1.03-bgs/qmail-BGSshowctl differ diff -d -p -P -U 3 -r -N qmail-1.03/qmail-BGSshowctl.c qmail-1.03-bgs/qmail-BGSshowctl.c --- qmail-1.03/qmail-BGSshowctl.c 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03-bgs/qmail-BGSshowctl.c 2003-04-14 17:38:01.000000000 +0200 @@ -0,0 +1,270 @@ +#include +#include +#include "substdio.h" +#include "subfd.h" +#include "exit.h" +#include "fmt.h" +#include "str.h" +#include "control.h" +#include "constmap.h" +#include "stralloc.h" +#include "direntry.h" +#include "auto_uids.h" +#include "auto_qmail.h" +#include "auto_break.h" +#include "auto_patrn.h" +#include "auto_spawn.h" +#include "auto_split.h" + +stralloc me = {0}; +int meok; + +stralloc line = {0}; +char num[FMT_ULONG]; + +void safeput(buf,len) +char *buf; +unsigned int len; +{ + char ch; + + while (len > 0) { + ch = *buf; + if ((ch < 32) || (ch > 126)) ch = '?'; + substdio_put(subfdout,&ch,1); + ++buf; + --len; + } +} + +void do_int(fn,def,pre,post) +char *fn; +char *def; +char *pre; +char *post; +{ + int i; + substdio_puts(subfdout,"\n"); + substdio_puts(subfdout,fn); + substdio_puts(subfdout,": "); + switch(control_readint(&i,fn)) { + case 0: + substdio_puts(subfdout,"(Default.) "); + substdio_puts(subfdout,pre); + substdio_puts(subfdout,def); + substdio_puts(subfdout,post); + substdio_puts(subfdout,".\n"); + break; + case 1: + if (i < 0) i = 0; + substdio_puts(subfdout,pre); + substdio_put(subfdout,num,fmt_uint(num,i)); + substdio_puts(subfdout,post); + substdio_puts(subfdout,".\n"); + break; + default: + substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); + break; + } +} + +void do_str(fn,flagme,def,pre) +char *fn; +int flagme; +char *def; +char *pre; +{ + substdio_puts(subfdout,"\n"); + substdio_puts(subfdout,fn); + substdio_puts(subfdout,": "); + switch(control_readline(&line,fn)) { + case 0: + substdio_puts(subfdout,"(Default.) "); + if (!stralloc_copys(&line,def)) { + substdio_puts(subfdout,"Oops! Out of memory.\n"); + break; + } + if (flagme && meok) + if (!stralloc_copy(&line,&me)) { + substdio_puts(subfdout,"Oops! Out of memory.\n"); + break; + } + case 1: + substdio_puts(subfdout,pre); + safeput(line.s,line.len); + substdio_puts(subfdout,".\n"); + break; + default: + substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); + break; + } +} + +int do_lst(fn,def,pre,post) +char *fn; +char *def; +char *pre; +char *post; +{ + int i; + int j; + + substdio_puts(subfdout,"\n"); + substdio_puts(subfdout,fn); + substdio_puts(subfdout,": "); + switch(control_readfile(&line,fn)) { + case 0: + substdio_puts(subfdout,"(Default.) "); + substdio_puts(subfdout,def); + substdio_puts(subfdout,"\n"); + return 0; + case 1: + substdio_puts(subfdout,"\n"); + i = 0; + for (j = 0;j < line.len;++j) + if (!line.s[j]) { + substdio_puts(subfdout,pre); + safeput(line.s + i,j - i); + substdio_puts(subfdout,post); + substdio_puts(subfdout,"\n"); + i = j + 1; + } + return 1; + default: + substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); + return -1; + } +} + +void main() +{ + DIR *dir; + direntry *d; + struct stat stmrh; + struct stat stmrhcdb; + + if (chdir(auto_qmail) == -1) { + substdio_puts(subfdout,"Oops! Unable to chdir to "); + substdio_puts(subfdout,auto_qmail); + substdio_puts(subfdout,".\n"); + substdio_flush(subfdout); + _exit(111); + } + if (chdir("control") == -1) { + substdio_puts(subfdout,"Oops! Unable to chdir to control.\n"); + substdio_flush(subfdout); + _exit(111); + } + + dir = opendir("."); + if (!dir) { + substdio_puts(subfdout,"Oops! Unable to open current directory.\n"); + substdio_flush(subfdout); + _exit(111); + } + + meok = control_readline(&me,"me"); + if (meok == -1) { + substdio_puts(subfdout,"Oops! Trouble reading control/me."); + substdio_flush(subfdout); + _exit(111); + } + + substdio_puts(subfdout,"\n\tCurrent server configuration:\n"); + substdio_flush(subfdout); + + + do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM."); + do_lst("badmailto","Any RCPT TO is allowed.",""," not accepted in RCPT TO."); + do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is "); + do_str("bouncehost",1,"bouncehost","Bounce host name is "); + do_int("concurrencylocal","10","Local concurrency is ",""); + do_int("concurrencyremote","20","Remote concurrency is ",""); + do_int("databytes","0","SMTP DATA limit is "," bytes"); + do_str("defaultdomain",1,"defaultdomain","Default domain name is "); + do_str("defaulthost",1,"defaulthost","Default host name is "); + do_str("doublebouncehost",1,"doublebouncehost","2B recipient host: "); + do_str("doublebounceto",0,"postmaster","2B recipient user: "); + do_str("envnoathost",1,"envnoathost","Presumed domain name is "); + do_str("helohost",1,"helohost","SMTP client HELO host name is "); + do_str("idhost",1,"idhost","Message-ID host name is "); + do_str("localiphost",1,"localiphost","Local IP address becomes "); + do_lst("locals","Messages for me are delivered locally.","Messages for "," are delivered locally."); + do_str("me",0,"undefined! Uh-oh","My name is "); + do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@","."); + do_str("plusdomain",1,"plusdomain","Plus domain name is "); + do_lst("qmqpservers","No QMQP servers.","QMQP server: ","."); + do_int("queuedelay","5","Minimal time between queue reruns: "," seconds"); + do_int("queuelifetime","172800","Message lifetime in the queue is "," seconds"); + + if (do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ",".")) + do_lst("morercpthosts","No effect.","SMTP clients may send messages to recipients at ","."); + else + do_lst("morercpthosts","No rcpthosts; morercpthosts is irrelevant.","No rcpthosts; doesn't matter that morercpthosts has ","."); + /* XXX: check morercpthosts.cdb contents */ + substdio_puts(subfdout,"\nmorercpthosts.cdb: "); + if (stat("morercpthosts",&stmrh) == -1) + if (stat("morercpthosts.cdb",&stmrhcdb) == -1) + substdio_puts(subfdout,"(Default.) No effect.\n"); + else + substdio_puts(subfdout,"Oops! morercpthosts.cdb exists but morercpthosts doesn't.\n"); + else + if (stat("morercpthosts.cdb",&stmrhcdb) == -1) + substdio_puts(subfdout,"Oops! morercpthosts exists but morercpthosts.cdb doesn't.\n"); + else + if (stmrh.st_mtime > stmrhcdb.st_mtime) + substdio_puts(subfdout,"Oops! morercpthosts.cdb is older than morercpthosts.\n"); + else + substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n"); + + do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 "); + do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ",""); + do_int("tarpitcount","Tarpitting not enabled.", "Tarpitting triggered at: ", ""); + do_int("tarpitdelay", "5", "Tarpitting delay set to: ", "seconds"); + do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds"); + do_int("timeoutremote","1200","SMTP client data timeout is "," seconds"); + do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds"); + do_lst("virtualdomains","No virtual domains.","Virtual domain: ",""); + + while (d = readdir(dir)) { + if (str_equal(d->d_name,".")) continue; + if (str_equal(d->d_name,"..")) continue; + if (str_equal(d->d_name,"bouncefrom")) continue; + if (str_equal(d->d_name,"bouncehost")) continue; + if (str_equal(d->d_name,"badmailfrom")) continue; + if (str_equal(d->d_name,"bouncefrom")) continue; + if (str_equal(d->d_name,"bouncehost")) continue; + if (str_equal(d->d_name,"concurrencylocal")) continue; + if (str_equal(d->d_name,"concurrencyremote")) continue; + if (str_equal(d->d_name,"databytes")) continue; + if (str_equal(d->d_name,"defaultdomain")) continue; + if (str_equal(d->d_name,"defaulthost")) continue; + if (str_equal(d->d_name,"doublebouncehost")) continue; + if (str_equal(d->d_name,"doublebounceto")) continue; + if (str_equal(d->d_name,"envnoathost")) continue; + if (str_equal(d->d_name,"helohost")) continue; + if (str_equal(d->d_name,"idhost")) continue; + if (str_equal(d->d_name,"localiphost")) continue; + if (str_equal(d->d_name,"locals")) continue; + if (str_equal(d->d_name,"me")) continue; + if (str_equal(d->d_name,"morercpthosts")) continue; + if (str_equal(d->d_name,"morercpthosts.cdb")) continue; + if (str_equal(d->d_name,"percenthack")) continue; + if (str_equal(d->d_name,"plusdomain")) continue; + if (str_equal(d->d_name,"qmqpservers")) continue; + if (str_equal(d->d_name,"queuelifetime")) continue; + if (str_equal(d->d_name,"rcpthosts")) continue; + if (str_equal(d->d_name,"smtpgreeting")) continue; + if (str_equal(d->d_name,"smtproutes")) continue; + if (str_equal(d->d_name,"timeoutconnect")) continue; + if (str_equal(d->d_name,"timeoutremote")) continue; + if (str_equal(d->d_name,"timeoutsmtpd")) continue; + if (str_equal(d->d_name,"virtualdomains")) continue; + substdio_puts(subfdout,"\n"); + substdio_puts(subfdout,d->d_name); + substdio_puts(subfdout,": I have no idea what this file does.\n"); + } + + substdio_flush(subfdout); + _exit(0); +} Binary files qmail-1.03/qmail-BGSshowctl.o and qmail-1.03-bgs/qmail-BGSshowctl.o differ diff -d -p -P -U 3 -r -N qmail-1.03/qmail-control.9 qmail-1.03-bgs/qmail-control.9 --- qmail-1.03/qmail-control.9 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-control.9 2003-04-14 17:37:09.000000000 +0200 @@ -55,6 +55,7 @@ control default used by .I idhost \fIme \fRqmail-inject .I localiphost \fIme \fRqmail-smtpd .I locals \fIme \fRqmail-send +.I minqueuedelay \fR2 \fRqmail-send .I morercpthosts \fR(none) \fRqmail-smtpd .I percenthack \fR(none) \fRqmail-send .I plusdomain \fIme \fRqmail-inject @@ -63,6 +64,8 @@ control default used by .I rcpthosts \fR(none) \fRqmail-smtpd .I smtpgreeting \fIme \fRqmail-smtpd .I smtproutes \fR(none) \fRqmail-remote +.I tarpitcount \fR0 \fRqmail-smtpd +.I tarpitdelay \fR5 \fRqmail-smtpd .I timeoutconnect \fR60 \fRqmail-remote .I timeoutremote \fR1200 \fRqmail-remote .I timeoutsmtpd \fR1200 \fRqmail-smtpd diff -d -p -P -U 3 -r -N qmail-1.03/qmail-pop3d.8 qmail-1.03-bgs/qmail-pop3d.8 --- qmail-1.03/qmail-pop3d.8 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-pop3d.8 2003-04-14 17:37:09.000000000 +0200 @@ -37,6 +37,25 @@ to work around serious bugs in certain c .B qmail-pop3d is based on a program contributed by Russ Nelson. + +.B qmail-pop3d +sends a notification through syslog with +.IR LOG_ALERT +if the environment variable +.IR DELE_NOTIFY +is set. + +.B qmail-pop3d +denies DELE commands (delete mail) if the environment variable +.IR DELE_DENY +is set. It sends a log through syslog (similar to +.IR DELE_NOTIFY ) +and returns an +.IR -ERR +to the client with the contents of +.IR DELE_DENY . + + .SH "SEE ALSO" maildir(5), qmail-local(8), diff -d -p -P -U 3 -r -N qmail-1.03/qmail-pop3d.c qmail-1.03-bgs/qmail-pop3d.c --- qmail-1.03/qmail-pop3d.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-pop3d.c 2003-04-14 17:37:09.000000000 +0200 @@ -1,5 +1,7 @@ #include #include +#include +#include #include "commands.h" #include "sig.h" #include "getln.h" @@ -17,6 +19,7 @@ #include "timeoutread.h" #include "timeoutwrite.h" + void die() { _exit(0); } int saferead(fd,buf,len) int fd; char *buf; int len; @@ -212,8 +215,19 @@ void pop3_dele(arg) char *arg; int i; i = msgno(arg); if (i == -1) return; - m[i].flagdeleted = 1; +if ((getenv("DELE_DENY")) == NULL) { + m[i].flagdeleted = 1; + } else { + openlog("qmail-pop3d",0,LOG_MAIL); + syslog(LOG_ALERT, "DELE denied for user from %s", getenv("TCPREMOTEIP")); + err(getenv("DELE_DENY")); + } if (i + 1 > last) last = i + 1; +if ((getenv("DELE_NOTIFY")) != NULL) { + openlog("qmail-pop3d",0,LOG_MAIL); + syslog(LOG_ALERT, "User from %s issued DELE command !", getenv("TCPREMOTEIP")); + closelog(); + } okay(); } diff -d -p -P -U 3 -r -N qmail-1.03/qmail-reinject qmail-1.03-bgs/qmail-reinject --- qmail-1.03/qmail-reinject 1970-01-01 01:00:00.000000000 +0100 +++ qmail-1.03-bgs/qmail-reinject 2003-04-14 17:37:09.000000000 +0200 @@ -0,0 +1,65 @@ +#!/bin/sh +# +# qmail-reinject: move a message from state 5 to state 4 +# ie from preprocessed to queued stat +# useful when a message is "stuck" in the wrong queue +# (local or remote) or to force a delivery retry +# usage: qmail-reinject [-v] inode +# reinjects the message int ~qmail/queue/mess/xx/inode +# + +function die() { + rm -f "$1"; shift + echo ${1+"$@"} + exit 1 +} + +if [ "$1" = "-v" ]; then + v=verbose + shift; +fi +if [ $# = 0 ]; then + echo usage: fixit [options] inode + echo options: -v verbose + exit +fi +q=/opt/qmail/queue +u=$UID +i=$1; echo $i | grep [^0-9] &>/dev/null && die "" "'$i' is not an inode" +p=$$ +if [ -n "$v" ]; then + echo my uid is $UID and my pid is $p + echo looking for message with inode $i +fi +F=$(cat $q/info/*/$i 2>/dev/null); [ -z "$F" ] && die "" bogus F +T=$(cat $q/remote/*/$i 2>/dev/null); [ -z "$F" ] && die "" bogus T +r=$(echo $q/mess/*/$i | sed "s@^$q/mess/@@;s@/$i@@"); [ -f $q/mess/$r/$i ] || die "" "Can't find mess subdirectory" +w=$(echo $q/local}/$r/$i | sed "s@^$q/@@;s@/$r/$i@@") +[ -f $q/$q/$r/$i ] || w=$(echo $q/remote/$r/$i | sed "s@^$q/@@;s@/$r/$i@@") +[ -f $q/$w/$r/$i ] || die "" "Can't find local or remote (looking for '$w')" +if [ -n "$v" ]; then + echo message lives in mess/$r + echo from ${F##F} to ${T##T} +fi + +# make todo +[ -n "$v" ] && echo writing pid/$p +printf 'u%s\0p%s\0%s\0%s\0' $u $p $F $T > $q/pid/$p +[ $? = 0 ] || die $q/pid/$p failed to create todo +[ -n "$v" ] && echo changing permission of pid/$p to 644 qmailq.users +chown qmailq.users $q/pid/$p && chmod 644 $q/pid/$p +[ $? = 0 ] || die $q/pid/$p failed to set ownership of todo +[ -n "$v" ] && echo linking pid/$p to todo/$r/$p +ln $q/pid/$p $q/todo/$r/$i +[ $? = 0 ] || die $q/pid/$p failed to link todo +[ -n "$v" ] && echo unlinking pid/$p +rm $q/pid/$p + +# make intd +[ -n "$v" ] && echo copying todo/$r/$p to intd/$r/$i +cp -p $q/todo/$r/$i $q/intd/$r/$i +[ $? = 0 ] || die "" failed to create intd + +# lose info and remote +[ -n "$v" ] && echo unlinking info/$r/$i and $w/$r/$i +rm -f $q/info/$r/$i $q/$w/$r/$i diff -d -p -P -U 3 -r -N qmail-1.03/qmail-send.9 qmail-1.03-bgs/qmail-send.9 --- qmail-1.03/qmail-send.9 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-send.9 2003-04-14 17:37:09.000000000 +0200 @@ -147,6 +147,14 @@ is considered local if is listed in .IR locals . .TP 5 +.I minqueuedelay +Minimum time before +.B qmail-send +is allowed to re-run the queue, regardless to +new incoming mail. Default: +.IR 2 +seconds. +.TP 5 .I percenthack List of domain names where the percent hack is applied. If diff -d -p -P -U 3 -r -N qmail-1.03/qmail-send.c qmail-1.03-bgs/qmail-send.c --- qmail-1.03/qmail-send.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-send.c 2003-04-14 17:37:09.000000000 +0200 @@ -36,13 +36,15 @@ /* critical timing feature #2: if triggered, respond within fixed time */ /* important timing feature: when triggered, respond instantly */ #define SLEEP_TODO 1500 /* check todo/ every 25 minutes in any case */ +//#define ONCEEVERY 10 /* run todo maximal once every N seconds */ #define SLEEP_FUZZ 1 /* slop a bit on sleeps to avoid zeno effect */ #define SLEEP_FOREVER 86400 /* absolute maximum time spent in select() */ #define SLEEP_CLEANUP 76431 /* time between cleanups */ #define SLEEP_SYSFAIL 123 #define OSSIFIED 129600 /* 36 hours; _must_ exceed q-q's DEATH (24 hours) */ -int lifetime = 604800; +int lifetime = 172800; +int minqueuedelay = 2; stralloc percenthack = {0}; struct constmap mappercenthack; @@ -1215,7 +1217,7 @@ void pass_do() /* this file is too long ---------------------------------------------- TODO */ -datetime_sec nexttodorun; +datetime_sec nexttodorun, lasttodorun; DIR *tododir; /* if 0, have to opendir again */ stralloc todoline = {0}; char todobuf[SUBSTDIO_INSIZE]; @@ -1225,6 +1227,7 @@ char todobufchan[CHANNELS][1024]; void todo_init() { tododir = 0; + lasttodorun = 0; nexttodorun = now(); trigger_set(); } @@ -1265,6 +1268,39 @@ fd_set *rfds; if (flagexitasap) return; + /* + * qmail normally does a queue run for every injected message and then + * schedules it for local/remote delivery. + * If we get too many injections the queue runs will stall scheduling + * of local/remote deliveries. Usually we see a sharp drop in concurrent + * deliveries while new messages arrive at high rate in the queue. + * In such a situation it doesn't make sense to process the queue after + * each and every injection. It is more important to fill the delivery + * slots with work to drain the queue. + * This patch will allow for only one queue run every N seconds. It + * remembers the last complete queue run and will just return if we + * get triggered before last queue run plus N seconds. If we get + * triggered before N seconds it will schedule a forced queue run at + * last complete queue run plus N seconds to not miss the new additions + * to the queue. + * Some more thoughts: + * - This is proof of concept and should be made at least dynamically + * configureable through a control file (and reread with -HUP) + * - This could even be made selftuning by measuring the time it takes + * to do a queue run and do the run delay only after a certain + * threshold has been reached + * - the optimal values for delaying have to found + * + * 20011108, Initial revision, opi@nrg4u.com + */ + + /* run todo maximal once every N seconds */ + if (recent < (lasttodorun + minqueuedelay)) + { + nexttodorun = lasttodorun + minqueuedelay; /* do this to wake us up in N secs */ + return; /* skip todo run this time */ + } + if (!tododir) { if (!trigger_pulled(rfds)) @@ -1277,6 +1313,7 @@ fd_set *rfds; pausedir("todo"); return; } + lasttodorun = recent; nexttodorun = recent + SLEEP_TODO; } @@ -1443,6 +1480,7 @@ fd_set *rfds; int getcontrols() { if (control_init() == -1) return 0; if (control_readint(&lifetime,"control/queuelifetime") == -1) return 0; + if (control_readint(&minqueuedelay,"control/minqueuedelay") == -1) return 0; if (control_readint(&concurrency[0],"control/concurrencylocal") == -1) return 0; if (control_readint(&concurrency[1],"control/concurrencyremote") == -1) return 0; if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0; diff -d -p -P -U 3 -r -N qmail-1.03/qmail-smtpd.8 qmail-1.03-bgs/qmail-smtpd.8 --- qmail-1.03/qmail-smtpd.8 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-smtpd.8 2003-04-14 17:37:09.000000000 +0200 @@ -164,6 +164,24 @@ The first word of .I smtpgreeting should be the current host's name. .TP 5 +.I tarpitcount +Number of +.IR RCPT +.IR TO: +commands before +.IR tarpidelay +starts delaying additional rcpts. Zero means disabled. The NOTARPIT +environment variable overrides a non-zero +.IR tarpitcount +Default: +.IR 0 +.TP 5 +.IR tarpitdelay +Wait this many seconds between +.IR RCPT +.IR TO: +commands if tarpitting is triggered. +.TP 5 .I timeoutsmtpd Number of seconds .B qmail-smtpd diff -d -p -P -U 3 -r -N qmail-1.03/qmail-smtpd.c qmail-1.03-bgs/qmail-smtpd.c --- qmail-1.03/qmail-smtpd.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03-bgs/qmail-smtpd.c 2003-04-14 17:37:09.000000000 +0200 @@ -1,3 +1,4 @@ +#include #include "sig.h" #include "readwrite.h" #include "stralloc.h" @@ -23,6 +24,7 @@ #include "timeoutread.h" #include "timeoutwrite.h" #include "commands.h" +#include "strerr.h" #define MAXHOPS 100 unsigned int databytes = 0; @@ -96,6 +98,8 @@ stralloc liphost = {0}; int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; +int tarpitcount = 0; +int tarpitdelay = 5; void setup() { @@ -110,6 +114,15 @@ void setup() if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); if (timeout <= 0) timeout = 1; + if (control_readint(&tarpitcount,"control/tarpitcount") == -1) die_control(); + if (tarpitcount < 0) tarpitcount = 0; + x = env_get("TARPITCOUNT"); + if (x) { scan_ulong(x,&u); tarpitcount = u; }; + if (control_readint(&tarpitdelay,"control/tarpitdelay") == -1) die_control(); + if (tarpitdelay < 0) tarpitdelay = 0; + x = env_get("TARPITDELAY"); + if (x) { scan_ulong(x,&u); tarpitdelay = u; }; + if (rcpthosts_init() == -1) die_control(); bmfok = control_readfile(&bmf,"control/badmailfrom",0); @@ -221,6 +234,7 @@ int seenmail = 0; int flagbarf; /* defined if seenmail */ stralloc mailfrom = {0}; stralloc rcptto = {0}; +int rcptcount; void smtp_helo(arg) char *arg; { @@ -245,6 +259,7 @@ void smtp_mail(arg) char *arg; if (!stralloc_copys(&rcptto,"")) die_nomem(); if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); if (!stralloc_0(&mailfrom)) die_nomem(); + rcptcount = 0; out("250 ok\r\n"); } void smtp_rcpt(arg) char *arg; { @@ -257,10 +272,15 @@ void smtp_rcpt(arg) char *arg; { if (!stralloc_0(&addr)) die_nomem(); } else - if (!addrallowed()) { err_nogateway(); return; } + if (!addrallowed()) { + strerr_warn6("qmail-smtpd: Attempted relay from ",mailfrom.s," at ",remoteip," to ",addr.s,0); + err_nogateway(); + return; + } if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); + if ((tarpitcount && ++rcptcount >= tarpitcount) && (getenv("NOTARPIT") == NULL) ) while (sleep(tarpitdelay)); out("250 ok\r\n"); }