X-Git-Url: https://git.distorted.org.uk/~mdw/qmail/blobdiff_plain/212b6f5da7c68d4577de2855da3c57ecf476dc96..HEAD:/qmail-smtpd.c diff --git a/qmail-smtpd.c b/qmail-smtpd.c index 1e28c88..88f4ea6 100644 --- a/qmail-smtpd.c +++ b/qmail-smtpd.c @@ -20,6 +20,7 @@ #include "now.h" #include "exit.h" #include "rcpthosts.h" +#include "addrcheck.h" #include "timeoutread.h" #include "timeoutwrite.h" #include "commands.h" @@ -47,10 +48,12 @@ 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 die_badaddr() { out("553 too many bad recipients: sulking (#5.5.1)\r\n"); flush(); _exit(1); } 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_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } +void err_badaddr() { out("550 unknown mailbox (#5.1.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"); } void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } @@ -93,9 +96,17 @@ void dohelo(arg) char *arg; { int liphostok = 0; stralloc liphost = {0}; +int relayhostsok = 0; +stralloc relayhosts = {0}; +struct constmap maprelayhosts; int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; +static int ac_slow = 5; +static int ac_limit = 50; +static int ac_delay = 2; +static int ac_count = 0; +static int ac_fd = -1; void setup() { @@ -116,6 +127,23 @@ void setup() if (bmfok == -1) die_control(); if (bmfok) if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); + + switch (control_readfile(&relayhosts, "control/relayhosts", 0)) { + case -1: + die_control(); + case 1: + relayhostsok = 1; + if (!constmap_init(&maprelayhosts, relayhosts.s, relayhosts.len, 1)) + die_nomem(); + } + + if (control_readint(&ac_slow, "control/addrcheck-slow") == -1 || + control_readint(&ac_slow, "control/addrcheck-limit") == -1 || + control_readint(&ac_slow, "control/addrcheck-delay") == -1) + die_control(); + + if ((ac_fd = open_read("control/addrcheck.cdb")) < 0 && errno != error_noent) + die_control(); if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); @@ -131,6 +159,18 @@ void setup() if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); relayclient = env_get("RELAYCLIENT"); + if (!relayclient && relayhostsok) { + int j; + int l = str_len(remotehost); + relayclient = constmap(&maprelayhosts, remotehost, l); + if (!relayclient) for (j = 0; j < l; ++j) { + if (remotehost[j] == '.' && + (relayclient = constmap(&maprelayhosts, + remotehost + j, + l - j)) != 0) + break; + } + } dohelo(remotehost); } @@ -258,6 +298,22 @@ void smtp_rcpt(arg) char *arg; { } else if (!addrallowed()) { err_nogateway(); return; } + if (ac_fd != -1) { + int rc; + if (addrcheck(ac_fd, addr.s, mailfrom.s, &rc) < 0) { + if (errno == error_nomem) + die_nomem(); + else + die_control(); + } + if (!rc) { + ac_count++; + if (ac_limit && ac_count >= ac_limit) die_badaddr(); + if (ac_delay && ac_count >= ac_slow) sleep(ac_delay); + err_badaddr(); + return; + } + } if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem();