X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/42055a338593d66f0abb6eeb6b03f0eaf4439f57..925ac8e4f1c5d365ddea2f7aee460cd0a3cd409d:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index e28a5bfe6..454c0f74d 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1186,20 +1186,24 @@ tlsa_lookup(const host_item * host, dns_answer * dnsa, BOOL dane_required) /* 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 */ @@ -1553,34 +1557,17 @@ if (sx->smtps) 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; @@ -1592,7 +1579,9 @@ if (continue_hostname == NULL) ) 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", @@ -1608,12 +1597,32 @@ if (continue_hostname == NULL) 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. */ @@ -2202,12 +2211,7 @@ tls_close(FALSE, TRUE); /* 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) @@ -2254,6 +2258,9 @@ included in the count.) */ 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++; } @@ -2611,7 +2618,8 @@ for (fd_bits = 3; fd_bits; ) 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); @@ -3370,18 +3378,22 @@ if (sx.completed_addr && sx.ok && sx.send_quit) 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; @@ -3390,6 +3402,9 @@ if (sx.completed_addr && sx.ok && sx.send_quit) "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 { @@ -3406,7 +3421,10 @@ if (sx.completed_addr && sx.ok && sx.send_quit) # 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. */ @@ -3429,6 +3447,7 @@ propagate it from the initial 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); @@ -3439,7 +3458,10 @@ propagate it from the initial 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); }