s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-smtpd.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "wildmat.h"
3#include "buffer.h"
4#include "stralloc.h"
5#include "genalloc.h"
6#include "alloc.h"
7#include "qmail.h"
8#include "auto_qmail.h"
9#include "control.h"
10#include "received.h"
11#include "constmap.h"
12#include "logmsg.h"
13#include "ipme.h"
14#include "fd.h"
15#include "ip.h"
16#include "qmail.h"
17#include "str.h"
18#include "fmt.h"
19#include "scan.h"
20#include "byte.h"
21#include "case.h"
22#include "env.h"
23#include "now.h"
24#include "exit.h"
25#include "rcpthosts.h"
26#include "recipients.h"
27#include "mfrules.h"
28#include "tls_start.h"
29#include "smtpdlog.h"
30#include "timeout.h"
31#include "commands.h"
32#include "cdbread.h"
33#include "dns.h"
34#include "wait.h"
35#include "sig.h"
36#include "close.h"
37#include "open.h"
38#include "base64.h"
39#include "spf.h"
40#include "buffer.h"
41
45#define PAM111421
46#define AUTHSLEEP 5
47#define PORT_SMTPS "465"
48#define SMTP_TIMEOUT 1200
49
50#define MIMETYPE_LEN 9
51#define LOADER_LEN 5
52#define BASE64MESSAGE "content-transfer-encoding: base64"
53#define FDIN 0
54#define FDOUT 1
55#define FDLOG 2
56#define FDAUTH 3
57
58#define MAXHOPS 100
59unsigned long databytes = 0;
60unsigned long timeout = SMTP_TIMEOUT;
61
62int modssl_info();
63
64ssize_t safewrite(int fd,char *buf,int len)
65{
66 int r;
67 r = timeoutwrite(timeout,fd,buf,len);
68 if (r <= 0) _exit(1);
69 return r;
70}
71
72ssize_t saferead(int fd,char *buf,int len)
73{
74 int r;
75 flush();
76 r = timeoutread(timeout,fd,buf,len);
77 if (r == -1) if (errno == ETIMEDOUT) die_alarm();
78 if (r <= 0) _exit(0);
79 return r;
80}
81
83buffer bi = BUFFER_INIT(saferead,FDIN,inbuf,sizeof(inbuf));
84
86buffer bo = BUFFER_INIT(safewrite,FDOUT,outbuf,sizeof(outbuf));
87
89buffer bl = BUFFER_INIT(buffer_unixwrite,FDLOG,buflog,sizeof(buflog));
90
91void flush() { buffer_flush(&bo); } // this triggers writing to STDIO
92void out(char *s) { buffer_puts(&bo,s); }
93
94stralloc sa = {0};
95ipalloc ia = {0};
96
97int bhelocheck(void);
98
99/* this file is too long -------------------------------------- DNS helper */
100
101int dnsq(char *arg,char type)
102{
103 unsigned int random;
104 int at;
105 int r = -2;
106 int len;
107
108 len = str_len(arg);
109 if (len < 1) return r;
110
111 if (arg[len-1] == ' ') len--; /* trailing blank */
112 if (len < 1) return r;
113
114 at = byte_rchr(arg,len,'@');
115 if (at < len) {
116 if (!stralloc_copyb(&sa,arg + at + 1,len - at - 1)) die_nomem();
117 } else
118 if (!stralloc_copyb(&sa,arg,len)) die_nomem();
119
120 random = now() + (getpid() << 16);
121
122 switch (type) { /* Common for IPv4 and IPv6 */
123 case 'A': r = dns_ip(&ia,&sa); break;
124 case 'M': r = dns_mxip(&ia,&sa,random); break;
125 }
126
127 switch (r) {
128 case DNS_ERR: out("451 DNS temporary failure (#4.3.0)\r\n"); return -1;
129 case DNS_MEM: die_nomem();
130 default: if (ia.len) return 0;
131 }
132
133 return 1;
134}
135
136/* this file is too long -------------------------------------- Greeting */
137
138static stralloc greeting = {0};
139
140void smtp_greet(char *code)
141{
142 buffer_puts(&bo,code);
143 buffer_put(&bo,greeting.s,greeting.len);
144}
146{
147 out("214 s/qmail home page: https://www.fehcom.de/sqmail.html\r\n");
148}
150{
151 smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
152}
153
157char *local;
160int flagutf8 = 0;
161int flaglf = 0;
162
163stralloc protocol = {0};
164stralloc helohost = {0};
165char *fakehelo; /* pointer into helohost, or 0 */
166stralloc tlsinfo = {0};
167
171int seenhelo = 0;
172
175
176void dohelo(char *helo)
177{
178 if (!stralloc_copys(&helohost,helo)) die_nomem();
179 if (!stralloc_0(&helohost)) die_nomem();
180 fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0;
181 if (helocheck) {
182 if (str_len(helocheck) == 1) {
183 switch (*helocheck) {
184 case '=': flagbadhelo = bhelocheck();
185 if (fakehelo) { flagdnshelo = 1; badhelocond = "="; }
186 break;
187 case 'A': flagbadhelo = bhelocheck();
188 if (flagbadhelo == 0) { flagdnshelo = dnsq(helohost.s,'A'); badhelocond = "A"; }
189 break;
190 case 'M': flagbadhelo = bhelocheck();
191 if (flagbadhelo == 0) { flagdnshelo = dnsq(helohost.s,'M'); badhelocond = "M"; }
192 break;
193 case '.': flagbadhelo = bhelocheck();
194 if (!str_len(helo)) flagbadhelo = -2;
195 break;
196 case '!': if (!str_len(helo)) flagbadhelo = -2;
197 break;
198 }
199 } else {
201 }
202 if (flagbadhelo == -3) flagbadhelo = 0;
203 }
204 if (!env_put("HELOHOST",helohost.s)) die_nomem();
205}
206
207int liphostok = 0;
208stralloc liphost = {0};
209
210int bmfok = 0;
211stralloc bmf = {0};
213
214int brtok= 0;
215stralloc brt = {0};
217
218int badhelook = 0;
219stralloc badhelo = {0};
221
222static struct cdb cdbm;
223static struct cdb cdbl;
224
225static int fdbmt;
226int flagmimetype = 0; /* 1: white; 2: cdb; 3: white+cdb; 4: !relay+white; 6: !relay+white+cdb; -1: found in cdb; -2: found white */
228
229static int fdblt;
230int flagloadertype = 0; /* 1: cdb; 2: !relay+cdb; -1: found in cdb */
232
233static int fdmav;
234int flagmav = 0;
235int localmf = 0; /* 1: domainpart->rcpthosts; 2: ->mailformrules; 3: ->remoteinfo; 4: ->DN(Email) */
237
239char *qhpsi;
240char *base64;
241
245
248
249int greylist = 0;
250stralloc pgbind = {0};
251
252char *auth;
253int smtpauth = 0; /* -1:Cert 0:none 1:login/plain 2:cram 3:login/plain/cram 11:must_login/plain 12:must_2 13:must_3 */
254int seenauth = 0; /* 1:ESMTPA 2:~CLIENTDN */
255stralloc authmethod = {0};
256
257int starttls = 0; /* -1:TLS 0:none 1:STARTTLS 2:require_STARTTLS 3:relay_if_CLIENTDN 4:require_+_relay_if_CLIENTDN */
258int seentls = 0; /* 1:~STARTTLS 2:~TLS 3:~CLIENTDN */
259char *ucspitls = 0;
261char *cipher;
264char *clientdn = 0;
265char *clientcn = 0;
267
268stralloc mailto = {0};
269stralloc deliverto = {0};
271stralloc rblinfo = {0};
273
274int flagspf = 0;
275static stralloc spfbounce = {0};
276
277void setup()
278{
279 char *x;
280 unsigned long u;
281 int r;
282 flagip6 = 1; // GCC 10 implicit int declarition if global var
283
284 if (control_init() == -1) die_control();
285 if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1)
286 die_control();
287 liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0);
288 if (liphostok == -1) die_control();
289 if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
290 if (timeout <= 0) timeout = 1;
291
292 if (rcpthosts_init() == -1) die_control();
293 if (recipients_init() == -1) die_control();
294
295 bmfok = control_readfile(&bmf,"control/badmailfrom",0);
296 if (bmfok == -1) die_control();
297 if (bmfok)
298 if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
299
300 brtok = control_readfile(&brt,"control/badrcptto",0);
301 if (brtok == -1) die_control();
302 if (brtok)
303 if (!constmap_init(&mapbrt,brt.s,brt.len,0)) die_nomem();
304
305 if (control_readint(&databytes,"control/databytes") == -1) die_control();
306 x = env_get("DATABYTES");
307 if (x) { scan_ulong(x,&u); databytes = u; }
308 if (!(databytes + 1)) --databytes;
309
310 if (!stralloc_copys(&protocol,"ESMTP")) die_nomem(); /* RFC 3848 */
311 remoteip = env_get("TCP6REMOTEIP"); /* compactified IPv6 */
312 if (!remoteip) remoteip = env_get("TCPREMOTEIP"); /* allow other tcpserver/sslserver */
313 if (remoteip && (str_chr(remoteip,':') < str_len(remoteip))) {
314 if (byte_equal(remoteip,7,V4MAPPREFIX))
315 { remoteip = remoteip + 7; flagip6 = 0; }
316 } else flagip6 = 0;
317 if (!remoteip) { remoteip = "unknown"; flagip6 = -1; }
318 local = env_get("TCP6LOCALHOST");
319 if (!local) local = env_get("TCPLOCALHOST");
320 if (!local) local = env_get("TCP6LOCALIP");
321 if (!local) local = env_get("TCPLOCALIP");
322 if (!local) local = "unknown";
323 localport = env_get("TCP6LOCALPORT");
324 if (!localport) localport = env_get("TCPLOCALPORT");
325 if (!localport) localport = "0";
326 remotehost = env_get("TCP6REMOTEHOST");
327 if (!remotehost) remotehost = env_get("TCPREMOTEHOST");
328 if (!remotehost) remotehost = "unknown";
329 remoteinfo = env_get("TCP6REMOTEINFO");
330 if (!remoteinfo) remoteinfo = env_get("TCPREMOTEINFO");
331 relayclient = env_get("RELAYCLIENT");
332
333 if (!case_diffs(localport,PORT_SMTPS)) {
334 if (!modssl_info()) die_tls();
335 starttls = -1;
336 }
337
338 mfdnscheck = env_get("MFDNSCHECK");
339 x = env_get("MAXRECIPIENTS");
340 if (x) { scan_ulong(x,&u); maxrcptcount = u; };
341 if (!(maxrcptcount + 1)) --maxrcptcount;
342
343 helocheck = env_get("HELOCHECK");
344 if (helocheck) {
345 badhelook = control_readfile(&badhelo,"control/badhelo",0);
346 if (badhelook == -1) die_control();
347 if (badhelook)
349 }
350
351 x = env_get("TARPITCOUNT");
352 if (x) { scan_ulong(x,&u); tarpitcount = u; };
353 x = env_get("TARPITDELAY");
354 if (x) { scan_ulong(x,&u); tarpitdelay = u; };
355
356 x = env_get("POSTGREY"); // RFC 6647
357 if (x) {
358 if (case_diffs(x,"-")) {
359 greylist = 1;
360 if (!stralloc_copys(&pgbind,x)) die_nomem();
361 if (!stralloc_append(&pgbind,"")) die_nomem();
362 }
363 }
364
365 localmfcheck = env_get("LOCALMFCHECK");
366 if (localmfcheck) {
367 localmf = 1;
368 if (str_len(localmfcheck) == 1 && *localmfcheck == '!') {
369 localmf = 2;
370 fdmav = open_read("control/mailfromrules.cdb");
371 if (fdmav == -1 ) localmf = 1;
372 }
373 if (str_len(localmfcheck) == 1 && *localmfcheck == '=') {
374 localmf = 3;
375 }
376 if (str_len(localmfcheck) == 1 && *localmfcheck == '?') {
377 localmf = 4;
378 }
379 }
380
381 badmimeinit = env_get("BADMIMETYPE");
382 if (badmimeinit) {
383 fdbmt = open_read("control/badmimetypes.cdb");
384 if (str_len(badmimeinit) == 1) {
385 if (*badmimeinit == '-')
386 flagmimetype = 0;
387 else {
388 if (*badmimeinit == '!') flagmimetype = 1;
389 if (*badmimeinit == '+') flagmimetype = 4;
390 }
391 }
392 if (fdbmt != -1 ) flagmimetype = flagmimetype + 2;
393 }
394
395 badloaderinit = env_get("BADLOADERTYPE");
396 if (badloaderinit) {
397 if (str_len(badloaderinit) == 1) {
398 if (*badloaderinit == '-')
399 flagloadertype = 0;
400 else {
401 flagloadertype = 1;
402 if (*badloaderinit == '+') flagloadertype = 2;
403 fdblt = open_read("control/badloadertypes.cdb");
404 if (fdblt == -1 ) flagloadertype = 0;
405 }
406 }
407 }
408
409 base64 = env_get("BASE64");
410 qhpsi = env_get("QHPSI");
411 auth = env_get("SMTPAUTH");
412 if (auth) {
413 smtpauth = 1;
414 if (!case_diffs(auth,"-")) smtpauth = 0;
415 if (!case_diffs(auth,"!")) smtpauth = 11;
416 if (case_starts(auth,"cram")) smtpauth = 2;
417 if (case_starts(auth,"+cram")) smtpauth = 3;
418 if (case_starts(auth,"!cram")) smtpauth = 12;
419 if (case_starts(auth,"!+cram")) smtpauth = 13;
420 }
421
422 if (!seentls) {
423 ucspitls = env_get("UCSPITLS");
424 if (ucspitls) {
425 starttls = 1;
426 if (!case_diffs(ucspitls,"-")) starttls = 0;
427 if (!case_diffs(ucspitls,"!")) starttls = 2;
428 if (!case_diffs(ucspitls,"?")) starttls = 3;
429 if (!case_diffs(ucspitls,"@")) starttls = 4;
430 }
431 }
432
433 delivermailto = env_get("DELIVERTO");
434 if (delivermailto) {
435 if (!stralloc_cats(&mailto,delivermailto)) die_nomem();
436 if (!stralloc_cats(&mailto," ")) die_nomem();
437 }
438
439 rblsmtpd = env_get("RBLSMTPD");
440 if (rblsmtpd) {
441 if (!stralloc_cats(&rblinfo,rblsmtpd)) die_nomem();
442 if (!stralloc_0(&rblinfo)) die_nomem();
443 }
444
445 x = env_get("SPF");
446 if (x) { scan_ulong(x,&u); flagspf = u; }
447 if (flagspf < 0 || flagspf > 6) die_control();
448 if (flagspf) {
449 r = control_readline(&spflocalrules,"control/spflocalrules");
450 if (r == -1) die_control();
451 if (!stralloc_0(&spflocalrules)) die_nomem();
452 if (control_rldef(&spfexplain,"control/spfexplain",0,SPF_DEFEXP) == -1) die_control();
453 if (!stralloc_0(&spfexplain)) die_nomem();
454 }
455
456 x = env_get("UTF8");
457 if (x) flagutf8 = 1;
458
459 x = env_get("BARELF");
460 if (x) flaglf = 1;
461 if (flaglf && !case_diffs(x,"-")) flaglf = 0;
462
463 if (!stralloc_copys(&helohost,"")) die_nomem(); // helohost is initially empty
464 if (!stralloc_0(&helohost)) die_nomem();
465 fakehelo = 0;
466
467}
468
469void auth_info(char *method)
470{
471 if (!env_put("AUTHPROTOCOL",method)) die_nomem();
472 if (!env_put("AUTHUSER",remoteinfo)) die_nomem();
473 if (!env_unset("TCPREMOTEINFO")) die_read();
474 if (!env_put("TCPREMOTEINFO",remoteinfo)) die_nomem();
475 if (!env_unset("TCP6REMOTEINFO")) die_read();
476 if (!env_put("TCP6REMOTEINFO",remoteinfo)) die_nomem();
477
478 if (!stralloc_append(&protocol,"A")) die_nomem();
479}
480
482{
483 tlsversion = env_get("SSL_PROTOCOL");
484 if (!tlsversion) return 0;
485
486 cipher = env_get("SSL_CIPHER");
487 if (!cipher) cipher = "unknown";
488 cipherperm = env_get("SSL_CIPHER_ALGKEYSIZE");
489 if (!cipherperm) cipherperm = "unknown";
490 cipherused = env_get("SSL_CIPHER_USEKEYSIZE");
491 if (!cipherused) cipherused = "unknown";
492 clientdn = env_get("SSL_CLIENT_S_DN");
493 if (clientdn) {
494 seentls = 3;
495 seenauth = 2;
496 smtpauth = -1;
497 relayclient = "";
498 }
499
501 if (!stralloc_cats(&tlsinfo,": ")) die_nomem();
502 if (!stralloc_cats(&tlsinfo,cipher)) die_nomem();
503 if (!stralloc_cats(&tlsinfo," [")) die_nomem();
504 if (!stralloc_cats(&tlsinfo,cipherused)) die_nomem();
505 if (!stralloc_cats(&tlsinfo,"/")) die_nomem();
506 if (!stralloc_cats(&tlsinfo,cipherperm)) die_nomem();
507 if (!stralloc_cats(&tlsinfo,"]")) die_nomem();
508 if (clientdn) {
509 if (!stralloc_cats(&tlsinfo,"\n DN=")) die_nomem();
510 if (!stralloc_cats(&tlsinfo,clientdn)) die_nomem();
511 } else
512 if (!stralloc_0(&tlsinfo)) die_nomem();
513
514 if (!stralloc_append(&protocol,"S")) die_nomem();
515
516 if (seentls == 3 && starttls == 4) {
517 clientcn = env_get("SSL_CLIENT_S_DN_CN");
519 dnemail = env_get("SSL_CLIENT_S_DN_Email");
520 if (!dnemail) dnemail = "unknown";
521 if (!stralloc_cats(&authmethod,"cert")) die_nomem();
523 }
524 return 1;
525}
526
527/* this file is too long --------------------------------- Address checks */
528
529stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */
530stralloc eddr = {0}; /* extended address; used for smart address recognition */
531stralloc rddr = {0}; /* test anti-spoofing host name */
532stralloc mailfrom = {0};
533stralloc rcptto = {0};
534stralloc user = {0};
535stralloc fuser = {0};
536stralloc mfparms = {0};
537
538int seenmail = 0;
539int flagaddr; /* defined if seenmail */
541int flagdnsmf = 0;
543int rcptcount = 0;
544
545int addrparse(char *arg)
546{
547 int i;
548 char ch;
549 char terminator;
550 struct ip4_address ip4s;
551 struct ip6_address ip6s;
552 int flagesc;
553 int flagquoted;
554
555 terminator = '>';
556 i = str_chr(arg,'<');
557 if (arg[i])
558 arg += i + 1;
559 else
560 return 0;
561
562 /* strip source route */
563 if (*arg == '@') while (*arg) if (*arg++ == ':') break;
564
565 if (!stralloc_copys(&addr,"")) die_nomem();
566 flagesc = 0;
567 flagquoted = 0;
568 for (i = 0; ch = arg[i]; ++i) { /* copy arg to addr, stripping quotes */
569 if (flagesc) {
570 if (!stralloc_append(&addr,&ch)) die_nomem();
571 flagesc = 0;
572 }
573 else {
574 if (!flagquoted && (ch == terminator)) break;
575 switch (ch) {
576 case '\\': flagesc = 1; break;
577 case '"': flagquoted = !flagquoted; break;
578 default: if (!stralloc_append(&addr,&ch)) die_nomem();
579 }
580 }
581 }
582 /* could check for termination failure here, but why bother? */
583 if (!stralloc_append(&addr,"")) die_nomem();
584
585 if (liphostok) {
586 i = byte_rchr(addr.s,addr.len,'@');
587 if (i < addr.len) /* if not, partner should go read rfc 821 */
588 if (addr.s[i + 1] == '[') {
589 if (byte_rchr(addr.s + i + 2,addr.len - i - 2,':') < str_len(addr.s)) { /* @[IPv6::] */
590 if (!addr.s[i + 1 + ip6_scanbracket(addr.s + i + 1,(char *)&ip6s.d)])
591 if (ipme_is6(&ip6s)) {
592 addr.len = i + 1;
593 if (!stralloc_cat(&addr,&liphost)) die_nomem();
594 }
595 } else { /* @[IPv4] */
596 if (!addr.s[i + 1 + ip4_scanbracket(addr.s + i + 1,(char *)&ip4s.d)])
597 if (ipme_is4(&ip4s)) {
598 addr.len = i + 1;
599 if (!stralloc_cat(&addr,&liphost)) die_nomem();
600 }
601 }
602 }
603 if (!stralloc_0(&addr)) die_nomem();
604 }
605
606 if (addr.len > 900) return 0;
607 return 1;
608}
609
611{
612 int i;
613 int j;
614 int k = 0;
615 char subvalue;
616
617 if (badhelook && helohost.len > 1) { /* helohost! */
618 if (!stralloc_copyb(&eddr,helohost.s,helohost.len - 1)) die_nomem();
619 if (!stralloc_append(&eddr,"!")) die_nomem();
620 if (!stralloc_0(&eddr)) die_nomem();
621 if (constmap(&mapbhlo,eddr.s,eddr.len - 1)) return -3;
622
623 if (constmap(&mapbhlo,helohost.s,helohost.len - 1)) return -1;
624
625 i = 0;
626 for (j = 0; j < badhelo.len; ++j)
627 if (!badhelo.s[j]) {
628 subvalue = badhelo.s[i] != '!';
629 if (!subvalue) i++;
630 if ((k != subvalue) && wildmat(helohost.s,badhelo.s + i)) k = subvalue;
631 i = j + 1;
632 }
633 return k;
634 }
635 return 0;
636}
637
639{
640 int i = 0;
641 int j = 0;
642 int k = 0;
643 int at = 0;
644 int dlen;
645 int rlen;
646 char subvalue;
647
648 if (bmfok && mailfrom.len > 1) {
649 rlen = str_len(remotehost);
650 at = byte_rchr(mailfrom.s,mailfrom.len,'@');
651
652/* '?' enhanced address to skip all other tests including MFDNSCHECK */
653
654 if (!stralloc_copys(&eddr,"?")) die_nomem();
655 if (!stralloc_cat(&eddr,&mailfrom)) die_nomem();
656 case_lowerb(eddr.s,eddr.len);
657 if (constmap(&mapbmf,eddr.s,eddr.len - 1)) return -110;
658
659/* '+' extended address for none-RELAYCLIENTS */
660
661 if (at && !relayclient) {
662 if (!stralloc_copyb(&eddr,mailfrom.s,mailfrom.len - 1)) die_nomem();
663 if (!stralloc_append(&eddr,"+")) die_nomem();
664 if (!stralloc_0(&eddr)) die_nomem();
665 case_lowerb(eddr.s,eddr.len);
666 if (constmap(&mapbmf,eddr.s + at,eddr.len - at - 1)) return -5;
667 }
668
669/* '-' extended address from UNKNOWN */
670
671 if (at && !case_diffs(remotehost,"unknown")) {
672 if (!stralloc_copyb(&eddr,mailfrom.s,mailfrom.len - 1)) die_nomem();
673 if (!stralloc_append(&eddr,"-")) die_nomem();
674 if (!stralloc_0(&eddr)) die_nomem();
675 case_lowerb(eddr.s,eddr.len);
676 if (constmap(&mapbmf,eddr.s + at,eddr.len - at - 1)) return -4;
677 }
678
679/* '=' extended address for WELLKNOWN senders */
680
681 else if (at && rlen >= mailfrom.len - at - 1) {
682 dlen = mailfrom.len - at - 2;
683 if (!stralloc_copyb(&eddr,mailfrom.s,mailfrom.len - 1)) die_nomem();
684 if (!stralloc_append(&eddr,"=")) die_nomem();
685 if (!stralloc_0(&eddr)) die_nomem();
686 case_lowerb(eddr.s,eddr.len);
687 if (case_diffb(remotehost + rlen - dlen,dlen,eddr.s + at + 1))
688 if (constmap(&mapbmf,eddr.s + at,eddr.len - at - 1)) return -3;
689
690/* '~' extended address for MISMATCHED Domains */
691
692 if (case_diffrs(remotehost,mailfrom.s + at + 1)) {
693 j = 0;
694 do {
695 if (!stralloc_copys(&eddr,"~")) die_nomem();
696 if (!stralloc_cats(&eddr,remotehost + j)) die_nomem();
697 if (!stralloc_0(&eddr)) die_nomem();
698 if (constmap(&mapbmf,eddr.s,eddr.len - 1)) return -2;
699 j = byte_chr(remotehost + j,rlen - j,'.') + j + 1;
700 } while (j > 0 && rlen - j > 0);
701 }
702 }
703
704/* Standard */
705
706 if (constmap(&mapbmf,mailfrom.s,mailfrom.len - 1)) return -1;
707 if (at && at < mailfrom.len)
708 if (constmap(&mapbmf,mailfrom.s + at,mailfrom.len - at - 1)) return -1;
709
710/* Wildmating */
711
712 i = k = 0;
713 for (j = 0; j < bmf.len; ++j) {
714 if (!bmf.s[j]) {
715 subvalue = bmf.s[i] != '!';
716 if (!subvalue) i++;
717 if ((k != subvalue) && wildmat(mailfrom.s,bmf.s + i)) k = subvalue;
718 i = j + 1;
719 }
720 }
721 return k;
722 }
723
724 return 0;
725}
726
728{
729 int i;
730 int j = 0;
731 int k = 0;
732 char subvalue;
733
734 if (brtok) {
735 if (constmap(&mapbrt,addr.s,addr.len - 1)) return -2;
736
737 int at = byte_rchr(addr.s,addr.len,'@');
738 if (at < addr.len)
739 if (constmap(&mapbrt,addr.s + at,addr.len - at - j)) return -1;
740
741/* '#' enhanced address to consider invalid rcptto addresses for none-relayclients */
742
743 if (!relayclient) {
744 if (!stralloc_copys(&eddr,"+")) die_nomem();
745 if (!stralloc_cat(&eddr,&addr)) die_nomem();
746 if (!stralloc_0(&eddr)) die_nomem();
747 case_lowerb(eddr.s,eddr.len);
748 if (constmap(&mapbmf,eddr.s,eddr.len - 1)) return 110;
749 }
750
751 i = 0;
752 for (j = 0; j < brt.len; ++j)
753 if (!brt.s[j]) {
754 subvalue = brt.s[i] != '!';
755 if (!subvalue) i++;
756 if ((k != subvalue) && wildmat(addr.s,brt.s + i)) k = subvalue;
757 i = j + 1;
758 }
759 return k;
760 }
761 return 0;
762}
763
764int addrallowed(char *arg)
765{
766 int r;
767 r = rcpthosts(arg,str_len(arg));
768 if (r == -1) die_control();
769 return r;
770}
771
773{
774 int r;
775 r = recipients(addr.s,str_len(addr.s));
776#ifdef PAM111421
777 if (r == 111) die_recipients();
778#endif
779 if (r == -3) die_recipients();
780 if (r == -2) die_nomem();
781 if (r == -1) die_control();
782 return r;
783}
784
785int localaddr(char *mf)
786{
787 int at;
788 int mflen;
789
790 mflen = str_len(mf);
791 if (mflen < 1 ) return 0;
792
793 if (localmf == 4) {
794 if (!case_diffs(dnemail,mf)) return 2;
795 return -4;
796 }
797 if (localmf == 3) {
798 if (!case_diffs(remoteinfo,mf)) return 2;
799 return -3;
800 }
801 else if (localmf == 2)
802 return mfrules(fdmav,remoteip,remotehost,remoteinfo,mf);
803 else {
804 if (str_len(localmfcheck) > 1) {
805 at = byte_rchr(mf,mflen,'@');
806 if (at < mflen)
807 if (!case_diffb(localmfcheck,mflen - at - 1,mf + at + 1)) return 2;
808 }
809 if (addrallowed(mf)) return 3;
810 return -2;
811 }
812}
813
814int spf_check(int flag6)
815{
816 int r;
817
818 if (mailfrom.len <= 1) { flagspf = 0; return 0; }
819
822 if (r == SPF_NOMEM) die_nomem();
823 if (!stralloc_0(&spfinfo)) die_nomem();
824
825 switch (r) {
826 case SPF_ME:
827 case SPF_OK:
828 if (!env_put("SPFRESULT","pass")) die_nomem();
829 flagspf = 10;
830 break;
831 case SPF_LOOP:
832 case SPF_ERROR:
833 case SPF_SYNTAX:
834 case SPF_EXHAUST:
835 if (!env_put("SPFRESULT","error")) die_nomem();
836 if (flagspf < 2) { flagspf = 0; break; }
837 out("451 SPF lookup failure (#4.3.0)\r\n");
838 return -1;
839 case SPF_NONE:
840 if (!env_put("SPFRESULT","none")) die_nomem();
841 flagspf = 0;
842 break;
843 case SPF_UNKNOWN:
844 if (!env_put("SPFRESULT","unknown")) die_nomem();
845 if (flagspf < 6) break;
846 else return 4;
847 case SPF_NEUTRAL:
848 if (!env_put("SPFRESULT","neutral")) die_nomem();
849 if (flagspf < 5) break;
850 else return 3;
851 case SPF_SOFTFAIL:
852 if (!env_put("SPFRESULT","softfail")) die_nomem();
853 if (flagspf < 4) break;
854 else return 2;
855 case SPF_FAIL:
856 if (!env_put("SPFRESULT","fail")) die_nomem();
857 if (flagspf < 3) break;
858 if (!spf_parse(&spfbounce,spfexpmsg.s,expdomain.s)) die_nomem();
859 return 1;
860 }
861
862 return 0;
863}
864
865/* this file is too long --------------------------------- MF parser */
866
867int mailfrom_size(char *arg)
868{
869 unsigned long r;
870 unsigned long sizebytes = 0;
871
872 scan_ulong(arg,&r);
873 sizebytes = r;
874 if (databytes) if (sizebytes > databytes) return 1;
875 return 0;
876}
877
878void mailfrom_auth(char *arg,int len)
879{
880 if (!stralloc_copys(&fuser,"")) die_nomem();
881 if (case_starts(arg,"<>")) {
882 if (!stralloc_cats(&fuser,"unknown")) die_nomem();
883 } else {
884 while (len) {
885 if (*arg == '+') {
886 if (case_starts(arg,"+3D")) {
887 arg = arg + 2; len = len - 2;
888 if (!stralloc_cats(&fuser,"=")) die_nomem();
889 }
890 if (case_starts(arg,"+2B")) {
891 arg = arg + 2; len = len - 2;
892 if (!stralloc_cats(&fuser,"+")) die_nomem();
893 }
894 } else {
895 if (!stralloc_catb(&fuser,arg,1)) die_nomem();
896 }
897 arg++; len--;
898 }
899 }
900
901 if (!stralloc_0(&fuser)) die_nomem();
902 if (!remoteinfo) {
903 remoteinfo = fuser.s;
904 if (!env_unset("TCPREMOTEINFO")) die_read();
905 if (!env_put("TCPREMOTEINFO",remoteinfo)) die_nomem();
906 if (!env_unset("TCP6REMOTEINFO")) die_read();
907 if (!env_put("TCP6REMOTEINFO",remoteinfo)) die_nomem();
908 }
909}
910
911void mailfrom_parms(char *arg)
912{
913 int len;
914
915 if ((len = str_len(arg))) {
916 if (!stralloc_copys(&mfparms,"")) die_nomem();
917 while (len) {
918 arg++; len--;
919 if (*arg == ' ' || *arg == '\0' ) {
920 if (flagutf8) if (case_starts(mfparms.s,"SMTPUTF8")) flagutf8 = 2;
921 if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s + 5)) { flagsize = 1; return; }
922 if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s + 5,mfparms.len - 5);
923 if (!stralloc_copys(&mfparms,"")) die_nomem();
924 }
925 else
926 if (!stralloc_catb(&mfparms,arg,1)) die_nomem();
927 }
928 }
929}
930
931/* this file is too long --------------------------------- SMTP dialog */
932
933void smtp_helo(char *arg)
934{
935 smtp_greet("250 "); out("\r\n"); flush();
936 seenmail = 0; rcptcount = 0; seenhelo++;
937 dohelo(arg);
938}
939
940void smtp_ehlo(char *arg)
941{
942 char size[FMT_ULONG];
943
944 smtp_greet("250-"); out("\r\n");
945 out("250-PIPELINING\r\n250-8BITMIME\r\n");
946 if (flagutf8) out("250-SMTPUTF8\r\n");
947 if (starttls > 0 && !seentls) out("250-STARTTLS\r\n");
948
949 switch (smtpauth) {
950 case 1: case 11: out("250-AUTH LOGIN PLAIN\r\n"); break;
951 case 2: case 12: out("250-AUTH CRAM-MD5\r\n"); break;
952 case 3: case 13: out("250-AUTH LOGIN PLAIN CRAM-MD5\r\n"); break;
953 }
954
955 size[fmt_ulong(size,(unsigned long) databytes)] = 0;
956 out("250 SIZE "); out(size); out("\r\n");
957
958 seenhelo++; seenmail = 0; rcptcount = 0;
959 dohelo(arg);
960}
961
962void smtp_rset(void)
963{
964 seenmail = 0; rcptcount = 0; /* RFC 5321: seenauth + seentls stay */
965
966 if (!stralloc_copys(&mailfrom,"")) die_nomem();
967 if (!stralloc_copys(&rcptto,"")) die_nomem();
968 out("250 flushed\r\n");
969}
970
972{
973 if (starttls == 0) err_starttls();
974
975 out("220 Ready to start TLS (#5.7.0)\r\n");
976 flush();
977
978 if (!starttls_init()) die_tls();
979 buffer_init(&bi,saferead,FDIN,inbuf,sizeof(inbuf));
980 seentls = 2;
981
982 if (!starttls_info()) die_tls();
983 if (!modssl_info()) die_tls();
984
985/* reset SMTP state */
986
987 seenhelo = 0; seenmail = 0; rcptcount = 0;
988 if (!stralloc_copys(&addr,"")) die_nomem();
989 if (!stralloc_copys(&helohost,"")) die_nomem();
990 if (!stralloc_copys(&mailfrom,"")) die_nomem();
991 if (!stralloc_copys(&rcptto,"")) die_nomem();
992 if (seenauth == 1) seenauth = 0; /* Otherwise Auth by client Cert */
993}
994
995void smtp_mail(char *arg)
996{
997 if (flagutf8) if (!stralloc_cats(&protocol,"UTF8")) die_nomem();
998 if (!stralloc_0(&protocol)) die_nomem();
999
1000 if ((starttls > 1) && !seentls) {
1001 err_tlsreq("Reject::TLS::Missing",protocol.s,remoteip,remotehost,helohost.s);
1002 return;
1003 }
1004 if (smtpauth > 10 && !seenauth) {
1005 err_authreq("Reject::AUTH::Missing",protocol.s,remoteip,remotehost,helohost.s);
1006 return;
1007 }
1008 if (!addrparse(arg)) { err_syntax(); return; }
1009
1010 flagsize = 0;
1011 rcptcount = 0;
1012 mailfrom_parms(arg);
1013 seenmail++;
1014 if (relayclient && localmf) {
1015 flagmav = localaddr(addr.s);
1016 if (flagmav > 0) if (!stralloc_append(&protocol,"M")) die_nomem();
1017 }
1018 if (!stralloc_copys(&rcptto,"")) die_nomem();
1020 if (!stralloc_0(&mailfrom)) die_nomem();
1021 if (!env_put("MAILFROM",mailfrom.s)) die_nomem();
1022
1023 flagaddr = bmfcheck();
1024 if (flagaddr != -110)
1025 if (mfdnscheck) flagdnsmf = dnsq(mailfrom.s,'M');
1026
1027 out("250 ok\r\n");
1028}
1029
1030/* this file is too long --------------------------------- Greylisting */
1031
1033{
1034 int child;
1035 int wstat;
1036
1037 char *postgrey_scannerarg[] = {"bin/qmail-postgrey",pgbind.s,mailfrom.s,addr.s,remoteip,remotehost,0};
1038
1039 switch (child = fork()) {
1040 case -1:
1041 return err_forkgl();
1042 case 0:
1043 execv(*postgrey_scannerarg,postgrey_scannerarg);
1044 _exit(1);
1045 }
1046
1047 wait_pid(&wstat,child);
1048 if (wait_crashed(wstat)) return err_postgl();
1049
1050 switch (wait_exitcode(wstat)) {
1051 case 10: return 1;
1052 default: return 0;
1053 }
1054}
1055
1056void smtp_rcpt(char *arg)
1057{
1058 char *rcptok = 0;
1059 if (!seenmail) { err_wantmail(); return; }
1060 if (!addrparse(arg)) { err_syntax(); return; }
1061 rcptcount++;
1062
1063/* this file is too long --------------------------------- Split Horizon envelope checks */
1064
1065 if (!relayclient) {
1066 if (!seenhelo && helocheck) /* Helo rejects */
1067 if (str_len(helocheck) == 1) {
1068 err_helo("Reject::SNDR::Bad_Helo",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"0");
1069 return;
1070 }
1071 if (flagbadhelo) {
1072 switch (flagbadhelo) {
1073 case -2: badhelocond = "!"; break;
1074 case -1: badhelocond = "."; break;
1075 default: badhelocond = "*"; break;
1076 }
1077 err_helo("Reject::SNDR::Bad_Helo",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badhelocond);
1078 return;
1079 }
1080 if (flagdnshelo > 0) {
1081 err_helo("Reject::SNDR::DNS_Helo",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badhelocond);
1082 return;
1083 }
1084
1085 if (flagdnsmf > 0) { /* Mail from rejects */
1086 err_mfdns("Reject::ORIG::DNS_MF",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1087 return;
1088 }
1089
1090 if (!addrallowed(addr.s)) { /* Relaying rejects */
1091 err_nogateway("Reject::SNDR::Invalid_Relay",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1092 return;
1093 }
1094
1095 if (greylist && (postgrey_scanner() == 1)) { /* Greylisting */
1096 postgrey("Deferred::SNDR::Grey_Listed",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1097 return;
1098 }
1099
1100 if (tarpitcount && flagerrcpts >= tarpitcount) { /* Tarpitting et al. */
1101 if (tarpitdelay == 999) flagnotorious++;
1102 err_rcpts("Reject::RCPT::Toomany_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1103 return;
1104 }
1106 if (tarpitdelay > 0 && tarpitdelay < 999) sleep(tarpitdelay);
1107
1108 flagrcpt = rcptallowed(); /* Rcpt to rejects */
1109 if (!flagrcpt) {
1110 err_recipient("Reject::RCPT::Failed_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1111 flagerrcpts++;
1112 return;
1113 }
1114
1115 if (flagspf) /* SPF rejects */
1116 if (spf_check(flagip6) > 0) {
1117 if (!stralloc_0(&spfbounce)) die_nomem();
1118 err_spf("Reject::SPF::Fail",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,spfbounce.s);
1119 return;
1120 }
1121 }
1122
1123/* this file is too long --------------------------------- Local checks */
1124
1125 else {
1126 if (flagmimetype == 4 || flagmimetype == 6) flagmimetype = 0;
1127 if (flagloadertype == 2) flagloadertype = 0;
1128
1129 if (flagmav < 0) {
1130 err_mav("Reject::ORIG::Invalid_Mailfrom",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1131 return;
1132 }
1133 --addr.len;
1134 if (!stralloc_cats(&addr,relayclient)) die_nomem();
1135 if (!stralloc_0(&addr)) die_nomem();
1136 }
1137
1138/* this file is too long --------------------------------- Common checks */
1139
1140 if (flagmimetype == 2 || flagmimetype == 3 || flagmimetype == 6) cdb_init(&cdbm,fdbmt);
1141 if (flagloadertype == 1) cdb_init(&cdbl,fdblt);
1142
1143 if (flagaddr && flagaddr != -110) {
1144 switch (flagaddr) {
1145 case -1: badmailcond = "@"; break;
1146 case -2: badmailcond = "~"; break;
1147 case -3: badmailcond = "="; break;
1148 case -4: badmailcond = "-"; break;
1149 case -5: badmailcond = "+"; break;
1150 default: badmailcond = "*"; break;
1151 }
1152 err_bmf("Reject::ORIG::Bad_Mailfrom",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badmailcond);
1153 return;
1154 }
1155
1156 flagrcpt = brtcheck();
1157 if (flagrcpt == 110) {
1158 err_brt("Reject::RCPT::Invalid_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1159 return;
1160 } else if (flagrcpt > 0) {
1161 err_brt("Reject::RCPT::Bad_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1162 return;
1163 }
1164
1165 if (flagsize) {
1166 err_size("Reject::DATA::Invalid_Size",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1167 return;
1168 }
1169
1171 err_rcpts("Reject::RCPT::Toomany_Rcptto",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1172 return;
1173 }
1174
1175/* this file is too long --------------------------------- Checks done; mailfrom/recipient accepted */
1176
1177 if (!stralloc_cats(&rcptto,"T")) die_nomem();
1178 if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
1179 if (!stralloc_0(&rcptto)) die_nomem();
1180
1181 if (!stralloc_cats(&mailto,addr.s)) die_nomem();
1182 if (!stralloc_cats(&mailto," ")) die_nomem();
1184 if (!stralloc_0(&deliverto)) die_nomem();
1185 if (!env_put("RCPTTO",deliverto.s)) die_nomem();
1186
1187/* this file is too long --------------------------------- Additional logging */
1188
1189 switch (flagrcpt) {
1190 case 1: rcptok = "Recipients_Cdb"; break;
1191 case 2: rcptok = "Recipients_Pam"; break;
1192 case 3: rcptok = "Recipients_Users"; break;
1193 case 4: rcptok = "Recipients_Wild"; break;
1194 default: rcptok = "Rcpthosts_Rcptto"; break;
1195 }
1196 if (seenauth)
1198 else if (flagmav > 0)
1199 smtp_logg("Accept::ORIG::Local_Sender",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1200 else if (relayclient)
1201 smtp_logg("Accept::SNDR::Relay_Client",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1202 else if (flagspf == 10)
1203 smtp_logr("Accept::SPF::",rcptok,protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1204 else
1205 smtp_logr("Accept::RCPT::",rcptok,protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1206
1207 out("250 ok\r\n");
1208}
1209
1210struct qmail qqt;
1211unsigned long bytestooverflow = 0;
1212
1213stralloc line = {0};
1214stralloc base64types = {0};
1215stralloc badmimetype = {0};
1216stralloc badloadertype = {0};
1217
1218unsigned int nolines = 0;
1219unsigned int flagb64 = 0; /* lineno with BASE64MESSAGE */
1220unsigned int flagbase = 0; /* lineno with actual base64 content */
1221unsigned int flagblank = 0;
1222
1223static void queue_put(char *ch)
1224{
1225 int i;
1226
1227 if (flagmimetype > 0 || flagloadertype > 0 ) {
1228 if (line.len <= BUFSIZE_LINE)
1229 if (!stralloc_catb(&line,ch,1)) die_nomem(); /* Reassamble chars to line; prepend with 'L' */
1230
1231 if (*ch == '\n') {
1232 nolines++;
1233 if (line.len == 2) { flagblank = nolines; flagbase = 0; }
1234
1235 if (*(line.s + 1) == 'C' || *(line.s + 1) == 'c')
1236 if (case_startb(line.s + 1,line.len - 2,BASE64MESSAGE)) flagb64 = nolines;
1237 if (flagb64 && nolines == flagblank + 1 && line.len > MIMETYPE_LEN + 2) flagbase = nolines;
1238 if (*(line.s + 1) == '-') { flagb64 = 0; flagbase = 0; }
1239
1240 if (flagmimetype > 0 && flagbase == nolines) { /* badmimetype */
1241 if (!stralloc_catb(&base64types,line.s + 1,MIMETYPE_LEN)) die_nomem();
1242 if (!stralloc_0(&base64types)) die_nomem();
1243
1244 if (flagmimetype == 2 || flagmimetype == 3 || flagmimetype == 6) {
1245 if (cdb_find(&cdbm,line.s + 1,MIMETYPE_LEN)) {
1246 cdb_free(&cdbm); close(fdbmt);
1247 if (!stralloc_copyb(&badmimetype,line.s + 1,MIMETYPE_LEN)) die_nomem();
1248 if (!stralloc_0(&badmimetype)) die_nomem();
1249 if (!stralloc_cats(&rcptto,"M")) die_nomem();
1250 if (!stralloc_0(&rcptto)) die_nomem();
1251 qmail_fail(&qqt);
1252 flagmimetype = -1;
1253 }
1254 }
1255 }
1256
1257 if (flagbase && line.len > LOADER_LEN + 2) {
1258 if (flagloadertype >= 1 || flagmimetype >= 1) {
1259 for (i = 0; i < line.len - LOADER_LEN; ++i) {
1260 if (flagloadertype == 1 && *(line.s+i) == *badloaderinit) { /* badloadertype */
1261 if (cdb_find(&cdbl,line.s + i,LOADER_LEN)) {
1262 cdb_free(&cdbl); close(fdbmt);
1263 if (!stralloc_copyb(&badloadertype,line.s + i,LOADER_LEN)) die_nomem();
1264 if (!stralloc_0(&badloadertype)) die_nomem();
1265 if (!stralloc_cats(&rcptto,"L")) die_nomem();
1266 if (!stralloc_0(&rcptto)) die_nomem();
1267 qmail_fail(&qqt);
1268 flagloadertype = -1;
1269 }
1270 }
1271 if (flagmimetype == 1 || flagmimetype == 3 || flagmimetype == 4) {
1272 if (*(line.s + i) == ' ' || *(line.s + i) == '\t') { /* white spaces */
1273 if (!stralloc_copyb(&badmimetype,line.s + i - 2,MIMETYPE_LEN)) die_nomem();
1274 if (!stralloc_0(&badmimetype)) die_nomem();
1275 if (!stralloc_cats(&rcptto,"M")) die_nomem();
1276 if (!stralloc_0(&rcptto)) die_nomem();
1277 qmail_fail(&qqt);
1278 flagmimetype = -2;
1279 }
1280 }
1281 }
1282 }
1283 }
1284 line.len = 0;
1285 if (!stralloc_copys(&line,"L")) die_nomem();
1286 }
1287 }
1288
1289 if (bytestooverflow)
1290 if (!--bytestooverflow)
1291 qmail_fail(&qqt);
1292 qmail_put(&qqt,ch,1);
1293}
1294
1295void blast(int *hops)
1296{
1297 char ch;
1298 int state;
1299 int flaginheader;
1300 int pos; /* number of bytes since most recent \n, if fih */
1301 int flagmaybex; /* 1 if this line might match RECEIVED, if fih */
1302 int flagmaybey; /* 1 if this line might match \r\n, if fih */
1303 int flagmaybez; /* 1 if this line might match DELIVERED, if fih */
1304 int seencr = 0; /* only required if flaglf is set */
1305
1306 state = 1;
1307 *hops = 0;
1308 flaginheader = 1;
1309 pos = 0; flagmaybex = flagmaybey = flagmaybez = 1;
1310 for (;;) {
1311 buffer_get(&bi,&ch,1);
1312 if (flaglf) {
1313 if (ch == '\n') {
1314 if (seencr == 0) { buffer_seek(&bi,-1); ch = '\r'; }
1315 }
1316 if (ch == '\r') seencr = 1; else seencr = 0;
1317 }
1318 if (flaginheader) {
1319 if (pos < 9) {
1320 if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0;
1321 if (flagmaybez) if (pos == 8) ++*hops;
1322 if (pos < 8)
1323 if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0;
1324 if (flagmaybex) if (pos == 7) ++*hops;
1325 if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0;
1326 if (flagmaybey) if (pos == 1) flaginheader = 0;
1327 ++pos;
1328 }
1329 if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
1330 }
1331 switch (state) {
1332 case 0:
1333 if (ch == '\n') straynewline();
1334 if (ch == '\r') { state = 4; continue; }
1335 break;
1336 case 1: /* \r\n */
1337 if (ch == '\n') straynewline();
1338 if (ch == '.') { state = 2; continue; }
1339 if (ch == '\r') { state = 4; continue; }
1340 state = 0;
1341 break;
1342 case 2: /* \r\n + . */
1343 if (ch == '\n') straynewline();
1344 if (ch == '\r') { state = 3; continue; }
1345 state = 0;
1346 break;
1347 case 3: /* \r\n + .\r */
1348 if (ch == '\n') return;
1349 queue_put(".");
1350 queue_put("\r");
1351 if (ch == '\r') { state = 4; continue; }
1352 state = 0;
1353 break;
1354 case 4: /* + \r */
1355 if (ch == '\n') { state = 1; break; }
1356 if (ch != '\r') { queue_put("\r"); state = 0; }
1357 }
1358 queue_put(&ch);
1359 }
1360}
1361
1362char accept_buf[FMT_ULONG];
1363
1364void acceptmessage(unsigned long qp)
1365{
1366 datetime_sec when;
1367 when = now();
1368 out("250 ok ");
1369 accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0;
1370 out(accept_buf);
1371 out(" qp ");
1372 accept_buf[fmt_ulong(accept_buf,qp)] = 0;
1373 out(accept_buf);
1374 out("\r\n");
1375}
1376
1378{
1379 int hops;
1380 unsigned long qp;
1381 char *qqx;
1382
1383 if (!seenmail) { err_wantmail(); return; }
1384 if (!rcptto.len) { err_wantrcpt(); return; }
1385 if (flagnotorious) { err_notorious(); }
1386 seenmail = 0;
1388
1389 if (!stralloc_copys(&addr,"")) die_nomem();
1390 if (!stralloc_cats(&addr,rcptto.s + 1)) die_nomem();
1391 if (!stralloc_0(&addr)) die_nomem();
1392
1393 if (qmail_open(&qqt) == -1) { err_qqt(); return; }
1394 qp = qmail_qp(&qqt);
1395
1396 out("354 go ahead\r\n");
1397
1400 blast(&hops);
1401 hops = (hops >= MAXHOPS);
1402 if (hops) qmail_fail(&qqt);
1403 if (base64 && base64types.len == 0) {
1404 if (!stralloc_cats(&rcptto,"Q")) die_nomem();
1405 if (!stralloc_0(&rcptto)) die_nomem();
1406 }
1408 qmail_put(&qqt,rcptto.s,rcptto.len);
1409
1410 qqx = qmail_close(&qqt);
1411 if (!*qqx) { acceptmessage(qp); return; }
1412 if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
1413 if (databytes)
1414 if (!bytestooverflow) {
1415 err_size("Reject::DATA::Invalid_Size",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s);
1416 return;
1417 }
1418 if (flagmimetype < 0) {
1419 err_data("Reject::DATA::Bad_MIME",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badmimetype.s);
1420 return;
1421 }
1422 if (flagloadertype < 0) {
1423 err_data("Reject::DATA::Bad_Loader",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,badloadertype.s);
1424 return;
1425 }
1426 if (*qqx == 'I') {
1427 err_data("Reject::DKIM::Signature",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"fail");
1428 return;
1429 }
1430 if (*qqx == 'S') {
1431 err_data("Reject::DATA::Spam_Message",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"spam");
1432 return;
1433 }
1434 if (*qqx == 'A') {
1435 err_data("Reject::DATA::MIME_Attach",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"MIME");
1436 return;
1437 }
1438 if (*qqx == 'V') {
1439 if (qhpsi)
1440 err_data("Reject::DATA::Virus_Infected",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,qhpsi);
1441 else
1442 err_data("Reject::DATA::Virus_Infected",protocol.s,remoteip,remotehost,helohost.s,mailfrom.s,addr.s,"AV scanner");
1443 return;
1444 }
1445 if (*qqx == 'D') out("554 "); else out("451 ");
1446 out(qqx + 1);
1447 out("\r\n");
1448}
1449
1450/* this file is too long --------------------------------- SMTP Auth */
1451
1452char unique[FMT_ULONG + FMT_ULONG + 3];
1453static stralloc authin = {0}; /* input from SMTP client */
1454static stralloc pass = {0}; /* plain passwd or digest */
1455static stralloc resp = {0}; /* b64 response */
1456static stralloc chal = {0}; /* CRAM-MD5 plain challenge */
1457static stralloc slop = {0}; /* CRAM-MD5 b64 challenge */
1458
1461buffer ba = BUFFER_INIT(safewrite,FDAUTH,authbuf,sizeof(authbuf));
1462
1463int authgetl(void)
1464{
1465 int i;
1466
1467 if (!stralloc_copys(&authin,"")) die_nomem();
1468 for (;;) {
1469 if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
1470 i = buffer_get(&bi,authin.s + authin.len,1);
1471 if (i != 1) die_read();
1472 if (authin.s[authin.len] == '\n') break;
1473 ++authin.len;
1474 }
1475
1476 if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
1477 authin.s[authin.len] = 0;
1478 if (*authin.s == '*' && *(authin.s + 1) == 0) return err_authabort();
1479 if (authin.len == 0) return err_authinput();
1480 return authin.len;
1481}
1482
1484{
1485 int child;
1486 int wstat;
1487 int pi[2];
1488
1489 if (!stralloc_0(&user)) die_nomem();
1490 if (!stralloc_0(&pass)) die_nomem();
1491 if (!stralloc_0(&chal)) die_nomem();
1492 if (!env_put("AUTHUSER",user.s)) die_nomem();
1493
1494 if (pipe(pi) == -1) return err_pipe();
1495 switch (child = fork()) {
1496 case -1:
1497 return err_fork();
1498 case 0:
1499 close(pi[1]);
1500 if (fd_copy(FDAUTH,pi[0]) == -1) return err_pipe();
1501 sig_pipedefault();
1502 execvp(*childargs,childargs);
1503 _exit(1);
1504 }
1505 close(pi[0]);
1506
1507 buffer_init(&ba,write,pi[1],authbuf,sizeof(authbuf));
1508 if (buffer_put(&ba,user.s,user.len) == -1) return err_write();
1509 if (buffer_put(&ba,pass.s,pass.len) == -1) return err_write();
1510 if (smtpauth == 2 || smtpauth == 3 || smtpauth == 12 || smtpauth == 13)
1511 if (buffer_put(&ba,chal.s,chal.len) == -1) return err_write();
1512 if (buffer_flush(&ba) == -1) return err_write();
1513
1514 close(pi[1]);
1515 if (!stralloc_copys(&chal,"")) die_nomem();
1516 if (!stralloc_copys(&slop,"")) die_nomem();
1517 byte_zero(authbuf,sizeof(authbuf));
1518 if (wait_pid(&wstat,child) == -1) return err_child();
1519 if (wait_crashed(wstat)) return err_child();
1520 if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */
1521 return 0; /* yes */
1522}
1523
1524int auth_login(char *arg)
1525{
1526 int r;
1527 if (smtpauth == 2 || smtpauth == 12) return 1; /* only login/plain */
1528
1529 if (*arg) {
1530 if ((r = b64decode((unsigned char *)arg,str_len(arg),&user)) == 1) return err_authinput();
1531 }
1532 else {
1533 out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
1534 if (authgetl() < 0) return -1;
1535 if ((r = b64decode((unsigned char *)authin.s,authin.len,&user)) == 1) return err_authinput();
1536 }
1537 if (r == -1) die_nomem();
1538
1539 out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
1540
1541 if (authgetl() < 0) return -1;
1542 if ((r = b64decode((unsigned char *)authin.s,authin.len,&pass)) == 1) return err_authinput();
1543 if (r == -1) die_nomem();
1544
1545 if (!user.len || !pass.len) return err_authinput();
1546 return authenticate();
1547}
1548
1549int auth_plain(char *arg)
1550{
1551 int r, id = 0;
1552 if (smtpauth == 2 || smtpauth == 12) return 1; /* only login/plain */
1553
1554 if (*arg) {
1555 if ((r = b64decode((unsigned char *)arg,str_len(arg),&resp)) == 1) return err_authinput();
1556 }
1557 else {
1558 out("334 \r\n"); flush();
1559 if (authgetl() < 0) return -1;
1560 if ((r = b64decode((unsigned char *)authin.s,authin.len,&resp)) == 1) return err_authinput();
1561 }
1562 if (r == -1 || !stralloc_0(&resp)) die_nomem();
1563 while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */
1564
1565 if (resp.len > id + 1)
1566 if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
1567 if (resp.len > id + user.len + 2)
1568 if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
1569
1570 if (!user.len || !pass.len) return err_authinput();
1571 return authenticate();
1572}
1573
1575{
1576 int i, r;
1577 char *s;
1578 if (smtpauth == 1 || smtpauth == 11) return 1; /* no challenge if login/plain */
1579
1580 s = unique; /* generate challenge */
1581 s += fmt_uint(s,getpid());
1582 *s++ = '.';
1583 s += fmt_ulong(s,(unsigned long) now());
1584 *s++ = '@';
1585 *s++ = 0;
1586 if (!stralloc_copys(&chal,"<")) die_nomem();
1587 if (!stralloc_cats(&chal,unique)) die_nomem();
1588 if (!stralloc_cats(&chal,local)) die_nomem();
1589 if (!stralloc_cats(&chal,">")) die_nomem();
1590 if (b64encode(&chal,&slop) < 0) die_nomem();
1591 if (!stralloc_0(&slop)) die_nomem();
1592
1593 out("334 "); /* "334 base64_challenge \r\n" */
1594 out(slop.s);
1595 out("\r\n");
1596 flush();
1597
1598 if (authgetl() < 0) return -1; /* got response */
1599 if ((r = b64decode((unsigned char *)authin.s,authin.len,&resp)) == 1) return err_authinput();
1600 if (r == -1 || !stralloc_0(&resp)) die_nomem();
1601
1602 i = str_rchr(resp.s,' ');
1603 s = resp.s + i;
1604 while (*s == ' ') ++s;
1605 resp.s[i] = 0;
1606 if (!stralloc_copys(&user,resp.s)) die_nomem(); /* userid */
1607 if (!stralloc_copys(&pass,s)) die_nomem(); /* digest */
1608
1609 if (!user.len || !pass.len) return err_authinput();
1610 return authenticate();
1611}
1612
1613struct authcmd {
1614 char *text;
1615 int (*fun)();
1616} authcmds[] = {
1617 { "login", auth_login }
1618, { "plain", auth_plain }
1619, { "cram-md5", auth_cram }
1620, { 0, err_noauth }
1622
1623void smtp_auth(char *arg)
1624{
1625 int i;
1626 char *cmd = arg;
1627
1628 /* prevent users to expose userid + password over unencrypted connection */
1629
1630 if ((starttls > 1) && !seentls) {
1631 if (!stralloc_append(&protocol,"A")) die_nomem();
1632 if (!stralloc_0(&protocol)) die_nomem();
1633 err_authsetup("Reject::TLS::Required",protocol.s,remoteip,remotehost,helohost.s);
1634 return;
1635 }
1636
1637 if ((starttls > 1) && !seenhelo) {
1638 if (!stralloc_append(&protocol,"A")) die_nomem();
1639 if (!stralloc_0(&protocol)) die_nomem();
1640 err_tlsreq("Reject::AUTH::Invalid",protocol.s,remoteip,remotehost,helohost.s);
1641 return;
1642 }
1643
1644 if (!smtpauth) { out("503 auth not available (#5.3.3)\r\n"); flush(); _exit(0); }
1645 if (smtpauth && !*childargs) {
1646 err_authsetup("Reject::AUTH::Setup",protocol.s,remoteip,remotehost,helohost.s);
1647 flush(); _exit(1);
1648 }
1649 if (seenauth) { err_authd(); return; }
1650 if (seenmail) { err_authmail(); return; }
1651
1652 if (!stralloc_copys(&user,"")) die_nomem();
1653 if (!stralloc_copys(&pass,"")) die_nomem();
1654 if (!stralloc_copys(&resp,"")) die_nomem();
1655 if (!stralloc_copys(&chal,"")) die_nomem(); /* only needed for CRAM-MD5 */
1656
1657 i = str_chr(cmd,' '); /* get AUTH type */
1658 arg = cmd + i;
1659 while (*arg == ' ') ++arg;
1660 cmd[i] = 0;
1661
1662 for (i = 0; authcmds[i].text; ++i)
1663 if (case_equals(authcmds[i].text,cmd)) break;
1664
1665 if (!authcmds[i].text) { /* invalid auth cmd */
1666 if (!stralloc_append(&protocol,"A")) die_nomem();
1667 if (!stralloc_0(&protocol)) die_nomem();
1668 err_authinvalid("Reject::AUTH::Method",protocol.s,remoteip,remotehost,helohost.s);
1669 return;
1670 }
1671
1673 if (!stralloc_0(&authmethod)) die_nomem();
1674
1675 switch (authcmds[i].fun(arg)) {
1676 case 0:
1677 seenauth = 1;
1678 relayclient = "";
1679 remoteinfo = user.s;
1681 out("235 ok, go ahead (#2.0.0)\r\n");
1682 break;
1683 case 1:
1684 if (!stralloc_append(&protocol,"A")) die_nomem();
1685 if (!stralloc_0(&protocol)) die_nomem();
1687 return;
1688 }
1689}
1690
1691/* this file is too long --------------------------------- GO ON */
1692
1694 { "rcpt", smtp_rcpt, 0 }
1695, { "mail", smtp_mail, 0 }
1696, { "data", smtp_data, flush }
1697, { "auth", smtp_auth, flush }
1698, { "quit", smtp_quit, flush }
1699, { "helo", smtp_helo, flush }
1700, { "ehlo", smtp_ehlo, flush }
1701, { "rset", smtp_rset, flush }
1702, { "help", smtp_help, flush }
1703, { "noop", err_noop, flush }
1704, { "vrfy", err_vrfy, flush }
1705, { "starttls", smtp_starttls, flush }
1706, { 0, err_unimpl, flush }
1707} ;
1708
1709int main(int argc,char * const *argv)
1710{
1711 childargs = argv + 1;
1712 sig_pipeignore();
1713 if (chdir(auto_qmail) == -1) die_control();
1714 setup();
1715 smtpdlog_init();
1716 if (ipme_init() != 1) die_ipme();
1717 smtp_greet("220 ");
1718 out(" ESMTP\r\n");
1719 flush();
1720 if (commands(&bi,(struct commands *)smtpcommands) == 0) die_read();
1721 die_nomem();
1722
1723 return 0;
1724}
char auto_qmail[]
int b64encode(stralloc *in, stralloc *out)
Definition: base64.c:88
int b64decode(const unsigned char *in, int l, stralloc *out)
Definition: base64.c:11
int main()
Definition: chkshsgr.c:6
void die_read()
Definition: columnt.c:16
int constmap_init(struct constmap *cm, char *s, int len, int flagcolon)
Definition: constmap.c:35
int control_readint(unsigned long *i, char *fn)
Definition: control.c:72
int control_readline(stralloc *sa, char *fn)
Definition: control.c:53
int control_rldef(stralloc *sa, char *fn, int flagme, char *def)
Definition: control.c:42
int control_readfile(stralloc *sa, char *fn, int flagme)
Definition: control.c:87
int control_init(void)
Definition: control.c:33
long datetime_sec
Definition: datetime.h:15
int stralloc_copys(stralloc *, char const *)
int dns_mxip(ipalloc *ia, stralloc *sa, unsigned long random)
Definition: dns.c:105
int dns_ip(ipalloc *ia, stralloc *sa)
Definition: dns.c:194
#define DNS_INIT
Definition: dns.h:12
stralloc out
Definition: dnscname.c:12
void _exit(int)
char qp[FMT_ULONG]
Definition: fastforward.c:53
struct cdb cdb
Definition: fastforward.c:119
uint32 dlen
Definition: fastforward.c:117
char buf[100+FMT_ULONG]
Definition: hier.c:11
int ipme_init(void)
Definition: ipme.c:61
int ipme_is6(struct ip6_address *)
Definition: ipme.c:38
int ipme_is4(struct ip4_address *)
Definition: ipme.c:26
stralloc text
Definition: maildirwatch.c:21
int mfrules(int, char *, char *, char *, char *)
Definition: mfrules.c:135
datetime_sec now()
Definition: now.c:5
int fd
int
Definition: qmail-mrtg.c:27
unsigned long size
Definition: qmail-qread.c:56
char * received
Definition: qmail-queue.c:69
unsigned long code
Definition: qmail-remote.c:603
void blast()
Definition: qmail-remote.c:385
stralloc pass
Definition: qmail-remote.c:676
stralloc slop
Definition: qmail-remote.c:679
stralloc chal
Definition: qmail-remote.c:678
int j
Definition: qmail-send.c:926
int bmfcheck()
Definition: qmail-smtpd.c:638
int authenticate(void)
Definition: qmail-smtpd.c:1483
int seentls
Definition: qmail-smtpd.c:258
stralloc tlsinfo
Definition: qmail-smtpd.c:166
char * dnemail
Definition: qmail-smtpd.c:266
stralloc bmf
Definition: qmail-smtpd.c:211
ssize_t saferead(int fd, char *buf, int len)
Definition: qmail-smtpd.c:72
int flagdnshelo
Definition: qmail-smtpd.c:170
int flagutf8
Definition: qmail-smtpd.c:160
char * qhpsi
Definition: qmail-smtpd.c:239
char * delivermailto
Definition: qmail-smtpd.c:270
stralloc rcptto
Definition: qmail-smtpd.c:533
char * base64
Definition: qmail-smtpd.c:240
int addrparse(char *arg)
Definition: qmail-smtpd.c:545
int modssl_info()
Definition: qmail-smtpd.c:481
int seenauth
Definition: qmail-smtpd.c:254
char * cipherused
Definition: qmail-smtpd.c:263
int flagerrcpts
Definition: qmail-smtpd.c:243
void dohelo(char *helo)
Definition: qmail-smtpd.c:176
char * local
Definition: qmail-smtpd.c:157
int localmf
Definition: qmail-smtpd.c:235
stralloc brt
Definition: qmail-smtpd.c:215
int flagnotorious
Definition: qmail-smtpd.c:244
buffer ba
Definition: qmail-smtpd.c:1461
int flagdnsmf
Definition: qmail-smtpd.c:541
stralloc rddr
Definition: qmail-smtpd.c:531
char * clientdn
Definition: qmail-smtpd.c:264
char authbuf[BUFSIZE_AUTH]
Definition: qmail-smtpd.c:1460
int maxrcptcount
Definition: qmail-smtpd.c:242
stralloc deliverto
Definition: qmail-smtpd.c:269
#define BASE64MESSAGE
Definition: qmail-smtpd.c:52
char * cipher
Definition: qmail-smtpd.c:261
void smtp_help()
Definition: qmail-smtpd.c:145
char * clientcn
Definition: qmail-smtpd.c:265
char * badmailcond
Definition: qmail-smtpd.c:173
int starttls
Definition: qmail-smtpd.c:257
char * fakehelo
Definition: qmail-smtpd.c:165
int mailfrom_size(char *arg)
Definition: qmail-smtpd.c:867
unsigned long databytes
Definition: qmail-smtpd.c:59
int flagmav
Definition: qmail-smtpd.c:234
stralloc helohost
Definition: qmail-smtpd.c:164
void setup()
Definition: qmail-smtpd.c:277
char ** childargs
Definition: qmail-smtpd.c:1459
void auth_info(char *method)
Definition: qmail-smtpd.c:469
int auth_login(char *arg)
Definition: qmail-smtpd.c:1524
int badhelook
Definition: qmail-smtpd.c:218
int flaglf
Definition: qmail-smtpd.c:161
stralloc mailto
Definition: qmail-smtpd.c:268
#define SMTP_TIMEOUT
Definition: qmail-smtpd.c:48
int addrallowed(char *arg)
Definition: qmail-smtpd.c:764
stralloc pgbind
Definition: qmail-smtpd.c:250
unsigned long timeout
Definition: qmail-smtpd.c:60
stralloc protocol
Definition: qmail-smtpd.c:163
char * relayclient
Definition: qmail-smtpd.c:159
char buflog[BUFSIZE_LOG]
Definition: qmail-smtpd.c:88
stralloc badmimetype
Definition: qmail-smtpd.c:1215
void smtp_ehlo(char *arg)
Definition: qmail-smtpd.c:940
void smtp_helo(char *arg)
Definition: qmail-smtpd.c:933
int auth_plain(char *arg)
Definition: qmail-smtpd.c:1549
stralloc user
Definition: qmail-smtpd.c:534
ipalloc ia
Definition: qmail-smtpd.c:95
int greylist
Definition: qmail-smtpd.c:249
int brtcheck()
Definition: qmail-smtpd.c:727
char * cipherperm
Definition: qmail-smtpd.c:262
char * remoteip
Definition: qmail-smtpd.c:154
struct qmail qqt
Definition: qmail-smtpd.c:1210
int tarpitcount
Definition: qmail-smtpd.c:246
int flagrcpt
Definition: qmail-smtpd.c:540
int bhelocheck(void)
Definition: qmail-smtpd.c:610
stralloc liphost
Definition: qmail-smtpd.c:208
char * tlsversion
Definition: qmail-smtpd.c:260
int flagbadhelo
Definition: qmail-smtpd.c:169
buffer bl
Definition: qmail-smtpd.c:89
char * ucspitls
Definition: qmail-smtpd.c:259
stralloc eddr
Definition: qmail-smtpd.c:530
stralloc mailfrom
Definition: qmail-smtpd.c:532
stralloc base64types
Definition: qmail-smtpd.c:1214
int postgrey_scanner()
Definition: qmail-smtpd.c:1032
stralloc fuser
Definition: qmail-smtpd.c:535
void acceptmessage(unsigned long qp)
Definition: qmail-smtpd.c:1364
stralloc mfparms
Definition: qmail-smtpd.c:536
int liphostok
Definition: qmail-smtpd.c:207
#define FDAUTH
Definition: qmail-smtpd.c:56
char * mfdnscheck
Definition: qmail-smtpd.c:238
unsigned int flagbase
Definition: qmail-smtpd.c:1220
struct constmap mapbrt
Definition: qmail-smtpd.c:216
void mailfrom_auth(char *arg, int len)
Definition: qmail-smtpd.c:878
struct constmap mapbhlo
Definition: qmail-smtpd.c:220
int spf_check(int flag6)
Definition: qmail-smtpd.c:814
void smtp_mail(char *arg)
Definition: qmail-smtpd.c:995
void smtp_rcpt(char *arg)
Definition: qmail-smtpd.c:1056
unsigned int nolines
Definition: qmail-smtpd.c:1218
char * localmfcheck
Definition: qmail-smtpd.c:236
char outbuf[BUFSIZE_LINE]
Definition: qmail-smtpd.c:85
char inbuf[BUFSIZE_MESS]
Definition: qmail-smtpd.c:82
char unique[FMT_ULONG+FMT_ULONG+3]
Definition: qmail-smtpd.c:1452
#define MIMETYPE_LEN
Definition: qmail-smtpd.c:50
void smtp_rset(void)
Definition: qmail-smtpd.c:962
#define AUTHSLEEP
Definition: qmail-smtpd.c:46
int rcptallowed()
Definition: qmail-smtpd.c:772
int seenhelo
Definition: qmail-smtpd.c:171
stralloc line
Definition: qmail-smtpd.c:1213
char * localport
Definition: qmail-smtpd.c:158
struct commands smtpcommands[]
Definition: qmail-smtpd.c:1693
buffer bi
Definition: qmail-smtpd.c:83
int seenmail
Definition: qmail-smtpd.c:538
#define FDOUT
Definition: qmail-smtpd.c:54
char * rblsmtpd
Definition: qmail-smtpd.c:272
stralloc sa
Definition: qmail-smtpd.c:94
stralloc authmethod
Definition: qmail-smtpd.c:255
int rcptcount
Definition: qmail-smtpd.c:543
void smtp_quit()
Definition: qmail-smtpd.c:149
ssize_t safewrite(int fd, char *buf, int len)
Definition: qmail-smtpd.c:64
unsigned int flagblank
Definition: qmail-smtpd.c:1221
char * badmimeinit
Definition: qmail-smtpd.c:227
char * auth
Definition: qmail-smtpd.c:252
void mailfrom_parms(char *arg)
Definition: qmail-smtpd.c:911
int tarpitdelay
Definition: qmail-smtpd.c:247
unsigned int flagb64
Definition: qmail-smtpd.c:1219
int bmfok
Definition: qmail-smtpd.c:210
char * badloaderinit
Definition: qmail-smtpd.c:231
void smtp_greet(char *code)
Definition: qmail-smtpd.c:140
int localaddr(char *mf)
Definition: qmail-smtpd.c:785
int flagaddr
Definition: qmail-smtpd.c:539
char * remotehost
Definition: qmail-smtpd.c:155
struct constmap mapbmf
Definition: qmail-smtpd.c:212
stralloc badloadertype
Definition: qmail-smtpd.c:1216
char accept_buf[FMT_ULONG]
Definition: qmail-smtpd.c:1362
#define FDLOG
Definition: qmail-smtpd.c:55
#define FDIN
Definition: qmail-smtpd.c:53
buffer bo
Definition: qmail-smtpd.c:86
struct authcmd authcmds[]
void flush()
Definition: qmail-smtpd.c:91
char * helocheck
Definition: qmail-smtpd.c:168
stralloc badhelo
Definition: qmail-smtpd.c:219
#define LOADER_LEN
Definition: qmail-smtpd.c:51
stralloc addr
Definition: qmail-smtpd.c:529
int auth_cram()
Definition: qmail-smtpd.c:1574
#define PORT_SMTPS
Definition: qmail-smtpd.c:47
unsigned long bytestooverflow
Definition: qmail-smtpd.c:1211
#define MAXHOPS
Definition: qmail-smtpd.c:58
char * remoteinfo
Definition: qmail-smtpd.c:156
int flagloadertype
Definition: qmail-smtpd.c:230
void smtp_starttls()
Definition: qmail-smtpd.c:971
int authgetl(void)
Definition: qmail-smtpd.c:1463
int brtok
Definition: qmail-smtpd.c:214
int flagspf
Definition: qmail-smtpd.c:274
int smtpauth
Definition: qmail-smtpd.c:253
int flagmimetype
Definition: qmail-smtpd.c:226
int dnsq(char *arg, char type)
Definition: qmail-smtpd.c:101
char * badhelocond
Definition: qmail-smtpd.c:174
int flagsize
Definition: qmail-smtpd.c:542
void smtp_data()
Definition: qmail-smtpd.c:1377
void smtp_auth(char *arg)
Definition: qmail-smtpd.c:1623
stralloc rblinfo
Definition: qmail-smtpd.c:271
#define BUFSIZE_LOG
Definition: qmail.h:11
#define BUFSIZE_MESS
Definition: qmail.h:7
#define BUFSIZE_LINE
Definition: qmail.h:8
void qmail_from(struct qmail *, char *)
Definition: qmail.c:73
void qmail_put(struct qmail *, char *, int)
Definition: qmail.c:63
char * qmail_close(struct qmail *)
Definition: qmail.c:90
unsigned long qmail_qp(struct qmail *)
Definition: qmail.c:53
#define BUFSIZE_AUTH
Definition: qmail.h:9
int qmail_open(struct qmail *)
Definition: qmail.c:21
void qmail_fail(struct qmail *)
Definition: qmail.c:58
int rcpthosts(char *, int)
Definition: rcpthosts.c:35
int rcpthosts_init(void)
Definition: rcpthosts.c:22
void spfheader(struct qmail *, char *, char *, char *, char *, char *)
Definition: received.c:100
int recipients(char *, int)
Definition: recipients.c:238
int recipients_init(void)
Definition: recipients.c:48
uint32_t k[64]
Definition: sha256.c:26
void err_wantmail(void)
Definition: smtpdlog.c:159
void err_authreq(char *, char *, char *, char *, char *)
Definition: smtpdlog.c:128
void err_wantrcpt(void)
Definition: smtpdlog.c:209
void err_mav(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:161
void err_brt(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:225
void err_syntax(void)
Definition: smtpdlog.c:73
void err_rcpts(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:232
int err_child(void)
Definition: smtpdlog.c:78
void postgrey(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:211
int err_fork(void)
Definition: smtpdlog.c:79
void smtpdlog_init(void)
Definition: smtpdlog.c:28
void err_notorious(void)
Definition: smtpdlog.c:256
void die_nomem(void)
Definition: qreceipt.c:23
int err_forkgl(void)
Definition: smtpdlog.c:84
void err_unimpl(void)
Definition: smtpdlog.c:72
int err_noauth(void)
Definition: smtpdlog.c:151
void err_authinvalid(char *, char *, char *, char *, char *)
Definition: smtpdlog.c:146
void err_recipient(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:237
int err_authabort(void)
Definition: smtpdlog.c:136
int err_authinput(void)
Definition: smtpdlog.c:141
void die_recipients(void)
Definition: smtpdlog.c:70
void err_qqt(void)
Definition: smtpdlog.c:76
void err_authfail(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:124
int err_starttls(void)
Definition: smtpdlog.c:88
void err_vrfy(void)
Definition: smtpdlog.c:75
void err_size(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:262
int err_pipe(void)
Definition: smtpdlog.c:80
void err_authmail(void)
Definition: smtpdlog.c:120
void die_control(void)
Definition: qmail-qmqpc.c:31
void err_bmf(char *, char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:168
void smtp_loga(char *, char *, char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:51
void err_authsetup(char *, char *, char *, char *, char *)
Definition: smtpdlog.c:111
int err_write(void)
Definition: smtpdlog.c:81
int err_postgl(void)
Definition: smtpdlog.c:83
void err_mfdns(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:175
void err_helo(char *, char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:101
void err_spf(char *, char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:185
void die_ipme(void)
Definition: smtpdlog.c:68
void smtp_logg(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:55
void err_tlsreq(char *, char *, char *, char *, char *)
Definition: smtpdlog.c:93
void straynewline(void)
Definition: smtpdlog.c:250
void err_data(char *, char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:267
void err_noop(void)
Definition: smtpdlog.c:74
void err_authd(void)
Definition: smtpdlog.c:116
void die_alarm(void)
Definition: smtpdlog.c:65
void smtp_logr(char *, char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:61
void die_tls()
Definition: smtpdlog.c:69
void err_nogateway(char *, char *, char *, char *, char *, char *, char *)
Definition: smtpdlog.c:218
#define SPF_LOOP
Definition: spf.h:13
stralloc spfexpmsg
Definition: spf.c:30
stralloc expdomain
Definition: spf.c:31
#define SPF_ME
Definition: spf.h:11
#define SPF_ERROR
Definition: spf.h:16
#define SPF_NEUTRAL
Definition: spf.h:25
#define SPF_OK
Definition: spf.h:22
stralloc spfexplain
Definition: spf.c:23
#define SPF_FAIL
Definition: spf.h:27
#define SPF_DEFEXP
Definition: spf.h:34
#define SPF_SOFTFAIL
Definition: spf.h:26
stralloc spfinfo
Definition: spf.c:17
int spf_parse(stralloc *, char *, char *)
spf_parse parses the substructure of the SPF record and calls spf_macros
Definition: spf.c:461
#define SPF_EXHAUST
Definition: spf.h:12
#define SPF_NOMEM
Definition: spf.h:17
#define SPF_SYNTAX
Definition: spf.h:18
stralloc spflocalrules
Definition: spf.c:22
#define SPF_UNKNOWN
Definition: spf.h:24
int spf_query(const char *, const char *, const char *, const char *, const int)
spf_query prepares the SPF TXT record query
Definition: spf.c:58
int flagip6
Definition: spf.c:32
#define SPF_NONE
Definition: spf.h:23
char * text
Definition: qmail-smtpd.c:1614
int(* fun)()
Definition: qmail-smtpd.c:1615
Definition: qmail.h:14
int starttls_info(void)
Definition: tls_start.c:34
int starttls_init(void)
Definition: tls_start.c:14
void write()
int wildmat(char *, char *)
Definition: wildmat.c:102