summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2023-09-26 14:11:58 +0200
committermanuel <manuel@mausz.at>2023-09-26 14:11:58 +0200
commitff1e0ece50986156e0b6f5f37985833ed0ae6c97 (patch)
tree1f3c3a158ec75c6b175ba9b081bd5ff4ea819c81
parent52e4c7626ff891fbaf2eb2ced1d0f42eb05dd17d (diff)
downloadqmail-ff1e0ece50986156e0b6f5f37985833ed0ae6c97.tar.gz
qmail-ff1e0ece50986156e0b6f5f37985833ed0ae6c97.tar.bz2
qmail-ff1e0ece50986156e0b6f5f37985833ed0ae6c97.zip
Add support for "require TLS"-settings
-rw-r--r--qmail-remote.c48
-rw-r--r--qmail-smtpd.c21
2 files changed, 56 insertions, 13 deletions
diff --git a/qmail-remote.c b/qmail-remote.c
index 125d813..a743e06 100644
--- a/qmail-remote.c
+++ b/qmail-remote.c
@@ -9,6 +9,7 @@
9#include "substdio.h" 9#include "substdio.h"
10#include "subfd.h" 10#include "subfd.h"
11#include "scan.h" 11#include "scan.h"
12#include "byte.h"
12#include "case.h" 13#include "case.h"
13#include "error.h" 14#include "error.h"
14#include "auto_qmail.h" 15#include "auto_qmail.h"
@@ -401,6 +402,7 @@ static int tls_init(struct ip_mx *current_mx)
401 stralloc saciphers = {0}; 402 stralloc saciphers = {0};
402 const char *ciphers, *servercert = 0; 403 const char *ciphers, *servercert = 0;
403 const char *mx_host = current_mx->fqdn; 404 const char *mx_host = current_mx->fqdn;
405 const char *failure_class = "Z"; // per default we do temp failures
404 406
405 if (mx_host) { 407 if (mx_host) {
406 struct stat st; 408 struct stat st;
@@ -425,10 +427,26 @@ static int tls_init(struct ip_mx *current_mx)
425 } 427 }
426 } 428 }
427 429
428 /* DANE: lookup TLSA records */
429 int tls_required = (smtps || servercert != NULL); 430 int tls_required = (smtps || servercert != NULL);
430 stralloc tlsa_rr = { 0 };
431 431
432 /* per-domain "require TLS"-settings */
433 if (!tls_required) {
434 int at = byte_rchr(sender.s, sender.len, '@') + 1;
435 if (at < sender.len) {
436 stralloc tmp = { 0 };
437 if (!stralloc_copys(&tmp, "control/tlsrequire/")
438 || !stralloc_catb(&tmp, sender.s + at, sender.len - at)
439 || !stralloc_0(&tmp)) // sender is not 0-terminated
440 temp_nomem();
441 if (control_readint(&tls_required, tmp.s) == -1) temp_control();
442 tls_required = (tls_required & 0x02) ? 1 : 0; // 2nd bit is SMTP outgoing
443 if (tls_required)
444 failure_class = "D"; // do perm failures for faster user feedback
445 }
446 }
447
448 /* DANE: lookup TLSA records */
449 stralloc tlsa_rr = { 0 };
432 if (mx_host && !servercert && current_mx->validated) { 450 if (mx_host && !servercert && current_mx->validated) {
433 stralloc tlsa_label = { 0 }; 451 stralloc tlsa_label = { 0 };
434 char port[FMT_ULONG]; 452 char port[FMT_ULONG];
@@ -456,8 +474,10 @@ static int tls_init(struct ip_mx *current_mx)
456 for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ; 474 for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
457 if (!len) { 475 if (!len) {
458 if (!tls_required) return 0; 476 if (!tls_required) return 0;
459 out("ZNo TLS achieved while TLS is required by configuration"); 477 out(failure_class);
460 smtptext.len = 0; TLS_QUIT; 478 out("TLS is required, but was not offered by host");
479 smtptext.len = 0;
480 TLS_QUIT;
461 } 481 }
462 } 482 }
463 483
@@ -615,10 +635,12 @@ static int tls_init(struct ip_mx *current_mx)
615 635
616 /* read the responce to STARTTLS */ 636 /* read the responce to STARTTLS */
617 if (!smtps) { 637 if (!smtps) {
618 if (smtpcode() != 220) { 638 unsigned int code = smtpcode();
639 if (code != 220) {
619 SSL_free(myssl); 640 SSL_free(myssl);
620 if (!tls_required) return 0; 641 if (!tls_required) return 0;
621 out("ZSTARTTLS rejected while TLS is required by configuration"); 642 out((code >= 500) ? "D" : failure_class);
643 out("TLS is required, but host refused to start TLS");
622 TLS_QUIT; 644 TLS_QUIT;
623 } 645 }
624 smtptext.len = 0; 646 smtptext.len = 0;
@@ -626,8 +648,10 @@ static int tls_init(struct ip_mx *current_mx)
626 648
627 ssl = myssl; 649 ssl = myssl;
628 if (ssl_timeoutconn(timeout, smtpfd, smtpfd, myssl) <= 0) { 650 if (ssl_timeoutconn(timeout, smtpfd, smtpfd, myssl) <= 0) {
629 if (tls_required) 651 if (tls_required) {
630 tls_quit("ZTLS connect failed", ssl_error_str()); 652 out(failure_class);
653 tls_quit("TLS connect failed", ssl_error_str());
654 }
631 else { 655 else {
632 out("lTLS connect failed"); 656 out("lTLS connect failed");
633 const char *err = ssl_error_str(); 657 const char *err = ssl_error_str();
@@ -707,8 +731,12 @@ static int tls_init(struct ip_mx *current_mx)
707 } 731 }
708 } 732 }
709 733
710 if (smtps) if (smtpcode() != 220) 734 if (smtps) {
711 quit("ZTLS Connected to "," but greeting failed"); 735 unsigned int code = smtpcode();
736 if (code >= 500 && code < 600) quit("DTLS connected to "," but greeting failed");
737 if (code >= 400 && code < 500) return -1; /* try next MX, see RFC-2821 */
738 if (code != 220) quit("ZTLS connected to "," but greeting failed");
739 }
712 740
713 return 1; 741 return 1;
714} 742}
diff --git a/qmail-smtpd.c b/qmail-smtpd.c
index 48a66b1..d0395fc 100644
--- a/qmail-smtpd.c
+++ b/qmail-smtpd.c
@@ -78,7 +78,7 @@ void tls_nogateway();
78int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */ 78int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
79stralloc proto = {0}; 79stralloc proto = {0};
80int tls_before_auth = 0; 80int tls_before_auth = 0;
81int tls_require = 0; 81int tls_required = 0;
82#endif 82#endif
83 83
84#ifdef SMTPUTF8 84#ifdef SMTPUTF8
@@ -344,7 +344,7 @@ void setup()
344 344
345#ifdef TLS 345#ifdef TLS
346 if (env_get("TLSBEFOREAUTH")) tls_before_auth = 1; 346 if (env_get("TLSBEFOREAUTH")) tls_before_auth = 1;
347 if (env_get("TLSREQUIRE")) tls_require = 1; 347 if (env_get("TLSREQUIRE")) tls_required = 1;
348 if (env_get("SMTPS")) { smtps = 1; tls_init(); } 348 if (env_get("SMTPS")) { smtps = 1; tls_init(); }
349 else 349 else
350#endif 350#endif
@@ -722,7 +722,7 @@ void smtp_mail(arg) char *arg;
722{ 722{
723 if (!seenhelo) { err_wanthelo(); return; } 723 if (!seenhelo) { err_wanthelo(); return; }
724#if defined(TLS) 724#if defined(TLS)
725 if (tls_require && !ssl) { err_wantstarttls(); return; } 725 if (tls_required && !ssl) { err_wantstarttls(); return; }
726#endif 726#endif
727 if (!addrparse(arg)) { err_syntax(); return; } 727 if (!addrparse(arg)) { err_syntax(); return; }
728 flagsize = 0; 728 flagsize = 0;
@@ -818,6 +818,21 @@ void smtp_rcpt(arg) char *arg; {
818 return; 818 return;
819 } 819 }
820 } 820 }
821#if defined(TLS)
822 /* per-domain "require TLS"-settings */
823 if (!tls_required && !relayclient) {
824 int at = byte_rchr(addr.s, addr.len, '@') + 1;
825 if (at < addr.len) {
826 stralloc tmp = { 0 };
827 if (!stralloc_copys(&tmp, "control/tlsrequire/")
828 || !stralloc_catb(&tmp, addr.s + at, addr.len - at)) // addr is 0-terminated
829 die_nomem();
830 if (control_readint(&tls_required, tmp.s) == -1) die_control();
831 tls_required = (tls_required & 0x01) ? 1 : 0; // 1st bit is SMTP incoming
832 if (tls_required && !ssl) { err_wantstarttls(); return; }
833 }
834 }
835#endif
821 spp_rcpt_accepted(); 836 spp_rcpt_accepted();
822 if (!stralloc_cats(&rcptto,"T")) die_nomem(); 837 if (!stralloc_cats(&rcptto,"T")) die_nomem();
823 if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); 838 if (!stralloc_cats(&rcptto,addr.s)) die_nomem();