X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/20395676aba7fa5eb9a2c5e0b9f582ec2b3e71e4..c3d6f1ff09458b3e7619f9bc4799aec0ab5fc2f2:/src/src/smtp_out.c diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c index 4e8c44869..7b8212477 100644 --- a/src/src/smtp_out.c +++ b/src/src/smtp_out.c @@ -3,7 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2018 */ -/* Copyright (c) The Exim Maintainers 2020 */ +/* Copyright (c) The Exim Maintainers 2020 - 2021 */ /* See the file NOTICE for conditions of use and distribution. */ /* A number of functions for driving outgoing SMTP calls. */ @@ -27,7 +27,7 @@ Arguments: which case the function does nothing host_af AF_INET or AF_INET6 for the outgoing IP address addr the mail address being handled (for setting errors) - interface point this to the interface + interface point this to the interface if there is one defined msg to add to any error message Returns: TRUE on success, FALSE on failure, with error message @@ -53,8 +53,11 @@ if (!(expint = expand_string(istring))) return FALSE; } -if (is_tainted2(expint, LOG_MAIN|LOG_PANIC, "Tainted value '%s' from '%s' for interface", expint, istring)) +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); @@ -64,11 +67,10 @@ if (is_tainted2(expint, LOG_MAIN|LOG_PANIC, "Tainted value '%s' from '%s' for in Uskip_whitespace(&expint); if (!*expint) return TRUE; -/* we just tested to ensure no taint, so big_buffer is ok */ -while ((iface = string_nextinlist(&expint, &sep, big_buffer, - big_buffer_size))) +while ((iface = string_nextinlist(&expint, &sep, NULL, 0))) { - if (string_is_ip_address(iface, NULL) == 0) + int if_af = string_is_ip_address(iface, NULL); + if (if_af == 0) { addr->transport_return = PANIC; addr->message = string_sprintf("\"%s\" is not a valid IP " @@ -77,11 +79,11 @@ while ((iface = string_nextinlist(&expint, &sep, big_buffer, return FALSE; } - if (((Ustrchr(iface, ':') == NULL)? AF_INET:AF_INET6) == host_af) + if ((if_af == 4 ? AF_INET : AF_INET6) == host_af) break; } -if (iface) *interface = string_copy(iface); +*interface = iface; return TRUE; } @@ -151,9 +153,16 @@ return TRUE; #ifdef TCP_FASTOPEN +/* Try to record if TFO was attmepted and if it was successfully used. */ + static void tfo_out_check(int sock) { +static BOOL done_once = FALSE; + +if (done_once) return; +done_once = TRUE; + # ifdef __FreeBSD__ struct tcp_info tinfo; socklen_t len = sizeof(tinfo); @@ -277,7 +286,7 @@ const blob * fastopen_blob = NULL; #ifndef DISABLE_EVENT deliver_host_address = host->address; deliver_host_port = port; -if (event_raise(tb->event_action, US"tcp:connect", NULL)) return -1; +if (event_raise(tb->event_action, US"tcp:connect", NULL, &errno)) return -1; #endif if ((sock = ip_socket(SOCK_STREAM, host_af)) < 0) return -1; @@ -469,7 +478,7 @@ if (ob->socks_proxy) { int sock = socks_sock_connect(sc->host, sc->host_af, port, sc->interface, sc->tblock, ob->connect_timeout); - + if (sock >= 0) { if (early_data && early_data->data && early_data->len) @@ -518,13 +527,21 @@ flush_buffer(smtp_outblock * outblock, int mode) int rc; int n = outblock->ptr - outblock->buffer; BOOL more = mode == SCMD_MORE; +client_conn_ctx * cctx; HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n, more ? " (more expected)" : ""); +if (!(cctx = outblock->cctx)) + { + log_write(0, LOG_MAIN|LOG_PANIC, "null conn-context pointer"); + errno = 0; + return FALSE; + } + #ifndef DISABLE_TLS -if (outblock->cctx->tls_ctx) - rc = tls_write(outblock->cctx->tls_ctx, outblock->buffer, n, more); +if (cctx->tls_ctx) /*XXX have seen a null cctx here, rvfy sending QUIT, hence check above */ + rc = tls_write(cctx->tls_ctx, outblock->buffer, n, more); else #endif @@ -538,7 +555,7 @@ else requirement: TFO with data can, in rare cases, replay the data to the receiver. */ - if ( (outblock->cctx->sock = smtp_connect(outblock->conn_args, &early_data)) + if ( (cctx->sock = smtp_connect(outblock->conn_args, &early_data)) < 0) return FALSE; outblock->conn_args = NULL; @@ -546,7 +563,7 @@ else } else { - rc = send(outblock->cctx->sock, outblock->buffer, n, + rc = send(cctx->sock, outblock->buffer, n, #ifdef MSG_MORE more ? MSG_MORE : 0 #else @@ -561,7 +578,7 @@ else https://bugzilla.redhat.com/show_bug.cgi?id=1803806 */ if (!more) - setsockopt(outblock->cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off)); + setsockopt(cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off)); #endif } } @@ -579,6 +596,22 @@ return TRUE; +/* This might be called both due to callout and then from delivery. +Use memory that will not be released between those phases. +*/ +static void +smtp_debug_resp(const uschar * buf) +{ +#ifndef DISABLE_CLIENT_CMD_LOG +int old_pool = store_pool; +store_pool = POOL_PERM; +client_cmd_log = string_append_listele_n(client_cmd_log, ':', buf, + buf[3] == ' ' ? 3 : 4); +store_pool = old_pool; +#endif +} + + /************************************************* * Write SMTP command * *************************************************/ @@ -600,7 +633,7 @@ Returns: 0 if command added to pipelining buffer, with nothing transmitted */ int -smtp_write_command(void * sx, int mode, const char *format, ...) +smtp_write_command(void * sx, int mode, const char * format, ...) { smtp_outblock * outblock = &((smtp_context *)sx)->outblock; int rc = 0; @@ -656,9 +689,7 @@ if (format) while (*p) *p++ = '*'; } - HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP%c> %s\n", - mode == SCMD_BUFFER ? '|' : mode == SCMD_MORE ? '+' : '>', - big_buffer); + smtp_debug_cmd(big_buffer, mode); } if (mode != SCMD_BUFFER) @@ -796,8 +827,10 @@ smtp_context * sx = sx0; uschar * ptr = buffer; int count = 0; time_t timelimit = time(NULL) + timeout; +BOOL yield = FALSE; errno = 0; /* Ensure errno starts out zero */ +buffer[0] = '\0'; #ifndef DISABLE_PIPE_CONNECT if (sx->pending_BANNER || sx->pending_EHLO) @@ -806,9 +839,8 @@ if (sx->pending_BANNER || sx->pending_EHLO) if ((rc = smtp_reap_early_pipe(sx, &count)) != OK) { DEBUG(D_transport) debug_printf("failed reaping pipelined cmd responsess\n"); - buffer[0] = '\0'; if (rc == DEFER) errno = ERRNO_TLSFAILURE; - return FALSE; + goto out; } } #endif @@ -839,7 +871,7 @@ for (;;) (ptr[3] != '-' && ptr[3] != ' ' && ptr[3] != 0)) { errno = ERRNO_SMTPFORMAT; /* format error */ - return FALSE; + goto out; } /* If the line we have just read is a terminal line, line, we are done. @@ -857,7 +889,7 @@ for (;;) } #ifdef TCP_FASTOPEN - tfo_out_check(sx->cctx.sock); +tfo_out_check(sx->cctx.sock); #endif /* Return a value that depends on the SMTP return code. On some systems a @@ -867,7 +899,11 @@ distinguish between an unexpected return code and other errors such as timeouts, lost connections, etc. */ errno = 0; -return buffer[0] == okdigit; +yield = buffer[0] == okdigit; + +out: + smtp_debug_resp(buffer); + return yield; } /* End of smtp_out.c */