diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index e7b2847605..3c64961618 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -617,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 diff --git a/src/src/globals.c b/src/src/globals.c index e887c27410..4a4b729b49 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -134,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 diff --git a/src/src/globals.h b/src/src/globals.h index 5d912254d7..4b767423c3 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -138,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 diff --git a/src/src/readconf.c b/src/src/readconf.c index 5ef776fea0..f016531d59 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -383,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 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); {