return FALSE;
}
+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;
+ }
+
while (isspace(*expint)) expint++;
if (*expint == 0) 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);
default: break; /* compiler quietening */
}
-# endif
+# endif
+# endif /* Linux & Apple */
}
#endif
{
HDEBUG(D_transport|D_acl|D_v)
{
- debug_printf_indent("failed: %s", CUstrerror(save_errno));
+ debug_printf_indent(" failed: %s", CUstrerror(save_errno));
if (save_errno == ETIMEDOUT)
debug_printf(" (timeout=%s)", readconf_printtime(timeout));
debug_printf("\n");
union sockaddr_46 interface_sock;
EXIM_SOCKLEN_T size = sizeof(interface_sock);
- HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("connected\n");
+ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" connected\n");
if (getsockname(sock, (struct sockaddr *)(&interface_sock), &size) == 0)
sending_ip_address = host_ntoa(-1, &interface_sock, NULL, &sending_port);
else
HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
more ? " (more expected)" : "");
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (outblock->cctx->tls_ctx)
rc = tls_write(outblock->cctx->tls_ctx, outblock->buffer, n, more);
else
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);
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 */
inblock the SMTP input block (contains holding buffer, socket, etc.)
buffer where to put the line
size space available for the line
- timeout the timeout to use when reading a packet
+ timelimit deadline for reading the lime, seconds past epoch
Returns: length of a line that has been put in the buffer
-1 otherwise, with errno set
*/
static int
-read_response_line(smtp_inblock *inblock, uschar *buffer, int size, int timeout)
+read_response_line(smtp_inblock *inblock, uschar *buffer, int size, time_t timelimit)
{
uschar *p = buffer;
uschar *ptr = inblock->ptr;
/* Need to read a new input packet. */
- if((rc = ip_recv(cctx, inblock->buffer, inblock->buffersize, timeout)) <= 0)
+ if((rc = ip_recv(cctx, inblock->buffer, inblock->buffersize, timelimit)) <= 0)
{
- DEBUG(D_deliver|D_transport|D_acl)
+ DEBUG(D_deliver|D_transport|D_acl|D_v)
debug_printf_indent(errno ? " SMTP(%s)<<\n" : " SMTP(closed)<<\n",
strerror(errno));
break;
/*XXX could move to smtp transport; no other users */
BOOL
-smtp_read_response(void * sx0, uschar *buffer, int size, int okdigit,
+smtp_read_response(void * sx0, uschar * buffer, int size, int okdigit,
int timeout)
{
smtp_context * sx = sx0;
-uschar *ptr = buffer;
+uschar * ptr = buffer;
int count = 0;
+time_t timelimit = time(NULL) + timeout;
errno = 0; /* Ensure errno starts out zero */
-#ifdef EXPERIMENTAL_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
if (sx->pending_BANNER || sx->pending_EHLO)
- if (smtp_reap_early_pipe(sx, &count) != OK)
+ {
+ int rc;
+ 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;
}
+ }
#endif
/* This is a loop to read and concatenate the lines that make up a multi-line
for (;;)
{
- if ((count = read_response_line(&sx->inblock, ptr, size, timeout)) < 0)
+ if ((count = read_response_line(&sx->inblock, ptr, size, timelimit)) < 0)
return FALSE;
HDEBUG(D_transport|D_acl|D_v)