diff options
Diffstat (limited to 'qmail-smtpd.c')
| -rw-r--r-- | qmail-smtpd.c | 99 |
1 files changed, 88 insertions, 11 deletions
diff --git a/qmail-smtpd.c b/qmail-smtpd.c index 86c5bd9..4466168 100644 --- a/qmail-smtpd.c +++ b/qmail-smtpd.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include "wait.h" | 26 | #include "wait.h" |
| 27 | #include "qregex.h" | 27 | #include "qregex.h" |
| 28 | #include "strerr.h" | 28 | #include "strerr.h" |
| 29 | #include "cdb.h" | ||
| 29 | 30 | ||
| 30 | #define BMCHECK_BMF 0 | 31 | #define BMCHECK_BMF 0 |
| 31 | #define BMCHECK_BMFNR 1 | 32 | #define BMCHECK_BMFNR 1 |
| @@ -42,6 +43,12 @@ int timeout = 1200; | |||
| 42 | 43 | ||
| 43 | const char *protocol = "SMTP"; | 44 | const char *protocol = "SMTP"; |
| 44 | 45 | ||
| 46 | char *remoteip; | ||
| 47 | char *remotehost; | ||
| 48 | char *remoteinfo; | ||
| 49 | char *local; | ||
| 50 | char *relayclient; | ||
| 51 | |||
| 45 | #ifdef TLS | 52 | #ifdef TLS |
| 46 | #include <sys/stat.h> | 53 | #include <sys/stat.h> |
| 47 | #include "tls.h" | 54 | #include "tls.h" |
| @@ -69,19 +76,52 @@ int safewrite(fd,buf,len) int fd; char *buf; int len; | |||
| 69 | char ssoutbuf[512]; | 76 | char ssoutbuf[512]; |
| 70 | substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); | 77 | substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); |
| 71 | 78 | ||
| 79 | /* write errors to stderr */ | ||
| 80 | char erroutbuf[512]; | ||
| 81 | substdio errout = SUBSTDIO_FDBUF(safewrite,2,erroutbuf,sizeof erroutbuf); | ||
| 82 | |||
| 72 | void flush() { substdio_flush(&ssout); } | 83 | void flush() { substdio_flush(&ssout); } |
| 73 | void out(s) char *s; { substdio_puts(&ssout,s); } | 84 | void out(s) char *s; { substdio_puts(&ssout,s); } |
| 74 | 85 | ||
| 86 | void eflush() { substdio_flush(&errout); } | ||
| 87 | void eout(s) char *s; { substdio_puts(&errout,s); } | ||
| 88 | void enew() { substdio_puts(&errout,"qmail-smtpd: "); } | ||
| 89 | |||
| 75 | void die_read() { _exit(1); } | 90 | void die_read() { _exit(1); } |
| 76 | void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } | 91 | |
| 77 | void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } | 92 | void die_alarm() |
| 78 | void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } | 93 | { |
| 79 | void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); } | 94 | enew(); eout("Connection to "); eout(remoteip); eout(" timed out.\n"); |
| 80 | void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } | 95 | out("451 timeout (#4.4.2)\r\n"); flush(); eflush(); _exit(1); |
| 96 | } | ||
| 97 | void die_nomem() | ||
| 98 | { | ||
| 99 | enew(); eout("Out of memory while connected to "); eout(remoteip); eout("!\n"); | ||
| 100 | out("421 out of memory (#4.3.0)\r\n"); flush(); eflush(); _exit(1); | ||
| 101 | } | ||
| 102 | void die_control() | ||
| 103 | { | ||
| 104 | enew(); eout("Unable to read controls!\n"); | ||
| 105 | out("421 unable to read controls (#4.3.0)\r\n"); flush(); eflush(); | ||
| 106 | _exit(1); | ||
| 107 | } | ||
| 108 | void die_ipme() | ||
| 109 | { | ||
| 110 | enew(); eout("Unable to figure out my IP addresses!\n"); | ||
| 111 | out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); | ||
| 112 | eflush(); _exit(1); | ||
| 113 | } | ||
| 114 | void straynewline() | ||
| 115 | { | ||
| 116 | enew(); eout("Stray newline from "); eout(remoteip); eout(".\n"); | ||
| 117 | out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); | ||
| 118 | eflush(); _exit(1); | ||
| 119 | } | ||
| 81 | 120 | ||
| 82 | void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); } | 121 | void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); } |
| 83 | void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); } | 122 | void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); } |
| 84 | void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); } | 123 | void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); } |
| 124 | void err_brt() { out("550 sorry, this message is not deliverable (#5.7.1)\r\n"); } | ||
| 85 | void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); } | 125 | void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); } |
| 86 | #ifndef TLS | 126 | #ifndef TLS |
| 87 | void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } | 127 | void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } |
| @@ -129,12 +169,6 @@ void smtp_quit() | |||
| 129 | smtp_greet("221 "); out("\r\n"); flush(); _exit(0); | 169 | smtp_greet("221 "); out("\r\n"); flush(); _exit(0); |
| 130 | } | 170 | } |
| 131 | 171 | ||
| 132 | char *remoteip; | ||
| 133 | char *remotehost; | ||
| 134 | char *remoteinfo; | ||
| 135 | char *local; | ||
| 136 | char *relayclient; | ||
| 137 | |||
| 138 | stralloc helohost = {0}; | 172 | stralloc helohost = {0}; |
| 139 | char *fakehelo; /* pointer into helohost, or 0 */ | 173 | char *fakehelo; /* pointer into helohost, or 0 */ |
| 140 | 174 | ||
| @@ -159,6 +193,11 @@ stralloc bmt = {0}; | |||
| 159 | int bmtnrok = 0; | 193 | int bmtnrok = 0; |
| 160 | stralloc bmtnr = {0}; | 194 | stralloc bmtnr = {0}; |
| 161 | 195 | ||
| 196 | int brtok = 0; | ||
| 197 | stralloc brt = {0}; | ||
| 198 | struct constmap mapbrt; | ||
| 199 | int fdmbrt; | ||
| 200 | |||
| 162 | int bhelook = 0; | 201 | int bhelook = 0; |
| 163 | stralloc bhelo = {0}; | 202 | stralloc bhelo = {0}; |
| 164 | 203 | ||
| @@ -197,6 +236,17 @@ void setup() | |||
| 197 | 236 | ||
| 198 | if (env_get("LOGREGEX")) logregex = 1; | 237 | if (env_get("LOGREGEX")) logregex = 1; |
| 199 | 238 | ||
| 239 | |||
| 240 | brtok = control_readfile(&brt,"control/badrcptto",0); | ||
| 241 | if (brtok == -1) die_control(); | ||
| 242 | if (brtok) | ||
| 243 | if (!constmap_init(&mapbrt,brt.s,brt.len,0)) die_nomem(); | ||
| 244 | |||
| 245 | fdmbrt = open_read("control/morebadrcptto.cdb"); | ||
| 246 | if (fdmbrt == -1) if (errno != error_noent) die_control(); | ||
| 247 | |||
| 248 | |||
| 249 | |||
| 200 | if (control_readint(&databytes,"control/databytes") == -1) die_control(); | 250 | if (control_readint(&databytes,"control/databytes") == -1) die_control(); |
| 201 | x = env_get("DATABYTES"); | 251 | x = env_get("DATABYTES"); |
| 202 | if (x) { scan_ulong(x,&u); databytes = u; } | 252 | if (x) { scan_ulong(x,&u); databytes = u; } |
| @@ -282,6 +332,14 @@ char *arg; | |||
| 282 | return 1; | 332 | return 1; |
| 283 | } | 333 | } |
| 284 | 334 | ||
| 335 | static void log_deny(m,f,t) char *m,*f,*t; | ||
| 336 | { | ||
| 337 | enew(); eout(m); eout(" check failed ("); eout(f); eout(") -> ("); | ||
| 338 | eout(t); eout(") ["); eout(remoteip); eout("] (HELO "); | ||
| 339 | eout(helohost.s); eout(")\n"); | ||
| 340 | eflush(); | ||
| 341 | } | ||
| 342 | |||
| 285 | int bmcheck(which) int which; | 343 | int bmcheck(which) int which; |
| 286 | { | 344 | { |
| 287 | int i = 0; | 345 | int i = 0; |
| @@ -335,6 +393,19 @@ int bmcheck(which) int which; | |||
| 335 | return 0; | 393 | return 0; |
| 336 | } | 394 | } |
| 337 | 395 | ||
| 396 | int brtcheck() | ||
| 397 | { | ||
| 398 | int j; | ||
| 399 | if (brtok) if (constmap(&mapbrt,addr.s,addr.len - 1)) return 1; | ||
| 400 | if (fdmbrt != -1) { | ||
| 401 | uint32 dlen; | ||
| 402 | j = cdb_seek(fdmbrt, addr.s, addr.len - 1, &dlen); | ||
| 403 | if (j == -1) die_control(); | ||
| 404 | if (j) return j; | ||
| 405 | } | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 338 | int addrallowed() | 409 | int addrallowed() |
| 339 | { | 410 | { |
| 340 | int r; | 411 | int r; |
| @@ -364,6 +435,7 @@ int addrrelay() | |||
| 364 | int seenmail = 0; | 435 | int seenmail = 0; |
| 365 | int flagbarfbmf; /* defined if seenmail */ | 436 | int flagbarfbmf; /* defined if seenmail */ |
| 366 | int flagbarfbmt; | 437 | int flagbarfbmt; |
| 438 | int flagbrt; /* defined if any bad rcpts */ | ||
| 367 | int flagbarfbhelo; | 439 | int flagbarfbhelo; |
| 368 | int flagsize; | 440 | int flagsize; |
| 369 | stralloc mailfrom = {0}; | 441 | stralloc mailfrom = {0}; |
| @@ -523,6 +595,10 @@ void smtp_rcpt(arg) char *arg; { | |||
| 523 | } | 595 | } |
| 524 | else | 596 | else |
| 525 | if (!addrallowed()) { err_nogateway(); return; } | 597 | if (!addrallowed()) { err_nogateway(); return; } |
| 598 | if (!env_get("RELAYCLIENT") && brtcheck()) { | ||
| 599 | flagbrt = 1; | ||
| 600 | log_deny("BAD RCPT TO", mailfrom.s,addr.s); | ||
| 601 | } | ||
| 526 | if (!stralloc_cats(&rcptto,"T")) die_nomem(); | 602 | if (!stralloc_cats(&rcptto,"T")) die_nomem(); |
| 527 | if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); | 603 | if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); |
| 528 | if (!stralloc_0(&rcptto)) die_nomem(); | 604 | if (!stralloc_0(&rcptto)) die_nomem(); |
| @@ -642,6 +718,7 @@ void smtp_data() { | |||
| 642 | 718 | ||
| 643 | if (!seenmail) { err_wantmail(); return; } | 719 | if (!seenmail) { err_wantmail(); return; } |
| 644 | if (!rcptto.len) { err_wantrcpt(); return; } | 720 | if (!rcptto.len) { err_wantrcpt(); return; } |
| 721 | if (flagbrt) { err_brt(); return; } | ||
| 645 | seenmail = 0; | 722 | seenmail = 0; |
| 646 | if (databytes) bytestooverflow = databytes + 1; | 723 | if (databytes) bytestooverflow = databytes + 1; |
| 647 | if (qmail_open(&qqt) == -1) { err_qqt(); return; } | 724 | if (qmail_open(&qqt) == -1) { err_qqt(); return; } |
