s/qmail 4.3.25a
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-remote.c
Go to the documentation of this file.
1#ifdef IDN2
2#include <idn2.h>
3#endif
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <sys/socket.h>
7#include <netinet/in.h>
8#include <arpa/inet.h>
9#include <unistd.h>
10#include "sig.h"
11#include "stralloc.h"
12#include "buffer.h"
13#include "scan.h"
14#include "case.h"
15#include "byte.h"
16#include "qmail.h"
17#include "auto_qmail.h"
18#include "control.h"
19#include "dns.h"
20#include "alloc.h"
21#include "genalloc.h"
22#include "quote.h"
23#include "fmt.h"
24#include "ip.h"
25#include "ipalloc.h"
26#include "ipme.h"
27#include "str.h"
28#include "now.h"
29#include "exit.h"
30#include "constmap.h"
31#include "tcpto.h"
32#include "timeout.h"
33#include "timeoutconn.h"
34#include "base64.h"
35#include "socket_if.h"
36#include "ucspissl.h"
37#include "tls_remote.h"
38#include "tls_errors.h"
39#include "tls_timeoutio.h"
40#include "uint_t.h"
41#include "hmac_md5.h"
42
43#define WHO "qmail-remote"
44
45#define QMTP_MAX 200000000 /* 190 MB for QMTP */
46#define HUGESMTPTEXT 1000 /* RFC 5322; was 5000 chars/line */
47#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */
48#define PORT_QMTP 209
49#define PORT_SMTPS 465
50#define PORT_SUBMISSION 587
51#define PORT_QMTPS 6209
52#define VERIFYDEPTH 1
53#define TCP_TIMEOUT 60
54#define SMTP_TIMEOUT 1200
55
56unsigned long port = PORT_SMTP;
57
60int flagauth = 0; /* 1 = login; 2 = plain; 3 = crammd5 */
61int flagsmtps = 0; /* RFC 8314 - 'implicit TLS' */
62int flagtlsdomain = 0; /* 0 = no; 1 = yes; 2 = cert */
63int flagtls = 0; /* flagtls: XYZ
64 (mode) Z: -2 = rejected; -1 = not; 0 = no, default; Z > 0 see tls_remote.c
65 (prot) Y: 0 = StartTLS; 1 = SMTPS; 2 = QMTPS
66 (active) X: 1 = running TLS connection (after DNS lookup)
67 (done) Z: 1: CA chain; 2: Cert wildname; 3: Cert exactname;
68 4: Cert fingerprint; 5: TLSA record */
69int flagverify = 0; /* 1 = verify Cert against CA; 2 = verify against Dir; 3 = triggerd by TLSA;
70 -2 = Cert pinning; -1 = no TLSA validation */
71int flagutf8 = 0;
72
73GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
74GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
75static stralloc sauninit = {0};
76
77stralloc helohost = {0};
78stralloc eaihost = {0};
79stralloc host = {0};
80stralloc idnhost = {0};
81stralloc sender = {0};
82stralloc canonhost = {0};
83stralloc remotehost = {0};
84stralloc canonbox = {0};
85stralloc senddomain = {0};
86stralloc sendip = {0};
87
88stralloc domainips = {0};
90char ip4[4];
91char ip6[16];
92uint32 ifidx = 0;
93char *authsender = 0;
94
95stralloc smtproutes = {0};
97stralloc qmtproutes = {0};
99
100saa reciplist = {0};
101stralloc recip = {0};
102
103char msgsize[FMT_ULONG];
104unsigned long msize = 0;
106
107SSL *ssl;
108SSL_CTX *ctx;
109
110char bufsmall[BUFFER_SMALL];
111buffer bs = BUFFER_INIT(buffer_unixwrite,1,bufsmall,sizeof(bufsmall));
112
113void out(char *s)
114{
115 if (buffer_puts(&bs,s) == -1)
116 _exit(0);
117 }
118void zero()
119{
120 if (buffer_put(&bs,"\0",1) == -1)
121 _exit(0);
122}
123void zerodie()
124{
125 zero();
126 buffer_flush(&bs);
127 if (ssl) tls_exit(ssl);
128 _exit(0);
129}
130
131void outsafe(stralloc *sa)
132{
133 int i;
134 char ch;
135 for (i = 0; i < sa->len; ++i) {
136 ch = sa->s[i];
137 if (ch == 0) continue;
138 if (ch < 33) ch = '?';
139 if (ch > 126) ch = '?';
140 if (buffer_put(&bs,&ch,1) == -1) _exit(0);
141 }
142}
143
145{
146 out("ZInvalid ipaddr in control/domainips (#4.3.0)\n");
147 zerodie();
148}
150{
151 out("ZOut of memory. (#4.3.0)\n");
152 zerodie();
153}
155{
156 out("ZSystem resources temporarily unavailable. (#4.3.0)\n");
157 zerodie();
158}
160{
161 out("ZCan't bind to local ip address: ");
162 outsafe(&sendip);
163 out(". (#4.3.0)\n");
164 zerodie();
165}
167{
168 out("ZSorry, I wasn't able to establish a SMTP connection: ");
170 out(". (#4.3.0)\n");
171 zerodie();
172}
174{
175 out("ZSorry, I wasn't able to establish a QMTP connection: ");
177 out(". (#4.3.1)\n");
178 zerodie();
179}
181{
182 out("ZUnable to read message. (#4.3.0)\n");
183 zerodie();
184}
186{
187 out("ZCNAME lookup failed temporarily for: ");
189 out(". (#4.4.3)\n");
190 zerodie();
191}
192void temp_dns()
193{
194 out("ZSorry, I couldn't find any host named: ");
195 outsafe(&host);
196 out(". (#4.1.2)\n");
197 zerodie();
198}
200{
201 out("ZSorry, I couldn't find a mail exchanger or IP address for: ");
202 outsafe(&host);
203 out(". Will try again. (#4.1.2)\n");
204 zerodie();
205}
207{
208 out("ZUnable to switch to home directory. (#4.3.0)\n");
209 zerodie();
210}
212{
213 out("ZUnable to read control files. (#4.3.0)\n");
214 zerodie();
215}
217{
218 out("DSMTP cannot transfer messages with partial final line. (#5.6.2)\n");
219 zerodie();
220}
222{
223 out("ZRecipient did not talk proper QMTP. (#4.3.0)\n");
224 zerodie();
225}
227{
228 out("Dqmail-remote was invoked improperly. (#5.3.5)\n");
229 zerodie();
230}
231void perm_dns()
232{
233 out("DSorry, I couldn't find any host named: ");
234 outsafe(&host);
235 out(". (#5.1.2)\n");
236 zerodie();
237}
239{
240 out("DSorry, I couldn't find a mail exchanger or IP address for: ");
241 outsafe(&host);
242 out(". (#5.4.4)\n");
243 zerodie();
244}
246{
247 out("DSorry, I could no deliver mail to MX: ");
248 outsafe(&host);
249 out(" ; domain does not accept mails. (#5.1.10)\n");
250 zerodie();
251}
253{
254 out("DSorry. Although I'm listed as a best-preference MX or A for that host,\n\
255it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
256 zerodie();
257}
259{
260 out("ZSorry, no supported AUTH method found, trying later again. (#4.7.1)\n");
261 zerodie();
262}
263
265{
266 char ipaddr[IPFMT];
267 int len = 0;
268
269 switch (partner.af) {
270 case AF_INET:
271 len = ip4_fmt(ipaddr,(char *)&partner.addr.ip4.d); break;
272 case AF_INET6:
273 len = ip6_fmt(ipaddr,(char *)&partner.addr.ip6.d); break;
274 }
275 if (buffer_put(&bs,ipaddr,len) == -1) _exit(0);
276}
277
279
280void dropped()
281{
282 out("ZConnected to ");
283 outhost();
284 out(" but connection died. ");
285 if (flagcritical) out("Possible duplicate! ");
286 out("(#4.4.2)\n");
287 zerodie();
288}
289
291unsigned long timeout = SMTP_TIMEOUT;
293
294ssize_t saferead(int fd,char *buf,size_t len)
295{
296 int r;
297 if (ssl) {
299 if (r < 0) temp_tlserr();
300 } else {
301 r = timeoutread(timeout,smtpfd,buf,len);
302 }
303 if (r <= 0) dropped();
304 return r;
305}
306
307ssize_t safewrite(int fd,char *buf,size_t len)
308{
309 int r;
310 if (ssl) {
312 if (r < 0) temp_tlserr();
313 } else {
314 r = timeoutwrite(timeout,smtpfd,buf,len);
315 }
316 if (r <= 0) dropped();
317 return r;
318}
319
320char inbuf[BUFFER_MTUSIZE];
321buffer bi = BUFFER_INIT(buffer_unixread,0,inbuf,sizeof(inbuf));
322char outbuf[BUFFER_MTUSIZE];
323buffer bo = BUFFER_INIT(safewrite,-1,outbuf,sizeof(outbuf));
324char frombuf[BUFFER_SMALL];
325buffer bf = BUFFER_INIT(saferead,-1,frombuf,sizeof(frombuf));
326
327static stralloc smtptext = {0};
328static stralloc header = {0};
329
330void get(char *ch)
331{
332 buffer_get(&bf,ch,1);
333 if (*ch != '\r')
334 if (smtptext.len < HUGESMTPTEXT)
335 if (!stralloc_append(&smtptext,ch)) temp_nomem();
336}
337
338unsigned long smtpcode()
339{
340 char ch;
341 long code;
342
343 if (!stralloc_copys(&smtptext,"")) temp_nomem();
344
345 get(&ch); code = ch - '0';
346 get(&ch); code = code * 10 + (ch - '0');
347 get(&ch); code = code * 10 + (ch - '0');
348 for (;;) {
349 get(&ch);
350 if (ch != '-') break;
351 while (ch != '\n') get(&ch);
352 get(&ch);
353 get(&ch);
354 get(&ch);
355 }
356 while (ch != '\n') get(&ch);
357
358 return code;
359}
360
362{
363 int i;
364 if (smtptext.s) if (smtptext.len) {
365 out("Remote host said: ");
366 for (i = 0; i < smtptext.len; ++i)
367 if (!smtptext.s[i]) smtptext.s[i] = '?';
368 if (buffer_put(&bs,smtptext.s,smtptext.len) == -1) _exit(0);
369 smtptext.len = 0;
370 }
371}
372
373void quit(char *prepend,char *append)
374{
375 buffer_putsflush(&bo,"QUIT\r\n");
376 /* waiting for remote side is just too ridiculous */
377 out(prepend);
378 outhost();
379 out(append);
380 out(".\n");
381 outsmtptext();
382 zerodie();
383}
384
385void blast()
386{
387 int r;
388 int in;
389 int out;
390 int eom = 1; // end-of-message <CRLF>.<CRLF>
391 char tmpbuf[BUFSIZE_MESS]; // intermediate write buffer
392
393// New blast code; inspired by Bruce Guenter's 'fastremote patch' (2005)
394
395 while ((r = buffer_get(&bi,inbuf,sizeof(inbuf)))) { // read into buffer
396 if (r == -1) temp_read();
397
398 for (in = out = 0; in < r;) {
399 if (eom && inbuf[in] == '.') {
400 tmpbuf[out++] = '.';
401 tmpbuf[out++] = inbuf[in++];
402 }
403 eom = 0;
404 while (in < r) {
405 if (inbuf[in] == '\r') { in++; continue; } // CR is DKIM input
406 if (inbuf[in] == '\n') {
407 eom = 1;
408 ++in;
409 tmpbuf[out++] = '\r';
410 tmpbuf[out++] = '\n';
411 break;
412 }
413 tmpbuf[out++] = inbuf[in++];
414 }
415 }
416 if (out) buffer_put(&bo,tmpbuf,out);
417 }
418
419 if (!eom) perm_partialline();
420 flagcritical = 1;
421 buffer_put(&bo,".\r\n",3); // LF seen; finish with .<CRLF>
422 buffer_flush(&bo);
423}
424
425/* this file is too long -------------------------------------- client TLS */
426
427stralloc cafile = {0};
428stralloc cadir = {0};
429stralloc certfile = {0};
430stralloc keyfile = {0};
431stralloc keypwd = {0};
432stralloc ciphers = {0};
433
434char *tlsdestinfo = 0;
436
437stralloc domaincerts = {0};
439stralloc tlsdestinations = {0};
441unsigned long verifydepth = VERIFYDEPTH;
442
444{
445 ctx = ssl_client();
446 ssl_errstr();
447 if (!ctx) temp_tlsctx();
448
449/* Fetch CA infos for dest */
450
451 if (flagverify > 0)
452 if (cafile.len || cadir.len)
453 if (!ssl_ca(ctx,cafile.s,cadir.s,(int) verifydepth)) temp_tlsca();
454
455 if (ciphers.len)
457
458/* Prepare for Certificate Request */
459
460 if (flagtlsdomain == 2)
461 switch (tls_certkey(ctx,certfile.s,keyfile.s,keypwd.s)) {
462 case 0: break;
463 case -1: temp_tlscert();
464 case -2: temp_tlskey();
465 case -3: temp_tlschk();
466 }
467
468/* Set SSL Context */
469
471 if (!ssl) temp_tlsctx();
472
473/* Setup SSL FDs */
474
475 if (!tls_conn(ssl,smtpfd)) temp_tlscon();
476
477/* Go on in none-blocking mode */
478
480 temp_tlserr();
481}
482
484{
485 int i = 0;
486
487 do {
488 if (case_startb(smtptext.s + i + 4,8,"STARTTLS")) return 1;
489 if (*(smtptext.s + i + 3) == ' ') return 0;
490 } while ((i += str_chr(smtptext.s + i,'\n') + 1) && // next line
491 (i < smtptext.len - 12));
492
493 return 0;
494}
495
497{
498 X509 *cert;
499 STACK_OF(X509) *certs;
500 int ncerts = 0;
501
502 cert = SSL_get_peer_certificate(ssl);
503 if (!cert) { flagtls = 100; return; }
504
505 if ((certs = SSL_get_peer_cert_chain(ssl)) == NULL) {
506 certs = sk_X509_new_null();
507 ncerts++;
508 sk_X509_push(certs,cert);
509 }
510
511 if (flagverify == -2) { // fingerprinting is silent
512 if (cafile.len) case_lowerb(cafile.s,cafile.len);
513 switch (tls_fingerprint(cert,cafile.s + 1,cafile.len - 2)) {
514 case -1: temp_tlspeercert();
515 case -2: temp_tlsdigest();
516 case -3: temp_invaliddigest();
517 case 0: temp_tlscertfp();
518 case 1: flagtls = 104; break;
519 }
520 }
521
522 if (flagverify >= 0) { // TLSA is default
523 switch (tlsa_check(certs,remotehost,port)) {
524 case -4: temp_tlsamissing(); break; /* FIXME */
525 case -3: temp_tlsainvalid(); break;
526 case -2: break; // unsupported type; may happen
527 case -1: break; // weird TLSA record
528 case 0: break; // no TLSA record given
529 case 1: case 2: flagtls = 107; flagverify = 3; break; // full certchain available (-PKIX)
530 case 3: flagtls = 106; flagverify = 0; break; // TA-CA; verify wont work
531 case 4: flagtls = 105; flagverify = 0; break; // Endpoint only
532 }
533 }
534
535 if (flagverify > 0) {
537 case -1: temp_tlspeercert();
538 case -2: temp_tlspeerverify();
539 case -3: temp_tlspeervalid();
540 case 1: flagtls = 101; break;
541 case 2: flagtls = 102; break;
542 case 3: flagtls = 103; break;
543 }
544 }
545
546 if (flagtls < 100) flagtls = 100;
547
548 if (ncerts) sk_X509_free(certs);
549 X509_free(cert);
550
551 return;
552}
553
554/* this file is too long --------------------------------------- smtp UTF8 */
555
556int utf8string(char *ch,int len)
557{
558 int i = 0;
559 while (i < len)
560 if ((unsigned char) ch[i++] > 127) return 1;
561 return 0;
562}
563
565{
566 int r;
567 int i;
568 int received = 0;
569 char ch;
570 stralloc receivedline = {0};
571
572/* we consider only our own last written header */
573
574 for (;;) {
575 r = buffer_get(&bi,&ch,1);
576 if (r == 0) break;
577 if (r == -1) temp_read();
578 if (ch == '\r') continue; // DKIM
579
580 if (ch == '\n') {
581 if (!stralloc_append(&header,"\r")) temp_nomem(); /* received.c does not add '\r' */
582 if (!stralloc_append(&header,"\n")) temp_nomem();
583 if (case_starts(receivedline.s,"Date:")) return 0; /* header to quit asap */
584 if (case_starts(receivedline.s,"Received: from")) received++; /* found Received header */
585 if (received) {
586 if (case_starts(receivedline.s," by ")) {
587 for (i = 6; i < receivedline.len - 6; ++i)
588 if (*(receivedline.s + i) == ' ')
589 if (case_starts(receivedline.s + i + 1,"with UTF8")) return 1;
590 return 0;
591 }
592 }
593 if (!stralloc_copys(&receivedline,"")) temp_nomem();
594 } else {
595 if (!stralloc_append(&header,&ch)) temp_nomem();
596 if (!stralloc_catb(&receivedline,&ch,1)) temp_nomem();
597 }
598 }
599 return 0;
600}
601
602/* this file is too long -------------------------------------- smtp client */
603
604unsigned long code;
605int flagsize = 0;
606
608{
609 int i = 0;
610
611 do {
612 if (case_startb(smtptext.s + i + 4,4,"SIZE")) return 1;
613 if (*(smtptext.s + i + 3) == ' ') return 0;
614 } while ((i += str_chr(smtptext.s + i,'\n') + 1) && // next line
615 (i < smtptext.len - 8));
616
617 return 0;
618}
619
621{
622 buffer_puts(&bo,"EHLO ");
623 buffer_put(&bo,helohost.s,helohost.len);
624 buffer_puts(&bo,"\r\n");
625 buffer_flush(&bo);
626
627 if (smtpcode() != 250) {
628 buffer_puts(&bo,"HELO ");
629 buffer_put(&bo,helohost.s,helohost.len);
630 buffer_puts(&bo,"\r\n");
631 buffer_flush(&bo);
632
633 code = smtpcode();
634 authsender = 0;
635 if (code >= 500) quit("DConnected to "," but my name was rejected");
636 if (code != 250) quit("ZConnected to "," but my name was rejected");
637 }
639}
640
642{
643 buffer_puts(&bo,"STARTTLS\r\n");
644 buffer_flush(&bo);
645
646 if (smtpcode() == 220) {
647 tls_init();
650 }
651 else {
652 flagtls = -2;
653 quit("ZConnected to "," but STARTTLS was rejected");
654 }
655}
656
658{
659 buffer_puts(&bo,"MAIL FROM:<");
660 buffer_put(&bo,sender.s,sender.len);
661 buffer_puts(&bo,">");
662 if (flagutf8 || utf8received())
663 buffer_puts(&bo," SMTPUTF8");
664 if (flagsize && msize) {
665 buffer_puts(&bo," SIZE=");
666 buffer_puts(&bo,msgsize);
667 }
668 buffer_puts(&bo,"\r\n");
669 buffer_flush(&bo);
670}
671
672/* this file is too long -------------------------------------- client auth */
673
674stralloc authsenders = {0};
676
677stralloc user = {0};
678stralloc pass = {0};
679stralloc auth = {0};
680stralloc chal = {0};
681stralloc slop = {0};
682stralloc plain = {0};
683stralloc xuser = {0};
684
685static const char hextab[] = "0123456789abcdef";
686
687int xtext(stralloc *sa,char *s,int len)
688{
689 int i;
690 unsigned char c;
691 char xch[2];
692
693 if (!stralloc_copys(sa,"")) temp_nomem();
694
695 for (i = 0; i < len; i++) {
696 c = s[i];
697 if (c < 33 || c > 126 || c == '=' || c == '+') {
698 xch[0] = hextab[(c >> 4) & 0x0f];
699 xch[1] = hextab[c & 0x0f];
700 if (!stralloc_catb(sa,xch,2)) temp_nomem();
701 } else
702 if (!stralloc_catb(sa,s + i,1)) temp_nomem();
703 }
704
705 return sa->len;
706}
707
709{
710 if (!xtext(&xuser,user.s,user.len)) temp_nomem();
711 buffer_puts(&bo,"MAIL FROM:<");
712 buffer_put(&bo,sender.s,sender.len);
713 buffer_puts(&bo,"> AUTH=");
714 buffer_put(&bo,xuser.s,xuser.len);
715 if (flagutf8 || utf8received())
716 buffer_puts(&bo," SMTPUTF8");
717 if (flagsize && msize) {
718 buffer_puts(&bo," SIZE=");
719 buffer_puts(&bo,msgsize);
720 }
721 buffer_puts(&bo,"\r\n");
722 buffer_flush(&bo);
723}
724
726{
727 buffer_puts(&bo,"AUTH PLAIN\r\n");
728 buffer_flush(&bo);
729
730 if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH PLAIN)");
731
732 if (!stralloc_cats(&plain,"")) temp_nomem(); /* RFC 4616 section 2 */
733 if (!stralloc_0(&plain)) temp_nomem();
734 if (!stralloc_cat(&plain,&user)) temp_nomem(); /* user-id */
735 if (!stralloc_0(&plain)) temp_nomem();
736 if (!stralloc_cat(&plain,&pass)) temp_nomem(); /* password */
737 if (b64encode(&plain,&auth)) quit("ZConnected to "," but unable to base64encode (plain)");
738 buffer_put(&bo,auth.s,auth.len);
739 buffer_puts(&bo,"\r\n");
740 buffer_flush(&bo);
741
742 switch (smtpcode()) {
743 case 235: mailfrom_xtext(); break;
744 case 432: quit("DConnected to "," but password expired");
745 case 534: quit("ZConnected to "," but authentication mechamism too weak (plain)");
746 default: quit("ZConnected to "," but authentication was rejected (plain)");
747 }
748 return 0;
749}
750
752{
753 buffer_puts(&bo,"AUTH LOGIN\r\n");
754 buffer_flush(&bo);
755
756 if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)");
757 if (!stralloc_copys(&auth,"")) temp_nomem();
758 if (b64encode(&user,&auth)) quit("ZConnected to "," but unable to base64encode user");
759
760 buffer_put(&bo,auth.s,auth.len);
761 buffer_puts(&bo,"\r\n");
762 buffer_flush(&bo);
763
764 if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username)");
765
766 if (!stralloc_copys(&auth,"")) temp_nomem();
767 if (b64encode(&pass,&auth)) quit("ZConnected to "," but unable to base64encode pass");
768 buffer_put(&bo,auth.s,auth.len);
769 buffer_puts(&bo,"\r\n");
770 buffer_flush(&bo);
771
772 switch (smtpcode()) {
773 case 235: mailfrom_xtext(); break;
774 case 432: quit("DConnected to "," but password expired");
775 case 534: quit("ZConnected to "," but authentication mechanism is too weak (login)");
776 default: quit("ZConnected to "," but authentication was rejected (login)");
777 }
778 return 0;
779}
780
782{
783 int j;
784 char digest[16]; /* signed is ok */
785 char digascii[33];
786
787 buffer_puts(&bo,"AUTH CRAM-MD5\r\n");
788 buffer_flush(&bo);
789
790 if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH CRAM-MD5)");
791 if (str_chr(smtptext.s + 4,' ')) { /* Challenge */
792 if (!stralloc_copys(&slop,"")) temp_nomem();
793 if (!stralloc_copyb(&slop,smtptext.s + 4,smtptext.len - 5)) temp_nomem();
794 if (b64decode((unsigned char *) slop.s,slop.len,&chal))
795 quit("ZConnected to "," but unable to base64decode challenge");
796 }
797
798 hmac_md5(chal.s,chal.len,pass.s,pass.len,digest);
799
800 for (j = 0; j < 16; j++) { /* HEX => ASCII */
801 digascii[2 * j] = hextab[(unsigned char) digest[j] >> 4];
802 digascii[2 * j + 1] = hextab[(unsigned char) digest[j] & 0x0f];
803 }
804 digascii[32] = 0;
805
806 if (!stralloc_copys(&slop,"")) temp_nomem();
807 if (!stralloc_cat(&slop,&user)) temp_nomem(); /* user-id */
808 if (!stralloc_cats(&slop," ")) temp_nomem();
809 if (!stralloc_catb(&slop,digascii,32)) temp_nomem(); /* digest */
810
811 if (!stralloc_copys(&auth,"")) temp_nomem();
812 if (b64encode(&slop,&auth)) quit("ZConnected to "," but unable to base64encode username+digest");
813
814 buffer_put(&bo,auth.s,auth.len);
815 buffer_puts(&bo,"\r\n");
816 buffer_flush(&bo);
817
818 switch (smtpcode()) {
819 case 235: mailfrom_xtext(); break;
820 case 432: quit("DConnected to "," but password expired");
821 case 534: quit("ZConnected to "," but authentication mechamism too weak (cram)");
822 default: quit("ZConnected to "," but authentication was rejected (cram)");
823 }
824 return 0;
825}
826
828{
829 int i = 0;
830
831 do {
832 if (case_startb(smtptext.s + i + 4,4,"AUTH"))
833 for (i = 4; i < smtptext.len - 5; ++i) {
834 if (case_startb(smtptext.s + i,4,"CRAM"))
835 if (mailfrom_cram() >= 0) return;
836 if (case_startb(smtptext.s + i,5,"LOGIN"))
837 if (mailfrom_login() >= 0) return;
838 if (case_startb(smtptext.s + i,5,"PLAIN"))
839 if (mailfrom_plain() >= 0) return;
840 }
841 } while ((i += str_chr(smtptext.s + i,'\n') + 1) &&
842 (i < smtptext.len - 12));
843
844 err_authprot();
845 mailfrom();
846}
847
848/* this file is too long ------------------------------------------- GO ON */
849
850void smtp()
851{
852 int flagbother;
853 int i;
854
855 if (flagtls > 10 && flagtls < 20) { /* SMTPS */
856 tls_init();
857 tls_peercheck();
858 }
859
860 code = smtpcode();
861 if (code >= 500) quit("DConnected to "," but sender was rejected");
862 if (code == 421 || code == 450) quit("ZConnected to "," but probably greylisted"); /* RFC 6647 */
863 if (code >= 400) quit("ZConnected to "," but sender was rejected");
864 if (code != 220) quit("ZConnected to "," but greeting failed");
865
867
868 if (flagtls > 0 && flagtls < 10) { /* STARTTLS */
869 if (ehlo_starttls())
871 else if (flagtls > 3 && flagtls != 9) {
872 if (!stralloc_0(&host)) temp_nomem();
873 temp_tlshost();
874 }
875 }
876 if (user.len && pass.len) /* AUTH */
877 ehlo_auth();
878 else
879 mailfrom(); /* Mail From */
880
881 code = smtpcode();
882 if (code >= 500) quit("DConnected to "," but sender was rejected");
883 if (code >= 400) quit("ZConnected to "," but sender was probably greylisted");
884
885 flagbother = 0; /* Rcpt To */
886 for (i = 0; i < reciplist.len; ++i) {
887 buffer_puts(&bo,"RCPT TO:<");
888 buffer_put(&bo,reciplist.sa[i].s,reciplist.sa[i].len);
889 buffer_puts(&bo,">\r\n");
890 buffer_flush(&bo);
891
892 code = smtpcode(); /* Data */
893 if (flagsize) {
894 if (code == 552) quit("DConnected to "," but message size is too large");
895 if (code == 452) quit("ZConnected to "," however insufficient storage space available");
896 }
897 if (code == 421 || code == 450) { // Postfix merde ;-)
898 out("s"); outhost(); out(" sender is greylisting.\n");
899 outsmtptext(); zero();
900 } else if (code >= 500) {
901 out("h"); outhost(); out(" does not like recipient.\n");
902 outsmtptext(); zero();
903 } else if (code >= 400) {
904 out("s"); outhost(); out(" does not like recipient.\n");
905 outsmtptext(); zero();
906 } else {
907 out("r"); zero();
908 flagbother = 1;
909 }
910 }
911 if (!flagbother) quit("DGiving up on ","");
912
913 buffer_putsflush(&bo,"DATA\r\n");
914
915 code = smtpcode();
916 if (code >= 500) quit("D"," failed on DATA command");
917 if (code >= 400) quit("Z"," failed on DATA command");
918
919 buffer_putflush(&bo,header.s,header.len);
920
921 blast();
922 code = smtpcode();
923 flagcritical = 0;
924 if (code >= 500) quit("D"," failed after I sent the message");
925 if (code >= 400) quit("Z"," failed after I sent the message");
926 switch (flagtls) { // StartTLS + SMTPS
927 case 100: case 110: quit("K"," TLS transmitted message accepted"); break;
928 case 101: case 111: quit("K"," TLS (verified CA) transmitted message accepted"); break;
929 case 102: case 112: quit("K"," TLS (validated CA+DN*) transmitted message accepted"); break;
930 case 103: case 113: quit("K"," TLS (validated CA+DN) transmitted message accepted"); break;
931 case 104: case 114: quit("K"," TLS (CERT pinning) transmitted message accepted"); break;
932 case 105: case 115: quit("K"," TLS (TLSA EE validated) transmitted message accepted"); break;
933 case 106: case 116: quit("K"," TLS (TLSA TA validated) transmitted message accepted"); break;
934 case 107: case 117: quit("K"," TLS (TLSA PKIX verified) transmitted message accepted"); break;
935 default: quit("K"," accepted message"); break;
936 }
937}
938
939/* this file is too long -------------------------------------- qmtp client */
940
941int qmtpsend = 0;
942
943void qmtp()
944{
945 unsigned long len = 0;
946 char *x;
947 int i = 0;
948 int n = 0;
949 char ch;
950 char num[FMT_ULONG];
951 int flagallok;
952
953 if (qmtpsend == 2) { /* QMTPS */
954 tls_init();
956 }
957
958/* the following code was substantially taken from serialmail's serialqmtp.c */
959
960 if (msize)
961 len = msize;
962 else {
963 out("DMessage for: "); outhost(); out(" has zero bytes. Giving up.\n");
964 }
965
966 buffer_put(&bo,num,fmt_ulong(num,len + 1));
967 buffer_put(&bo,":\n",2);
968 while (len > 0) {
969 n = buffer_feed(&bi);
970 if (n <= 0) _exit(1); /* wise guy again */
971 x = buffer_PEEK(&bi);
972 buffer_put(&bo,x,n);
973 buffer_SEEK(&bi,n);
974 len -= n;
975 }
976 buffer_put(&bo,",",1);
977
978 len = sender.len;
979 buffer_put(&bo,num,fmt_ulong(num,len));
980 buffer_put(&bo,":",1);
981 buffer_put(&bo,sender.s,sender.len);
982 buffer_put(&bo,",",1);
983
984 len = 0;
985 for (i = 0; i < reciplist.len; ++i)
986 len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1;
987 buffer_put(&bo,num,fmt_ulong(num,len));
988 buffer_put(&bo,":",1);
989 for (i = 0; i < reciplist.len; ++i) {
990 buffer_put(&bo,num,fmt_ulong(num,reciplist.sa[i].len));
991 buffer_put(&bo,":",1);
992 buffer_put(&bo,reciplist.sa[i].s,reciplist.sa[i].len);
993 buffer_put(&bo,",",1);
994 }
995 buffer_put(&bo,",",1);
996 buffer_flush(&bo);
997
998 flagallok = 1;
999
1000 for (i = 0; i < reciplist.len; ++i) {
1001 len = 0;
1002 for (;;) {
1003 get(&ch);
1004 if (ch == ':') break;
1005 if (len > QMTP_MAX) temp_proto();
1006 if (ch - '0' > 9) temp_proto();
1007 len = 10 * len + (ch - '0');
1008 }
1009 if (!len) temp_proto();
1010 get(&ch); --len;
1011 if ((ch != 'Z') && (ch != 'D') && (ch != 'K')) temp_proto();
1012
1013 if (!stralloc_copyb(&smtptext,&ch,1)) temp_nomem();
1014 if (flagtls >= 100) {
1015 if (!stralloc_cats(&smtptext,"qmtps:")) temp_nomem();
1016 } else {
1017 if (!stralloc_cats(&smtptext,"qmtp:")) temp_nomem();
1018 }
1019
1020 while (len > 0) {
1021 get(&ch);
1022 --len;
1023 }
1024
1025 for (len = 0; len < smtptext.len; ++len) {
1026 ch = smtptext.s[len];
1027 if ((ch < 32) || (ch > 126)) smtptext.s[len] = '?';
1028 }
1029 get(&ch); // Read response
1030 if (ch != ',') temp_proto();
1031 smtptext.s[smtptext.len - 1] = '\n';
1032
1033 if (smtptext.s[0] == 'K') out("r");
1034 else if (smtptext.s[0] == 'D') {
1035 out("h");
1036 flagallok = 0;
1037 }
1038 else { /* if (smtptext.s[0] == 'Z') */
1039 out("s");
1040 flagallok = 0;
1041 }
1042 if (buffer_put(&bs,smtptext.s + 1,smtptext.len - 1) == -1) temp_qmtpnoc();
1043 zero();
1044 }
1045
1046 if (!flagallok) {
1047 out("DGiving up on "); outhost(); out("\n");
1048 } else {
1049 out("KAll received okay by "); outhost(); out("\n");
1050 }
1051 zerodie();
1052}
1053
1054/* this file is too long -------------------------------------- common */
1055
1056/* host has to be canonical [A/AAAA record], box has to be quoted */
1057
1058void addrmangle(stralloc *saout,char *address,int *flagalias,int flagcname)
1059{
1060 int at;
1061 int r = 0;
1062 stralloc cn = {0};
1063
1064 *flagalias = flagcname; /* saout + flagalias are output */
1065 if (!flagutf8)
1066 flagutf8 = utf8string(address,str_len(address));
1067
1068 at = str_rchr(address,'@');
1069 if (!address[at]) {
1070 if (!stralloc_copys(saout,address)) temp_nomem();
1071 return;
1072 }
1073
1075 canonbox.len = at;
1076 if (!quote(saout,&canonbox)) temp_nomem(); /* saout = 'inbox' name without quotes ;-) */
1077 if (!stralloc_cats(saout,"@")) temp_nomem();
1078
1079 if (!stralloc_copys(&canonhost,address + at + 1)) temp_nomem();
1080 if (flagcname) { /* no relayhost */
1081 DNS_INIT
1082 switch ((r = dns_cname(&cn,&canonhost))) {
1083 case DNS_MEM: temp_nomem();
1084 case DNS_SOFT: temp_dnscanon();
1085 case DNS_HARD: ; /* alias loop, not our problem */
1086 default: if (r > 0) *flagalias = 0;
1087 }
1088 }
1089 if (!stralloc_cat(saout,&canonhost)) temp_nomem();
1090}
1091
1093{
1094 if (control_init() == -1) temp_control();
1095 if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control();
1096 if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1)
1097 temp_control();
1098 if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1)
1099 temp_control();
1100 switch (control_readfile(&smtproutes,"control/smtproutes",0)) {
1101 case -1: temp_control();
1102 case 0: if (!constmap_init(&mapsmtproutes,"",0,1)) temp_nomem(); break;
1103 case 1: if (!constmap_init(&mapsmtproutes,smtproutes.s,smtproutes.len,1)) temp_nomem(); break;
1104 }
1105 switch (control_readfile(&domainips,"control/domainips",0)) {
1106 case -1: temp_control();
1107 case 0: if (!constmap_init(&mapdomainips,"",0,1)) temp_nomem(); break;
1108 case 1: if (!constmap_init(&mapdomainips,domainips.s,domainips.len,1)) temp_nomem(); break;
1109 }
1110 switch (control_readfile(&authsenders,"control/authsenders",0)) {
1111 case -1: temp_control();
1112 case 0: if (!constmap_init(&mapauthsenders,"",0,1)) temp_nomem(); break;
1113 case 1: if (!constmap_init(&mapauthsenders,authsenders.s,authsenders.len,1)) temp_nomem(); break;
1114 }
1115 switch (control_readfile(&qmtproutes,"control/qmtproutes",0)) {
1116 case -1: temp_control();
1117 case 0: if (!constmap_init(&mapqmtproutes,"",0,1)) temp_nomem(); break;
1118 case 1: if (!constmap_init(&mapqmtproutes,qmtproutes.s,qmtproutes.len,1)) temp_nomem(); break;
1119 }
1120 switch (control_readfile(&domaincerts,"control/domaincerts",0)) {
1121 case -1: temp_control();
1122 case 0: if (!constmap_init(&mapdomaincerts,"",0,1)) temp_nomem(); break;
1123 case 1: if (!constmap_init(&mapdomaincerts,domaincerts.s,domaincerts.len,1)) temp_nomem(); break;
1124 }
1125 switch (control_readfile(&tlsdestinations,"control/tlsdestinations",0)) {
1126 case -1: temp_control();
1127 case 0: if (!constmap_init(&maptlsdestinations,"",0,1)) temp_nomem(); break;
1129 }
1130}
1131
1132int main(int argc,char * const argv[])
1133{
1134 static ipalloc ip = {0};
1135 stralloc netif = {0};
1136 struct stat st;
1137 int i, j, k;
1138 int p; /* reserved for port */
1139 int r; /* reserved for return code */
1140 unsigned long random;
1141 char **recips;
1142 unsigned long prefme;
1143 int flagallaliases;
1144 int flagalias;
1145 char *relayhost;
1146 char *localip;
1147 int ip6flag = 0;
1148
1149 sig_pipeignore();
1150 if (argc < 4) perm_usage();
1151 if (chdir(auto_qmail) == -1) temp_chdir();
1152
1153 getcontrols();
1154 if (!stralloc_copys(&host,argv[1])) temp_nomem();
1155
1156 authsender = 0;
1157 relayhost = 0;
1158
1159 addrmangle(&sender,argv[2],&flagalias,0);
1160
1161 if (sender.len > 1) {
1162 i = str_chr(sender.s,'@');
1163 if (sender.s[i] == '@')
1164 if (!stralloc_copyb(&senddomain,sender.s + i + 1,sender.len - i - 1)) temp_nomem(); // un-terminated
1165 }
1166
1167/* this file is too long -------------------------------------- set domain ip + helohost */
1168
1169 localip = 0;
1170
1171 for (i = 0; i <= senddomain.len; ++i)
1172 if ((i == 0) || (senddomain.s[i] == '.'))
1173 if ((localip = constmap(&mapdomainips,senddomain.s + i,senddomain.len - i)))
1174 break;
1175
1176 if (!localip)
1177 localip = constmap(&mapdomainips,"*",1); /* one for all */
1178
1179 if (localip) {
1180 j = str_chr(localip,'%');
1181 if (localip[j] != '%') j = 0;
1182 k = str_chr(localip,'|');
1183 if (localip[k] != '|') k = 0;
1184 if (k) { /* helohost */
1185 if (!stralloc_copys(&helohost,localip + k + 1)) temp_nomem();
1186 localip[k] = 0;
1187 }
1188 if (j) { /* IF index */
1189 localip[j] = 0;
1190 if (!stralloc_copys(&netif,localip + j + 1)) temp_nomem();
1191 if (!stralloc_0(&netif)) temp_nomem();
1192 }
1193 }
1194
1195/* this file is too long -------------------------------------- authsender routes */
1196
1197 for (i = 0; i <= sender.len; ++i)
1198 if ((i == 0) || (i == sender.len) || (sender.s[i] == '.') || (sender.s[i] == '@'))
1199 if ((authsender = constmap(&mapauthsenders,sender.s + i,sender.len - i)))
1200 break;
1201
1202 if (authsender && !*authsender) authsender = 0;
1203
1204 if (authsender) {
1205 i = str_chr(authsender,'|');
1206 if (authsender[i] == '|') {
1207 j = str_chr(authsender + i + 1,'|');
1208 if (authsender[i + j + 1] == '|') {
1209 authsender[i] = 0;
1210 authsender[i + j + 1] = 0;
1211 if (!stralloc_copys(&user,"")) temp_nomem();
1212 if (!stralloc_copys(&user,authsender + i + 1)) temp_nomem();
1213 if (!stralloc_copys(&pass,"")) temp_nomem();
1214 if (!stralloc_copys(&pass,authsender + i + j + 2)) temp_nomem();
1215 }
1216 }
1217 p = str_chr(authsender,';');
1218 if (authsender[p] == ';') {
1219 if (authsender[p + 1] == 's') { flagsmtps = 1, p++; }
1220 scan_ulong(authsender + p + 1,&port);
1221 authsender[p] = 0;
1222 }
1223 relayhost = authsender;
1225 }
1226
1227/* this file is too long -------------------------------------- standard routes */
1228
1229 if (!authsender) {
1230 if (sender.len == 0) { /* bounce routes */
1231 if ((relayhost = constmap(&mapqmtproutes,"!@",2))) {
1232 qmtpsend = 1; port = PORT_QMTP;
1233 } else
1234 relayhost = constmap(&mapsmtproutes,"!@",2);
1235 }
1236
1237 if (relayhost && !*relayhost) relayhost = 0;
1238
1239 if (!relayhost) {
1240 for (i = 0; i <= host.len; ++i) { /* qmtproutes */
1241 if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
1242 if ((relayhost = constmap(&mapqmtproutes,host.s + i,host.len - i))) {
1243 qmtpsend = 1; port = PORT_QMTP;
1244 break;
1245 } /* default smtproutes */
1246 if ((relayhost = constmap(&mapsmtproutes,host.s + i,host.len - i)))
1247 break;
1248 }
1249 }
1250 if (relayhost && !*relayhost) relayhost = 0;
1251
1252 if (relayhost) { /* default smtproutes -- authenticated */
1253 i = str_chr(relayhost,'|');
1254 if (relayhost[i] == '|') {
1255 j = str_chr(relayhost + i + 1,'|'); // authenticate
1256 if (relayhost[i + j + 1] == '|') {
1257 relayhost[i] = 0;
1258 relayhost[i + j + 1] = 0;
1259 if (!stralloc_copys(&user,"")) temp_nomem();
1260 if (!stralloc_copys(&user,relayhost + i + 1)) temp_nomem();
1261 if (!stralloc_copys(&pass,"")) temp_nomem();
1262 k = str_chr(relayhost + i + j + 2,'|'); // local ip
1263 if (relayhost[i + j + k + 2] == '|') {
1264 relayhost[i + j + k + 2] = 0;
1265 localip = relayhost + i + j + k + 3;
1266 }
1267 if (!stralloc_copys(&pass,relayhost + i + j + 2)) temp_nomem();
1268 }
1269 }
1270 p = str_chr(relayhost,';');
1271 if (relayhost[p] == ';') {
1272 if (relayhost[p + 1] == 's') { flagsmtps = 1; p++; } // RFC 8314
1273 scan_ulong(relayhost + p + 1,&port);
1274 if (qmtpsend && port == PORT_QMTPS) qmtpsend = 2;
1275 relayhost[p] = 0;
1276 }
1277 if (!stralloc_copys(&host,relayhost)) temp_nomem();
1278#ifdef IDN2
1279 } else {
1280 char *asciihost = 0;
1281 if (!stralloc_0(&host)) temp_nomem();
1282 switch (idn2_lookup_u8(host.s,(uint8_t**)&asciihost,IDN2_NFC_INPUT)) {
1283 case IDN2_OK: break;
1284 case IDN2_MALLOC: temp_nomem();
1285 default: perm_dns();
1286 }
1287 if (!stralloc_copys(&idnhost,asciihost)) temp_nomem();
1288#endif
1289 }
1290 }
1291
1292/* this file is too long -------------------------------------- TLS destinations */
1293
1294
1295 flagtls = tls_destination((const stralloc) host); // host may not be 0-terminated
1296
1297 if (flagtls > 0) {
1298 if (tlsdestinfo) {
1299 i = str_chr(tlsdestinfo,'|'); /* ca file/dir or cert fingerprint */
1300 if (tlsdestinfo[i] == '|') {
1301 tlsdestinfo[i] = 0;
1302 j = str_chr(tlsdestinfo + i + 1,'|'); /* cipher */
1303 if (tlsdestinfo[i + j + 1] == '|') {
1304 tlsdestinfo[i + j + 1] = 0;
1305 k = str_chr(tlsdestinfo + i + j + 2,'|'); /* cone domain */
1306 if (tlsdestinfo[i + j + k + 2] == '|') {
1307 tlsdestinfo[i + j + k + 2] = 0;
1308 if (str_diffn(tlsdestinfo + j + k + 3,canonhost.s,canonhost.len)) flagtls = 0;
1309 }
1310 p = str_chr(tlsdestinfo + i + j + 2,';'); /* verifydepth;port */
1311 if (tlsdestinfo[i + j + p + 2] == ';') {
1312 tlsdestinfo[i + j + p + 2] = 0;
1313 if (p > 0) scan_ulong(tlsdestinfo + i + j + 2,&verifydepth);
1314 if (tlsdestinfo[i + j + p + 3] == 's') { flagsmtps = 1; p++; } /* RFC 8314 */
1315 scan_ulong(tlsdestinfo + i + j + p + 3,&port);
1316 }
1317 }
1318 if (j)
1319 if (!stralloc_copys(&ciphers,tlsdestinfo + i + 1)) temp_nomem();
1320 }
1321
1322 /* either ':[=]cafile/cadir' -or- ':;port' */
1323
1324 if (tlsdestinfo[0] == ';')
1325 scan_ulong(tlsdestinfo + 1,&port);
1326 else
1328 }
1329
1330/* cafile starts with '=' => it is a fingerprint
1331 cafile ends with '/' => consider it as cadir
1332 cafile and cadir are now 0-terminated
1333 ciphers are alway 0-terminated if given */
1334
1335 if (cafile.len > 2) {
1336 flagverify = 1;
1337 if (cafile.s[cafile.len] == '/') {
1338 cafile.len = 0;
1339 flagverify = 2;
1341 if (!stralloc_0(&cadir)) temp_nomem();
1342 } else {
1343 if (cafile.s[0] == '=') flagverify = -2;
1344 if (!stralloc_0(&cafile)) temp_nomem();
1345 }
1346 } else
1347 cafile.len = cadir.len = 0;
1348
1349 if (ciphers.len > 4) /* otherwise garbage */
1350 if (!stralloc_0(&ciphers)) temp_nomem();
1351 else
1352 ciphers.len = 0;
1353
1354 if (port == PORT_SMTPS || flagsmtps) flagtls += 10;
1355 if (port == PORT_QMTPS) flagtls += 20;
1356 }
1357
1358 if (flagtls == 8 || flagtls == 18 || flagtls == 28) flagverify = -1; /* no TLSA */
1359 if (!flagtls && qmtpsend == 2) flagtls = 20; /* QMTPS */
1360
1361
1362/* this file is too long -------------------------------------- Our Certs - per senddomain */
1363
1364 if (flagtls > 0) {
1365 flagtlsdomain = tls_domaincerts((const stralloc) senddomain); // senddomain un-terminated
1366
1368 i = str_chr(tlsdomaininfo,'|');
1369 if (tlsdomaininfo[i] == '|') {
1370 tlsdomaininfo[i] = 0;
1371 j = str_chr(tlsdomaininfo + i + 1,'|');
1372 if (tlsdomaininfo[i + j + 1] == '|') {
1373 tlsdomaininfo[i + j + 1] = 0;
1374 if (!stralloc_copys(&keypwd,"")) temp_nomem();
1375 if (!stralloc_copys(&keypwd,tlsdomaininfo + i + j + 2)) temp_nomem();
1376 if (!stralloc_0(&keypwd)) temp_nomem();
1377 }
1379 if (!stralloc_0(&keyfile)) temp_nomem();
1380 }
1382 if (!stralloc_0(&certfile)) temp_nomem();
1383 flagtlsdomain = 2;
1384 }
1385 }
1386
1387/* this file is too long -------------------------------------- work thru reciplist */
1388
1389 if (!saa_readyplus(&reciplist,0)) temp_nomem();
1390 if (ipme_init() != 1) temp_oserr();
1391
1392 flagallaliases = 1;
1393 recips = argv + 3;
1394
1395 if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin");
1396 msize = st.st_size;
1397 fmt_ulong(msgsize,msize);
1398
1399 while (*recips) {
1400 if (!saa_readyplus(&reciplist,1)) temp_nomem();
1401 reciplist.sa[reciplist.len] = sauninit;
1402 addrmangle(reciplist.sa + reciplist.len,*recips,&flagalias,!relayhost);
1403 if (!flagalias) flagallaliases = 0;
1404 ++reciplist.len;
1405 ++recips;
1406 }
1407
1408 random = now() + (getpid() << 16);
1409#ifdef IDN2
1410 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&idnhost,random)) {
1411#else
1412 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) {
1413#endif
1414 case DNS_MEM: temp_nomem();
1415 case DNS_ERR: temp_dns();
1416 case DNS_COM: temp_dns();
1417 case DNS_SOFT: temp_dns();
1418#ifdef DEFERREDBOUNCES
1419 default: if (!ip.len) temp_nomx();
1420#else
1421 default: if (!ip.len) perm_nomx();
1422#endif
1423 }
1424
1425 prefme = 100000;
1426 for (i = 0; i < ip.len; ++i)
1427 if (ipme_is(&ip.ix[i])) {
1428#ifdef NULLMX
1429 if (ip.ix[i].pref == 0 && ip.ix[i].mxh[0] == '.')
1430 perm_nullmx(); /* RFC 7505 MX = 0 */
1431#endif
1432 if (ip.ix[i].pref < prefme)
1433 prefme = ip.ix[i].pref;
1434 }
1435
1436 if (relayhost) prefme = 300000;
1437 if (flagallaliases) prefme = 500000;
1438
1439 if (localip) {
1440 i = str_chr(localip,':');
1441 if (localip[i] == ':') ip6flag = 1;
1442 else ip6flag = -1;
1443 }
1444
1445 for (i = 0; i < ip.len; ++i) { /* MX with smallest distance */
1446 if (ip6flag == -1 && ip.ix[i].af == AF_INET6) continue;
1447 if (ip6flag == 1 && ip.ix[i].af == AF_INET) continue;
1448 if (ip.ix[i].pref < prefme) break;
1449 }
1450
1451 if (i >= ip.len) perm_ambigmx();
1452
1453 if (!stralloc_copys(&remotehost,ip.ix[i].mxh)) temp_nomem(); /* take MX hostname for TLSA */
1454 if (!stralloc_0(&remotehost)) temp_nomem();
1455
1456 for (i = 0; i < ip.len; ++i) {
1457 if (ip.ix[i].pref < prefme) {
1458 if (ip6flag == -1 && ip.ix[i].af == AF_INET6) continue; /* explicit binding */
1459 if (ip6flag == 1 && ip.ix[i].af == AF_INET) continue;
1460 if (tcpto(&ip.ix[i])) continue;
1461
1462 smtpfd = socket(ip.ix[i].af,SOCK_STREAM,0);
1463 if (smtpfd == -1) continue;
1464
1465 if (localip) { /* set domain ip */
1466 if (!stralloc_copyb(&sendip,localip,str_len(localip))) temp_nomem();
1467 j = str_chr(localip,':');
1468 if (localip[j] == ':') {
1469 if (!ip6_scan(localip,ip6)) temp_noip(); /* IPv6 */
1470 if (byte_equal((char *)ip.ix[i].addr.ip6.d,16,ip6)) continue;
1471 ifidx = socket_getifidx(netif.s);
1472 if (socket_bind6(smtpfd,ip6,0,ifidx) < 0) temp_osip();
1473 } else {
1474 if (!ip4_scan(localip,ip4)) temp_noip(); /* IPv4 */
1475 if (byte_equal((char *)ip.ix[i].addr.ip4.d,4,ip4)) continue;
1476 if (socket_bind4(smtpfd,ip4,0) < 0) temp_osip();
1477 }
1478 }
1479
1480
1481 AGAIN:
1482 if (ip.ix[i].af == AF_INET6)
1483 r = timeoutconn6(smtpfd,(char *)&ip.ix[i].addr.ip6.d,(unsigned int) port,timeoutconnect,ifidx);
1484 else
1485 r = timeoutconn4(smtpfd,(char *)&ip.ix[i].addr.ip4.d,(unsigned int) port,timeoutconnect);
1486 if (r == 0) {
1487 tcpto_err(&ip.ix[i],0);
1488 partner = ip.ix[i];
1489 if (qmtpsend)
1490 qmtp();
1491 else
1492 smtp(); /* read qmail/THOUGHTS; section 6 */
1493 }
1494 if (flagtls == 9 && errno == EPROTO) {
1495 flagtls = 0; goto AGAIN;
1496 }
1497 if (errno == ETIMEDOUT || errno == ECONNREFUSED || errno == EPROTO)
1498 tcpto_err(&ip.ix[i],1);
1499 close(smtpfd);
1500 }
1501 }
1502 temp_noconn();
1503}
char auto_qmail[]
int b64encode(stralloc *in, stralloc *out)
Definition: base64.c:97
int b64decode(const unsigned char *in, int len, stralloc *out)
Definition: base64.c:12
int main()
Definition: chkshsgr.c:6
char num[FMT_ULONG]
Definition: chkspawn.c:8
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_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
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_SOFT
Definition: dns.h:14
#define DNS_HARD
Definition: dns.h:15
#define DNS_INIT
Definition: dns.h:12
stralloc out
Definition: dnscname.c:12
stralloc sa
Definition: dnscname.c:11
void _exit(int)
char buf[100+FMT_ULONG]
Definition: hier.c:11
void c(char *, char *, char *, int, int, int)
Definition: install.c:67
void p(char *, char *, int, int, int)
Definition: install.c:49
void hmac_md5(char *text, int text_len, char *key, int key_len, char *digest)
Definition: hmac_md5.c:16
int ipme_init(void)
Definition: ipme.c:61
int ipme_is(struct ip_mx *)
Definition: ipme.c:50
char ipaddr[IPFMT]
Definition: ipmeprint.c:11
stralloc address
Definition: newaliases.c:90
char tmpbuf[BUFSIZE_LINE]
Definition: newinclude.c:38
datetime_sec now()
Definition: now.c:5
GEN_ALLOC_readyplus(prioq, struct prioq_elt, p, len, a, i, n, x, 100, prioq_readyplus)
Definition: prioq.c:5
int fd
buffer in
Definition: qmail-pw2u.c:240
int flagalias
Definition: qmail-pw2u.c:82
char * received
Definition: qmail-queue.c:69
stralloc canonhost
Definition: qmail-remote.c:82
unsigned long code
Definition: qmail-remote.c:604
stralloc idnhost
Definition: qmail-remote.c:80
int utf8string(char *ch, int len)
Definition: qmail-remote.c:556
ssize_t safewrite(int fd, char *buf, size_t len)
Definition: qmail-remote.c:307
char inbuf[BUFFER_MTUSIZE]
Definition: qmail-remote.c:320
buffer bs
Definition: qmail-remote.c:111
void outhost()
Definition: qmail-remote.c:264
void zero()
Definition: qmail-remote.c:118
stralloc recip
Definition: qmail-remote.c:101
int flagcritical
Definition: qmail-remote.c:278
char * authsender
Definition: qmail-remote.c:93
void temp_read()
Definition: qmail-remote.c:180
int flagutf8
Definition: qmail-remote.c:71
struct constmap mapauthsenders
Definition: qmail-remote.c:675
void temp_noip()
Definition: qmail-remote.c:144
stralloc qmtproutes
Definition: qmail-remote.c:97
void temp_dns()
Definition: qmail-remote.c:192
stralloc remotehost
Definition: qmail-remote.c:83
#define QMTP_MAX
Definition: qmail-remote.c:45
struct constmap mapqmtproutes
Definition: qmail-remote.c:98
void temp_chdir()
Definition: qmail-remote.c:206
#define PORT_QMTPS
Definition: qmail-remote.c:51
int xtext(stralloc *sa, char *s, int len)
Definition: qmail-remote.c:687
void temp_qmtpnoc()
Definition: qmail-remote.c:173
int flagverify
Definition: qmail-remote.c:69
stralloc certfile
Definition: qmail-remote.c:429
char frombuf[BUFFER_SMALL]
Definition: qmail-remote.c:324
void perm_usage()
Definition: qmail-remote.c:226
void addrmangle(stralloc *saout, char *address, int *flagalias, int flagcname)
int mailfrom_cram()
Definition: qmail-remote.c:781
void smtp_greeting()
Definition: qmail-remote.c:620
void getcontrols()
stralloc authsenders
Definition: qmail-remote.c:674
uint32 ifidx
Definition: qmail-remote.c:92
void perm_ambigmx()
Definition: qmail-remote.c:252
void temp_control()
Definition: qmail-remote.c:211
int flagtlsdomain
Definition: qmail-remote.c:62
stralloc helohost
Definition: qmail-remote.c:77
unsigned long port
Definition: qmail-remote.c:56
stralloc host
Definition: qmail-remote.c:79
void dropped()
Definition: qmail-remote.c:280
int flagsmtps
Definition: qmail-remote.c:61
stralloc sender
Definition: qmail-remote.c:81
struct constmap mapdomainips
Definition: qmail-remote.c:89
char * tlsdomaininfo
Definition: qmail-remote.c:435
void blast()
Definition: qmail-remote.c:385
void temp_dnscanon()
Definition: qmail-remote.c:185
void ehlo_auth()
Definition: qmail-remote.c:827
#define SMTP_TIMEOUT
Definition: qmail-remote.c:54
stralloc domainips
Definition: qmail-remote.c:88
void temp_nomx()
Definition: qmail-remote.c:199
struct ip_mx partner
Definition: qmail-remote.c:105
char ip6[16]
Definition: qmail-remote.c:91
void perm_dns()
Definition: qmail-remote.c:231
char msgsize[FMT_ULONG]
Definition: qmail-remote.c:103
unsigned long timeout
Definition: qmail-remote.c:291
void temp_noconn()
Definition: qmail-remote.c:166
GEN_ALLOC_typedef(GEN_ALLOC_readyplus(saa, GEN_ALLOC_readyplus(stralloc, GEN_ALLOC_readyplus(sa, GEN_ALLOC_readyplus(len, GEN_ALLOC_readyplus(a)
Definition: qmail-remote.c:73
void temp_oserr()
Definition: qmail-remote.c:154
#define PORT_SMTP
Definition: qmail-remote.c:47
stralloc user
Definition: qmail-remote.c:677
struct constmap maptlsdestinations
Definition: qmail-remote.c:440
int qmtpsend
Definition: qmail-remote.c:941
stralloc sendip
Definition: qmail-remote.c:86
void quit(char *prepend, char *append)
Definition: qmail-remote.c:373
stralloc pass
Definition: qmail-remote.c:678
unsigned long verifydepth
Definition: qmail-remote.c:441
void smtp()
Definition: qmail-remote.c:850
void outsafe(stralloc *sa)
Definition: qmail-remote.c:131
stralloc keyfile
Definition: qmail-remote.c:430
#define TCP_TIMEOUT
Definition: qmail-remote.c:53
void outsmtptext()
Definition: qmail-remote.c:361
struct constmap mapdomaincerts
Definition: qmail-remote.c:438
void perm_partialline()
Definition: qmail-remote.c:216
void get(char *ch)
Definition: qmail-remote.c:330
int utf8received()
Definition: qmail-remote.c:564
stralloc cadir
Definition: qmail-remote.c:428
int smtpfd
Definition: qmail-remote.c:292
#define HUGESMTPTEXT
Definition: qmail-remote.c:46
int flagauth
Definition: qmail-remote.c:60
stralloc slop
Definition: qmail-remote.c:681
stralloc keypwd
Definition: qmail-remote.c:431
#define PORT_QMTP
Definition: qmail-remote.c:48
void temp_nomem()
Definition: qmail-remote.c:149
char * tlsdestinfo
Definition: qmail-remote.c:434
int ehlo_starttls()
Definition: qmail-remote.c:483
stralloc ciphers
Definition: qmail-remote.c:432
stralloc xuser
Definition: qmail-remote.c:683
char bufsmall[BUFFER_SMALL]
Definition: qmail-remote.c:110
unsigned long timeoutconnect
Definition: qmail-remote.c:290
void temp_osip()
Definition: qmail-remote.c:159
buffer bi
Definition: qmail-remote.c:321
char ip4[4]
Definition: qmail-remote.c:90
#define VERIFYDEPTH
Definition: qmail-remote.c:52
struct constmap mapsmtproutes
Definition: qmail-remote.c:96
int mailfrom_login()
Definition: qmail-remote.c:751
buffer bf
Definition: qmail-remote.c:325
int ehlo_size()
Definition: qmail-remote.c:607
saa reciplist
Definition: qmail-remote.c:100
unsigned long msize
Definition: qmail-remote.c:104
stralloc smtproutes
Definition: qmail-remote.c:95
void tls_peercheck()
Definition: qmail-remote.c:496
void temp_proto()
Definition: qmail-remote.c:221
stralloc auth
Definition: qmail-remote.c:679
int mailfrom_plain()
Definition: qmail-remote.c:725
stralloc cafile
Definition: qmail-remote.c:427
buffer bo
Definition: qmail-remote.c:323
SSL_CTX * ctx
Definition: qmail-remote.c:108
void qmtp()
Definition: qmail-remote.c:943
void tls_init()
Definition: qmail-remote.c:443
stralloc eaihost
Definition: qmail-remote.c:78
stralloc senddomain
Definition: qmail-remote.c:85
void err_authprot()
Definition: qmail-remote.c:258
void zerodie()
Definition: qmail-remote.c:123
#define PORT_SMTPS
Definition: qmail-remote.c:49
unsigned long smtpcode()
Definition: qmail-remote.c:338
SSL * ssl
Definition: qmail-remote.c:107
void smtp_starttls()
Definition: qmail-remote.c:641
void perm_nomx()
Definition: qmail-remote.c:238
stralloc tlsdestinations
Definition: qmail-remote.c:439
ssize_t saferead(int fd, char *buf, size_t len)
Definition: qmail-remote.c:294
stralloc canonbox
Definition: qmail-remote.c:84
void mailfrom_xtext()
Definition: qmail-remote.c:708
stralloc domaincerts
Definition: qmail-remote.c:437
void perm_nullmx()
Definition: qmail-remote.c:245
int flagtls
Definition: qmail-remote.c:63
stralloc chal
Definition: qmail-remote.c:680
int flagsize
Definition: qmail-remote.c:605
stralloc plain
Definition: qmail-remote.c:682
void mailfrom()
Definition: qmail-remote.c:657
char outbuf[BUFFER_MTUSIZE]
Definition: qmail-remote.c:322
int j
Definition: qmail-send.c:926
#define BUFSIZE_MESS
Definition: qmail.h:7
int quote(stralloc *, stralloc *)
Definition: quote.c:62
uint32_t k[64]
Definition: sha256.c:27
Definition: ipalloc.h:8
struct ip6_address ip6
Definition: ipalloc.h:12
struct ip4_address ip4
Definition: ipalloc.h:11
union ip_mx::@0 addr
unsigned short af
Definition: ipalloc.h:9
void tcpto_err(struct ip_mx *, int)
Definition: tcpto.c:82
int tcpto(struct ip_mx *)
Definition: tcpto.c:42
void temp_tlspeercert()
Definition: tls_errors.c:93
void temp_tlsctx(void)
Definition: tls_errors.c:56
void temp_tlshost(void)
Definition: tls_errors.c:82
void temp_tlscipher(void)
Definition: tls_errors.c:46
void temp_tlscert(void)
Definition: tls_errors.c:12
void temp_tlskey(void)
Definition: tls_errors.c:20
void temp_tlschk(void)
Definition: tls_errors.c:28
void temp_tlspeervalid()
Definition: tls_errors.c:109
void temp_tlsdigest(void)
Definition: tls_errors.c:151
void temp_tlsca(void)
Definition: tls_errors.c:36
void temp_tlspeerverify()
Definition: tls_errors.c:101
void temp_tlsamissing(void)
Definition: tls_errors.c:135
void temp_tlscon()
Definition: tls_errors.c:64
void temp_tlsainvalid(void)
Definition: tls_errors.c:143
void temp_tlserr(void)
Definition: tls_errors.c:73
void temp_tlscertfp(void)
Definition: tls_errors.c:117
void temp_invaliddigest(void)
Definition: tls_errors.c:127
int tlsa_check(const STACK_OF(X509) *, const stralloc, const unsigned long)
Definition: tls_remote.c:168
int tls_destination(stralloc)
tls_destination
Definition: tls_remote.c:275
int tls_exit(SSL *)
Definition: tls_remote.c:254
int tls_conn(SSL *, int)
Definition: tls_remote.c:49
int tls_domaincerts(stralloc)
Definition: tls_remote.c:365
int tls_fingerprint(X509 *, const char *, const int)
Definition: tls_remote.c:230
int tls_certkey(SSL_CTX *, const char *, const char *, char *)
Definition: tls_remote.c:29
int tls_checkpeer(SSL *, X509 *, const stralloc, const int, const int)
Definition: tls_remote.c:56
int tls_timeoutconn(int, int, int, SSL *)
Definition: tls_timeoutio.c:67
int tls_timeoutwrite(int, int, int, SSL *, char *, int)
int tls_timeoutread(int, int, int, SSL *, char *, int)
Definition: tls_timeoutio.c:96
#define ssl_client()
Definition: ucspitls.h:16
int ssl_ciphers(SSL_CTX *, const char *)
#define ssl_errstr()
Definition: ucspitls.h:35
SSL * ssl_new(SSL_CTX *, int)
int ssl_ca(SSL_CTX *, const char *, const char *, int)