*** qmail-rcptcheck-20070418.patch *** Author: Fabio Busatto Applies to: qmail-1.03, netqmail-1.05 *** qmail-rcptcheck-20070418.patch *** diff -uNr qmail-1.03-orig/qmail-control.9 qmail-1.03/qmail-control.9 --- qmail-1.03-orig/qmail-control.9 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-control.9 2007-04-18 15:15:15.000000000 +0200 @@ -61,6 +61,7 @@ .I qmqpservers \fR(none) \fRqmail-qmqpc .I queuelifetime \fR604800 \fRqmail-send .I rcpthosts \fR(none) \fRqmail-smtpd +.I rcptcheck \fR(none) \fRqmail-smtpd .I smtpgreeting \fIme \fRqmail-smtpd .I smtproutes \fR(none) \fRqmail-remote .I timeoutconnect \fR60 \fRqmail-remote diff -uNr qmail-1.03-orig/qmail-showctl.c qmail-1.03/qmail-showctl.c --- qmail-1.03-orig/qmail-showctl.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-showctl.c 2007-04-18 15:15:15.000000000 +0200 @@ -234,6 +234,7 @@ do_str("plusdomain",1,"plusdomain","Plus domain name is "); do_lst("qmqpservers","No QMQP servers.","QMQP server: ","."); do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds"); + do_str("rcptcheck",0,"disabled","Recipient check helper is "); 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 ","."); @@ -289,6 +290,7 @@ 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,"rcptcheck")) 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; diff -uNr qmail-1.03-orig/qmail-smtpd.8 qmail-1.03/qmail-smtpd.8 --- qmail-1.03-orig/qmail-smtpd.8 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-smtpd.8 2007-04-18 15:15:15.000000000 +0200 @@ -120,6 +120,16 @@ and the rest into .IR morercpthosts . .TP 5 +.I rcptcheck +Recipient check program. +If +.I rcptcheck +is supplied, +.B qmail-smtpd +will reject every recipient address for a message +if the program exits non-zero +and no other recipient check authorizes the delivery. +.TP 5 .I rcpthosts Allowed RCPT domains. If diff -uNr qmail-1.03-orig/qmail-smtpd.c qmail-1.03/qmail-smtpd.c --- qmail-1.03-orig/qmail-smtpd.c 1998-06-15 12:53:16.000000000 +0200 +++ qmail-1.03/qmail-smtpd.c 2007-04-18 15:15:15.000000000 +0200 @@ -23,6 +23,7 @@ #include "timeoutread.h" #include "timeoutwrite.h" #include "commands.h" +#include "wait.h" #define MAXHOPS 100 unsigned int databytes = 0; @@ -50,6 +51,7 @@ void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } +void err_nomailbox() { out("553 sorry, no mailbox here by that name (#5.1.1)\r\n"); } void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); } void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } @@ -96,6 +98,8 @@ int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; +int rcptcheckok = 0; +stralloc rcptcheckbin = {0}; void setup() { @@ -116,6 +120,8 @@ if (bmfok == -1) die_control(); if (bmfok) if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + rcptcheckok = control_readline(&rcptcheckbin,"control/rcptcheck"); + if (rcptcheckok == -1) die_control(); if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); @@ -208,6 +214,42 @@ return 0; } +stralloc rcptcheckcmd = {0}; + +int rcptcheck() +{ + int child; + char *(args[4]); + int wstat; + + if (!rcptcheckok) return 0; + if (!addr.s[0]) return 1; + + switch(child = fork()) + { + case -1: + return 0; + case 0: + if (!stralloc_copys(&rcptcheckcmd,"")) die_nomem(); + if (!stralloc_copy(&rcptcheckcmd,&rcptcheckbin)) die_nomem(); + if (!stralloc_cats(&rcptcheckcmd," ")) die_nomem(); + if (!stralloc_cat(&rcptcheckcmd,&addr)) die_nomem(); + if (!stralloc_0(&rcptcheckcmd)) die_nomem(); + close(0); + close(1); + close(2); + args[0] = "/bin/sh"; + args[1] = "-c"; + args[2] = rcptcheckcmd.s; + args[3] = 0; + execv(*args,args); + _exit(1); + } + + wait_pid(&wstat,child); + return wait_exitcode(wstat); +} + int addrallowed() { int r; @@ -256,8 +298,10 @@ if (!stralloc_cats(&addr,relayclient)) die_nomem(); if (!stralloc_0(&addr)) die_nomem(); } - else + else { if (!addrallowed()) { err_nogateway(); return; } + if (rcptcheck()) { err_nomailbox(); return; } + } if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem();