From 1ad6489edabbfce85ee7362370cee4b34739c234 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 12 Jan 2015 16:01:38 +0000 Subject: [PATCH] Make smtp_receive_timeout main option expanded. Bug 564 --- doc/doc-docbook/spec.xfpt | 6 ++- doc/doc-txt/ChangeLog | 2 + src/src/functions.h | 2 +- src/src/globals.c | 1 + src/src/globals.h | 1 + src/src/macros.h | 2 +- src/src/readconf.c | 39 +++++++++++++++++--- src/src/smtp_in.c | 13 +++++++ test/confs/0092 | 3 +- test/scripts/0000-Basic/0092 | 7 ++++ test/stderr/0092 | 71 ++++++++++++++++++++++++++++++++++++ test/stdout/0092 | 10 +++++ 12 files changed, 148 insertions(+), 9 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index a102ad790..63fef7fc4 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -16084,7 +16084,7 @@ See &%smtp_ratelimit_hosts%& above. See &%smtp_ratelimit_hosts%& above. -.option smtp_receive_timeout main time 5m +.option smtp_receive_timeout main time&!! 5m .cindex "timeout" "for SMTP input" .cindex "SMTP" "input timeout" This sets a timeout value for SMTP reception. It applies to all forms of SMTP @@ -16099,6 +16099,10 @@ SMTP data timeout on connection from... The former means that Exim was expecting to read an SMTP command; the latter means that it was in the DATA phase, reading the contents of a message. +If the first character of the option is a &"$"& the option is +expanded before use and may depend on +&$sender_host_name$&, &$sender_host_address$& and &$sender_host_port$&. + .oindex "&%-os%&" The value set by this option can be overridden by the diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 78658c776..f333752d7 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -39,6 +39,8 @@ JH/09 A timeout of 2 minutes is now applied to all malware scanner types by default, modifiable by a malware= option. The list separator for the options can now be changed in the usual way. +JH/10 The smtp_receive_timeout main option is now expanded before use. + Exim version 4.85 diff --git a/src/src/functions.h b/src/src/functions.h index a906e921f..2e18fd963 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -292,7 +292,7 @@ extern void readconf_main(void); extern void readconf_print(uschar *, uschar *, BOOL); extern uschar *readconf_printtime(int); extern uschar *readconf_readname(uschar *, int, uschar *); -extern int readconf_readtime(uschar *, int, BOOL); +extern int readconf_readtime(const uschar *, int, BOOL); extern void readconf_rest(); extern uschar *readconf_retry_error(uschar *, uschar *, int *, int *); extern void read_message_body(BOOL); diff --git a/src/src/globals.c b/src/src/globals.c index 85d2e5c36..a8670e414 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1254,6 +1254,7 @@ uschar *smtp_ratelimit_mail = NULL; uschar *smtp_ratelimit_rcpt = NULL; uschar *smtp_read_error = US""; int smtp_receive_timeout = 5*60; +uschar *smtp_receive_timeout_s = NULL; uschar *smtp_reserve_hosts = NULL; BOOL smtp_return_error_details = FALSE; int smtp_rlm_base = 0; diff --git a/src/src/globals.h b/src/src/globals.h index 7ca07d56c..5495f54db 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -801,6 +801,7 @@ extern uschar *smtp_ratelimit_mail; /* Parameters for MAIL limiting */ extern uschar *smtp_ratelimit_rcpt; /* Parameters for RCPT limiting */ extern uschar *smtp_read_error; /* Message for SMTP input error */ extern int smtp_receive_timeout; /* Applies to each received line */ +extern uschar *smtp_receive_timeout_s; /* ... expandable version */ extern uschar *smtp_reserve_hosts; /* Hosts for reserved slots */ extern BOOL smtp_return_error_details; /* TRUE to return full info */ extern int smtp_rlm_base; /* Base interval for MAIL rate limit */ diff --git a/src/src/macros.h b/src/src/macros.h index 2085c3f41..43179a531 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -629,7 +629,7 @@ can be easily tested as a group. That is the only use of opt_bool_last. */ enum { opt_bit = 32, opt_bool_verify, opt_bool_set, opt_expand_bool, opt_bool_last, opt_rewrite, opt_timelist, opt_uid, opt_gid, opt_uidlist, opt_gidlist, - opt_expand_uid, opt_expand_gid, opt_void }; + opt_expand_uid, opt_expand_gid, opt_func, opt_void }; /* There's a high-ish bit which is used to flag duplicate options, kept for compatibility, which shouldn't be output. Also used for hidden options diff --git a/src/src/readconf.c b/src/src/readconf.c index 687b35223..60df37afc 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -11,6 +11,9 @@ implementation of the conditional .ifdef etc. */ #include "exim.h" +static void fn_smtp_receive_timeout(const uschar * name, const uschar * str); + + #define CSTATE_STACK_SIZE 10 @@ -392,7 +395,7 @@ static optionlist optionlist_config[] = { { "smtp_ratelimit_hosts", opt_stringptr, &smtp_ratelimit_hosts }, { "smtp_ratelimit_mail", opt_stringptr, &smtp_ratelimit_mail }, { "smtp_ratelimit_rcpt", opt_stringptr, &smtp_ratelimit_rcpt }, - { "smtp_receive_timeout", opt_time, &smtp_receive_timeout }, + { "smtp_receive_timeout", opt_func, &fn_smtp_receive_timeout }, { "smtp_reserve_hosts", opt_stringptr, &smtp_reserve_hosts }, { "smtp_return_error_details",opt_bool, &smtp_return_error_details }, #ifdef WITH_CONTENT_SCAN @@ -1027,7 +1030,7 @@ Returns: the time value, or -1 on syntax error */ int -readconf_readtime(uschar *s, int terminator, BOOL return_msec) +readconf_readtime(const uschar *s, int terminator, BOOL return_msec) { int yield = 0; for (;;) @@ -1036,7 +1039,7 @@ for (;;) double fraction; if (!isdigit(*s)) return -1; - (void)sscanf(CS s, "%d%n", &value, &count); + (void)sscanf(CCS s, "%d%n", &value, &count); s += count; switch (*s) @@ -1050,7 +1053,7 @@ for (;;) case '.': if (!return_msec) return -1; - (void)sscanf(CS s, "%lf%n", &fraction, &count); + (void)sscanf(CCS s, "%lf%n", &fraction, &count); s += count; if (*s++ != 's') return -1; yield += (int)(fraction * 1000.0); @@ -1350,6 +1353,26 @@ return yield; } +/************************************************* +* Custom-handler options * +*************************************************/ +static void +fn_smtp_receive_timeout(const uschar * name, const uschar * str) +{ +int value; + +if (*str == '$') + smtp_receive_timeout_s = string_copy(str); +else + { + /* "smtp_receive_timeout", opt_time, &smtp_receive_timeout */ + smtp_receive_timeout = readconf_readtime(str, 0, FALSE); + if (smtp_receive_timeout < 0) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "invalid time value for %s", + name); + } +} + /************************************************* * Handle option line * *************************************************/ @@ -2116,9 +2139,15 @@ switch (type) name); if (count > 0 && list[2] == 0) count = 0; list[1] = count; + break; } - break; + case opt_func: + { + void (*fn)() = ol->value; + fn(name, s); + break; + } } return TRUE; diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index d646fe0bd..4fc2cfd41 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -2129,6 +2129,19 @@ if (!sender_host_unknown) set_process_info("handling incoming connection from %s", host_and_ident(FALSE)); + /* Expand smtp_receive_timeout, if needed */ + + if (smtp_receive_timeout_s) + { + uschar * exp; + if ( !(exp = expand_string(smtp_receive_timeout_s)) + || !(*exp) + || (smtp_receive_timeout = readconf_readtime(exp, 0, FALSE)) < 0 + ) + log_write(0, LOG_MAIN|LOG_PANIC, + "bad value for smtp_receive_timeout: '%s'", exp ? exp : US""); + } + /* Start up TLS if tls_on_connect is set. This is for supporting the legacy smtps port for use with older style SSL MTAs. */ diff --git a/test/confs/0092 b/test/confs/0092 index 15f1f5d1c..62157cb33 100644 --- a/test/confs/0092 +++ b/test/confs/0092 @@ -17,7 +17,8 @@ gecos_name = CALLER_NAME # ----- Main settings ----- -smtp_receive_timeout = 2s +OPT = 2s +smtp_receive_timeout = OPT receive_timeout = 2s diff --git a/test/scripts/0000-Basic/0092 b/test/scripts/0000-Basic/0092 index 78c713e1c..153431753 100644 --- a/test/scripts/0000-Basic/0092 +++ b/test/scripts/0000-Basic/0092 @@ -19,6 +19,13 @@ data The quick brown fox **** 1 +3 exim -d+expand '-DOPT=${if eq {V4NET.0.0.1} {$sender_host_address} {2} {30}}s' -bh V4NET.0.0.1 +mail from:userx@test.ex +rcpt to:userx@test.ex +data +The quick brown fox +**** +1 3 exim userx@test.ex **** 1 diff --git a/test/stderr/0092 b/test/stderr/0092 index 09bf352d1..4cae3dbf7 100644 --- a/test/stderr/0092 +++ b/test/stderr/0092 @@ -32,6 +32,77 @@ LOG: SMTP command timeout on connection from [V4NET.0.0.1] >>> accept: condition test succeeded in ACL "check_recipient" >>> end of ACL "check_recipient": ACCEPT LOG: SMTP data timeout (message abandoned) on connection from [V4NET.0.0.1] F= +Exim version x.yz .... +changed uid/gid: forcing real = effective + uid=uuuu gid=CALLER_GID pid=pppp +configuration file is TESTSUITE/test-config +admin user +changed uid/gid: privilege not needed + uid=EXIM_UID gid=EXIM_GID pid=pppp +DSN: fail_remote_domains propagating DSN +DSN: forward propagating DSN +originator: uid=CALLER_UID gid=CALLER_GID login=CALLER name=CALLER_NAME +sender address = CALLER@myhost.test.ex +sender_fullhost = [V4NET.0.0.1] +sender_rcvhost = [V4NET.0.0.1] +host in hosts_connection_nolog? no (option unset) +LOG: smtp_connection MAIN + SMTP connection from [V4NET.0.0.1] +host in host_lookup? no (option unset) +set_process_info: pppp handling incoming connection from [V4NET.0.0.1] +expanding: V4NET.0.0.1 + result: V4NET.0.0.1 +expanding: $sender_host_address + result: V4NET.0.0.1 +condition: eq {V4NET.0.0.1} {$sender_host_address} + result: true +expanding: 2 + result: 2 +expanding: 30 + result: 30 +skipping: result is not used +expanding: ${if eq {V4NET.0.0.1} {$sender_host_address} {2} {30}}s + result: 2s +host in host_reject_connection? no (option unset) +host in sender_unqualified_hosts? no (option unset) +host in recipient_unqualified_hosts? no (option unset) +host in helo_verify_hosts? no (option unset) +host in helo_try_verify_hosts? no (option unset) +host in helo_accept_junk_hosts? no (option unset) +expanding: $smtp_active_hostname ESMTP Exim $version_number $tod_full + result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +SMTP>> 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +smtp_setup_msg entered +SMTP<< mail from:userx@test.ex +SMTP>> 250 OK +SMTP<< rcpt to:userx@test.ex +using ACL "check_recipient" +processing "accept" +check hosts = : +host in ":"? no (end of list) +accept: condition test failed in ACL "check_recipient" +processing "deny" + message: unrouteable address +check recipients = verify@test.ex +address match test: subject=userx@test.ex pattern=verify@test.ex +userx@test.ex in "verify@test.ex"? no (end of list) +deny: condition test failed in ACL "check_recipient" +processing "accept" +check domains = +local_domains +test.ex in "test.ex : *.test.ex"? yes (matched "test.ex") +test.ex in "+local_domains"? yes (matched "+local_domains") +accept: condition test succeeded in ACL "check_recipient" +end of ACL "check_recipient": ACCEPT +SMTP>> 250 Accepted +DSN: orcpt: NULL flags: 0 +SMTP<< data +SMTP>> 354 Enter message, ending with "." on a line by itself +search_tidyup called +LOG: lost_incoming_connection MAIN + SMTP data timeout (message abandoned) on connection from [V4NET.0.0.1] F= +SMTP>> 421 myhost.test.ex SMTP incoming data timeout - closing connection. +search_tidyup called +>>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=1 >>>>>>>>>>>>>>>> exim: timed out while reading - message abandoned exim: timed out while reading - message abandoned >>> host in hosts_connection_nolog? no (option unset) diff --git a/test/stdout/0092 b/test/stdout/0092 index 3656b9120..6e8d05716 100644 --- a/test/stdout/0092 +++ b/test/stdout/0092 @@ -27,6 +27,16 @@ **** but without any ident (RFC 1413) callback. **** This is not for real! +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +421 myhost.test.ex SMTP incoming data timeout - closing connection. + +**** SMTP testing session as if from host V4NET.0.0.1 +**** but without any ident (RFC 1413) callback. +**** This is not for real! + 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 250 OK 550 unrouteable address -- 2.25.1