X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/adb21834f3684b6484d8c2214ee4c3c9c504d632..5c161fa615ab4a2d40170fedd71d1b9a7f079ff6:/src/src/smtp_out.c diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c index 4f8a84e2b..911dd537e 100644 --- a/src/src/smtp_out.c +++ b/src/src/smtp_out.c @@ -3,6 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2018 */ +/* Copyright (c) The Exim Maintainers 2020 */ /* See the file NOTICE for conditions of use and distribution. */ /* A number of functions for driving outgoing SMTP calls. */ @@ -52,8 +53,19 @@ if (!(expint = expand_string(istring))) return FALSE; } -while (isspace(*expint)) expint++; -if (*expint == 0) return TRUE; +if (is_tainted(expint)) + { + log_write(0, LOG_MAIN|LOG_PANIC, + "attempt to use tainted value '%s' from '%s' for interface", + expint, istring); + addr->transport_return = PANIC; + addr->message = string_sprintf("failed to expand \"interface\" " + "option for %s: configuration error", msg); + return FALSE; + } + +Uskip_whitespace(&expint); +if (!*expint) return TRUE; while ((iface = string_nextinlist(&expint, &sep, big_buffer, big_buffer_size))) @@ -144,7 +156,28 @@ return TRUE; static void tfo_out_check(int sock) { -# if defined(TCP_INFO) && defined(EXIM_HAVE_TCPI_UNACKED) +# ifdef __FreeBSD__ +struct tcp_info tinfo; +int val; +socklen_t len = sizeof(val); + +/* The observability as of 12.1 is not useful as a client, only telling us that +a TFO option was used on SYN. It could have been a TFO-R, or ignored by the +server. */ + +/* +if (tcp_out_fastopen == TFO_ATTEMPTED_NODATA || tcp_out_fastopen == TFO_ATTEMPTED_DATA) + if (getsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &val, &len) == 0 && val != 0) {} +*/ +switch (tcp_out_fastopen) + { + case TFO_ATTEMPTED_NODATA: tcp_out_fastopen = TFO_USED_NODATA; break; + case TFO_ATTEMPTED_DATA: tcp_out_fastopen = TFO_USED_DATA; break; + default: break; /* compiler quietening */ + } + +# else /* Linux & Apple */ +# if defined(TCP_INFO) && defined(EXIM_HAVE_TCPI_UNACKED) struct tcp_info tinfo; socklen_t len = sizeof(tinfo); @@ -194,7 +227,8 @@ switch (tcp_out_fastopen) default: break; /* compiler quietening */ } -# endif +# endif +# endif /* Linux & Apple */ } #endif @@ -341,7 +375,7 @@ smtp_port_for_connect(host_item * host, int port) { if (host->port != PORT_NONE) { - HDEBUG(D_transport|D_acl|D_v) + HDEBUG(D_transport|D_acl|D_v) if (port != host->port) debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port, host->port); port = host->port; @@ -467,7 +501,7 @@ else rc = n; } else - + { rc = send(outblock->cctx->sock, outblock->buffer, n, #ifdef MSG_MORE more ? MSG_MORE : 0 @@ -475,6 +509,17 @@ else 0 #endif ); + +#if defined(__linux__) + /* This is a workaround for a current linux kernel bug: as of + 5.6.8-200.fc31.x86_64 small (cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off)); +#endif + } } if (rc <= 0) @@ -521,8 +566,14 @@ if (format) gstring gs = { .size = big_buffer_size, .ptr = 0, .s = big_buffer }; va_list ap; + /* Use taint-unchecked routines for writing into big_buffer, trusting that + we'll never expand the results. Actually, the error-message use - leaving + the results in big_buffer for potential later use - is uncomfortably distant. + XXX Would be better to assume all smtp commands are short, use normal pool + alloc rather than big_buffer, and another global for the data-for-error. */ + va_start(ap, format); - if (!string_vformat(&gs, FALSE, CS format, ap)) + if (!string_vformat(&gs, SVFMT_TAINT_NOCHK, CS format, ap)) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing " "SMTP"); va_end(ap); @@ -538,7 +589,7 @@ if (format) if (!flush_buffer(outblock, SCMD_FLUSH)) return -1; } - Ustrncpy(CS outblock->ptr, gs.s, gs.ptr); + Ustrncpy(outblock->ptr, gs.s, gs.ptr); outblock->ptr += gs.ptr; outblock->cmd_count++; gs.ptr -= 2; string_from_gstring(&gs); /* remove \r\n for error message */ @@ -558,7 +609,7 @@ if (format) while (!isspace(*p)) p++; while (isspace(*p)) p++; } - while (*p != 0) *p++ = '*'; + while (*p) *p++ = '*'; } HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> %s\n", big_buffer); @@ -700,7 +751,7 @@ time_t timelimit = time(NULL) + timeout; errno = 0; /* Ensure errno starts out zero */ -#ifdef SUPPORT_PIPE_CONNECT +#ifndef DISABLE_PIPE_CONNECT if (sx->pending_BANNER || sx->pending_EHLO) { int rc;