X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/a505cf777f90755bce69ab53a899b284a304127b..8b7d4ba8903ace7e3e3db70343798a5a0b7cea23:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 6ca4552a6..8fecf7eef 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1020,7 +1020,7 @@ fail: (void) smtp_discard_responses(sx, sx->conn_args.ob, *countp); return rc; } -#endif +#endif /*!DISABLE_PIPE_CONNECT*/ /************************************************* @@ -1087,7 +1087,7 @@ if (sx->pending_MAIL) { DEBUG(D_transport) debug_printf("%s expect mail\n", __FUNCTION__); count--; - sx->pending_MAIL = FALSE; + sx->pending_MAIL = sx->RCPT_452 = FALSE; if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', ob->command_timeout)) { @@ -1227,7 +1227,7 @@ while (count-- > 0) if (addr->more_errno >> 8 == 52 && yield & 3) { - if (!sx->RCPT_452) + if (!sx->RCPT_452) /* initialised at MAIL-ack above */ { DEBUG(D_transport) debug_printf("%s: seen first 452 too-many-rcpts\n", __FUNCTION__); @@ -1274,6 +1274,8 @@ while (count-- > 0) } } } + if (count && !(addr = addr->next)) + return -2; } /* Loop for next RCPT response */ /* Update where to start at for the next block of responses, unless we @@ -1549,7 +1551,9 @@ if ( sx->esmtp if (require_auth == OK && !f.smtp_authenticated) { +#ifndef DISABLE_PIPE_CONNECT invalidate_ehlo_cache_entry(sx); +#endif set_errno_nohost(sx->addrlist, ERRNO_AUTHFAIL, string_sprintf("authentication required but %s", fail_reason), DEFER, FALSE, &sx->delivery_start); @@ -1620,8 +1624,8 @@ return FALSE; typedef struct smtp_compare_s { - uschar *current_sender_address; - struct transport_instance *tblock; + uschar * current_sender_address; + struct transport_instance * tblock; } smtp_compare_t; @@ -1989,7 +1993,80 @@ if (sx->smtps) DEFER, FALSE, &sx->delivery_start); return ERROR; } -#endif +#else + +/* If we have a proxied TLS connection, check usability for this message */ + +if (continue_hostname && continue_proxy_cipher) + { + int rc; + const uschar * sni = US""; + +# ifdef SUPPORT_DANE + /* Check if the message will be DANE-verified; if so force its SNI */ + + tls_out.dane_verified = FALSE; + smtp_port_for_connect(sx->conn_args.host, sx->port); + if ( sx->conn_args.host->dnssec == DS_YES + && ( sx->dane_required + || verify_check_given_host(CUSS &ob->hosts_try_dane, sx->conn_args.host) == OK + ) ) + switch (rc = tlsa_lookup(sx->conn_args.host, &sx->conn_args.tlsa_dnsa, sx->dane_required)) + { + case OK: sx->conn_args.dane = TRUE; + ob->tls_tempfail_tryclear = FALSE; /* force TLS */ + ob->tls_sni = sx->first_addr->domain; /* force SNI */ + break; + case FAIL_FORCED: break; + default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER, + string_sprintf("DANE error: tlsa lookup %s", + rc_to_string(rc)), + rc, FALSE, &sx->delivery_start); +# ifndef DISABLE_EVENT + (void) event_raise(sx->conn_args.tblock->event_action, + US"dane:fail", sx->dane_required + ? US"dane-required" : US"dnssec-invalid"); +# endif + return rc; + } +# endif + + /* If the SNI or the DANE status required for the new message differs from the + existing conn drop the connection to force a new one. */ + + if (ob->tls_sni && !(sni = expand_cstring(ob->tls_sni))) + log_write(0, LOG_MAIN|LOG_PANIC, + "<%s>: failed to expand transport's tls_sni value: %s", + sx->addrlist->address, expand_string_message); + +# ifdef SUPPORT_DANE + if ( (continue_proxy_sni ? (Ustrcmp(continue_proxy_sni, sni) == 0) : !*sni) + && continue_proxy_dane == sx->conn_args.dane) + { + tls_out.sni = US sni; + if ((tls_out.dane_verified = continue_proxy_dane)) + sx->conn_args.host->dnssec = DS_YES; + } +# else + if ((continue_proxy_sni ? (Ustrcmp(continue_proxy_sni, sni) == 0) : !*sni)) + tls_out.sni = US sni; +# endif + else + { + DEBUG(D_transport) + debug_printf("Closing proxied-TLS connection due to SNI mismatch\n"); + + HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> QUIT\n"); + write(0, "QUIT\r\n", 6); + close(0); + continue_hostname = continue_proxy_cipher = NULL; + f.continue_more = FALSE; + continue_sequence = 1; /* Unfortunately, this process cannot affect success log + which is done by delivery proc. Would have to pass this + back through reporting pipe. */ + } + } +#endif /*!DISABLE_TLS*/ /* Make a connection to the host if this isn't a continued delivery, and handle the initial interaction and HELO/EHLO/LHLO. Connect timeout errors are handled @@ -2023,8 +2100,7 @@ if (!continue_hostname) ob->tls_sni = sx->first_addr->domain; /* force SNI */ break; case FAIL_FORCED: break; - default: - set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER, + default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER, string_sprintf("DANE error: tlsa lookup %s", rc_to_string(rc)), rc, FALSE, &sx->delivery_start); @@ -3431,7 +3507,9 @@ BOOL pass_message = FALSE; uschar *message = NULL; uschar new_message_id[MESSAGE_ID_LENGTH + 1]; smtp_context * sx = store_get(sizeof(*sx), TRUE); /* tainted, for the data buffers */ +#ifdef SUPPORT_DANE BOOL dane_held; +#endif suppress_tls = suppress_tls; /* stop compiler warning when no TLS support */ *message_defer = FALSE; @@ -3448,8 +3526,10 @@ sx->conn_args.tblock = tblock; gettimeofday(&sx->delivery_start, NULL); sx->sync_addr = sx->first_addr = addrlist; +#ifdef SUPPORT_DANE DANE_DOMAINS: dane_held = FALSE; +#endif /* Get the channel set up ready for a message, MAIL FROM being the next SMTP command to send. */ @@ -3461,7 +3541,7 @@ if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK) goto TIDYUP; } -/*XXX*/ +#ifdef SUPPORT_DANE /* If the connection used DANE, ignore for now any addresses with incompatible domains. The SNI has to be the domain. Arrange a whole new TCP conn later, just in case only TLS isn't enough. */ @@ -3479,6 +3559,7 @@ if (sx->conn_args.dane) a->transport_return = DANE; } } +#endif /* If there is a filter command specified for this transport, we can now set it up. This cannot be done until the identity of the host is known. */ @@ -3845,9 +3926,10 @@ else } /* Process all transported addresses - for LMTP or PRDR, read a status for - each one. */ + each one. We used to drop out at first_addr, until someone returned a 452 + followed by a 250... and we screwed up the accepted addresses. */ - for (address_item * addr = addrlist; addr != sx->first_addr; addr = addr->next) + for (address_item * addr = addrlist; addr; addr = addr->next) { if (addr->transport_return != PENDING_OK) continue; @@ -4180,8 +4262,8 @@ if (sx->completed_addr && sx->ok && sx->send_quit) t_compare.tblock = tblock; t_compare.current_sender_address = sender_address; - if ( sx->first_addr != NULL - || f.continue_more + if ( sx->first_addr != NULL /* more addrs for this message */ + || f.continue_more /* more addrs for coninued-host */ || ( #ifndef DISABLE_TLS ( tls_out.active.sock < 0 && !continue_proxy_cipher @@ -4228,7 +4310,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit) if (sx->first_addr != NULL) /* More addresses still to be sent */ - { /* on this connection */ + { /* for this message */ continue_sequence++; /* Causes * in logging */ pipelining_active = sx->pipelining_used; /* was cleared at DATA */ goto SEND_MESSAGE; @@ -4252,6 +4334,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit) tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WAIT); sx->cctx.tls_ctx = NULL; + tls_out.active.sock = -1; smtp_peer_options = smtp_peer_options_wrap; sx->ok = !sx->smtps && smtp_write_command(sx, SCMD_FLUSH, "EHLO %s\r\n", sx->helo_data) @@ -4395,7 +4478,7 @@ if (sx->send_quit) (void) event_raise(tblock->event_action, US"tcp:close", NULL); #endif -/*XXX*/ +#ifdef SUPPORT_DANE if (dane_held) { sx->first_addr = NULL; @@ -4414,15 +4497,18 @@ if (dane_held) } goto DANE_DOMAINS; } +#endif continue_transport = NULL; continue_hostname = NULL; return yield; TIDYUP: +#ifdef SUPPORT_DANE if (dane_held) for (address_item * a = sx->addrlist->next; a; a = a->next) if (a->transport_return == DANE) a->transport_return = PENDING_DEFER; +#endif return yield; } @@ -4629,11 +4715,8 @@ if (!hostlist || (ob->hosts_override && ob->hosts)) else if (ob->hosts_randomize) s = expanded_hosts = string_copy(s); - if (is_tainted(s)) + if (is_tainted2(s, LOG_MAIN|LOG_PANIC, "Tainted host list '%s' from '%s' in transport %s", s, ob->hosts, tblock->name)) { - log_write(0, LOG_MAIN|LOG_PANIC, - "attempt to use tainted host list '%s' from '%s' in transport %s", - s, ob->hosts, tblock->name); /* Avoid leaking info to an attacker */ addrlist->message = US"internal configuration error"; addrlist->transport_return = PANIC;