summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile29
-rw-r--r--TARGETS4
-rw-r--r--qmail-newbrt.941
-rw-r--r--qmail-newbrt.c70
-rw-r--r--qmail-showctl.c22
-rw-r--r--qmail-smtpd.824
-rw-r--r--qmail-smtpd.c99
7 files changed, 276 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 5f676dd..10e8255 100644
--- a/Makefile
+++ b/Makefile
@@ -807,7 +807,7 @@ qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \
807predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \ 807predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
808qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ 808qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
809qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ 809qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
810qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ 810qmail-smtpd sendmail tcp-env qmail-newmrh qmail-newbrt config config-fast dnscname \
811dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ 811dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
812forward preline condredirect bouncesaying except maildirmake \ 812forward preline condredirect bouncesaying except maildirmake \
813maildir2mbox maildirwatch qail elq pinq idedit install-big install \ 813maildir2mbox maildirwatch qail elq pinq idedit install-big install \
@@ -963,7 +963,7 @@ make-makelib warn-auto.sh systype
963man: \ 963man: \
964qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \ 964qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \
965qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \ 965qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \
966qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \ 966qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newbrt.0 qmail-newu.0 \
967qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \ 967qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \
968qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \ 968qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \
969qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \ 969qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \
@@ -1280,6 +1280,31 @@ getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
1280uint32.h substdio.h 1280uint32.h substdio.h
1281 ./compile qmail-newmrh.c 1281 ./compile qmail-newmrh.c
1282 1282
1283qmail-newbrt: \
1284load qmail-newbrt.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
1285stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
1286 ./load qmail-newbrt cdbmss.o getln.a open.a cdbmake.a \
1287 seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
1288 error.a str.a auto_qmail.o
1289
1290qmail-newbrt.o: \
1291compile qmail-newbrt.c strerr.h stralloc.h gen_alloc.h substdio.h \
1292getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
1293uint32.h substdio.h
1294 ./compile qmail-newbrt.c
1295
1296qmail-newbrt.0: \
1297qmail-newbrt.8
1298 nroff -man qmail-newbrt.8 > qmail-newbrt.0
1299
1300qmail-newbrt.8: \
1301qmail-newbrt.9 conf-break conf-spawn
1302 cat qmail-newbrt.9 \
1303 | sed s}QMAILHOME}"`head -n 1 conf-qmail`"}g \
1304 | sed s}BREAK}"`head -n 1 conf-break`"}g \
1305 | sed s}SPAWN}"`head -n 1 conf-spawn`"}g \
1306 > qmail-newbrt.8
1307
1283qmail-newu: \ 1308qmail-newu: \
1284load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \ 1309load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \
1285stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o 1310stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o
diff --git a/TARGETS b/TARGETS
index 949bc46..27706f3 100644
--- a/TARGETS
+++ b/TARGETS
@@ -238,6 +238,8 @@ cdbmake_hash.o
238cdbmake_add.o 238cdbmake_add.o
239cdbmake.a 239cdbmake.a
240qmail-newu 240qmail-newu
241qmail-newbrt.o
242qmail-newbrt
241qmail-pw2u.o 243qmail-pw2u.o
242qmail-pw2u 244qmail-pw2u
243qmail-qread.o 245qmail-qread.o
@@ -350,6 +352,8 @@ qmail-queue.0
350qmail-inject.0 352qmail-inject.0
351mailsubj.0 353mailsubj.0
352qmail-showctl.0 354qmail-showctl.0
355qmail-newbrt.8
356qmail-newbrt.0
353qmail-newu.8 357qmail-newu.8
354qmail-newu.0 358qmail-newu.0
355qmail-pw2u.8 359qmail-pw2u.8
diff --git a/qmail-newbrt.9 b/qmail-newbrt.9
new file mode 100644
index 0000000..d1798d0
--- /dev/null
+++ b/qmail-newbrt.9
@@ -0,0 +1,41 @@
1.TH qmail-newbrt 8
2.SH NAME
3qmail-newbrt \- prepare morebadrcptto for qmail-smtpd
4.SH SYNOPSIS
5.B qmail-newbrt
6.SH DESCRIPTION
7.B qmail-newbrt
8reads the instructions in
9.B QMAILHOME/control/morebadrcptto
10and writes them into
11.B QMAILHOME/control/morebadrcptto.cdb
12in a binary format suited
13for quick access by
14.BR qmail-smtpd .
15
16If there is a problem with
17.BR control/morebadrcptto ,
18.B qmail-newbrt
19complains and leaves
20.B control/morebadrcptto.cdb
21alone.
22
23.B qmail-newbrt
24ensures that
25.B control/morebadrcptto.cdb
26is updated atomically,
27so
28.B qmail-smtpd
29never has to wait for
30.B qmail-newbrt
31to finish.
32However,
33.B qmail-newbrt
34makes no attempt to protect against two simultaneous updates of
35.BR control/morebadrcptto.cdb .
36
37The binary
38.B control/morebadrcptto.cdb
39format is portable across machines.
40.SH "SEE ALSO"
41qmail-smtpd(8)
diff --git a/qmail-newbrt.c b/qmail-newbrt.c
new file mode 100644
index 0000000..9344444
--- /dev/null
+++ b/qmail-newbrt.c
@@ -0,0 +1,70 @@
1#include "strerr.h"
2#include "stralloc.h"
3#include "substdio.h"
4#include "getln.h"
5#include "exit.h"
6#include "readwrite.h"
7#include "open.h"
8#include "auto_qmail.h"
9#include "cdbmss.h"
10
11#define FATAL "qmail-newbrt: fatal: "
12
13void die_read()
14{
15 strerr_die2sys(111,FATAL,"unable to read control/morebadrcptto: ");
16}
17void die_write()
18{
19 strerr_die2sys(111,FATAL,"unable to write to control/morebadrcptto.tmp: ");
20}
21
22char inbuf[1024];
23substdio ssin;
24
25int fd;
26int fdtemp;
27
28struct cdbmss cdbmss;
29stralloc line = {0};
30int match;
31
32void main()
33{
34 umask(033);
35 if (chdir(auto_qmail) == -1)
36 strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
37
38 fd = open_read("control/morebadrcptto");
39 if (fd == -1) die_read();
40
41 substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf);
42
43 fdtemp = open_trunc("control/morebadrcptto.tmp");
44 if (fdtemp == -1) die_write();
45
46 if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write();
47
48 for (;;) {
49 if (getln(&ssin,&line,&match,'\n') != 0) die_read();
50 case_lowerb(line.s,line.len);
51 while (line.len) {
52 if (line.s[line.len - 1] == ' ') { --line.len; continue; }
53 if (line.s[line.len - 1] == '\n') { --line.len; continue; }
54 if (line.s[line.len - 1] == '\t') { --line.len; continue; }
55 if (line.s[0] != '#')
56 if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1)
57 die_write();
58 break;
59 }
60 if (!match) break;
61 }
62
63 if (cdbmss_finish(&cdbmss) == -1) die_write();
64 if (fsync(fdtemp) == -1) die_write();
65 if (close(fdtemp) == -1) die_write(); /* NFS stupidity */
66 if (rename("control/morebadrcptto.tmp","control/morebadrcptto.cdb") == -1)
67 strerr_die2sys(111,FATAL,"unable to move control/morebadrcpto.tmp to control/morebadrcptto.cdb");
68
69 _exit(0);
70}
diff --git a/qmail-showctl.c b/qmail-showctl.c
index bbaa2bc..9d4e1bc 100644
--- a/qmail-showctl.c
+++ b/qmail-showctl.c
@@ -219,6 +219,25 @@ void main()
219 do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set."); 219 do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set.");
220 do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern."); 220 do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern.");
221 do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set."); 221 do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set.");
222 if (do_lst("badrcptto","Any RCPT TO is allowed."," not accepted in RCPT TO ","."))
223 do_lst("morebadrcptto","No effect."," no accepted in RCPT TO ",".");
224 else
225 do_lst("morebadrcptto","No badrcptto; morebadrcpto is irrelevant.","No badrcptto; doesn't matter that morebadrcptto has ",".");
226 /* XXX: check badrcptto.cdb contents */
227 substdio_puts(subfdout,"\nmorebadrcptto.cdb: ");
228 if (stat("morebadrcptto",&stmrh) == -1)
229 if (stat("morebadrcptto.cdb",&stmrhcdb) == -1)
230 substdio_puts(subfdout,"(Default.) No effect.\n");
231 else
232 substdio_puts(subfdout,"Oops! morebadrcptto.cdb exists but morebadrcptto doesn't.\n");
233 else
234 if (stat("morebadrcptto.cdb",&stmrhcdb) == -1)
235 substdio_puts(subfdout,"Oops! morebadrcptto exists but morebadrcptto.cdb doesn't.\n");
236 else
237 if (stmrh.st_mtime > stmrhcdb.st_mtime)
238 substdio_puts(subfdout,"Oops! morebadrcptto.cdb is older than morebadrcptto.\n");
239 else
240 substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
222 do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is "); 241 do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is ");
223 do_str("bouncehost",1,"bouncehost","Bounce host name is "); 242 do_str("bouncehost",1,"bouncehost","Bounce host name is ");
224 do_int("concurrencylocal","10","Local concurrency is ",""); 243 do_int("concurrencylocal","10","Local concurrency is ","");
@@ -276,6 +295,7 @@ void main()
276 if (str_equal(d->d_name,"badmailfromnorelay")) continue; 295 if (str_equal(d->d_name,"badmailfromnorelay")) continue;
277 if (str_equal(d->d_name,"badmailto")) continue; 296 if (str_equal(d->d_name,"badmailto")) continue;
278 if (str_equal(d->d_name,"badmailtonorelay")) continue; 297 if (str_equal(d->d_name,"badmailtonorelay")) continue;
298 if (str_equal(d->d_name,"badrcptto")) continue;
279 if (str_equal(d->d_name,"bouncefrom")) continue; 299 if (str_equal(d->d_name,"bouncefrom")) continue;
280 if (str_equal(d->d_name,"bouncehost")) continue; 300 if (str_equal(d->d_name,"bouncehost")) continue;
281 if (str_equal(d->d_name,"concurrencylocal")) continue; 301 if (str_equal(d->d_name,"concurrencylocal")) continue;
@@ -291,6 +311,8 @@ void main()
291 if (str_equal(d->d_name,"localiphost")) continue; 311 if (str_equal(d->d_name,"localiphost")) continue;
292 if (str_equal(d->d_name,"locals")) continue; 312 if (str_equal(d->d_name,"locals")) continue;
293 if (str_equal(d->d_name,"me")) continue; 313 if (str_equal(d->d_name,"me")) continue;
314 if (str_equal(d->d_name,"morebadrcptto")) continue;
315 if (str_equal(d->d_name,"morebadrcptto.cdb")) continue;
294 if (str_equal(d->d_name,"morercpthosts")) continue; 316 if (str_equal(d->d_name,"morercpthosts")) continue;
295 if (str_equal(d->d_name,"morercpthosts.cdb")) continue; 317 if (str_equal(d->d_name,"morercpthosts.cdb")) continue;
296 if (str_equal(d->d_name,"percenthack")) continue; 318 if (str_equal(d->d_name,"percenthack")) continue;
diff --git a/qmail-smtpd.8 b/qmail-smtpd.8
index ce0dc02..0103984 100644
--- a/qmail-smtpd.8
+++ b/qmail-smtpd.8
@@ -136,6 +136,13 @@ should contain the CRLs of the CAs in
136and client certs will be checked for revocation. 136and client certs will be checked for revocation.
137 137
138.TP 5 138.TP 5
139.I badrcptto
140Unacceptable envelope recipient addresses.
141.B qmail-smtpd
142will reject every recipient address for a message
143if the envelope recipient address is listed in
144.IR badrcptto .
145.TP 5
139.I databytes 146.I databytes
140Maximum number of bytes allowed in a message, 147Maximum number of bytes allowed in a message,
141or 0 for no limit. 148or 0 for no limit.
@@ -195,6 +202,23 @@ with
195This is done before 202This is done before
196.IR rcpthosts . 203.IR rcpthosts .
197.TP 5 204.TP 5
205.I morebadrcptto
206Extra not allowed RCPT TO addresses.
207If
208.I badrcptto
209and
210.I morebadrcptto
211both exist,
212.I morebardrcptto
213is effectively appended to
214.IR badrcptto .
215
216You must run
217.B qmail-newbrt
218whenever
219.I morebadrcptto
220changes.
221.TP 5
198.I morercpthosts 222.I morercpthosts
199Extra allowed RCPT domains. 223Extra allowed RCPT domains.
200If 224If
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
43const char *protocol = "SMTP"; 44const char *protocol = "SMTP";
44 45
46char *remoteip;
47char *remotehost;
48char *remoteinfo;
49char *local;
50char *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;
69char ssoutbuf[512]; 76char ssoutbuf[512];
70substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); 77substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
71 78
79/* write errors to stderr */
80char erroutbuf[512];
81substdio errout = SUBSTDIO_FDBUF(safewrite,2,erroutbuf,sizeof erroutbuf);
82
72void flush() { substdio_flush(&ssout); } 83void flush() { substdio_flush(&ssout); }
73void out(s) char *s; { substdio_puts(&ssout,s); } 84void out(s) char *s; { substdio_puts(&ssout,s); }
74 85
86void eflush() { substdio_flush(&errout); }
87void eout(s) char *s; { substdio_puts(&errout,s); }
88void enew() { substdio_puts(&errout,"qmail-smtpd: "); }
89
75void die_read() { _exit(1); } 90void die_read() { _exit(1); }
76void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } 91
77void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } 92void die_alarm()
78void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } 93{
79void 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");
80void 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}
97void 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}
102void 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}
108void 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}
114void 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
82void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); } 121void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
83void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); } 122void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); }
84void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); } 123void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
124void err_brt() { out("550 sorry, this message is not deliverable (#5.7.1)\r\n"); }
85void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); } 125void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); }
86#ifndef TLS 126#ifndef TLS
87void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } 127void 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
132char *remoteip;
133char *remotehost;
134char *remoteinfo;
135char *local;
136char *relayclient;
137
138stralloc helohost = {0}; 172stralloc helohost = {0};
139char *fakehelo; /* pointer into helohost, or 0 */ 173char *fakehelo; /* pointer into helohost, or 0 */
140 174
@@ -159,6 +193,11 @@ stralloc bmt = {0};
159int bmtnrok = 0; 193int bmtnrok = 0;
160stralloc bmtnr = {0}; 194stralloc bmtnr = {0};
161 195
196int brtok = 0;
197stralloc brt = {0};
198struct constmap mapbrt;
199int fdmbrt;
200
162int bhelook = 0; 201int bhelook = 0;
163stralloc bhelo = {0}; 202stralloc 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
335static 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
285int bmcheck(which) int which; 343int 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
396int 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
338int addrallowed() 409int addrallowed()
339{ 410{
340 int r; 411 int r;
@@ -364,6 +435,7 @@ int addrrelay()
364int seenmail = 0; 435int seenmail = 0;
365int flagbarfbmf; /* defined if seenmail */ 436int flagbarfbmf; /* defined if seenmail */
366int flagbarfbmt; 437int flagbarfbmt;
438int flagbrt; /* defined if any bad rcpts */
367int flagbarfbhelo; 439int flagbarfbhelo;
368int flagsize; 440int flagsize;
369stralloc mailfrom = {0}; 441stralloc 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; }