From 63bd58173f876ac8cc44940263483482f43f4bcd Mon Sep 17 00:00:00 2001 From: divinity76 Date: Sat, 12 Oct 2024 14:15:16 +0200 Subject: [PATCH 1/5] Add new option tls_ignore_missing_close_notify - Introduced tls_ignore_missing_close_notify to handle servers that do not send the TLS close_notify alert on shutdown. - This addresses a common issue with both Gmail and Yandex servers, which intentionally omit close_notify to save a roundtrip, despite it being against the TLS protocol. - Without this option, the omission generates spurious errors in logs, such as: "2024-10-12 09:22:27 1szVWE-0071qn-2C H=gmail-smtp-in.l.google.com [142.250.102.27] TLS error on connection (recv_tls_read): The TLS connection was non-properly terminated." - The new option allows treating this as a normal EOF, equivalent to OpenSSL's SSL_OP_IGNORE_UNEXPECTED_EOF. --- doc/doc-txt/OptionLists.txt | 1 + src/src/globals.c | 1 + src/src/globals.h | 1 + src/src/readconf.c | 1 + src/src/tls-gnu.c | 14 ++++++++++---- src/src/tls-openssl.c | 6 ++++++ 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index e7b2847605..41adf08f64 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -267,6 +267,7 @@ gecos_pattern string unset main gethostbyname boolean false smtp gnutls_allow_auto_pkcs11 boolean false main 4.82 gnutls_compat_mode boolean unset main 4.70 +tls_ignore_missing_close_notify boolean true main (todo git master) gnutls_require_kx string* unset main 4.67 deprecated, warns string* unset smtp 4.67 deprecated, warns gnutls_require_mac string* unset main 4.67 deprecated, warns diff --git a/src/src/globals.c b/src/src/globals.c index e887c27410..ff2aadd2e6 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -120,6 +120,7 @@ uschar *dsn_advertise_hosts = NULL; #ifndef DISABLE_TLS BOOL gnutls_compat_mode = FALSE; +BOOL tls_ignore_missing_close_notify = TRUE; BOOL gnutls_allow_auto_pkcs11 = FALSE; uschar *hosts_require_alpn = NULL; uschar *openssl_options = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index 5d912254d7..1af9a71864 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -128,6 +128,7 @@ extern tls_support tls_out; #ifndef DISABLE_TLS extern BOOL gnutls_compat_mode; /* Less security, more compatibility */ +extern BOOL tls_ignore_missing_close_notify; /* For semi-broken TLS servers like Gmail and Yandex */ extern BOOL gnutls_allow_auto_pkcs11; /* Let GnuTLS autoload PKCS11 modules */ extern uschar *hosts_require_alpn; /* Mandatory ALPN successful nogitiation */ extern uschar *openssl_options; /* OpenSSL compatibility options */ diff --git a/src/src/readconf.c b/src/src/readconf.c index 5ef776fea0..b8ac110402 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -168,6 +168,7 @@ static optionlist optionlist_config[] = { #ifndef DISABLE_TLS { "gnutls_allow_auto_pkcs11", opt_bool, {&gnutls_allow_auto_pkcs11} }, { "gnutls_compat_mode", opt_bool, {&gnutls_compat_mode} }, + { "tls_ignore_missing_close_notify", opt_bool, {&tls_ignore_missing_close_notify} }, #endif { "header_line_maxsize", opt_int, {&header_line_maxsize} }, { "header_maxsize", opt_int, {&header_maxsize} }, diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 7963e2c97b..96da8ba7b7 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -4034,14 +4034,20 @@ do while (inbytes == GNUTLS_E_AGAIN); if (inbytes > 0) return inbytes; -if (inbytes == 0) +if (inbytes == 0 + // there is a "bug" in Gmail and Yandex servers where they do not send the tls-protocol-mandated `close_notify` on connection close. + // They do it intentionally to save time (skip a roundtrip), but it is against tls-protocol and does spam the exim4 errorlogs like + // 2024-10-12 09:22:27 1szVWE-0071qn-2C H=gmail-smtp-in.l.google.com [142.250.102.27] TLS error on connection (recv_tls_read): The TLS connection was non-properly terminated. + // optionally treat this as a normal EOF. + // This is equivalent to OpenSSL's SSL_OP_IGNORE_UNEXPECTED_EOF flag. + || (tls_ignore_missing_close_notify && inbytes == GNUTLS_E_PREMATURE_TERMINATION)) { - DEBUG(D_tls) debug_printf("Got TLS_EOF\n"); + DEBUG(D_tls) debug_printf("Got TLS_EOF\n"); } else { - DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv\n", __FUNCTION__); - record_io_error(state, (int)inbytes, US"recv", NULL); + DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv\n", __FUNCTION__); + record_io_error(state, (int)inbytes, US"recv", NULL); } return -1; diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 302404b6c9..ef90c0a918 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2954,6 +2954,12 @@ if (init_options) #ifdef OPENSSL_MIN_PROTO_VERSION SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION); #endif +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF + if(tls_ignore_missing_close_notify) { + init_options |= SSL_OP_IGNORE_UNEXPECTED_EOF; + } +#endif + DEBUG(D_tls) debug_printf("setting SSL CTX options: %016lx\n", init_options); SSL_CTX_set_options(ctx, init_options); { From 34d4ce03260bf7b6ded8a5f61e7b02601461f9b4 Mon Sep 17 00:00:00 2001 From: divinity76 Date: Sat, 12 Oct 2024 16:15:14 +0200 Subject: [PATCH 2/5] sort alphabetically https://github.com/Exim/exim/pull/94#discussion_r1797707572 --- src/src/readconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src/readconf.c b/src/src/readconf.c index b8ac110402..f016531d59 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -168,7 +168,6 @@ static optionlist optionlist_config[] = { #ifndef DISABLE_TLS { "gnutls_allow_auto_pkcs11", opt_bool, {&gnutls_allow_auto_pkcs11} }, { "gnutls_compat_mode", opt_bool, {&gnutls_compat_mode} }, - { "tls_ignore_missing_close_notify", opt_bool, {&tls_ignore_missing_close_notify} }, #endif { "header_line_maxsize", opt_int, {&header_line_maxsize} }, { "header_maxsize", opt_int, {&header_maxsize} }, @@ -384,6 +383,7 @@ static optionlist optionlist_config[] = { { "tls_dh_max_bits", opt_int, {&tls_dh_max_bits} }, { "tls_dhparam", opt_stringptr, {&tls_dhparam} }, { "tls_eccurve", opt_stringptr, {&tls_eccurve} }, + { "tls_ignore_missing_close_notify", opt_bool, {&tls_ignore_missing_close_notify} }, # ifndef DISABLE_OCSP { "tls_ocsp_file", opt_stringptr, {&tls_ocsp_file} }, # endif From fa0fad6efbef7131202c4631c27a6249691a9d14 Mon Sep 17 00:00:00 2001 From: divinity76 Date: Sat, 12 Oct 2024 16:17:45 +0200 Subject: [PATCH 3/5] sort alphabetically --- doc/doc-txt/OptionLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index 41adf08f64..3c64961618 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -267,7 +267,6 @@ gecos_pattern string unset main gethostbyname boolean false smtp gnutls_allow_auto_pkcs11 boolean false main 4.82 gnutls_compat_mode boolean unset main 4.70 -tls_ignore_missing_close_notify boolean true main (todo git master) gnutls_require_kx string* unset main 4.67 deprecated, warns string* unset smtp 4.67 deprecated, warns gnutls_require_mac string* unset main 4.67 deprecated, warns @@ -618,6 +617,7 @@ tls_certificate string* unset main tls_dh_max_bits integer 2236 main 4.80 tls_dh_min_bits integer 1024 smtp 4.82 tls_dhparam string* unset main 3.20 +tls_ignore_missing_close_notify boolean true main (todo git master) tls_ocsp_file string* unset main 4.80 if experimental_ocsp tls_on_connect_ports string unset main 4.43 tls_privatekey string* unset main 3.20 From 8c8d6b910f3743933d8b6223759462fa0623c57e Mon Sep 17 00:00:00 2001 From: divinity76 Date: Sat, 12 Oct 2024 16:19:36 +0200 Subject: [PATCH 4/5] sort alphabetically --- src/src/globals.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src/globals.c b/src/src/globals.c index ff2aadd2e6..4a4b729b49 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -120,7 +120,6 @@ uschar *dsn_advertise_hosts = NULL; #ifndef DISABLE_TLS BOOL gnutls_compat_mode = FALSE; -BOOL tls_ignore_missing_close_notify = TRUE; BOOL gnutls_allow_auto_pkcs11 = FALSE; uschar *hosts_require_alpn = NULL; uschar *openssl_options = NULL; @@ -135,6 +134,7 @@ bit-count as "NORMAL" (2432) and Thunderbird dropping connection. */ int tls_dh_max_bits = 2236; uschar *tls_dhparam = NULL; uschar *tls_eccurve = US"auto"; +BOOL tls_ignore_missing_close_notify = TRUE; # ifndef DISABLE_OCSP uschar *tls_ocsp_file = NULL; # endif From 46e010f3bb4ebe7ad9327af99f8025837f7a797b Mon Sep 17 00:00:00 2001 From: divinity76 Date: Sat, 12 Oct 2024 16:21:56 +0200 Subject: [PATCH 5/5] sort alphabetically --- src/src/globals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src/globals.h b/src/src/globals.h index 1af9a71864..4b767423c3 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -128,7 +128,6 @@ extern tls_support tls_out; #ifndef DISABLE_TLS extern BOOL gnutls_compat_mode; /* Less security, more compatibility */ -extern BOOL tls_ignore_missing_close_notify; /* For semi-broken TLS servers like Gmail and Yandex */ extern BOOL gnutls_allow_auto_pkcs11; /* Let GnuTLS autoload PKCS11 modules */ extern uschar *hosts_require_alpn; /* Mandatory ALPN successful nogitiation */ extern uschar *openssl_options; /* OpenSSL compatibility options */ @@ -139,6 +138,7 @@ extern uschar *tls_crl; /* CRL File */ extern int tls_dh_max_bits; /* don't accept higher lib suggestions */ extern uschar *tls_dhparam; /* DH param file */ extern uschar *tls_eccurve; /* EC curve */ +extern BOOL tls_ignore_missing_close_notify; /* For semi-broken TLS servers like Gmail and Yandex */ # ifndef DISABLE_OCSP extern uschar *tls_ocsp_file; /* OCSP stapling proof file */ # endif