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