git://git.exim.org
/
exim.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
583e0f4
)
OpenSSL: track shutdown calls. Bug 2864
author
Jeremy Harris
<jgh146exb@wizmail.org>
Thu, 10 Mar 2022 15:23:26 +0000
(15:23 +0000)
committer
Jeremy Harris
<jgh146exb@wizmail.org>
Wed, 16 Mar 2022 13:23:18 +0000
(13:23 +0000)
doc/doc-txt/ChangeLog
patch
|
blob
|
history
src/src/macros.h
patch
|
blob
|
history
src/src/tls-gnu.c
patch
|
blob
|
history
src/src/tls-openssl.c
patch
|
blob
|
history
src/src/transports/smtp.c
patch
|
blob
|
history
diff --git
a/doc/doc-txt/ChangeLog
b/doc/doc-txt/ChangeLog
index 5ba587b8e5c538addbd023478652612ecefacd33..1c799b6640731e3c8f91866c8c46d1a092b5a231 100644
(file)
--- a/
doc/doc-txt/ChangeLog
+++ b/
doc/doc-txt/ChangeLog
@@
-95,6
+95,11
@@
JH/21 Remove the "allow_insecure_tainted_data" main config option and the
JH/22 Fix static address-list lookups to properly return the matched item.
Previously only the domain part was returned.
JH/22 Fix static address-list lookups to properly return the matched item.
Previously only the domain part was returned.
+JH/23 Bug 2864: FreeBSD: fix transport hang after 4xx/5xx response. Previously
+ the call into OpenSSL to send a TLS Close was being repeated; this
+ resulted in the library waiting for the peer's Close. If that was never
+ sent we waited forever. Fix by tracking send calls.
+
Exim version 4.95
-----------------
Exim version 4.95
-----------------
diff --git
a/src/src/macros.h
b/src/src/macros.h
index 92f2cc08f8da5b1f37663cfd02a5b9d4a59c6f02..659a70f481f08557bb29c799cfd5bc0fae1814d1 100644
(file)
--- a/
src/src/macros.h
+++ b/
src/src/macros.h
@@
-1051,9
+1051,10
@@
enum { FILTER_UNSET, FILTER_FORWARD, FILTER_EXIM, FILTER_SIEVE };
/* Options on tls_close */
/* Options on tls_close */
-#define TLS_NO_SHUTDOWN 0
-#define TLS_SHUTDOWN_NOWAIT 1
-#define TLS_SHUTDOWN_WAIT 2
+#define TLS_NO_SHUTDOWN 0 /* Just forget the context */
+#define TLS_SHUTDOWN_NOWAIT 1 /* Send alert; do not wait */
+#define TLS_SHUTDOWN_WAIT 2 /* Send alert & wait for peer's alert */
+#define TLS_SHUTDOWN_WONLY 3 /* only wait for peer's alert */
#ifdef COMPILE_UTILITY
#ifdef COMPILE_UTILITY
diff --git
a/src/src/tls-gnu.c
b/src/src/tls-gnu.c
index 1215f852e075d60127a7099bc230a704fbc5c0c1..62278236906d728b4cfd566900a89dab6af872e6 100644
(file)
--- a/
src/src/tls-gnu.c
+++ b/
src/src/tls-gnu.c
@@
-3744,17
+3744,21
@@
if (!tlsp || tlsp->active.sock < 0) return; /* TLS was not active */
if (do_shutdown)
{
DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS%s\n",
if (do_shutdown)
{
DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS%s\n",
- do_shutdown >
1
? " (with response-wait)" : "");
+ do_shutdown >
TLS_SHUTDOWN_NOWAIT
? " (with response-wait)" : "");
tls_write(ct_ctx, NULL, 0, FALSE); /* flush write buffer */
#ifdef EXIM_TCP_CORK
tls_write(ct_ctx, NULL, 0, FALSE); /* flush write buffer */
#ifdef EXIM_TCP_CORK
- if (do_shutdown
> 1
)
+ if (do_shutdown
== TLS_SHUTDOWN_WAIT
)
(void) setsockopt(tlsp->active.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &off, sizeof(off));
#endif
(void) setsockopt(tlsp->active.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &off, sizeof(off));
#endif
+ /* The library seems to have no way to only wait for a peer's
+ shutdown, so handle the same as TLS_SHUTDOWN_WAIT */
+
ALARM(2);
ALARM(2);
- gnutls_bye(state->session, do_shutdown > 1 ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
+ gnutls_bye(state->session,
+ do_shutdown > TLS_SHUTDOWN_NOWAIT ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
ALARM_CLR(0);
}
ALARM_CLR(0);
}
diff --git
a/src/src/tls-openssl.c
b/src/src/tls-openssl.c
index d5c5778fca70a2e06ea425e78c49c089d8b50f74..7bf62f504849efe29abeaf71fa2bb3f22d88e03b 100644
(file)
--- a/
src/src/tls-openssl.c
+++ b/
src/src/tls-openssl.c
@@
-4519,22
+4519,25
@@
int * fdp = o_ctx ? &tls_out.active.sock : &tls_in.active.sock;
if (*fdp < 0) return; /* TLS was not active */
if (*fdp < 0) return; /* TLS was not active */
-if (do_shutdown)
+if (do_shutdown
> TLS_NO_SHUTDOWN
)
{
int rc;
DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS%s\n",
{
int rc;
DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS%s\n",
- do_shutdown >
1
? " (with response-wait)" : "");
+ do_shutdown >
TLS_SHUTDOWN_NOWAIT
? " (with response-wait)" : "");
tls_write(ct_ctx, NULL, 0, FALSE); /* flush write buffer */
tls_write(ct_ctx, NULL, 0, FALSE); /* flush write buffer */
- if ( (rc = SSL_shutdown(*sslp)) == 0 /* send "close notify" alert */
- && do_shutdown > 1)
+ if ( ( do_shutdown >= TLS_SHUTDOWN_WONLY
+ || (rc = SSL_shutdown(*sslp)) == 0 /* send "close notify" alert */
+ )
+ && do_shutdown > TLS_SHUTDOWN_NOWAIT
+ )
{
#ifdef EXIM_TCP_CORK
(void) setsockopt(*fdp, IPPROTO_TCP, EXIM_TCP_CORK, US &off, sizeof(off));
#endif
ALARM(2);
{
#ifdef EXIM_TCP_CORK
(void) setsockopt(*fdp, IPPROTO_TCP, EXIM_TCP_CORK, US &off, sizeof(off));
#endif
ALARM(2);
- rc = SSL_shutdown(*sslp); /* wait for response */
+ rc = SSL_shutdown(*sslp);
/* wait for response */
ALARM_CLR(0);
}
ALARM_CLR(0);
}
diff --git
a/src/src/transports/smtp.c
b/src/src/transports/smtp.c
index e2c2680a0f8f7131d02d91e121c1dbbc1563353e..524f18633ab5a492fab2761e2e4eaf602782e9f2 100644
(file)
--- a/
src/src/transports/smtp.c
+++ b/
src/src/transports/smtp.c
@@
-4085,7
+4085,7
@@
else
sx->send_quit = FALSE; /* avoid sending it later */
#ifndef DISABLE_TLS
sx->send_quit = FALSE; /* avoid sending it later */
#ifndef DISABLE_TLS
- if (sx->cctx.tls_ctx
)
/* need to send TLS Close Notify */
+ if (sx->cctx.tls_ctx
&& sx->send_tlsclose)
/* need to send TLS Close Notify */
{
# ifdef EXIM_TCP_CORK /* Use _CORK to get Close Notify in FIN segment */
(void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
{
# ifdef EXIM_TCP_CORK /* Use _CORK to get Close Notify in FIN segment */
(void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
@@
-4429,7
+4429,8
@@
if (!sx->ok)
# ifndef DISABLE_TLS
if (sx->cctx.tls_ctx)
{
# ifndef DISABLE_TLS
if (sx->cctx.tls_ctx)
{
- tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WAIT);
+ tls_close(sx->cctx.tls_ctx,
+ sx->send_tlsclose ? TLS_SHUTDOWN_WAIT : TLS_SHUTDOWN_WONLY);
sx->cctx.tls_ctx = NULL;
}
# endif
sx->cctx.tls_ctx = NULL;
}
# endif
@@
-4640,7
+4641,8
@@
if (sx->completed_addr && sx->ok && sx->send_quit)
a new EHLO. If we don't get a good response, we don't attempt to pass
the socket on. */
a new EHLO. If we don't get a good response, we don't attempt to pass
the socket on. */
- tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WAIT);
+ tls_close(sx->cctx.tls_ctx,
+ sx->send_tlsclose ? TLS_SHUTDOWN_WAIT : TLS_SHUTDOWN_WONLY);
sx->send_tlsclose = FALSE;
sx->cctx.tls_ctx = NULL;
tls_out.active.sock = -1;
sx->send_tlsclose = FALSE;
sx->cctx.tls_ctx = NULL;
tls_out.active.sock = -1;
@@
-4742,7
+4744,7
@@
if (sx->send_quit)
{ /* Use _MORE to get QUIT in FIN segment */
(void)smtp_write_command(sx, SCMD_MORE, "QUIT\r\n");
#ifndef DISABLE_TLS
{ /* Use _MORE to get QUIT in FIN segment */
(void)smtp_write_command(sx, SCMD_MORE, "QUIT\r\n");
#ifndef DISABLE_TLS
- if (sx->cctx.tls_ctx)
+ if (sx->cctx.tls_ctx
&& sx->send_tlsclose
)
{
# ifdef EXIM_TCP_CORK /* Use _CORK to get TLS Close Notify in FIN segment */
(void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
{
# ifdef EXIM_TCP_CORK /* Use _CORK to get TLS Close Notify in FIN segment */
(void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
@@
-4797,10
+4799,15
@@
if (sx->send_quit || tcw_done && !tcw)
while (!sigalrm_seen && n > 0);
ALARM_CLR(0);
while (!sigalrm_seen && n > 0);
ALARM_CLR(0);
+ if (sx->send_tlsclose)
+ {
# ifdef EXIM_TCP_CORK
# ifdef EXIM_TCP_CORK
- (void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
+
(void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
# endif
# endif
- tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WAIT);
+ tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WAIT);
+ }
+ else
+ tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WONLY);
sx->cctx.tls_ctx = NULL;
}
#endif
sx->cctx.tls_ctx = NULL;
}
#endif