[exim-cvs] Acl expansions: tests and documentation

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Acl expansions: tests and documentation
Gitweb: http://git.exim.org/exim.git/commitdiff/bef3ea7f5de507f4eda7f32ac767ec6ac0441d57
Commit:     bef3ea7f5de507f4eda7f32ac767ec6ac0441d57
Parent:     f60d98e8a1d3f9ca2805fdeee7c8062b44c5362d
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Wed Jun 27 20:55:23 2012 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Wed Jun 27 20:55:23 2012 +0100


    Acl expansions: tests and documentation
---
 doc/doc-docbook/spec.xfpt    |   29 +++++++++++++++++++++++++----
 doc/doc-txt/ChangeLog        |    4 +++-
 doc/doc-txt/NewStuff         |   13 +++++++++----
 src/src/acl.c                |   11 ++++++++---
 src/src/expand.c             |   15 +++++++++------
 test/confs/0002              |    7 +++++++
 test/scripts/0000-Basic/0002 |   10 +++++++++-
 test/stdout/0002             |   14 +++++++++++---
 8 files changed, 81 insertions(+), 22 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 29aacf6..eb5bd4c 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -8764,14 +8764,15 @@ expansion item below.
.cindex "&%acl%&" "call from expansion"
The name and zero to nine argument strings are first expanded separately. The expanded
arguments are assigned to the variables &$acl_arg1$& to &$acl_arg9$& in order.
-Any used are made empty. The variable &$acl_narg$& is set to the number of
+Any unused are made empty. The variable &$acl_narg$& is set to the number of
arguments. The named ACL (see chapter &<<CHAPACL>>&) is called
and may use the variables; if another acl expansion is used the values
are overwritten. If the ACL sets
-a value using a "message =" modifier and returns accept, the value becomes
+a value using a "message =" modifier and returns accept or deny, the value becomes
the result of the expansion.
-If no message was set but the ACL returned accept, or if the ACL returned defer,
-the value is an empty string. Otherwise the expansion fails.
+If no message was set and the ACL returned accept or deny
+the value is an empty string.
+If the ACL returned defer the result is a forced-fail. Otherwise the expansion fails.


.vitem "&*${dlfunc{*&<&'file'&>&*}{*&<&'function'&>&*}{*&<&'arg'&>&*}&&&
@@ -10059,6 +10060,21 @@ In all cases, a relative comparator OP is testing if <&'string1'&> OP
10M, not if 10M is larger than &$message_size$&.


+.vitem &*acl&~{{*&<&'name'&>&*}{*&<&'arg1'&>&*}&&&
+    {*&<&'arg2'&>&*}...}*&
+.cindex "expansion" "calling an acl"
+.cindex "&%acl%&" "expansion condition"
+The name and zero to nine argument strings are first expanded separately.  The expanded
+arguments are assigned to the variables &$acl_arg1$& to &$acl_arg9$& in order.
+Any unused are made empty.  The variable &$acl_narg$& is set to the number of
+arguments.  The named ACL (see chapter &<<CHAPACL>>&) is called
+and may use the variables; if another acl expansion is used the values
+are overwritten.  If the ACL sets
+a value using a "message =" modifier the variable $value becomes
+the result of the expansion, otherwise it is empty.
+If the ACL returns accept the condition is true; if deny, false.
+If the ACL returns defer the result is a forced-fail.
+
 .vitem &*bool&~{*&<&'string'&>&*}*&
 .cindex "expansion" "boolean parsing"
 .cindex "&%bool%& expansion condition"
@@ -27301,6 +27317,7 @@ The conditions are as follows:
 .vitem &*acl&~=&~*&<&'name&~of&~acl&~or&~ACL&~string&~or&~file&~name&~'&>
 .cindex "&ACL;" "nested"
 .cindex "&ACL;" "indirect"
+.cindex "&ACL;" "arguments"
 .cindex "&%acl%& ACL condition"
 The possible values of the argument are the same as for the
 &%acl_smtp_%&&'xxx'& options. The named or inline ACL is run. If it returns
@@ -27310,6 +27327,10 @@ condition is on a &%warn%& verb. In that case, a &"defer"& return makes the
 condition false. This means that further processing of the &%warn%& verb
 ceases, but processing of the ACL continues.


