From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Tue, 4 Feb 2020 14:32:17 +0000 (+0000)
Subject: ACL: Fix parsing of control=queue_only
X-Git-Tag: exim-4_94_RC0~113
X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=cfe6f17c3c1f76ce403195dbae8ac4141f527ba7;p=exim.git

ACL: Fix parsing of control=queue_only

Broken-by: 9438970c97
---

diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index f7002b9fe..0d22aaefa 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -30151,7 +30151,7 @@ in several different ways. For example:
 It can be at the end of an &%accept%& statement:
 .code
     accept  ...some conditions
-            control = queue_only
+            control = queue
 .endd
 In this case, the control is applied when this statement yields &"accept"&, in
 other words, when the conditions are all true.
@@ -30160,7 +30160,7 @@ other words, when the conditions are all true.
 It can be in the middle of an &%accept%& statement:
 .code
     accept  ...some conditions...
-            control = queue_only
+            control = queue
             ...some more conditions...
 .endd
 If the first set of conditions are true, the control is applied, even if the
diff --git a/src/src/acl.c b/src/src/acl.c
index 952195d4a..74ec1ef33 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -112,7 +112,8 @@ enum { ACLC_ACL,
 /* ACL conditions/modifiers: "delay", "control", "continue", "endpass",
 "message", "log_message", "log_reject_target", "logwrite", "queue" and "set" are
 modifiers that look like conditions but always return TRUE. They are used for
-their side effects. */
+their side effects.  Do not invent new modifier names that result in one name
+being the prefix of another; the binary-search in the list will go wrong. */
 
 typedef struct condition_def {
   uschar	*name;
@@ -367,7 +368,6 @@ enum {
   CONTROL_NO_PIPELINING,
 
   CONTROL_QUEUE,
-  CONTROL_QUEUE_ONLY,
   CONTROL_SUBMISSION,
   CONTROL_SUPPRESS_LOCAL_FIXUPS,
 #ifdef SUPPORT_I18N
@@ -511,15 +511,6 @@ static control_def controls_list[] = {
 	    // ACL_BIT_PRDR|    /* Not allow one user to freeze for all */
 	    ACL_BIT_NOTSMTP | ACL_BIT_MIME)
   },
-[CONTROL_QUEUE_ONLY] =
-  { US"queue_only",		TRUE,
-	  (unsigned)
-	  ~(ACL_BIT_MAIL | ACL_BIT_RCPT |
-	    ACL_BIT_PREDATA | ACL_BIT_DATA |
-	    // ACL_BIT_PRDR|    /* Not allow one user to freeze for all */
-	    ACL_BIT_NOTSMTP | ACL_BIT_MIME)
-  },
-
 
 [CONTROL_SUBMISSION] =
   { US"submission",              TRUE,
@@ -2122,7 +2113,9 @@ return ERROR;
 *        Check argument for control= modifier    *
 *************************************************/
 
-/* Called from acl_check_condition() below
+/* Called from acl_check_condition() below.
+To handle the case "queue_only" we accept an _ in the
+initial / option-switch position.
 
 Arguments:
   arg         the argument string for control=
@@ -2138,10 +2131,11 @@ decode_control(const uschar *arg, const uschar **pptr, int where, uschar **log_m
 {
 int idx, len;
 control_def * d;
+uschar c;
 
 if (  (idx = find_control(arg, controls_list, nelem(controls_list))) < 0
-   || (  arg[len = Ustrlen((d = controls_list+idx)->name)] != 0
-      && (!d->has_option || arg[len] != '/')
+   || (  (c = arg[len = Ustrlen((d = controls_list+idx)->name)]) != 0
+      && (!d->has_option || c != '/' && c != '_')
    )  )
   {
   *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg);
@@ -3168,15 +3162,17 @@ for (; cb; cb = cb->next)
 	  break;
 
 	case CONTROL_QUEUE:
-	case CONTROL_QUEUE_ONLY:
 	  f.queue_only_policy = TRUE;
+	  if (Ustrcmp(p, "_only") == 0)
+	    p += 5;
+	  else while (*p == '/')
+	    if (Ustrncmp(p, "/only", 5) == 0)
+	      { p += 5; f.queue_smtp = FALSE; }
+	    else if (Ustrncmp(p, "/first_pass_route", 17) == 0)
+	      { p += 17; f.queue_smtp = TRUE; }
+	    else
+	      break;
 	  cancel_cutthrough_connection(TRUE, US"queueing forced");
-	  while (*p == '/')
-	    if (Ustrncmp(p, "/first_pass_route", 17) == 0)
-	      {
-	      p += 17;
-	      f.queue_smtp = TRUE;
-	      }
 	  break;
 
 	case CONTROL_SUBMISSION:
diff --git a/test/log/0505 b/test/log/0505
index 1141546ad..45fb63f05 100644
--- a/test/log/0505
+++ b/test/log/0505
@@ -3,4 +3,4 @@
 1999-03-02 09:44:33 U=CALLER temporarily rejected EHLO or HELO xxx: cannot use "control=submission" in EHLO or HELO ACL
 1999-03-02 09:44:33 ACL for QUIT returned ERROR: cannot use "control=freeze" in QUIT ACL
 1999-03-02 09:44:33 10HmaY-0005vi-00 F=<CALLER@myhost.test.ex> rejected by non-SMTP ACL: cannot use "control=enforce_sync" in non-SMTP ACL
-1999-03-02 09:44:33 U=CALLER temporarily rejected connection in "connect" ACL: cannot use "control=queue_only" in connection ACL
+1999-03-02 09:44:33 U=CALLER temporarily rejected connection in "connect" ACL: cannot use "control=queue" in connection ACL
diff --git a/test/rejectlog/0505 b/test/rejectlog/0505
index 2c56b7f1e..41fd97e5b 100644
--- a/test/rejectlog/0505
+++ b/test/rejectlog/0505
@@ -19,4 +19,4 @@ P Received: from CALLER by myhost.test.ex with local (Exim x.yz)
 I Message-Id: <E10HmaY-0005vi-00@myhost.test.ex>
 F From: CALLER_NAME <CALLER@myhost.test.ex>
   Date: Tue, 2 Mar 1999 09:44:33 +0000
-1999-03-02 09:44:33 U=CALLER temporarily rejected connection in "connect" ACL: cannot use "control=queue_only" in connection ACL
+1999-03-02 09:44:33 U=CALLER temporarily rejected connection in "connect" ACL: cannot use "control=queue" in connection ACL