diff options
| author | manuel <manuel@mausz.at> | 2023-09-26 14:11:58 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2023-09-26 14:11:58 +0200 |
| commit | ff1e0ece50986156e0b6f5f37985833ed0ae6c97 (patch) | |
| tree | 1f3c3a158ec75c6b175ba9b081bd5ff4ea819c81 /qmail-remote.c | |
| parent | 52e4c7626ff891fbaf2eb2ced1d0f42eb05dd17d (diff) | |
| download | qmail-ff1e0ece50986156e0b6f5f37985833ed0ae6c97.tar.gz qmail-ff1e0ece50986156e0b6f5f37985833ed0ae6c97.tar.bz2 qmail-ff1e0ece50986156e0b6f5f37985833ed0ae6c97.zip | |
Add support for "require TLS"-settings
Diffstat (limited to 'qmail-remote.c')
| -rw-r--r-- | qmail-remote.c | 48 |
1 files changed, 38 insertions, 10 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 | } |