+If the argument is a named ACL, up to nine space-separated optional values
+can be appended; they appear in $acl_arg1 to $acl_arg9, and $acl_narg is set
+to the count of values. The name and values are expanded separately.
+
If the nested &%acl%& returns &"drop"& and the outer condition denies access,
the connection is dropped. If it returns &"discard"&, the verb must be
&%accept%& or &%discard%&, and the action is taken immediately &-- no further
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 504c3f5..9dbc65c 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -44,7 +44,9 @@ NM/01 Bugzilla 1197 - Spec typo

JH/03 Add expansion operators ${listnamed:name} and ${listcount:string}

-JH/04 Add expansion item ${acl {name}{arg}...}
+JH/04 Add expansion item ${acl {name}{arg}...}, expansion condition
+      "acl {{name}{arg}...}", and optional args on acl condition
+      "acl = name arg..."


 Exim version 4.80
 -----------------
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 3c5c491..df2ede8 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -87,10 +87,15 @@ Version 4.81
  8. New expansion operators ${listnamed:name} to get the content of a named list
     and ${listcount:string} to count the items in a list.


- 9. New expansion item ${acl {name}{arg}...} to call an ACL.  The argument can
-    be accessed by the ACL in $acl_arg1 to $acl_arg9.  $acl_narg will be the
-    number of arguments. The expansion result is set by a "message =" modifier
-    and an "accept" return from the ACL.
+ 9. The "acl = name" condition on an ACL now supports optional arguments.
+    New expansion item "${acl {name}{arg}...}" and expansion condition
+    "acl {{name}{arg}...}" are added.  In all cases up to nine arguments
+    can be used, appearing in $acl_arg1 to $acl_arg9 for the called ACL.
+    Variable $acl_narg contains the number of arguments.  If the ACL sets
+    a "message =" value this becomes the result of the expansion item,
+    or the value of $value for the expansion condition.  If the ACL returns
+    accept the expansion condition is true; if reject, false.  A defer
+    return results in a forced fail.


 Version 4.80
 ------------
diff --git a/src/src/acl.c b/src/src/acl.c
index d0db717..5cd0c35 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -3873,23 +3873,28 @@ acl_check_wargs(int where, address_item *addr, uschar *s, int level,
   uschar **user_msgptr, uschar **log_msgptr)
 {
 uschar * tmp;
+uschar * tmp_arg[9];    /* must match acl_arg[] */
 uschar * name;
+int i;


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++)
+for (i = 0; i < 9; i++)
   {
   while (*s && isspace(*s)) s++;
   if (!*s) break;
-  if (!(tmp = string_dequote(&s)) || !(acl_arg[acl_narg] = expand_string(tmp)))
+  if (!(tmp = string_dequote(&s)) || !(tmp_arg[i] = expand_string(tmp)))
     {
     tmp = name;
     goto bad;
     }
   }
+acl_narg = i;
+for (i = 0; i < acl_narg; i++) acl_arg[i] = tmp_arg[i];
+while (i < 9) acl_arg[i++] = NULL;


-return acl_check_internal(where, addr, name, level+1, user_msgptr, log_msgptr);
+return acl_check_internal(where, addr, name, level, user_msgptr, log_msgptr);

bad:
if (expand_string_forcedfail) return ERROR;
diff --git a/src/src/expand.c b/src/src/expand.c
index 60552a8..767e477 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1855,7 +1855,7 @@ uschar *dummy_log_msg;
for (i = 1; i < nsub && sub[i]; i++)
acl_arg[i-1] = sub[i];
acl_narg = i-1;
-while (i < sizeof(sub)/sizeof(*sub))
+while (i < nsub)
acl_arg[i++ - 1] = NULL;

DEBUG(D_expand)
@@ -2111,11 +2111,13 @@ switch(cond_type)
*/

   case ECOND_ACL:
-    /* ${if acl {{name}{arg1}{arg2}...}  {yes}{no}}
+    /* ${if acl {{name}{arg1}{arg2}...}  {yes}{no}} */
     {
     uschar *nameargs;
     uschar *user_msg;
     BOOL cond = FALSE;
+    int size = 0;
+    int ptr = 0;


     while (isspace(*s)) s++;
     if (*s++ != '{') goto COND_FAILED_CURLY_START;
@@ -2129,16 +2131,17 @@ switch(cond_type)
       case 3: return NULL;
       }


