X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f70940c9489d0ff5dc44db5ba5ed5258a8fe8772..4687a69c269ee3f2a7f0625e0147a503fd9d3d0b:/src/src/smtp_in.c diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index ffc7779f8..79176687d 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.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 */ @@ -1227,7 +1227,7 @@ for (smtp_cmd_list * p = cmd_list; p < cmd_list + nelem(cmd_list); p++) follow the sender address. */ smtp_cmd_argument = smtp_cmd_buffer + p->len; - while (isspace(*smtp_cmd_argument)) smtp_cmd_argument++; + Uskip_whitespace(&smtp_cmd_argument); Ustrcpy(smtp_data_buffer, smtp_cmd_argument); smtp_cmd_data = smtp_data_buffer; @@ -1352,7 +1352,7 @@ if (host_checking) g = string_cat(g, hostname); else if (f.sender_host_unknown || f.sender_host_notsocket) - g = string_cat(g, sender_ident); + g = string_cat(g, sender_ident ? sender_ident : US"NULL"); else if (f.is_inetd) g = string_append(g, 2, hostname, US" (via inetd)"); @@ -1876,10 +1876,11 @@ while (done <= 0) /* Check maximum number allowed */ - if (recipients_max > 0 && recipients_count + 1 > recipients_max) + if ( recipients_max_expanded > 0 + && recipients_count + 1 > recipients_max_expanded) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(smtp_cmd_buffer, "%s too many recipients", - recipients_max_reject? "552": "452"); + recipients_max_reject ? "552": "452"); /* Apply SMTP rewrite, then extract address. Don't allow "<>" as a recipient address */ @@ -2051,16 +2052,19 @@ else DEBUG(D_receive) static void log_connect_tls_drop(const uschar * what, const uschar * log_msg) { -gstring * g = s_tlslog(NULL); -uschar * tls = string_from_gstring(g); - -log_write(L_connection_reject, - log_reject_target, "%s%s%s dropped by %s%s%s", - LOGGING(dnssec) && sender_host_dnssec ? US" DS" : US"", - host_and_ident(TRUE), - tls ? tls : US"", - what, - log_msg ? US": " : US"", log_msg); +if (log_reject_target) + { + gstring * g = s_tlslog(NULL); + uschar * tls = string_from_gstring(g); + + log_write(L_connection_reject, + log_reject_target, "%s%s%s dropped by %s%s%s", + LOGGING(dnssec) && sender_host_dnssec ? US" DS" : US"", + host_and_ident(TRUE), + tls ? tls : US"", + what, + log_msg ? US": " : US"", log_msg); + } } @@ -2168,6 +2172,7 @@ lwr_receive_ungetc = NULL; /* Set up the message size limit; this may be host-specific */ +GET_OPTION("message_size_limit"); thismessage_size_limit = expand_string_integer(message_size_limit, TRUE); if (expand_string_message) { @@ -2537,6 +2542,11 @@ if (!f.sender_host_unknown) fl.helo_accept_junk = verify_check_host(&helo_accept_junk_hosts) == OK; } +/* Expand recipients_max, if needed */ + { + uschar * rme = expand_string(recipients_max); + recipients_max_expanded = atoi(CCS rme); + } /* For batch SMTP input we are now done. */ if (smtp_batched_input) return TRUE; @@ -2560,6 +2570,7 @@ if (proxy_protocol_host()) /* Run the connect ACL if it exists */ user_msg = NULL; +GET_OPTION("acl_smtp_connect"); if (acl_smtp_connect) { int rc; @@ -2606,16 +2617,20 @@ if (user_msg) esclen = codelen - 4; } } -else if (!(s = expand_string(smtp_banner))) +else { - log_write(0, f.expand_string_forcedfail ? LOG_MAIN : LOG_MAIN|LOG_PANIC_DIE, - "Expansion of \"%s\" (smtp_banner) failed: %s", - smtp_banner, expand_string_message); - /* for force-fail */ -#ifndef DISABLE_TLS - if (tls_in.on_connect) tls_close(NULL, TLS_SHUTDOWN_WAIT); -#endif - return FALSE; + GET_OPTION("smtp_banner"); + if (!(s = expand_string(smtp_banner))) + { + log_write(0, f.expand_string_forcedfail ? LOG_MAIN : LOG_MAIN|LOG_PANIC_DIE, + "Expansion of \"%s\" (smtp_banner) failed: %s", + smtp_banner, expand_string_message); + /* for force-fail */ + #ifndef DISABLE_TLS + if (tls_in.on_connect) tls_close(NULL, TLS_SHUTDOWN_WAIT); + #endif + return FALSE; + } } /* Remove any terminating newlines; might as well remove trailing space too */ @@ -3085,7 +3100,7 @@ else the connection is not forcibly to be dropped, return 0. Otherwise, log why it is closing if required and return 2. */ -if (log_reject_target != 0) +if (log_reject_target) { #ifndef DISABLE_TLS gstring * g = s_tlslog(NULL); @@ -3176,6 +3191,7 @@ fl.smtp_exit_function_called = TRUE; /* Call the not-QUIT ACL, if there is one, unless no reason is given. */ +GET_OPTION("acl_smtp_notquit"); if (acl_smtp_notquit && reason) { smtp_notquit_reason = reason; @@ -3512,6 +3528,7 @@ smtp_quit_handler(uschar ** user_msgp, uschar ** log_msgp) HAD(SCH_QUIT); f.smtp_in_quit = TRUE; incomplete_transaction_log(US"QUIT"); +GET_OPTION("acl_smtp_quit"); if ( acl_smtp_quit && acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, user_msgp, log_msgp) == ERROR) @@ -3685,6 +3702,7 @@ while (done <= 0) for (auth_instance * au = auths; au; au = au->next) if (strcmpic(US"tls", au->driver_name) == 0) { + GET_OPTION("acl_smtp_auth"); if ( acl_smtp_auth && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg)) != OK @@ -3763,6 +3781,7 @@ while (done <= 0) /* Check the ACL */ + GET_OPTION("acl_smtp_auth"); if ( acl_smtp_auth && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg)) != OK @@ -3788,8 +3807,8 @@ while (done <= 0) if (*smtp_cmd_data) { - *smtp_cmd_data++ = 0; - while (isspace(*smtp_cmd_data)) smtp_cmd_data++; + *smtp_cmd_data++ = '\0'; + Uskip_whitespace(&smtp_cmd_data); } /* Search for an authentication mechanism which is configured for use @@ -3900,10 +3919,10 @@ while (done <= 0) if (!f.sender_host_unknown) { BOOL old_helo_verified = f.helo_verified; - uschar *p = smtp_cmd_data; + uschar * p = smtp_cmd_data; - while (*p != 0 && !isspace(*p)) { *p = tolower(*p); p++; } - *p = 0; + while (*p && !isspace(*p)) { *p = tolower(*p); p++; } + *p = '\0'; /* Force a reverse lookup if HELO quoted something in helo_lookup_domains because otherwise the log can be confusing. */ @@ -3957,6 +3976,7 @@ while (done <= 0) /* Apply an ACL check if one is defined; afterwards, recheck synchronization in case the client started sending in a delay. */ + GET_OPTION("acl_smtp_helo"); if (acl_smtp_helo) if ((rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo, &user_msg, &log_msg)) != OK) @@ -4051,15 +4071,15 @@ while (done <= 0) g = string_catn(g, US"-SIZE\r\n", 7); } -#ifdef EXPERIMENTAL_ESMTP_LIMITS - if ( (smtp_mailcmd_max > 0 || recipients_max) +#ifndef DISABLE_ESMTP_LIMITS + if ( (smtp_mailcmd_max > 0 || recipients_max_expanded > 0) && verify_check_host(&limits_advertise_hosts) == OK) { g = string_fmt_append(g, "%.3s-LIMITS", smtp_code); if (smtp_mailcmd_max > 0) g = string_fmt_append(g, " MAILMAX=%d", smtp_mailcmd_max); - if (recipients_max) - g = string_fmt_append(g, " RCPTMAX=%d", recipients_max); + if (recipients_max_expanded > 0) + g = string_fmt_append(g, " RCPTMAX=%d", recipients_max_expanded); g = string_catn(g, US"\r\n", 2); } #endif @@ -4088,16 +4108,19 @@ while (done <= 0) /* Advertise ETRN/VRFY/EXPN if there's are ACL checking whether a host is permitted to issue them; a check is made when any host actually tries. */ + GET_OPTION("acl_smtp_etrn"); if (acl_smtp_etrn) { g = string_catn(g, smtp_code, 3); g = string_catn(g, US"-ETRN\r\n", 7); } + GET_OPTION("acl_smtp_vrfy"); if (acl_smtp_vrfy) { g = string_catn(g, smtp_code, 3); g = string_catn(g, US"-VRFY\r\n", 7); } + GET_OPTION("acl_smtp_expn"); if (acl_smtp_expn) { g = string_catn(g, smtp_code, 3); @@ -4493,6 +4516,7 @@ while (done <= 0) US"invalid data for AUTH"); goto COMMAND_LOOP; } + GET_OPTION("acl_smtp_mailauth"); if (!acl_smtp_mailauth) { ignore_msg = US"client not authenticated"; @@ -4689,6 +4713,7 @@ while (done <= 0) when pipelining is not advertised, do another sync check in case the ACL delayed and the client started sending in the meantime. */ + GET_OPTION("acl_smtp_mail"); if (acl_smtp_mail) { rc = acl_check(ACL_WHERE_MAIL, NULL, acl_smtp_mail, &user_msg, &log_msg); @@ -4897,7 +4922,8 @@ while (done <= 0) /* Check maximum allowed */ - if (rcpt_count+1 < 0 || rcpt_count > recipients_max && recipients_max > 0) + if ( rcpt_count+1 < 0 + || rcpt_count > recipients_max_expanded && recipients_max_expanded > 0) { if (recipients_max_reject) { @@ -4943,10 +4969,13 @@ while (done <= 0) if (f.recipients_discarded) rc = DISCARD; else + { + GET_OPTION("acl_smtp_rcpt"); if ( (rc = acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg, &log_msg)) == OK && !f.smtp_in_pipelining_advertised && !check_sync()) goto SYNC_FAILURE; + } /* The ACL was happy */ @@ -5102,13 +5131,14 @@ while (done <= 0) } if (chunking_state > CHUNKING_OFFERED) - rc = OK; /* No predata ACL or go-ahead output for BDAT */ + rc = OK; /* There is no predata ACL or go-ahead output for BDAT */ else { - /* If there is an ACL, re-check the synchronization afterwards, since the - ACL may have delayed. To handle cutthrough delivery enforce a dummy call - to get the DATA command sent. */ + /* If there is a predata-ACL, re-check the synchronization afterwards, + since the ACL may have delayed. To handle cutthrough delivery enforce a + dummy call to get the DATA command sent. */ + GET_OPTION("acl_smtp_predata"); if (!acl_smtp_predata && cutthrough.cctx.sock < 0) rc = OK; else @@ -5167,6 +5197,7 @@ while (done <= 0) US"verify"))) break; + GET_OPTION("acl_smtp_vrfy"); if ((rc = acl_check(ACL_WHERE_VRFY, address, acl_smtp_vrfy, &user_msg, &log_msg)) != OK) done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg); @@ -5205,6 +5236,7 @@ while (done <= 0) case EXPN_CMD: HAD(SCH_EXPN); + GET_OPTION("acl_smtp_expn"); rc = acl_check(ACL_WHERE_EXPN, NULL, acl_smtp_expn, &user_msg, &log_msg); if (rc != OK) done = smtp_handle_acl_fail(ACL_WHERE_EXPN, rc, user_msg, log_msg); @@ -5234,6 +5266,7 @@ while (done <= 0) /* Apply an ACL check if one is defined */ + GET_OPTION("acl_smtp_starttls"); if ( acl_smtp_starttls && (rc = acl_check(ACL_WHERE_STARTTLS, NULL, acl_smtp_starttls, &user_msg, &log_msg)) != OK @@ -5352,6 +5385,7 @@ while (done <= 0) case QUIT_CMD: f.smtp_in_quit = TRUE; user_msg = NULL; + GET_OPTION("acl_smtp_quit"); if ( acl_smtp_quit && ((rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, &user_msg, &log_msg)) == ERROR)) @@ -5471,6 +5505,7 @@ while (done <= 0) log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_cmd_argument, host_and_ident(FALSE)); + GET_OPTION("acl_smtp_etrn"); if ((rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn, &user_msg, &log_msg)) != OK) { @@ -5487,6 +5522,7 @@ while (done <= 0) since that is strictly the only kind of ETRN that can be implemented according to the RFC. */ + GET_OPTION("smtp_etrn_command"); if (smtp_etrn_command) { uschar *error;