Make smtp_receive_timeout main option expanded. Bug 564
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 12 Jan 2015 16:01:38 +0000 (16:01 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 12 Jan 2015 16:06:36 +0000 (16:06 +0000)
12 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/functions.h
src/src/globals.c
src/src/globals.h
src/src/macros.h
src/src/readconf.c
src/src/smtp_in.c
test/confs/0092
test/scripts/0000-Basic/0092
test/stderr/0092
test/stdout/0092

index 3498893a61a7db2f7bced9ca18090bc729d0fc04..ab65312199891f096d9f77753c6ff185b43daebc 100644 (file)
@@ -16086,7 +16086,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
@@ -16101,6 +16101,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
index 2dfd7d34767f6c20a2c9456da91039d5542cc248..e9d753153745ad2a35f03b6276470c62eedae5b9 100644 (file)
@@ -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
index ee2fd39c661ebcc75fe388861ea38424227533e9..c5f6d5ce186ba599ef3de34130461e18c952376b 100644 (file)
@@ -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);
index 85d2e5c36e2af42b327ac74d01fe7a769ac9cf11..a8670e414511e65ad6115a5d3399469036a5e6db 100644 (file)
@@ -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;
index 7ca07d56cab7c59c615e9e1cf050a995aabf77a7..5495f54db483fbc5156762412d07dfd8bcae9c7d 100644 (file)
@@ -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 */
index 2085c3f4152c8414acf6753a218ab9f1b03eea65..43179a531af44c303179ca196d3d5a09865dc89c 100644 (file)
@@ -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
index 687b35223f0d7c6c6f8fbbe78debaeddd765faec..60df37afc4bb321e9b535c784919dd69b27de1b8 100644 (file)
@@ -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;
index d646fe0bdfc5aea41938197ab94bcec895192b1e..4fc2cfd4175f8ab54a983f95658aaa2d1de089a4 100644 (file)
@@ -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. */
 
index 15f1f5d1c39384e253650a4156e7ee77c74fe456..62157cb3306b09a1d1d1e96129218914ee15be31 100644 (file)
@@ -17,7 +17,8 @@ gecos_name = CALLER_NAME
 
 # ----- Main settings -----
 
-smtp_receive_timeout = 2s
+OPT = 2s
+smtp_receive_timeout = OPT
 receive_timeout = 2s
 
 
index 78c713e1c0456a4f036a638487bef9c7db507118..153431753b4f801ec5ce97b769f93fddda4688d4 100644 (file)
@@ -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
index 09bf352d13f11fa33b6d21e60a06f4ba03950d56..4cae3dbf778b2144ded182e0475884f889be3fb3 100644 (file)
@@ -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=<userx@test.ex>
+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=<userx@test.ex>
+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)
index 3656b912018ac5e565074ca92e22b4b77dcdefb2..6e8d057169fdc09e3242948505ce7b30281185c6 100644 (file)
 **** 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\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+421 myhost.test.ex SMTP incoming data timeout - closing connection.\r
+
+**** 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\r
 250 OK\r
 550 unrouteable address\r