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