summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2023-08-08 23:37:39 +0200
committermanuel <manuel@mausz.at>2023-08-08 23:37:39 +0200
commit2ae3dd41c6d46d80574c59eec9689c16093edf2b (patch)
tree716a3cab8fffbf19db48e95b0c4d187c17b09d11
parent718ae19d5571f8d0132575b5aea4684dc5f40054 (diff)
downloadqmail-2ae3dd41c6d46d80574c59eec9689c16093edf2b.tar.gz
qmail-2ae3dd41c6d46d80574c59eec9689c16093edf2b.tar.bz2
qmail-2ae3dd41c6d46d80574c59eec9689c16093edf2b.zip
Make qmail openssl 3.0 compatible
- remove support for loading custom DH params from pem. use opensslconf if really required - remove support for loading custom ec group from params - reimplement DANE support using openssl DANE functions
-rw-r--r--Makefile2
-rw-r--r--qmail-remote.c197
-rw-r--r--qmail-smtpd.c213
3 files changed, 130 insertions, 282 deletions
diff --git a/Makefile b/Makefile
index 5f0c0f6..5bd3765 100644
--- a/Makefile
+++ b/Makefile
@@ -1533,7 +1533,7 @@ dns.lib socket.lib
1533 ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ 1533 ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
1534 lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ 1534 lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
1535 env.a str.a fs.a auto_qmail.o base64.o \ 1535 env.a str.a fs.a auto_qmail.o base64.o \
1536 `cat dns.lib` `cat socket.lib` -lval -lsres -lidn2 1536 `cat dns.lib` `cat socket.lib` -lidn2
1537 1537
1538qmail-remote.0: \ 1538qmail-remote.0: \
1539qmail-remote.8 1539qmail-remote.8
diff --git a/qmail-remote.c b/qmail-remote.c
index 0e2377e..1a09df9 100644
--- a/qmail-remote.c
+++ b/qmail-remote.c
@@ -63,8 +63,6 @@ struct ip_address partner;
63# include "tls.h" 63# include "tls.h"
64# include "ssl_timeoutio.h" 64# include "ssl_timeoutio.h"
65# include <openssl/x509v3.h> 65# include <openssl/x509v3.h>
66# include <validator/validator.h>
67# include <validator/val_dane.h>
68 66
69# define EHLO 1 67# define EHLO 1
70# define CLIENTCERT "control/clientcert.pem" 68# define CLIENTCERT "control/clientcert.pem"
@@ -72,10 +70,6 @@ struct ip_address partner;
72int tls_init(); 70int tls_init();
73const char *ssl_err_str = 0; 71const char *ssl_err_str = 0;
74char **myargv; 72char **myargv;
75val_context_t *dane_context = NULL;
76int dane_context_failed = 0;
77struct val_danestatus *dane_status = NULL;
78struct val_ssl_data *dane_ssl_data = NULL;
79#endif 73#endif
80 74
81#ifdef SMTPUTF8 75#ifdef SMTPUTF8
@@ -241,10 +235,6 @@ unsigned long ehlo()
241 if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len; 235 if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
242 ehlokw.len = 0; 236 ehlokw.len = 0;
243 237
244# ifdef MXPS
245 if (type == 's') return 0;
246# endif
247
248 substdio_puts(&smtpto, "EHLO "); 238 substdio_puts(&smtpto, "EHLO ");
249 substdio_put(&smtpto, helohost.s, helohost.len); 239 substdio_put(&smtpto, helohost.s, helohost.len);
250 substdio_puts(&smtpto, "\r\n"); 240 substdio_puts(&smtpto, "\r\n");
@@ -437,34 +427,28 @@ int tls_init()
437 } 427 }
438 } 428 }
439 429
440 /* DANE: starts here */ 430 /* DANE: lookup TLSA records */
441 int dane_retval = VAL_DANE_INTERNAL_ERROR;
442 int tls_required = (smtps || servercert != NULL); 431 int tls_required = (smtps || servercert != NULL);
443 432 stralloc tlsa_rr = { 0 };
444 if (partner_fqdn && !servercert && !dane_context_failed) { 433
445 if (dane_context == NULL && val_create_context(NULL, &dane_context) 434 if (partner_fqdn && !servercert) {
446 != VAL_NO_ERROR) { 435 stralloc tlsa_label = { 0 };
447 dane_context_failed = 1; 436 char port[FMT_ULONG];
448 out("lUnable to initialize libval context\n"); 437
449 zeroflush(); 438 if (!stralloc_copyb(&tlsa_label, "_", 1)) temp_nomem();
439 port[fmt_ulong(port, smtp_port)] = 0;
440 if (!stralloc_cats(&tlsa_label, port)) temp_nomem();
441 if (!stralloc_cats(&tlsa_label, "._tcp.")) temp_nomem();
442 if (!stralloc_cats(&tlsa_label, partner_fqdn)) temp_nomem();
443
444 switch (dns_tlsa(&tlsa_rr, &tlsa_label)) {
445 case DNS_MEM: temp_nomem();
446 case DNS_SOFT: temp_dns();
447 case DNS_HARD: tlsa_rr.len = 0; // no record found
450 } 448 }
451 449
452 if (dane_context) { 450 if (tlsa_rr.len)
453 val_free_dane(dane_status); 451 tls_required = 1;
454 val_free_dane_ssl(dane_ssl_data);
455
456 /* DANE: lookup TLSA records */
457 struct val_daneparams dane_params = {
458 .port = smtp_port,
459 .proto = DANE_PARAM_PROTO_TCP
460 };
461 dane_retval = val_getdaneinfo(dane_context, partner_fqdn, &dane_params, &dane_status);
462 /* work around a bug if no error but no also no records */
463 if (dane_retval == VAL_DANE_NOERROR && dane_status == NULL)
464 dane_retval = VAL_DANE_IGNORE_TLSA;
465 if (dane_retval == VAL_DANE_NOERROR)
466 tls_required = 1;
467 }
468 } 452 }
469 453
470 if (!smtps) { 454 if (!smtps) {
@@ -480,13 +464,20 @@ int tls_init()
480 } 464 }
481 465
482 SSL_library_init(); 466 SSL_library_init();
483 ctx = SSL_CTX_new(SSLv23_client_method()); 467 ctx = SSL_CTX_new(TLS_client_method());
484 if (!ctx) { 468 if (!ctx) {
485 if (!tls_required) return 0;
486 smtptext.len = 0; 469 smtptext.len = 0;
487 tls_quit_error("ZTLS error initializing ctx"); 470 tls_quit_error("ZTLS error initializing ctx");
488 } 471 }
489 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); 472 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
473
474 /* we verify ourself below. see SSL_get_verify_result */
475 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
476
477 if (SSL_CTX_dane_enable(ctx) <= 0) {
478 smtptext.len = 0;
479 tls_quit_error("ZTLS error initializing dane ctx");
480 }
490 481
491 if (servercert) { 482 if (servercert) {
492 if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) { 483 if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
@@ -497,19 +488,6 @@ int tls_init()
497 /* set the callback here; SSL_set_verify didn't work before 0.9.6c */ 488 /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
498 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); 489 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
499 } 490 }
500 else if (dane_retval == VAL_DANE_NOERROR) {
501 /* DANE: treat PKIX-EE as it were DANE-EE */
502 struct val_danestatus *dane_cur;
503 for (dane_cur = dane_status; dane_cur; dane_cur = dane_cur->next) {
504 if (dane_cur->usage == DANE_USE_SVC_CONSTRAINT)
505 dane_cur->usage = DANE_USE_DOMAIN_ISSUED;
506 }
507 /* DANE: set verify callback */
508 int err = val_enable_dane_ssl(dane_context, ctx, partner_fqdn, dane_status,
509 &dane_ssl_data);
510 if (err != VAL_NO_ERROR)
511 tls_quit("ZCould not enable dane verification", p_val_error(err));
512 }
513 491
514 /* let the other side complain if it needs a cert and we don't have one */ 492 /* let the other side complain if it needs a cert and we don't have one */
515 if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT)) 493 if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
@@ -518,14 +496,10 @@ int tls_init()
518 myssl = SSL_new(ctx); 496 myssl = SSL_new(ctx);
519 SSL_CTX_free(ctx); 497 SSL_CTX_free(ctx);
520 if (!myssl) { 498 if (!myssl) {
521 if (!tls_required) return 0;
522 smtptext.len = 0; 499 smtptext.len = 0;
523 tls_quit_error("ZTLS error initializing ssl"); 500 tls_quit_error("ZTLS error initializing ssl");
524 } 501 }
525 502
526 if (!smtps)
527 substdio_putsflush(&smtpto, "STARTTLS\r\n");
528
529 /* while the server is preparing a responce, do something else */ 503 /* while the server is preparing a responce, do something else */
530 if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1) 504 if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
531 { SSL_free(myssl); temp_control(); } 505 { SSL_free(myssl); temp_control(); }
@@ -539,14 +513,15 @@ int tls_init()
539 SSL_set_cipher_list(myssl, ciphers); 513 SSL_set_cipher_list(myssl, ciphers);
540 alloc_free(saciphers.s); 514 alloc_free(saciphers.s);
541 515
542#if OPENSSL_VERSION_NUMBER >= 0x10100005L
543 stralloc opensslconf = {0}; 516 stralloc opensslconf = {0};
544 if (control_readfile(&opensslconf, "control/opensslconf", 0) == -1) 517 if (control_readfile(&opensslconf, "control/opensslconf", 0) == -1)
545 { SSL_free(myssl); temp_control(); } 518 { SSL_free(myssl); temp_control(); }
546 if (opensslconf.len) { 519 if (opensslconf.len) {
547 SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); 520 SSL_CONF_CTX *cctx = SSL_CONF_CTX_new();
548 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); 521 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
522 /* client + server so we can share one single file */
549 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); 523 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
524 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
550 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); 525 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
551 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); 526 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
552 SSL_CONF_CTX_set_ssl(cctx, myssl); 527 SSL_CONF_CTX_set_ssl(cctx, myssl);
@@ -572,13 +547,68 @@ int tls_init()
572 547
573 (void)SSL_CONF_CTX_finish(cctx); 548 (void)SSL_CONF_CTX_finish(cctx);
574 } 549 }
575#endif
576 550
577 /* set SNI hostname */ 551 /* set SNI hostname */
578 if (partner_fqdn) 552 if (partner_fqdn)
579 SSL_set_tlsext_host_name(myssl, partner_fqdn); 553 SSL_set_tlsext_host_name(myssl, partner_fqdn);
580 554
581 /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */ 555 /* DANE: enable + add records */
556 if (tlsa_rr.len) {
557 if (SSL_dane_enable(myssl, partner_fqdn) <= 0) {
558 smtptext.len = 0;
559 tls_quit_error("ZTLS error enabling dane");
560 }
561 SSL_dane_set_flags(myssl, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
562
563 // loop through TLSA rr
564 int pos = 0, num_usable = 0;
565 unsigned char *rr_data = (unsigned char *)tlsa_rr.s;
566 while (pos < tlsa_rr.len && tlsa_rr.len - pos > 2 + 4) // sizeof(rrlen) + min(rrdata)
567 {
568 unsigned short rrlen = (rr_data[pos] << 8) + rr_data[pos + 1];
569 pos += 2;
570 uint8_t usage = rr_data[pos];
571 uint8_t selector = rr_data[pos + 1];
572 uint8_t mtype = rr_data[pos + 2];
573
574 /*
575 * Opportunistic DANE TLS clients support only DANE-TA(2) or DANE-EE(3).
576 * They treat all other certificate usages, and in particular PKIX-TA(0)
577 * and PKIX-EE(1), as unusable.
578 */
579 switch (usage) {
580 default:
581 case 0: /* PKIX-TA(0) */
582 case 1: /* PKIX-EE(1) */
583 pos += rrlen;
584 continue;
585 case 2: /* DANE-TA(2) */
586 case 3: /* DANE-EE(3) */
587 break;
588 }
589
590 // rrlen includes usage+selector+mtype (3) byte. remove
591 unsigned const char *cdata = rr_data + pos + 3;
592 size_t cdlen = rrlen - 3;
593 int tlsa_added = SSL_dane_tlsa_add(myssl, usage, selector, mtype, cdata, cdlen);
594 if (tlsa_added < 0) {
595 smtptext.len = 0;
596 tls_quit_error("ZTLS error adding DANE TLSA record");
597 }
598 else if (tlsa_added > 0)
599 ++num_usable;
600
601 pos += rrlen;
602 }
603
604 // no records usable. fallback to unauthenticated TLS
605 if (num_usable == 0)
606 tlsa_rr.len = 0;
607 }
608
609 if (!smtps)
610 substdio_putsflush(&smtpto, "STARTTLS\r\n");
611
582 SSL_set_fd(myssl, smtpfd); 612 SSL_set_fd(myssl, smtpfd);
583 613
584 /* read the responce to STARTTLS */ 614 /* read the responce to STARTTLS */
@@ -593,7 +623,7 @@ int tls_init()
593 } 623 }
594 624
595 ssl = myssl; 625 ssl = myssl;
596 if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0) { 626 if (ssl_timeoutconn(timeout, smtpfd, smtpfd, myssl) <= 0) {
597 if (tls_required) 627 if (tls_required)
598 tls_quit("ZTLS connect failed", ssl_error_str()); 628 tls_quit("ZTLS connect failed", ssl_error_str());
599 else { 629 else {
@@ -617,14 +647,14 @@ int tls_init()
617 X509 *peercert; 647 X509 *peercert;
618 STACK_OF(GENERAL_NAME) *gens; 648 STACK_OF(GENERAL_NAME) *gens;
619 649
620 int r = SSL_get_verify_result(ssl); 650 int r = SSL_get_verify_result(myssl);
621 if (r != X509_V_OK) { 651 if (r != X509_V_OK) {
622 out("ZTLS unable to verify server with "); 652 out("ZTLS unable to verify server with ");
623 tls_quit(servercert, X509_verify_cert_error_string(r)); 653 tls_quit(servercert, X509_verify_cert_error_string(r));
624 } 654 }
625 alloc_free(servercert); 655 alloc_free(servercert);
626 656
627 peercert = SSL_get_peer_certificate(ssl); 657 peercert = SSL_get_peer_certificate(myssl);
628 if (!peercert) { 658 if (!peercert) {
629 out("ZTLS unable to verify server "); 659 out("ZTLS unable to verify server ");
630 tls_quit(partner_fqdn, "no certificate provided"); 660 tls_quit(partner_fqdn, "no certificate provided");
@@ -651,10 +681,7 @@ int tls_init()
651 if (i >= 0) { 681 if (i >= 0) {
652 X509_NAME_ENTRY *entry = X509_NAME_get_entry(subj, i); 682 X509_NAME_ENTRY *entry = X509_NAME_get_entry(subj, i);
653 ASN1_STRING *s = X509_NAME_ENTRY_get_data(entry); 683 ASN1_STRING *s = X509_NAME_ENTRY_get_data(entry);
654#if OPENSSL_VERSION_NUMBER < 0x10100005L 684 if (s) { peer.len = ASN1_STRING_length(s); peer.s = (char *)ASN1_STRING_get0_data(s); }
655#define ASN1_STRING_get0_data ASN1_STRING_data
656#endif
657 if (s) { peer.len = ASN1_STRING_length(s); peer.s = (unsigned char *)ASN1_STRING_get0_data(s); }
658 } 685 }
659 if (peer.len <= 0) { 686 if (peer.len <= 0) {
660 out("ZTLS unable to verify server "); 687 out("ZTLS unable to verify server ");
@@ -669,8 +696,8 @@ int tls_init()
669 X509_free(peercert); 696 X509_free(peercert);
670 } 697 }
671 /* DANE: verify result */ 698 /* DANE: verify result */
672 else if (dane_retval == VAL_DANE_NOERROR) { 699 else if (tlsa_rr.len) {
673 if (!SSL_get_peer_certificate(ssl) || SSL_get_verify_result(ssl) != X509_V_OK) { 700 if (!SSL_get_peer_certificate(myssl) || SSL_get_verify_result(myssl) != X509_V_OK) {
674 out("lNo TLSA record matched: "); 701 out("lNo TLSA record matched: ");
675 out(partner_fqdn); 702 out(partner_fqdn);
676 quit2("/", NULL, 0); 703 quit2("/", NULL, 0);
@@ -746,33 +773,22 @@ void mail_without_auth()
746 773
747void smtp() 774void smtp()
748{ 775{
749 unsigned long code; 776 unsigned long code = 0;
750 int flagbother; 777 int flagbother;
751 int i, j;
752
753#ifndef PORT_SMTP
754 /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
755# define port smtp_port
756#endif
757 778
758#ifdef TLS 779#ifdef TLS
759# ifdef MXPS 780 if (smtp_port == 465) smtps = 1;
760 if (type == 'S') smtps = 1; 781 if (!smtps) {
761 else if (type != 's')
762# endif
763 if (port == 465) smtps = 1;
764 if (!smtps)
765#endif 782#endif
766
767 code = smtpcode(); 783 code = smtpcode();
768 if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed"); 784 if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed");
769 if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */ 785 if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */
770 if (code != 220) quit("ZConnected to "," but greeting failed"); 786 if (code != 220) quit("ZConnected to "," but greeting failed");
771 787
788 code = ehlo();
772#ifdef TLS 789#ifdef TLS
773 if (!smtps) 790 }
774#endif 791#endif
775 code = ehlo();
776 792
777#ifdef TLS 793#ifdef TLS
778 int tls = tls_init(); 794 int tls = tls_init();
@@ -782,7 +798,7 @@ void smtp()
782 ssl = NULL; 798 ssl = NULL;
783 return; /* try next MX */ 799 return; /* try next MX */
784 } 800 }
785 else if (tls) 801 else if (tls > 0)
786 /* RFC2487 says we should issue EHLO (even if we might not need 802 /* RFC2487 says we should issue EHLO (even if we might not need
787 * extensions); at the same time, it does not prohibit a server 803 * extensions); at the same time, it does not prohibit a server
788 * to reject the EHLO and make us fallback to HELO */ 804 * to reject the EHLO and make us fallback to HELO */
@@ -803,7 +819,7 @@ void smtp()
803 if (code != 250) quit("ZConnected to "," but my name was rejected"); 819 if (code != 250) quit("ZConnected to "," but my name was rejected");
804 } 820 }
805 821
806 i = 0; 822 int i = 0;
807 if (auth_smtp_user.len && auth_smtp_pass.len) { 823 if (auth_smtp_user.len && auth_smtp_pass.len) {
808 while((i += str_chr(smtptext.s+i,'\n') + 1) && 824 while((i += str_chr(smtptext.s+i,'\n') + 1) &&
809 (i+8 < smtptext.len) && 825 (i+8 < smtptext.len) &&
@@ -854,7 +870,7 @@ void smtp()
854 if (code >= 400) quit("ZConnected to "," but sender was rejected"); 870 if (code >= 400) quit("ZConnected to "," but sender was rejected");
855 871
856 flagbother = 0; 872 flagbother = 0;
857 for (i = 0;i < reciplist.len;++i) { 873 for (int i = 0;i < reciplist.len;++i) {
858 substdio_puts(&smtpto,"RCPT TO:<"); 874 substdio_puts(&smtpto,"RCPT TO:<");
859 substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); 875 substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len);
860 substdio_puts(&smtpto,">\r\n"); 876 substdio_puts(&smtpto,">\r\n");
@@ -907,7 +923,6 @@ void qmtp()
907{ 923{
908 struct stat st; 924 struct stat st;
909 unsigned long len; 925 unsigned long len;
910 int len2;
911 char *x; 926 char *x;
912 int i; 927 int i;
913 int n; 928 int n;
@@ -1039,9 +1054,11 @@ void getcontrols()
1039 case -1: 1054 case -1:
1040 temp_control(); 1055 temp_control();
1041 case 0: 1056 case 0:
1042 if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break; 1057 if (!constmap_init(&maproutes,"",0,1)) temp_nomem();
1058 break;
1043 case 1: 1059 case 1:
1044 if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; 1060 if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem();
1061 break;
1045 } 1062 }
1046} 1063}
1047 1064
@@ -1074,7 +1091,7 @@ char **argv;
1074 relayhost = 0; 1091 relayhost = 0;
1075 for (i = 0;i <= host.len;++i) 1092 for (i = 0;i <= host.len;++i)
1076 if ((i == 0) || (i == host.len) || (host.s[i] == '.')) 1093 if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
1077 if (relayhost = constmap(&maproutes,host.s + i,host.len - i)) 1094 if ((relayhost = constmap(&maproutes,host.s + i,host.len - i)))
1078 break; 1095 break;
1079 if (relayhost && !*relayhost) relayhost = 0; 1096 if (relayhost && !*relayhost) relayhost = 0;
1080 1097
diff --git a/qmail-smtpd.c b/qmail-smtpd.c
index 5ea23dc..0d3b16d 100644
--- a/qmail-smtpd.c
+++ b/qmail-smtpd.c
@@ -67,8 +67,6 @@ static const stralloc *client_get_session_id();
67 67
68#ifdef TLS 68#ifdef TLS
69# include <sys/stat.h> 69# include <sys/stat.h>
70# include <openssl/bn.h>
71# include <openssl/dh.h>
72# include "tls.h" 70# include "tls.h"
73# include "ssl_timeoutio.h" 71# include "ssl_timeoutio.h"
74 72
@@ -208,7 +206,7 @@ int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\
208void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); } 206void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
209void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); do_hard_errors(); } 207void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); do_hard_errors(); }
210int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); do_hard_errors(); return -1; } 208int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); do_hard_errors(); return -1; }
211int err_noauth2() { out("503 auth not available (#5.3.3)\r\n"); do_hard_errors(); } 209int err_noauth2() { out("503 auth not available (#5.3.3)\r\n"); do_hard_errors(); return -1; }
212int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; } 210int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; }
213int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; } 211int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
214int err_wantstarttls() { out("530 Must issue a STARTTLS command first (#5.7.0)\r\n"); return -1; }; 212int err_wantstarttls() { out("530 Must issue a STARTTLS command first (#5.7.0)\r\n"); return -1; };
@@ -386,7 +384,7 @@ char *arg;
386 if (!stralloc_copys(&addr,"")) die_nomem(); 384 if (!stralloc_copys(&addr,"")) die_nomem();
387 flagesc = 0; 385 flagesc = 0;
388 flagquoted = 0; 386 flagquoted = 0;
389 for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */ 387 for (i = 0; (ch = arg[i]); ++i) { /* copy arg to addr, stripping quotes */
390 if (flagesc) { 388 if (flagesc) {
391 if (!stralloc_append(&addr,&ch)) die_nomem(); 389 if (!stralloc_append(&addr,&ch)) die_nomem();
392 flagesc = 0; 390 flagesc = 0;
@@ -485,7 +483,7 @@ int bmcheck(which) int which;
485 } 483 }
486 if ((negate) && (x == 0)) { 484 if ((negate) && (x == 0)) {
487 if (!stralloc_copyb(&matchedregex,bmb.s + j - 1,(i - j + 1))) die_nomem(); 485 if (!stralloc_copyb(&matchedregex,bmb.s + j - 1,(i - j + 1))) die_nomem();
488 if (!stralloc_0(&matchedregex)) die_nomem(); 486 if (!stralloc_0(&matchedregex)) die_nomem();
489 return 1; 487 return 1;
490 } 488 }
491 if (!(negate) && (x > 0)) { 489 if (!(negate) && (x > 0)) {
@@ -582,8 +580,6 @@ void mailfrom_auth(arg,len)
582char *arg; 580char *arg;
583int len; 581int len;
584{ 582{
585 int j;
586
587 if (!stralloc_copys(&fuser,"")) die_nomem(); 583 if (!stralloc_copys(&fuser,"")) die_nomem();
588 if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); } 584 if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
589 else 585 else
@@ -610,7 +606,7 @@ void mailfrom_parms(arg) char *arg;
610 int len; 606 int len;
611 607
612 len = str_len(arg); 608 len = str_len(arg);
613 if (!stralloc_copys(&mfparms,"")) die_nomem; 609 if (!stralloc_copys(&mfparms,"")) die_nomem();
614 i = byte_chr(arg,len,'>'); 610 i = byte_chr(arg,len,'>');
615 if (i > 4 && i < len) { 611 if (i > 4 && i < len) {
616 while (len) { 612 while (len) {
@@ -622,10 +618,10 @@ void mailfrom_parms(arg) char *arg;
622 if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; } 618 if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
623 /* we do not support this */ 619 /* we do not support this */
624 //if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5); 620 //if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);
625 if (!stralloc_copys(&mfparms,"")) die_nomem; 621 if (!stralloc_copys(&mfparms,"")) die_nomem();
626 } 622 }
627 else 623 else
628 if (!stralloc_catb(&mfparms,arg,1)) die_nomem; 624 if (!stralloc_catb(&mfparms,arg,1)) die_nomem();
629 } 625 }
630 } 626 }
631} 627}
@@ -1094,17 +1090,17 @@ int authenticate(void)
1094 if (authout.len > 0) { 1090 if (authout.len > 0) {
1095 len = authout.len; 1091 len = authout.len;
1096 arg = authout.s; 1092 arg = authout.s;
1097 if (!stralloc_copys(&authparams, "")) die_nomem; 1093 if (!stralloc_copys(&authparams, "")) die_nomem();
1098 while (len) { 1094 while (len) {
1099 if (*arg == '\0') { 1095 if (*arg == '\0') {
1100 if (case_starts(authparams.s, "USER=") && (authparams.len - 5) > 0) { 1096 if (case_starts(authparams.s, "USER=") && (authparams.len - 5) > 0) {
1101 if (!stralloc_copyb(&user, authparams.s + 5, authparams.len - 5)) die_nomem(); 1097 if (!stralloc_copyb(&user, authparams.s + 5, authparams.len - 5)) die_nomem();
1102 if (!stralloc_0(&user)) die_nomem(); 1098 if (!stralloc_0(&user)) die_nomem();
1103 } 1099 }
1104 if (!stralloc_copys(&authparams, "")) die_nomem; 1100 if (!stralloc_copys(&authparams, "")) die_nomem();
1105 } 1101 }
1106 else 1102 else
1107 if (!stralloc_catb(&authparams, arg, 1)) die_nomem; 1103 if (!stralloc_catb(&authparams, arg, 1)) die_nomem();
1108 arg++; 1104 arg++;
1109 len--; 1105 len--;
1110 } 1106 }
@@ -1130,19 +1126,19 @@ int auth_login(arg) char *arg;
1130 if (tls_before_auth && !ssl) return err_wantstarttls(); 1126 if (tls_before_auth && !ssl) return err_wantstarttls();
1131#endif 1127#endif
1132 if (*arg) { 1128 if (*arg) {
1133 if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input(); 1129 if ((r = b64decode(arg,str_len(arg),&user)) == 1) return err_input();
1134 } 1130 }
1135 else { 1131 else {
1136 out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */ 1132 out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
1137 if (authgetl() < 0) return -1; 1133 if (authgetl() < 0) return -1;
1138 if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input(); 1134 if ((r = b64decode(authin.s,authin.len,&user)) == 1) return err_input();
1139 } 1135 }
1140 if (r == -1) die_nomem(); 1136 if (r == -1) die_nomem();
1141 1137
1142 out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */ 1138 out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
1143 1139
1144 if (authgetl() < 0) return -1; 1140 if (authgetl() < 0) return -1;
1145 if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input(); 1141 if ((r = b64decode(authin.s,authin.len,&pass)) == 1) return err_input();
1146 if (r == -1) die_nomem(); 1142 if (r == -1) die_nomem();
1147 1143
1148 if (!user.len || !pass.len) return err_input(); 1144 if (!user.len || !pass.len) return err_input();
@@ -1157,12 +1153,12 @@ int auth_plain(arg) char *arg;
1157 if (tls_before_auth && !ssl) return err_wantstarttls(); 1153 if (tls_before_auth && !ssl) return err_wantstarttls();
1158#endif 1154#endif
1159 if (*arg) { 1155 if (*arg) {
1160 if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input(); 1156 if ((r = b64decode(arg,str_len(arg),&resp)) == 1) return err_input();
1161 } 1157 }
1162 else { 1158 else {
1163 out("334 \r\n"); flush(); 1159 out("334 \r\n"); flush();
1164 if (authgetl() < 0) return -1; 1160 if (authgetl() < 0) return -1;
1165 if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input(); 1161 if ((r = b64decode(authin.s,authin.len,&resp)) == 1) return err_input();
1166 } 1162 }
1167 if (r == -1 || !stralloc_0(&resp)) die_nomem(); 1163 if (r == -1 || !stralloc_0(&resp)) die_nomem();
1168 while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */ 1164 while (resp.s[id]) id++; /* "authorize-id\0userid\0passwd\0" */
@@ -1297,140 +1293,6 @@ void smtp_tls(char *arg)
1297 else tls_init(); 1293 else tls_init();
1298} 1294}
1299 1295
1300/*
1301 * Grab well-defined DH parameters from OpenSSL, see the get_rfc*
1302 * functions in <openssl/bn.h> for all available primes.
1303 */
1304#if OPENSSL_VERSION_NUMBER < 0x10100005L
1305static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
1306{
1307 /* q is optional */
1308 if (p == NULL || g == NULL)
1309 return 0;
1310 BN_free(dh->p);
1311 BN_free(dh->q);
1312 BN_free(dh->g);
1313 dh->p = p;
1314 dh->q = q;
1315 dh->g = g;
1316
1317 if (q != NULL)
1318 dh->length = BN_num_bits(q);
1319
1320 return 1;
1321}
1322#endif
1323
1324static DH *make_dh_params(BIGNUM *(*prime)(BIGNUM *))
1325{
1326 BIGNUM *p, *g;
1327 DH *dh = DH_new();
1328 if (!dh)
1329 return NULL;
1330
1331 p = prime(NULL);
1332 g = BN_new();
1333 if (g != NULL)
1334 BN_set_word(g, 2);
1335 if (!p || !g || !DH_set0_pqg(dh, p, NULL, g)) {
1336 DH_free(dh);
1337 BN_free(p);
1338 BN_free(g);
1339 return NULL;
1340 }
1341 return dh;
1342}
1343
1344/* Storage and initialization for DH parameters. */
1345static struct dhparam {
1346 BIGNUM *(*const prime)(BIGNUM *); /* function to generate... */
1347 DH *dh; /* ...this, used for keys.... */
1348 const unsigned int min; /* ...of length >= this. */
1349} dhparams[] = {
1350 { get_rfc3526_prime_8192, NULL, 6145 },
1351 { get_rfc3526_prime_6144, NULL, 4097 },
1352 { get_rfc3526_prime_4096, NULL, 3073 },
1353 { get_rfc3526_prime_3072, NULL, 2049 },
1354 { get_rfc3526_prime_2048, NULL, 1025 },
1355 { get_rfc2409_prime_1024, NULL, 0 }
1356};
1357
1358/* Hand out the same DH structure though once generated as we leak
1359 * memory otherwise and freeing the structure up after use would be
1360 * hard to track and in fact is not needed at all as it is safe to
1361 * use the same parameters over and over again security wise (in
1362 * contrast to the keys itself) and code safe as the returned structure
1363 * is duplicated by OpenSSL anyway. Hence no modification happens
1364 * to our copy. */
1365static DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
1366{
1367 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
1368 int type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
1369 unsigned n;
1370
1371 /*
1372 * OpenSSL will call us with either keylen == 512 or keylen == 1024
1373 * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
1374 * Adjust the DH parameter length according to the size of the
1375 * RSA/DSA private key used for the current connection, and always
1376 * use at least 1024-bit parameters.
1377 * Note: This may cause interoperability issues with implementations
1378 * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
1379 * In this case, SSLCertificateFile can be used to specify fixed
1380 * 1024-bit DH parameters (with the effect that OpenSSL skips this
1381 * callback).
1382 */
1383 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA)
1384 keylen = EVP_PKEY_bits(pkey);
1385
1386 for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++) {
1387 if (keylen >= dhparams[n].min) {
1388 if (dhparams[n].dh == NULL)
1389 dhparams[n].dh = make_dh_params(dhparams[n].prime);
1390 return dhparams[n].dh;
1391 }
1392 }
1393
1394 return NULL; /* impossible to reach. */
1395}
1396
1397static DH *ssl_dh_GetParamFromFile(const char *file)
1398{
1399 DH *dh = NULL;
1400 BIO *bio;
1401
1402 if ((bio = BIO_new_file(file, "r")) == NULL)
1403 return NULL;
1404 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1405 BIO_free(bio);
1406 if (!dh)
1407 (void)ERR_get_error();
1408 return dh;
1409}
1410
1411#ifdef HAVE_ECC
1412static EC_GROUP *ssl_ec_GetParamFromFile(const char *file)
1413{
1414 EC_GROUP *group = NULL;
1415 BIO *bio;
1416
1417 if ((bio = BIO_new_file(file, "r")) == NULL)
1418 return NULL;
1419 group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL);
1420 BIO_free(bio);
1421 if (!group)
1422 (void)ERR_get_error();
1423 return group;
1424}
1425
1426#if !defined(SSL_set_ecdh_auto)
1427static EC_KEY *tmp_ecdh_cb(SSL *ssl, int export, int keylen)
1428{
1429 return EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1430}
1431#endif
1432#endif
1433
1434/* don't want to fail handshake if cert isn't verifiable */ 1296/* don't want to fail handshake if cert isn't verifiable */
1435int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; } 1297int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
1436 1298
@@ -1455,15 +1317,7 @@ void tls_init()
1455 SSL_CTX *ctx; 1317 SSL_CTX *ctx;
1456 const char *ciphers; 1318 const char *ciphers;
1457 stralloc saciphers = {0}; 1319 stralloc saciphers = {0};
1458 X509_STORE *store;
1459 X509_LOOKUP *lookup;
1460 const char *servercert, *servercert2; 1320 const char *servercert, *servercert2;
1461 DH *dhparams;
1462#ifdef HAVE_ECC
1463 EC_GROUP *ecparams;
1464 int nid;
1465 EC_KEY *eckey = NULL;
1466#endif
1467 struct stat st; 1321 struct stat st;
1468 1322
1469 /* if set, use servercert selected through SMTP_SERVERCERT env var */ 1323 /* if set, use servercert selected through SMTP_SERVERCERT env var */
@@ -1475,7 +1329,7 @@ void tls_init()
1475 SSL_library_init(); 1329 SSL_library_init();
1476 1330
1477 /* a new SSL context with the bare minimum of options */ 1331 /* a new SSL context with the bare minimum of options */
1478 ctx = SSL_CTX_new(SSLv23_server_method()); 1332 ctx = SSL_CTX_new(TLS_server_method());
1479 if (!ctx) { tls_err("unable to initialize ctx"); return; } 1333 if (!ctx) { tls_err("unable to initialize ctx"); return; }
1480 int min_ssl_version = (*childargs) ? TLS1_2_VERSION : TLS1_VERSION; 1334 int min_ssl_version = (*childargs) ? TLS1_2_VERSION : TLS1_VERSION;
1481 SSL_CTX_set_min_proto_version(ctx, min_ssl_version); 1335 SSL_CTX_set_min_proto_version(ctx, min_ssl_version);
@@ -1490,13 +1344,13 @@ void tls_init()
1490 1344
1491 /* this will also check whether public and private keys match */ 1345 /* this will also check whether public and private keys match */
1492 if (!SSL_CTX_use_PrivateKey_file(ctx, servercert, SSL_FILETYPE_PEM)) 1346 if (!SSL_CTX_use_PrivateKey_file(ctx, servercert, SSL_FILETYPE_PEM))
1493 { SSL_free(myssl); tls_err("no valid private key"); return; } 1347 { SSL_CTX_free(ctx); tls_err("no valid private key"); return; }
1494 1348
1495 if (stat(servercert2, &st) == 0) { 1349 if (stat(servercert2, &st) == 0) {
1496 if (!SSL_CTX_use_certificate_chain_file(ctx, servercert2)) 1350 if (!SSL_CTX_use_certificate_chain_file(ctx, servercert2))
1497 { SSL_CTX_free(ctx); tls_err("missing alternate certificate"); return; } 1351 { SSL_CTX_free(ctx); tls_err("invalid alternate certificate"); return; }
1498 if (!SSL_CTX_use_PrivateKey_file(ctx, servercert2, SSL_FILETYPE_PEM)) 1352 if (!SSL_CTX_use_PrivateKey_file(ctx, servercert2, SSL_FILETYPE_PEM))
1499 { SSL_free(myssl); tls_err("no valid alternate private key"); return; } 1353 { SSL_CTX_free(ctx); tls_err("no valid alternate private key"); return; }
1500 } 1354 }
1501 1355
1502 /* a new SSL object, with the rest added to it directly to avoid copying */ 1356 /* a new SSL object, with the rest added to it directly to avoid copying */
@@ -1519,39 +1373,17 @@ void tls_init()
1519 SSL_set_cipher_list(myssl, ciphers); 1373 SSL_set_cipher_list(myssl, ciphers);
1520 alloc_free(saciphers.s); 1374 alloc_free(saciphers.s);
1521 1375
1522 //TODO: we shouldn't use hardcoded DH: see https://weakdh.org/ 1376 SSL_set_dh_auto(myssl, 1);
1523 SSL_set_tmp_dh_callback(myssl, tmp_dh_cb); 1377 SSL_set_ecdh_auto(myssl, 1);
1524
1525 /* try to read DH parameters from certificate */
1526 if ((dhparams = ssl_dh_GetParamFromFile(servercert)))
1527 SSL_set_tmp_dh(myssl, dhparams);
1528
1529#ifdef HAVE_ECC
1530 /* similarly, try to read the ECDH curve name from certificate... */
1531 if ((ecparams = ssl_ec_GetParamFromFile(servercert)) &&
1532 (nid = EC_GROUP_get_curve_name(ecparams)) &&
1533 (eckey = EC_KEY_new_by_curve_name(nid))) {
1534 SSL_set_tmp_ecdh(myssl, eckey);
1535 }
1536 else {
1537#if defined(SSL_set_ecdh_auto)
1538 /* ...otherwise, enable auto curve selection (OpenSSL 1.0.2 and later) */
1539 SSL_set_ecdh_auto(myssl, 1);
1540#else
1541 /* or set callback, which will configure NIST P-256 */
1542 SSL_set_tmp_ecdh_callback(myssl, tmp_ecdh_cb);
1543#endif
1544 }
1545 EC_KEY_free(eckey);
1546#endif
1547 1378
1548#if OPENSSL_VERSION_NUMBER >= 0x10100005L
1549 stralloc opensslconf = {0}; 1379 stralloc opensslconf = {0};
1550 if (control_readfile(&opensslconf, "control/opensslconf", 0) == -1) 1380 if (control_readfile(&opensslconf, "control/opensslconf", 0) == -1)
1551 { SSL_free(myssl); die_control(); } 1381 { SSL_free(myssl); die_control(); }
1552 if (opensslconf.len) { 1382 if (opensslconf.len) {
1553 SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); 1383 SSL_CONF_CTX *cctx = SSL_CONF_CTX_new();
1554 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); 1384 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
1385 /* client + server so we can share one single file */
1386 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
1555 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); 1387 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
1556 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); 1388 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
1557 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); 1389 SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
@@ -1579,7 +1411,6 @@ void tls_init()
1579 1411
1580 (void)SSL_CONF_CTX_finish(cctx); 1412 (void)SSL_CONF_CTX_finish(cctx);
1581 } 1413 }
1582#endif
1583 1414
1584 SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin)); 1415 SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
1585 SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout)); 1416 SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));