X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f0989ec0ec69cc6a881ef9f7f118194c04875a36..583b7f82cdcc5ea24d2afb572f61b10e0da676d4:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 30facda00..0fa761e75 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -596,7 +596,7 @@ if (*errno_value == ERRNO_WRITEINCOMPLETE) return FALSE; } -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N /* Handle lack of advertised SMTPUTF8, for international message */ if (*errno_value == ERRNO_UTF8_FWD) { @@ -683,7 +683,7 @@ msglog_line(host_item * host, uschar * message) -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT /************************************************* * Post-defer action * *************************************************/ @@ -919,7 +919,7 @@ while (count-- > 0) addr->basic_errno = ERRNO_RCPT4XX; addr->more_errno |= ((buffer[1] - '0')*10 + buffer[2] - '0') << 8; -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT event_defer_errno = addr->more_errno; msg_event_raise(US"msg:rcpt:host:defer", addr); #endif @@ -930,7 +930,7 @@ while (count-- > 0) if (host->next) log_write(0, LOG_MAIN, "H=%s [%s]: %s", host->name, host->address, addr->message); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT else msg_event_raise(US"msg:rcpt:defer", addr); #endif @@ -1330,6 +1330,49 @@ return Ustrcmp(current_local_identity, message_local_identity) == 0; +uschar +ehlo_response(uschar * buf, size_t bsize, uschar checks) +{ +#ifdef SUPPORT_TLS +if (checks & PEER_OFFERED_TLS) + if (pcre_exec(regex_STARTTLS, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_TLS; +#endif + + if ( checks & PEER_OFFERED_IGNQ + && pcre_exec(regex_IGNOREQUOTA, NULL, CS buf, bsize, 0, + PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_IGNQ; + +#ifndef DISABLE_PRDR + if ( checks & PEER_OFFERED_PRDR + && pcre_exec(regex_PRDR, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_PRDR; +#endif + +#ifdef SUPPORT_I18N + if ( checks & PEER_OFFERED_UTF8 + && pcre_exec(regex_UTF8, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_UTF8; +#endif + + if ( checks & PEER_OFFERED_DSN + && pcre_exec(regex_DSN, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_DSN; + + if ( checks & PEER_OFFERED_PIPE + && pcre_exec(regex_PIPELINING, NULL, CS buf, bsize, 0, + PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_PIPE; + + if ( checks & PEER_OFFERED_SIZE + && pcre_exec(regex_SIZE, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0) + checks &= ~PEER_OFFERED_SIZE; + +return checks; +} + + /************************************************* * Deliver address list to given host * *************************************************/ @@ -1399,13 +1442,12 @@ BOOL completed_address = FALSE; BOOL esmtp = TRUE; BOOL pending_MAIL; BOOL pass_message = FALSE; +uschar peer_offered = 0; /*XXX should this be handed on cf. tls_offered, smtp_use_dsn ? */ #ifndef DISABLE_PRDR -BOOL prdr_offered = FALSE; BOOL prdr_active; #endif -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N BOOL utf8_needed = FALSE; -BOOL utf8_offered = FALSE; #endif BOOL dsn_all_lasthop = TRUE; #if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE) @@ -1535,7 +1577,7 @@ if (continue_hostname == NULL) delayed till here so that $sending_interface and $sending_port are set. */ helo_data = expand_string(ob->helo_data); -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N if (helo_data) { uschar * errstr = NULL; @@ -1562,7 +1604,7 @@ if (continue_hostname == NULL) #endif if (!good_response) goto RESPONSE_FAILED; -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT { uschar * s; lookup_dnssec_authenticated = host->dnssec==DS_YES ? US"yes" @@ -1684,43 +1726,21 @@ goto SEND_QUIT; if (!good_response) goto RESPONSE_FAILED; } - /* Set IGNOREQUOTA if the response to LHLO specifies support and the - lmtp_ignore_quota option was set. */ - - igquotstr = (lmtp && ob->lmtp_ignore_quota && - pcre_exec(regex_IGNOREQUOTA, NULL, CS buffer, Ustrlen(CS buffer), 0, - PCRE_EOPT, NULL, 0) >= 0)? US" IGNOREQUOTA" : US""; + if (esmtp || lmtp) + peer_offered = ehlo_response(buffer, Ustrlen(buffer), + PEER_OFFERED_TLS + | 0 /* IGNQ checked later */ + | 0 /* PRDR checked later */ + | 0 /* UTF8 checked later */ + | 0 /* DSN checked later */ + | 0 /* PIPE checked later */ + | 0 /* SIZE checked later */ + ); /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */ #ifdef SUPPORT_TLS - tls_offered = esmtp && - pcre_exec(regex_STARTTLS, NULL, CS buffer, Ustrlen(buffer), 0, - PCRE_EOPT, NULL, 0) >= 0; -#endif - -#ifndef DISABLE_PRDR - prdr_offered = esmtp - && pcre_exec(regex_PRDR, NULL, CS buffer, Ustrlen(buffer), 0, - PCRE_EOPT, NULL, 0) >= 0 - && verify_check_given_host(&ob->hosts_try_prdr, host) == OK; - - if (prdr_offered) - {DEBUG(D_transport) debug_printf("PRDR usable\n");} -#endif - -#ifdef EXPERIMENTAL_INTERNATIONAL - if (addrlist->prop.utf8_msg) - { - utf8_needed = !addrlist->prop.utf8_downcvt - && !addrlist->prop.utf8_downcvt_maybe; - DEBUG(D_transport) if (!utf8_needed) debug_printf("utf8: %s downconvert\n", - addrlist->prop.utf8_downcvt ? "mandatory" : "optional"); - - utf8_offered = esmtp - && pcre_exec(regex_UTF8, NULL, CS buffer, Ustrlen(buffer), 0, - PCRE_EOPT, NULL, 0) >= 0; - } + tls_offered = !!(peer_offered & PEER_OFFERED_TLS); #endif } @@ -1914,54 +1934,53 @@ if (continue_hostname == NULL #endif ) { + if (esmtp || lmtp) + peer_offered = ehlo_response(buffer, Ustrlen(buffer), + 0 /* no TLS */ + | (lmtp && ob->lmtp_ignore_quota ? PEER_OFFERED_IGNQ : 0) + | PEER_OFFERED_PRDR +#ifdef SUPPORT_I18N + | (addrlist->prop.utf8_msg ? PEER_OFFERED_UTF8 : 0) + /*XXX if we hand peercaps on to continued-conn processes, + must not depend on this addr */ +#endif + | PEER_OFFERED_DSN + | PEER_OFFERED_PIPE + | (ob->size_addition >= 0 ? PEER_OFFERED_SIZE : 0) + ); + /* Set for IGNOREQUOTA if the response to LHLO specifies support and the lmtp_ignore_quota option was set. */ - igquotstr = (lmtp && ob->lmtp_ignore_quota && - pcre_exec(regex_IGNOREQUOTA, NULL, CS buffer, Ustrlen(CS buffer), 0, - PCRE_EOPT, NULL, 0) >= 0)? US" IGNOREQUOTA" : US""; + igquotstr = peer_offered & PEER_OFFERED_IGNQ ? US" IGNOREQUOTA" : US""; /* If the response to EHLO specified support for the SIZE parameter, note this, provided size_addition is non-negative. */ - smtp_use_size = esmtp && ob->size_addition >= 0 && - pcre_exec(regex_SIZE, NULL, CS buffer, Ustrlen(CS buffer), 0, - PCRE_EOPT, NULL, 0) >= 0; + smtp_use_size = !!(peer_offered & PEER_OFFERED_SIZE); /* Note whether the server supports PIPELINING. If hosts_avoid_esmtp matched the current host, esmtp will be false, so PIPELINING can never be used. If the current host matches hosts_avoid_pipelining, don't do it. */ - smtp_use_pipelining = esmtp - && verify_check_given_host(&ob->hosts_avoid_pipelining, host) != OK - && pcre_exec(regex_PIPELINING, NULL, CS buffer, Ustrlen(CS buffer), 0, - PCRE_EOPT, NULL, 0) >= 0; + smtp_use_pipelining = peer_offered & PEER_OFFERED_PIPE + && verify_check_given_host(&ob->hosts_avoid_pipelining, host) != OK; DEBUG(D_transport) debug_printf("%susing PIPELINING\n", - smtp_use_pipelining? "" : "not "); + smtp_use_pipelining ? "" : "not "); #ifndef DISABLE_PRDR - prdr_offered = esmtp - && pcre_exec(regex_PRDR, NULL, CS buffer, Ustrlen(CS buffer), 0, - PCRE_EOPT, NULL, 0) >= 0 - && verify_check_given_host(&ob->hosts_try_prdr, host) == OK; + if ( peer_offered & PEER_OFFERED_PRDR + && verify_check_given_host(&ob->hosts_try_prdr, host) != OK) + peer_offered &= ~PEER_OFFERED_PRDR; - if (prdr_offered) + if (peer_offered & PEER_OFFERED_PRDR) {DEBUG(D_transport) debug_printf("PRDR usable\n");} #endif -#ifdef EXPERIMENTAL_INTERNATIONAL - if (addrlist->prop.utf8_msg) - utf8_offered = esmtp - && pcre_exec(regex_UTF8, NULL, CS buffer, Ustrlen(buffer), 0, - PCRE_EOPT, NULL, 0) >= 0; -#endif - /* Note if the server supports DSN */ - smtp_use_dsn = esmtp - && pcre_exec(regex_DSN, NULL, CS buffer, Ustrlen(CS buffer), 0, - PCRE_EOPT, NULL, 0) >= 0; - DEBUG(D_transport) debug_printf("use_dsn=%d\n", smtp_use_dsn); + smtp_use_dsn = !!(peer_offered & PEER_OFFERED_DSN); + DEBUG(D_transport) debug_printf("%susing DSN\n", smtp_use_dsn ? "" : "not "); /* Note if the response to EHLO specifies support for the AUTH extension. If it has, check that this host is one we want to authenticate to, and do @@ -1983,9 +2002,17 @@ message-specific. */ setting_up = FALSE; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N +if (addrlist->prop.utf8_msg) + { + utf8_needed = !addrlist->prop.utf8_downcvt + && !addrlist->prop.utf8_downcvt_maybe; + DEBUG(D_transport) if (!utf8_needed) debug_printf("utf8: %s downconvert\n", + addrlist->prop.utf8_downcvt ? "mandatory" : "optional"); + } + /* If this is an international message we need the host to speak SMTPUTF8 */ -if (utf8_needed && !utf8_offered) +if (utf8_needed && !(peer_offered & PEER_OFFERED_UTF8)) { errno = ERRNO_UTF8_FWD; goto RESPONSE_FAILED; @@ -2051,8 +2078,7 @@ if (smtp_use_size) #ifndef DISABLE_PRDR prdr_active = FALSE; -if (prdr_offered) - { +if (peer_offered & PEER_OFFERED_PRDR) for (addr = first_addr; addr; addr = addr->next) if (addr->transport_return == PENDING_DEFER) { @@ -2065,11 +2091,13 @@ if (prdr_offered) } break; } - } #endif -#ifdef EXPERIMENTAL_INTERNATIONAL -if (addrlist->prop.utf8_msg && !addrlist->prop.utf8_downcvt && utf8_offered) +#ifdef SUPPORT_I18N +if ( addrlist->prop.utf8_msg + && !addrlist->prop.utf8_downcvt + && peer_offered & PEER_OFFERED_UTF8 + ) sprintf(CS p, " SMTPUTF8"), p += 9; #endif @@ -2128,14 +2156,16 @@ pending_MAIL = TRUE; /* The block starts with MAIL */ { uschar * s = return_path; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N uschar * errstr = NULL; /* If we must downconvert, do the from-address here. Remember we had to for the to-addresses (done below), and also (ugly) for re-doing when building the delivery log line. */ - if (addrlist->prop.utf8_msg && (addrlist->prop.utf8_downcvt || !utf8_offered)) + if ( addrlist->prop.utf8_msg + && (addrlist->prop.utf8_downcvt || !(peer_offered & PEER_OFFERED_UTF8)) + ) { if (s = string_address_utf8_to_alabel(return_path, &errstr), errstr) { @@ -2239,7 +2269,7 @@ for (addr = first_addr; rcpt_addr = transport_rcpt_address(addr, tblock->rcpt_include_affixes); -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N { uschar * dummy_errstr; if ( testflag(addrlist, af_utf8_downcvt) @@ -2458,7 +2488,7 @@ if (!ok) ok = TRUE; else /* Set up confirmation if needed - applies only to SMTP */ if ( -#ifndef EXPERIMENTAL_EVENT +#ifdef DISABLE_EVENT LOGGING(smtp_confirmation) && #endif !lmtp @@ -2679,7 +2709,7 @@ if (!ok) switch(save_errno) { -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N case ERRNO_UTF8_FWD: code = '5'; /*FALLTHROUGH*/ @@ -2930,7 +2960,7 @@ case continue_more won't get set. */ (void)close(inblock.sock); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT (void) event_raise(tblock->event_action, US"tcp:close", NULL); #endif @@ -3663,7 +3693,7 @@ for (cutoff_retry = 0; expired && first_addr->basic_errno != ERRNO_TLSFAILURE) write_logs(first_addr, host); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT if (rc == DEFER) deferred_event_raise(first_addr, host); #endif @@ -3691,7 +3721,7 @@ for (cutoff_retry = 0; expired && &message_defer, TRUE); if (rc == DEFER && first_addr->basic_errno != ERRNO_AUTHFAIL) write_logs(first_addr, host); -# ifdef EXPERIMENTAL_EVENT +# ifndef DISABLE_EVENT if (rc == DEFER) deferred_event_raise(first_addr, host); # endif