/* move this out to host.c given the similarity to dns_lookup() ? */
uschar buffer[300];
const uschar * fullname = buffer;
+int rc;
+BOOL sec;
/* TLSA lookup string */
(void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port, host->name);
-switch (dns_lookup(dnsa, buffer, T_TLSA, &fullname))
+rc = dns_lookup(dnsa, buffer, T_TLSA, &fullname);
+sec = dns_is_secure(dnsa);
+DEBUG(D_transport)
+ debug_printf("TLSA lookup ret %d %sDNSSEC\n", rc, sec ? "" : "not ");
+
+switch (rc)
{
case DNS_SUCCEED:
- if (!dns_is_secure(dnsa))
- {
- log_write(0, LOG_MAIN, "DANE error: TLSA lookup not DNSSEC");
- return DEFER;
- }
- return OK;
+ if (sec) return OK;
+ log_write(0, LOG_MAIN, "DANE error: TLSA lookup not DNSSEC");
+ /*FALLTHROUGH*/
case DNS_AGAIN:
return DEFER; /* just defer this TLS'd conn */
the initial interaction and HELO/EHLO/LHLO. Connect timeout errors are handled
specially so they can be identified for retries. */
-if (continue_hostname == NULL)
+if (!continue_hostname)
{
if (sx->verify)
HDEBUG(D_verify) debug_printf("interface=%s port=%d\n", sx->interface, sx->port);
- /* This puts port into host->port */
- sx->inblock.sock = sx->outblock.sock =
- smtp_connect(sx->host, sx->host_af, sx->port, sx->interface,
- sx->ob->connect_timeout, sx->tblock);
+ /* Get the actual port the connection will use, into sx->host */
- if (sx->inblock.sock < 0)
- {
- uschar * msg = NULL;
- if (sx->verify)
- {
- msg = US strerror(errno);
- HDEBUG(D_verify) debug_printf("connect: %s\n", msg);
- }
- set_errno_nohost(sx->addrlist,
- errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
- sx->verify ? string_sprintf("could not connect: %s", msg)
- : NULL,
- DEFER, FALSE);
- sx->send_quit = FALSE;
- return DEFER;
- }
+ smtp_port_for_connect(sx->host, sx->port);
#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+ /* Do TLSA lookup for DANE */
{
tls_out.dane_verified = FALSE;
tls_out.tlsa_usage = 0;
)
switch (rc = tlsa_lookup(sx->host, &tlsa_dnsa, sx->dane_required))
{
- case OK: sx->dane = TRUE; break;
+ case OK: sx->dane = TRUE;
+ sx->ob->tls_tempfail_tryclear = FALSE;
+ break;
case FAIL_FORCED: break;
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
FAIL, FALSE);
return FAIL;
}
-
- if (sx->dane)
- sx->ob->tls_tempfail_tryclear = FALSE;
}
#endif /*DANE*/
+ /* Make the TCP connection */
+
+ sx->inblock.sock = sx->outblock.sock =
+ smtp_connect(sx->host, sx->host_af, sx->interface,
+ sx->ob->connect_timeout, sx->tblock);
+
+ if (sx->inblock.sock < 0)
+ {
+ uschar * msg = NULL;
+ if (sx->verify)
+ {
+ msg = US strerror(errno);
+ HDEBUG(D_verify) debug_printf("connect: %s\n", msg);
+ }
+ set_errno_nohost(sx->addrlist,
+ errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
+ sx->verify ? string_sprintf("could not connect: %s", msg)
+ : NULL,
+ DEFER, FALSE);
+ sx->send_quit = FALSE;
+ return DEFER;
+ }
+
/* Expand the greeting message while waiting for the initial response. (Makes
sense if helo_data contains ${lookup dnsdb ...} stuff). The expansion is
delayed till here so that $sending_interface and $sending_port are set. */
/* Close the socket, and return the appropriate value, first setting
works because the NULL setting is passed back to the calling process, and
remote_max_parallel is forced to 1 when delivering over an existing connection,
-
-If all went well and continue_more is set, we shouldn't actually get here if
-there are further addresses, as the return above will be taken. However,
-writing RSET might have failed, or there may be other addresses whose hosts are
-specified in the transports, and therefore not visible at top level, in which
-case continue_more won't get set. */
+*/
HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n");
if (sx->send_quit)
if (sx->peer_offered & PEER_OFFERED_SIZE)
{
+/*XXX problem here under spool_files_wireformat?
+Or just forget about lines? Or inflate by a fixed proportion? */
+
sprintf(CS p, " SIZE=%d", message_size+message_linecount+sx->ob->size_addition);
while (*p) p++;
}
else
{
for (nbytes = 0; rc - nbytes > 0; nbytes += i)
- if ((i = tls_write(FALSE, buf + nbytes, rc - nbytes)) < 0) return;
+ if ((i = tls_write(FALSE, buf + nbytes, rc - nbytes, FALSE)) < 0)
+ return;
}
else if (fd_bits & 2)
FD_SET(proxy_fd, &fds);
continue_sequence++; /* Causes * in logging */
goto SEND_MESSAGE;
}
- if (continue_more) return yield; /* More addresses for another run */
- /* Pass the connection on to a new Exim process. */
+ /* Unless caller said it already has more messages listed for this host,
+ pass the connection on to a new Exim process (below, the call to
+ transport_pass_socket). If the caller has more ready, just return with
+ the connection still open. */
+
#ifdef SUPPORT_TLS
if (tls_out.active >= 0)
- if (verify_check_given_host(&sx.ob->hosts_noproxy_tls, host) == OK)
+ if ( continue_more
+ || verify_check_given_host(&sx.ob->hosts_noproxy_tls, host) == OK)
{
- /* Pass the socket, for direct use, to a new Exim process. Before
- doing so, we must shut down TLS. Not all MTAs allow for the
- continuation of the SMTP session when TLS is shut down. We test for
- this by sending a new EHLO. If we don't get a good response, we don't
- attempt to pass the socket on. */
+ /* Before passing the socket on, or returning to caller with it still
+ open, we must shut down TLS. Not all MTAs allow for the continuation
+ of the SMTP session when TLS is shut down. We test for this by sending
+ a new EHLO. If we don't get a good response, we don't attempt to pass
+ the socket on. */
tls_close(FALSE, TRUE);
smtp_peer_options = smtp_peer_options_wrap;
"EHLO %s\r\n", sx.helo_data) >= 0
&& smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
'2', sx.ob->command_timeout);
+
+ if (sx.ok && continue_more)
+ return yield; /* More addresses for another run */
}
else
{
# endif
);
}
+ else
#endif
+ if (continue_more)
+ return yield; /* More addresses for another run */
/* If the socket is successfully passed, we mustn't send QUIT (or
indeed anything!) from here. */
int pid = fork();
if (pid > 0) /* parent */
{
+ DEBUG(D_transport) debug_printf("proxy-proc inter-pid %d\n", pid);
waitpid(pid, NULL, 0);
tls_close(FALSE, FALSE);
(void)close(sx.inblock.sock);
else if (pid == 0) /* child; fork again to disconnect totally */
{
if ((pid = fork()))
+ {
+ DEBUG(D_transport) debug_printf("proxy-prox final-pid %d\n", pid);
_exit(pid ? EXIT_FAILURE : EXIT_SUCCESS);
+ }
smtp_proxy_tls(sx.buffer, sizeof(sx.buffer), pfd[0], sx.ob->command_timeout);
exim_exit(0);
}