diff -ruN qmail-1.03-factory/Makefile qmail-1.03-patched/Makefile --- qmail-1.03-factory/Makefile 1998-06-15 06:53:16.000000000 -0400 +++ qmail-1.03-patched/Makefile 2005-05-16 19:13:06.000000000 -0400 @@ -1535,13 +1535,13 @@ 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: \ @@ -1553,7 +1553,7 @@ substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ -exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h +exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h cdb.h uint32.h ./compile qmail-smtpd.c qmail-start: \ diff -ruN qmail-1.03-factory/qmail-smtpd.c qmail-1.03-patched/qmail-smtpd.c --- qmail-1.03-factory/qmail-smtpd.c 1998-06-15 06:53:16.000000000 -0400 +++ qmail-1.03-patched/qmail-smtpd.c 2005-05-16 19:14:01.000000000 -0400 @@ -23,6 +23,8 @@ #include "timeoutread.h" #include "timeoutwrite.h" #include "commands.h" +#include "strerr.h" +#include "cdb.h" #define MAXHOPS 100 unsigned int databytes = 0; @@ -59,6 +61,8 @@ void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } +void err_vrt() { out("553 sorry, this recipient is not in my validrcptto list (#5.7.1)\r\n"); } +void die_vrt() { out("421 too many invalid addresses, goodbye (#4.3.0)\r\n"); flush(); _exit(1); } stralloc greeting = {0}; @@ -97,6 +101,11 @@ stralloc bmf = {0}; struct constmap mapbmf; +int vrtfd = -1; +int vrtcount = 0; +int vrtlimit = 10; +int vrtlog_do = 0; + void setup() { char *x; @@ -116,6 +125,9 @@ if (bmfok == -1) die_control(); if (bmfok) if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + + vrtfd = open_read("control/validrcptto.cdb"); + if (-1 == vrtfd) if (errno != error_noent) die_control(); if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); @@ -208,6 +220,71 @@ return 0; } +void vrtlog(a,b) +const char *a; +const char *b; +{ + if (vrtlog_do) strerr_warn2(a,b,0); +} + +int vrtcheck() +{ + static char *rcptto = "qmail-smtpd: validrcptto RCPT TO: "; + static char *found = "qmail-smtpd: validrcptto found: "; + int j,k,r; + uint32 dlen; + stralloc laddr = {0}; + + stralloc user = {0}; + stralloc adom = {0}; + stralloc utry = {0}; + + if (-1 == vrtfd) return 1; + + /* lowercase whatever we were sent */ + if (!stralloc_copy(&laddr,&addr)) die_nomem() ; + case_lowerb(laddr.s,laddr.len); + + vrtlog(rcptto,laddr.s,0); + + /* exact match? */ + r = cdb_seek(vrtfd,laddr.s,laddr.len-1,&dlen) ; + if (r>0) { vrtlog(found,laddr.s,0); return r; } + + j = byte_rchr(laddr.s,laddr.len,'@'); + if (j < laddr.len) + { + /* start "-default" search loop */ + stralloc_copyb(&user,laddr.s,j) ; + stralloc_copyb(&adom,laddr.s+j,laddr.len-j-1); + + while(1) + { + k = byte_rchr(user.s,user.len,'-'); + if (k >= user.len) break ; + + user.len = k+1; + stralloc_cats(&user,"default"); + + stralloc_copy(&utry,&user); + stralloc_cat (&utry,&adom); + stralloc_0(&utry); + + r = cdb_seek(vrtfd,utry.s,utry.len-1,&dlen); + if (r>0) { vrtlog(found,utry.s,0); return r; } + + user.len = k ; + } + + /* try "@domain" */ + + r = cdb_seek(vrtfd,laddr.s+j,laddr.len-j-1,&dlen) ; + if (r>0) { vrtlog(found,laddr.s+j,0); return r; } + } + + return 0; +} + int addrallowed() { int r; @@ -258,6 +335,17 @@ } else if (!addrallowed()) { err_nogateway(); return; } + if (!env_get("RELAYCLIENT") && !vrtcheck()) { + strerr_warn4("qmail-smtpd: not in validrcptto: ",addr.s, + " at ",remoteip,0); + if(vrtlimit && (++vrtcount >= vrtlimit)) { + strerr_warn2("qmail-smtpd: excessive validrcptto violations," + " hanging up on ",remoteip,0); + die_vrt(); + } + err_vrt(); + return; + } if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); @@ -410,8 +498,16 @@ void main() { + char *x ; + uint32 u; sig_pipeignore(); if (chdir(auto_qmail) == -1) die_control(); + + x = env_get("VALIDRCPTTO_LIMIT"); + if(x) { scan_ulong(x,&u); vrtlimit = (int) u; } + x = env_get("VALIDRCPTTO_LOG"); + if(x) { scan_ulong(x,&u); vrtlog_do = (int) u; } + setup(); if (ipme_init() != 1) die_ipme(); smtp_greet("220 ");