X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/1d28cc061677bd07d9bed48dd84bd5c590247043..fa1c8faf169384bebaa8d172f491574c45ae2aa4:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 1183fa478..c53e1000f 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) The Exim Maintainers 2020 - 2022 */ +/* Copyright (c) The Exim Maintainers 2020 - 2023 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* SPDX-License-Identifier: GPL-2.0-or-later */ @@ -114,7 +114,7 @@ optionlist smtp_transport_options[] = { { "interface", opt_stringptr, LOFF(interface) }, { "keepalive", opt_bool, LOFF(keepalive) }, { "lmtp_ignore_quota", opt_bool, LOFF(lmtp_ignore_quota) }, - { "max_rcpt", opt_int | opt_public, + { "max_rcpt", opt_stringptr | opt_public, OPT_OFF(transport_instance, max_addresses) }, { "message_linelength_limit", opt_int, LOFF(message_linelength_limit) }, { "multi_domain", opt_expand_bool | opt_public, @@ -203,9 +203,6 @@ smtp_transport_options_block smtp_transport_option_defaults = { .tls_tempfail_tryclear = TRUE, .tls_try_verify_hosts = US"*", .tls_verify_cert_hostnames = US"*", -# ifndef DISABLE_TLS_RESUME - .host_name_extract = US"${if and {{match{$host}{.outlook.com\\$}} {match{$item}{\\N^250-([\\w.]+)\\s\\N}}} {$1}}", -# endif #endif #ifdef SUPPORT_I18N .utf8_downconvert = US"-1", @@ -352,7 +349,7 @@ Returns: nothing void smtp_transport_init(transport_instance *tblock) { -smtp_transport_options_block *ob = SOB tblock->options_block; +smtp_transport_options_block * ob = SOB tblock->options_block; int old_pool = store_pool; /* Retry_use_local_part defaults FALSE if unset */ @@ -626,8 +623,8 @@ if (suffix) else message = string_fmt_append(message, " %s", exim_errstr(basic_errno)); -log_write(0, LOG_MAIN, "%s", string_from_gstring(message)); -deliver_msglog("%s %s\n", tod_stamp(tod_log), message->s); +log_write(0, LOG_MAIN, "%Y", message); +deliver_msglog("%s %.*s\n", tod_stamp(tod_log), message->ptr, message->s); } static void @@ -659,8 +656,7 @@ static void deferred_event_raise(address_item * addr, host_item * host, uschar * evstr) { uschar * action = addr->transport->event_action; -const uschar * save_domain; -uschar * save_local; +const uschar * save_domain, * save_local; if (!action) return; @@ -769,7 +765,7 @@ return TRUE; resumption when such servers do not share a session-cache */ static void -ehlo_response_lbserver(smtp_context * sx, smtp_transport_options_block * ob) +ehlo_response_lbserver(smtp_context * sx, const uschar * name_extract) { #if !defined(DISABLE_TLS) && !defined(DISABLE_TLS_RESUME) const uschar * s; @@ -778,7 +774,7 @@ uschar * save_item = iterate_item; if (sx->conn_args.have_lbserver) return; iterate_item = sx->buffer; -s = expand_cstring(ob->host_name_extract); +s = expand_cstring(name_extract); iterate_item = save_item; sx->conn_args.host_lbserver = s && !*s ? NULL : s; sx->conn_args.have_lbserver = TRUE; @@ -931,6 +927,16 @@ if ( sx->early_pipe_active && (dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))) { uschar * ehlo_resp_key = ehlo_cache_key(sx); + HDEBUG(D_transport) + { + dbdata_ehlo_resp * er; + + if (!(er = dbfn_read_enforce_length(dbm_file, ehlo_resp_key, sizeof(dbdata_ehlo_resp)))) + debug_printf("no ehlo-resp record!\n"); + else + debug_printf("ehlo-resp record is %d seconds old\n", time(NULL) - er->time_stamp); + } + dbfn_delete(dbm_file, ehlo_resp_key); dbfn_close(dbm_file); } @@ -990,7 +996,7 @@ return FALSE; /* Return an auths bitmap for the set of AUTH methods offered by the server -which match our authenticators. */ +which match our client-side authenticators. */ static unsigned short study_ehlo_auths(smtp_context * sx) @@ -1016,7 +1022,7 @@ for (au = auths, authnum = 0; au; au = au->next, authnum++) if (au->client) } DEBUG(D_transport) - debug_printf("server offers %s AUTH, methods '%s', bitmap 0x%04x\n", + debug_printf("server offers %s AUTH, methods '%s', usable-bitmap 0x%04x\n", tls_out.active.sock >= 0 ? "crypted" : "plaintext", names, authbits); if (tls_out.active.sock >= 0) @@ -1057,6 +1063,8 @@ sx->pending_EHLO = FALSE; if (pending_BANNER) { + const uschar * s; + DEBUG(D_transport) debug_printf("%s expect banner\n", __FUNCTION__); (*countp)--; if (!smtp_reap_banner(sx)) @@ -1066,7 +1074,10 @@ if (pending_BANNER) goto fail; } /*XXX EXPERIMENTAL_ESMTP_LIMITS ? */ - ehlo_response_lbserver(sx, sx->conn_args.ob); + + s = ((smtp_transport_options_block *)sx->conn_args.ob)->host_name_extract; + if (!s) s = HNE_DEFAULT; + ehlo_response_lbserver(sx, s); } if (pending_EHLO) @@ -1115,7 +1126,10 @@ if (pending_EHLO) write_ehlo_cache_entry(sx); } else + { invalidate_ehlo_cache_entry(sx); + sx->early_pipe_active = FALSE; /* cancel further early-pipe on this conn */ + } return OK; /* just carry on */ } @@ -1778,7 +1792,7 @@ return FALSE; typedef struct smtp_compare_s { - uschar * current_sender_address; + const uschar * current_sender_address; struct transport_instance * tblock; } smtp_compare_t; @@ -1788,7 +1802,7 @@ sender_address, helo_data and tls_certificate if enabled. */ static uschar * -smtp_local_identity(uschar * sender, struct transport_instance * tblock) +smtp_local_identity(const uschar * sender, struct transport_instance * tblock) { address_item * addr1; uschar * if1 = US""; @@ -1796,7 +1810,7 @@ uschar * helo1 = US""; #ifndef DISABLE_TLS uschar * tlsc1 = US""; #endif -uschar * save_sender_address = sender_address; +const uschar * save_sender_address = sender_address; uschar * local_identity = NULL; smtp_transport_options_block * ob = SOB tblock->options_block; @@ -2121,8 +2135,9 @@ sx->dane_required = verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK; #endif -if ((sx->max_mail = sx->conn_args.tblock->connection_max_messages) == 0) sx->max_mail = 999999; -if ((sx->max_rcpt = sx->conn_args.tblock->max_addresses) == 0) sx->max_rcpt = 999999; +if ((sx->max_mail = sx->conn_args.tblock->connection_max_messages) == 0) + sx->max_mail = UNLIMITED_ADDRS; +sx->max_rcpt = expand_max_rcpt(sx->conn_args.tblock->max_addresses); sx->igquotstr = US""; if (!sx->helo_data) sx->helo_data = ob->helo_data; @@ -2460,10 +2475,20 @@ goto SEND_QUIT; #ifndef DISABLE_TLS if (sx->smtps) { + const uschar * s; + smtp_peer_options |= OPTION_TLS; suppress_tls = FALSE; ob->tls_tempfail_tryclear = FALSE; smtp_command = US"SSL-on-connect"; + + /* Having no EHLO response yet, cannot peek there for a servername to detect + an LB. Call this anyway, so that a dummy host_name_extract option value can + force resumption attempts. */ + + if (!(s = ob->host_name_extract)) s = US"never-LB"; + ehlo_response_lbserver(sx, s); + goto TLS_NEGOTIATE; } #endif @@ -2551,6 +2576,8 @@ goto SEND_QUIT; if (!sx->early_pipe_active) #endif { + const uschar * s; + sx->peer_offered = ehlo_response(sx->buffer, OPTION_TLS /* others checked later */ #ifndef DISABLE_PIPE_CONNECT @@ -2586,7 +2613,8 @@ goto SEND_QUIT; } } #endif - ehlo_response_lbserver(sx, ob); + if (!(s = ob->host_name_extract)) s = HNE_DEFAULT; + ehlo_response_lbserver(sx, s); } /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */ @@ -2819,8 +2847,9 @@ if (tls_out.active.sock >= 0) #ifdef EXPERIMMENTAL_ESMTP_LIMITS /* As we are about to send another EHLO, forget any LIMITS received so far. */ sx->peer_limit_mail = sx->peer_limit_rcpt = sx->peer_limit_rcptdom = 0; - if ((sx->max_mail = sx->conn_args.tblock->connection_max_message) == 0) sx->max_mail = 999999; - if ((sx->max_rcpt = sx->conn_args.tblock->max_addresses) == 0) sx->max_rcpt = 999999; + if ((sx->max_mail = sx->conn_args.tblock->connection_max_message) == 0) + sx->max_mail = UNLIMITED_ADDRS; + sx->max_rcpt = expand_max_rcpt(sx->conn_args.tblock->max_addresses); sx->single_rcpt_domain = FALSE; #endif @@ -3404,7 +3433,7 @@ buffer. */ sx->pending_MAIL = TRUE; /* The block starts with MAIL */ { - uschar * s = sx->from_addr; + const uschar * s = sx->from_addr; #ifdef SUPPORT_I18N uschar * errstr = NULL; @@ -3475,7 +3504,7 @@ for (addr = sx->first_addr, address_count = 0, pipe_limit = 100; { int cmds_sent; BOOL no_flush; - uschar * rcpt_addr; + const uschar * rcpt_addr; #ifdef EXPERIMENTAL_ESMTP_LIMITS if ( sx->single_rcpt_domain /* restriction on domains */ @@ -3818,7 +3847,7 @@ if (tblock->filter_command) yield ERROR. */ if (!transport_set_up_command(&transport_filter_argv, - tblock->filter_command, TRUE, DEFER, addrlist, FALSE, + tblock->filter_command, TSUC_EXPAND_ARGS, DEFER, addrlist, string_sprintf("%.50s transport filter", tblock->name), NULL)) { set_errno_nohost(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER, @@ -4971,7 +5000,7 @@ smtp_transport_closedown(transport_instance *tblock) { smtp_transport_options_block * ob = SOB tblock->options_block; client_conn_ctx cctx; -smtp_context sx; +smtp_context sx = {0}; uschar buffer[256]; uschar inbuffer[4096]; uschar outbuffer[16];