diff -ruN qmail-1.03-7.06/qmail-smtpd.c qmail-1.03-7.07/qmail-smtpd.c --- qmail-1.03-7.06/qmail-smtpd.c 2008-05-12 16:52:02.000000000 -0400 +++ qmail-1.03-7.07/qmail-smtpd.c 2008-06-02 21:00:41.000000000 -0400 @@ -154,6 +154,9 @@ 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 die_fork() { out("421 unable to fork (#4.3.0)\r\n"); flush(); _exit(1); } +void die_rcpt() { out("421 unable to verify recipient (#4.3.0)\r\n"); flush(); _exit(1); } +void die_rcpt2() { out("421 unable to execute recipient check (#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_cannot_auth() { out("421 REQUIRE_AUTH set without valid AUTH program.\r\n"); flush(); _exit(1); } void die_cannot_cram() { out("421 ALLOW_CRAM not available\r\n"); flush(); _exit(1); } @@ -180,6 +183,7 @@ void err_noop() { out("250 ok\r\n"); } 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_badrcpt() { out("553 sorry, no mailbox here by that name. (#5.1.1)\r\n"); } int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; } int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; } @@ -227,6 +231,7 @@ char *remoteinfo; char *local; char *relayclient; +static char *rcptcheck[2] = { 0, 0 }; #ifdef TLS char *tlsciphers; #endif @@ -322,6 +327,8 @@ x = env_get("QMAILSMTPD_HELP_VERSION"); if(x) { scan_ulong(x,&u); help_version = (int) u; } + + rcptcheck[0] = env_get("RCPTCHECK"); } int logregex = 0; @@ -730,6 +737,34 @@ stralloc mailfrom = {0}; stralloc rcptto = {0}; +int addrvalid() +{ + int pid; + int wstat; + + if (!rcptcheck[0]) return 1; + + switch(pid = fork()) { + case -1: die_fork(); + case 0: + if (!env_put2("SENDER",mailfrom.s)) die_nomem(); + if (!env_put2("RECIPIENT",addr.s)) die_nomem(); + if (!env_put2("HELO",helohost.s)) die_nomem(); + close(1); + dup2(2,1); + execv(*rcptcheck,rcptcheck); + _exit(120); + } + if (wait_pid(&wstat,pid) == -1) die_rcpt2(); + if (wait_crashed(wstat)) die_rcpt2(); + switch(wait_exitcode(wstat)) { + case 100: return 0; + case 111: die_rcpt(); + case 120: die_rcpt2(); + } + return 1; +} + void smtp_helo(arg) char *arg; { smtp_greet("250 "); out("\r\n"); @@ -986,6 +1021,8 @@ return; } + if (!addrvalid()) { err_badrcpt(); return; } + if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem();