Change acl expansion-condition syntax to "acl {{name} {arg1}{arg2}...}"
[exim.git] / src / src / acl.c
index 3177ac842eb68f159d9abdc48b3f7b0730a433f2..d0db7171eac1153855a33b72396653dea878728c 100644 (file)
@@ -236,7 +236,7 @@ at the outer level. In the other cases, expansion already occurs in the
 checking functions. */
 
 static uschar cond_expand_at_top[] = {
-  TRUE,    /* acl */
+  FALSE,   /* acl */
   TRUE,    /* add_header */
   FALSE,   /* authenticated */
 #ifdef EXPERIMENTAL_BRIGHTMAIL
@@ -696,8 +696,8 @@ static uschar *ratelimit_option_string[] = {
 
 /* Enable recursion between acl_check_internal() and acl_check_condition() */
 
-static int acl_check_internal(int, address_item *, uschar *, int, uschar **,
-         uschar **);
+static int acl_check_wargs(int, address_item *, uschar *, int, uschar **,
+    uschar **);
 
 
 /*************************************************
@@ -2785,14 +2785,14 @@ for (; cb != NULL; cb = cb->next)
     "discard" verb. */
 
     case ACLC_ACL:
-    rc = acl_check_internal(where, addr, arg, level+1, user_msgptr, log_msgptr);
-    if (rc == DISCARD && verb != ACL_ACCEPT && verb != ACL_DISCARD)
-      {
-      *log_msgptr = string_sprintf("nested ACL returned \"discard\" for "
-        "\"%s\" command (only allowed with \"accept\" or \"discard\")",
-        verbs[verb]);
-      return ERROR;
-      }
+      rc = acl_check_wargs(where, addr, arg, level+1, user_msgptr, log_msgptr);
+      if (rc == DISCARD && verb != ACL_ACCEPT && verb != ACL_DISCARD)
+        {
+        *log_msgptr = string_sprintf("nested ACL returned \"discard\" for "
+          "\"%s\" command (only allowed with \"accept\" or \"discard\")",
+          verbs[verb]);
+        return ERROR;
+        }
     break;
 
     case ACLC_AUTHENTICATED:
@@ -3863,6 +3863,43 @@ return FAIL;
 }
 
 
+
+
+/* Same args as acl_check_internal() above, but the string s is
+the name of an ACL followed optionally by up to 9 space-separated arguments.
+The name and args are separately expanded.  Args go into $acl_arg globals. */
+static int
+acl_check_wargs(int where, address_item *addr, uschar *s, int level,
+  uschar **user_msgptr, uschar **log_msgptr)
+{
+uschar * tmp;
+uschar * name;
+
+if (!(tmp = string_dequote(&s)) || !(name = expand_string(tmp)))
+  goto bad;
+
+for (acl_narg = 0; acl_narg < sizeof(acl_arg)/sizeof(*acl_arg); acl_narg++)
+  {
+  while (*s && isspace(*s)) s++;
+  if (!*s) break;
+  if (!(tmp = string_dequote(&s)) || !(acl_arg[acl_narg] = expand_string(tmp)))
+    {
+    tmp = name;
+    goto bad;
+    }
+  }
+
+return acl_check_internal(where, addr, name, level+1, user_msgptr, log_msgptr);
+
+bad:
+if (expand_string_forcedfail) return ERROR;
+*log_msgptr = string_sprintf("failed to expand ACL string \"%s\": %s",
+  tmp, expand_string_message);
+return search_find_defer?DEFER:ERROR;
+}
+
+
+
 /*************************************************
 *        Check access using an ACL               *
 *************************************************/
@@ -3938,7 +3975,7 @@ switch (where)
 {
 case ACL_WHERE_RCPT:
   if( rcpt_count > 1 )
-    cancel_cutthrough_connection();
+    cancel_cutthrough_connection("more than one recipient");
   else if (rc == OK  &&  cutthrough_delivery  &&  cutthrough_fd < 0)
     open_cutthrough_connection(addr);
   break;
@@ -3947,12 +3984,12 @@ case ACL_WHERE_PREDATA:
   if( rc == OK )
     cutthrough_predata();
   else
-    cancel_cutthrough_connection();
+    cancel_cutthrough_connection("predata acl not ok");
   break;
 
 case ACL_WHERE_QUIT:
 case ACL_WHERE_NOTQUIT:
-  cancel_cutthrough_connection();
+  cancel_cutthrough_connection("quit or notquit");
   break;
 
 default: