summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Metzler <ametzler@bebt.de>2018-12-24 16:11:41 +0000
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2018-12-25 22:43:45 +0100
commit4896a3192ffac48885347460377edcd893eb9600 (patch)
treeb362c355a6f9e98cc1b773c6373282fce163aac3
parentb315e9a9f95471046f568ce4841b3b66746adcac (diff)
downloadexim4-4896a3192ffac48885347460377edcd893eb9600.tar.gz
GnuTLS: repeat lowlevel read and write operations while they request retry
(cherry picked from commit 06faf21f3a84a3ac4aa4f7b1512087423d8c8541)
-rw-r--r--doc/doc-txt/ChangeLog7
-rw-r--r--src/src/tls-gnu.c28
2 files changed, 26 insertions, 9 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 785d59bed..ec7c8accd 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -5,6 +5,13 @@ affect Exim's operation, with an unchanged configuration file. For new
options, and new features, see the NewStuff file next to this ChangeLog.
+Exim version 4.93
+-----------------
+
+JH/01 GnuTLS: repeat lowlevel read and write operations while they return error
+ codes indicating retry. Under TLS1.3 this becomes required.
+
+
Exim version 4.92
-----------------
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index bceb57395..c404dc29a 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -2562,8 +2562,12 @@ DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%p, %p, %u)\n",
sigalrm_seen = FALSE;
if (smtp_receive_timeout > 0) ALARM(smtp_receive_timeout);
-inbytes = gnutls_record_recv(state->session, state->xfer_buffer,
- MIN(ssl_xfer_buffer_size, lim));
+
+do
+ inbytes = gnutls_record_recv(state->session, state->xfer_buffer,
+ MIN(ssl_xfer_buffer_size, lim));
+while (inbytes == GNUTLS_E_AGAIN);
+
if (smtp_receive_timeout > 0) ALARM_CLR(0);
if (had_command_timeout) /* set by signal handler */
@@ -2618,7 +2622,7 @@ else if (inbytes == 0)
else if (inbytes < 0)
{
-debug_printf("%s: err from gnutls_record_recv(\n", __FUNCTION__);
+ DEBUG(D_tls) debug_printf("%s: err from gnutls_record_recv(\n", __FUNCTION__);
record_io_error(state, (int) inbytes, US"recv", NULL);
state->xfer_error = TRUE;
return FALSE;
@@ -2740,17 +2744,20 @@ DEBUG(D_tls)
debug_printf("Calling gnutls_record_recv(%p, %p, " SIZE_T_FMT ")\n",
state->session, buff, len);
-inbytes = gnutls_record_recv(state->session, buff, len);
+do
+ inbytes = gnutls_record_recv(state->session, buff, len);
+while (inbytes == GNUTLS_E_AGAIN);
+
if (inbytes > 0) return inbytes;
if (inbytes == 0)
{
DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
}
else
-{
-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;
}
@@ -2792,7 +2799,10 @@ while (left > 0)
{
DEBUG(D_tls) debug_printf("gnutls_record_send(SSL, %p, " SIZE_T_FMT ")\n",
buff, left);
- outbytes = gnutls_record_send(state->session, buff, left);
+
+ do
+ outbytes = gnutls_record_send(state->session, buff, left);
+ while (outbytes == GNUTLS_E_AGAIN);
DEBUG(D_tls) debug_printf("outbytes=" SSIZE_T_FMT "\n", outbytes);
if (outbytes < 0)