summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/src/smtp_in.c25
-rw-r--r--src/src/tls-gnu.c3
-rw-r--r--src/src/tls-openssl.c17
3 files changed, 28 insertions, 17 deletions
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 301f3c52c..b88fde1b5 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -947,16 +947,13 @@ if (fl.rcpt_in_progress)
/* Now write the string */
+if (
#ifndef DISABLE_TLS
-if (tls_in.active.sock >= 0)
- {
- if (tls_write(NULL, gs.s, gs.ptr, more) < 0)
- smtp_write_error = -1;
- }
-else
+ tls_in.active.sock >= 0 ? (tls_write(NULL, gs.s, gs.ptr, more) < 0) :
#endif
-
-if (fprintf(smtp_out, "%s", gs.s) < 0) smtp_write_error = -1;
+ (fwrite(gs.s, gs.ptr, 1, smtp_out) == 0)
+ )
+ smtp_write_error = -1;
}
@@ -967,8 +964,7 @@ if (fprintf(smtp_out, "%s", gs.s) < 0) smtp_write_error = -1;
/* This function isn't currently used within Exim (it detects errors when it
tries to read the next SMTP input), but is available for use in local_scan().
-For non-TLS connections, it flushes the output and checks for errors. For
-TLS-connections, it checks for a previously-detected TLS write error.
+It flushes the output and checks for errors.
Arguments: none
Returns: 0 for no error; -1 after an error
@@ -978,6 +974,15 @@ int
smtp_fflush(void)
{
if (tls_in.active.sock < 0 && fflush(smtp_out) != 0) smtp_write_error = -1;
+
+if (
+#ifndef DISABLE_TLS
+ tls_in.active.sock >= 0 ? (tls_write(NULL, NULL, 0, FALSE) < 0) :
+#endif
+ (fflush(smtp_out) != 0)
+ )
+ smtp_write_error = -1;
+
return smtp_write_error;
}
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index f3c3835fe..7b0f2f6ad 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -3311,6 +3311,9 @@ Arguments:
len number of bytes
more more data expected soon
+Calling with len zero and more unset will flush buffered writes. The buff
+argument can be null for that case.
+
Returns: the number of bytes after a successful write,
-1 after a failed write
*/
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 5ea4d964e..7e3cc3f78 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -3531,11 +3531,12 @@ Arguments:
Returns: the number of bytes after a successful write,
-1 after a failed write
-Used by both server-side and client-side TLS.
+Used by both server-side and client-side TLS. Calling with len zero and more unset
+will flush buffered writes; buff can be null for this case.
*/
int
-tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)
+tls_write(void * ct_ctx, const uschar * buff, size_t len, BOOL more)
{
size_t olen = len;
int outbytes, error;
@@ -3561,6 +3562,8 @@ a store reset there, so use POOL_PERM. */
if ((more || corked))
{
+ if (!len) buff = US &error; /* dummy just so that string_catn is ok */
+
#ifndef DISABLE_PIPE_CONNECT
int save_pool = store_pool;
store_pool = POOL_PERM;
@@ -3590,16 +3593,16 @@ for (int left = len; left > 0;)
DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
switch (error)
{
+ case SSL_ERROR_NONE: /* the usual case */
+ left -= outbytes;
+ buff += outbytes;
+ break;
+
case SSL_ERROR_SSL:
ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring));
log_write(0, LOG_MAIN, "TLS error (SSL_write): %s", ssl_errstring);
return -1;
- case SSL_ERROR_NONE:
- left -= outbytes;
- buff += outbytes;
- break;
-
case SSL_ERROR_ZERO_RETURN:
log_write(0, LOG_MAIN, "SSL channel closed on write");
return -1;