-    if (yield != NULL)
-      switch(eval_acl(sub, sizeof(sub)/sizeof(*sub), &user_msg))
+    if (yield != NULL) switch(eval_acl(sub, sizeof(sub)/sizeof(*sub), &user_msg))
     {
     case OK:
       cond = TRUE;
     case FAIL:
+          lookup_value = NULL;
       if (user_msg)
+        {
             lookup_value = string_cat(NULL, &size, &ptr, user_msg, Ustrlen(user_msg));
-      else
-        lookup_value = NULL;
+            lookup_value[ptr] = '\0';
+        }
       *yield = cond;
       break;


diff --git a/test/confs/0002 b/test/confs/0002
index df65e2c..eb473e6 100644
--- a/test/confs/0002
+++ b/test/confs/0002
@@ -51,5 +51,12 @@ a_none:
accept

a_deny:
+ deny message = ($acl_narg) [$acl_arg1] [$acl_arg2]
+
+a_defer:
+ defer
+
+a_sub:
+ require acl = a_deny "new arg1" $acl_arg1

# End
diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002
index 62a0a1f..3e2421b 100644
--- a/test/scripts/0000-Basic/0002
+++ b/test/scripts/0000-Basic/0002
@@ -88,7 +88,7 @@ reduce: ${reduce {<\x7f 1\x7f2\177 3}{0}{${eval:$value+$item}}}

acl: ${acl
acl: ${acl}
-acl: ${acl {a_bad}}
+acl: ${acl {a_nosuch}}
acl: ${acl {a_ret}}
acl: ${acl {a_ret}{person@???}}
acl: ${acl {a_ret}{firstarg}{secondarg}}
@@ -97,6 +97,8 @@ acl: ${acl {a_none}}
acl: ${acl {a_none}{person@???}}
acl: ${acl {a_deny}}
acl: ${acl {a_deny}{person@???}}
+acl: ${acl {a_defer}}
+acl: ${acl {a_sub}{top_arg_1}{top_arg_2}{top_arg_3}}
acl: ${reduce {1:2:3:4} {} {$value ${acl {a_ret}{$item}}}}

addrss: ${address:local-part@???}
@@ -421,6 +423,12 @@ first_delivery: ${if first_delivery{y}{n}}
queue_running after or: ${if or{{eq {0}{0}}{queue_running}}{y}{n}}
first_delivery after or: ${if or{{eq {0}{0}}{first_delivery}}{y}{n}}

+# acl expansion condition
+acl if: ${if acl {{a_ret}}               {Y:$value}{N:$value}}
+acl if: ${if acl {{a_ret}{argY}}         {Y:$value}{N:$value}}
+acl if: ${if acl {{a_deny}{argN}{arg2}}  {Y:$value}{N:$value}}
+acl if: ${if acl {{a_defer}{argN}{arg2}} {Y:$value}{N:$value}}
+
 # Default values for both if strings


\${if eq{1}{1}} >${if eq{1}{1}}<
diff --git a/test/stdout/0002 b/test/stdout/0002
index edf18d1..b4b96df 100644
--- a/test/stdout/0002
+++ b/test/stdout/0002
@@ -80,15 +80,17 @@
>
> Failed: missing or misplaced { or }
> Failed: missing or misplaced { or }

-> Failed: acl "a_bad" did not accept
+> Failed: error from acl "a_nosuch"
> acl: (0) [] []
> acl: (1) [person@???] []
> acl: (2) [firstarg] [secondarg]
> acl: (1) [arg with spaces] []
> acl:
> acl:

-> Failed: acl "a_deny" did not accept
-> Failed: acl "a_deny" did not accept
+> acl: (0) [] []
+> acl: (1) [person@???] []
+> Failed: error from acl "a_defer"
+> acl: (2) [new arg1] [top_arg_1]
> acl: (1) [1] [] (1) [2] [] (1) [3] [] (1) [4] []
>
> addrss: local-part@???

@@ -390,6 +392,12 @@
> queue_running after or: y
> first_delivery after or: y
>

+> # acl expansion condition
+> acl if: Y:(0) [] []
+> acl if: Y:(1) [argY] []
+> acl if: N:(2) [argN] [arg2]
+> Failed: error from acl "a_defer"
+>
> # Default values for both if strings
>
> ${if eq{1}{1}} >true<