[exim-cvs] Save/restore $acl_arg1 ... across acl calls, maki…

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Save/restore $acl_arg1 ... across acl calls, making them local variables.
Gitweb: http://git.exim.org/exim.git/commitdiff/ef21c07db8048e09fadab639d8946c9358d3d464
Commit:     ef21c07db8048e09fadab639d8946c9358d3d464
Parent:     be7a578175c0e43d8b7b28d9bf5475f512d5918b
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Thu Oct 25 22:28:01 2012 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Thu Oct 25 22:28:01 2012 +0100


    Save/restore $acl_arg1 ... across acl calls, making them local variables.
---
 doc/doc-docbook/spec.xfpt |   16 +++++++++-------
 src/src/acl.c             |   23 ++++++++++++++++++++---
 src/src/expand.c          |   29 +++++++++++++++++++++++------
 test/confs/0002           |    1 +
 4 files changed, 53 insertions(+), 16 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 18cff9e..34518d3 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -8791,12 +8791,12 @@ 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
+are restored after it returns. If the ACL sets
a value using a "message =" modifier and returns accept or deny, the value becomes
the result of the expansion.
-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.
+If no message is set and the ACL returns accept or deny
+the expansion result is an empty string.
+If the ACL returns defer the result is a forced-fail. Otherwise the expansion fails.


.vitem "&*${dlfunc{*&<&'file'&>&*}{*&<&'function'&>&*}{*&<&'arg'&>&*}&&&
@@ -10107,7 +10107,7 @@ 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
+are restored after it returns. 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.
@@ -27518,8 +27518,10 @@ 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.
+can be appended; they appear within the called ACL in $acl_arg1 to $acl_arg9,
+and $acl_narg is set to the count of values.
+Previous values of these variables are restored after the call returns.
+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
diff --git a/src/src/acl.c b/src/src/acl.c
index 6ae3680..6c81d34 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -3954,8 +3954,11 @@ acl_check_wargs(int where, address_item *addr, uschar *s, int level,
 {
 uschar * tmp;
 uschar * tmp_arg[9];    /* must match acl_arg[] */
+uschar * sav_arg[9];    /* must match acl_arg[] */
+int sav_narg;
 uschar * name;
 int i;
+int ret;


 if (!(tmp = string_dequote(&s)) || !(name = expand_string(tmp)))
   goto bad;
@@ -3970,11 +3973,25 @@ for (i = 0; i < 9; i++)
     goto bad;
     }
   }
+
+sav_narg = acl_narg;
 acl_narg = i;
-for (i = 0; i < acl_narg; i++) acl_arg[i] = tmp_arg[i];
-while (i < 9) acl_arg[i++] = NULL;
+for (i = 0; i < acl_narg; i++)
+  {
+  sav_arg[i] = acl_arg[i];
+  acl_arg[i] = tmp_arg[i];
+  }
+while (i < 9)
+  {
+  sav_arg[i] = acl_arg[i];
+  acl_arg[i++] = NULL;
+  }
+
+ret = acl_check_internal(where, addr, name, level, user_msgptr, log_msgptr);


-return acl_check_internal(where, addr, name, level, user_msgptr, log_msgptr);
+acl_narg = sav_narg;
+for (i = 0; i < 9; i++) acl_arg[i] = sav_arg[i];
+return ret;

bad:
if (expand_string_forcedfail) return ERROR;
diff --git a/src/src/expand.c b/src/src/expand.c
index 0e96978..4dea8b1 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1853,6 +1853,7 @@ if (Ustrncmp(name, "acl_", 4) == 0)

/*
Load args from sub array to globals, and call acl_check().
+Sub array will be corrupted on return.

 Returns:       OK         access is granted by an ACCEPT verb
                DISCARD    access is granted by a DISCARD verb
@@ -1865,13 +1866,23 @@ static int
 eval_acl(uschar ** sub, int nsub, uschar ** user_msgp)
 {
 int i;
-uschar *dummy_log_msg;
+uschar *tmp;
+int sav_narg = acl_narg;
+int ret;


-for (i = 1; i < nsub && sub[i]; i++)
-  acl_arg[i-1] = sub[i];
-acl_narg = i-1;
+if(--nsub > sizeof(acl_arg)/sizeof(*acl_arg)) nsub = sizeof(acl_arg)/sizeof(*acl_arg);
+for (i = 0; i < nsub && sub[i+1]; i++)
+  {
+  tmp = acl_arg[i];
+  acl_arg[i] = sub[i+1];    /* place callers args in the globals */
+  sub[i+1] = tmp;        /* stash the old args using our caller's storage */
+  }
+acl_narg = i;
 while (i < nsub)
-  acl_arg[i++ - 1] = NULL;
+  {
+  sub[i+1] = acl_arg[i];
+  acl_arg[i++] = NULL;
+  }


 DEBUG(D_expand)
   debug_printf("expanding: acl: %s  arg: %s%s\n",
@@ -1879,7 +1890,13 @@ DEBUG(D_expand)
     acl_narg>0 ? sub[1]   : US"<none>",
     acl_narg>1 ? " +more" : "");


-return acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], user_msgp, &dummy_log_msg);
+ret = acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], user_msgp, &tmp);
+
+for (i = 0; i < nsub; i++)
+  acl_arg[i] = sub[i+1];    /* restore old args */
+acl_narg = sav_narg;
+
+return ret;
 }



diff --git a/test/confs/0002 b/test/confs/0002
index eb473e6..409bd75 100644
--- a/test/confs/0002
+++ b/test/confs/0002
@@ -57,6 +57,7 @@ a_defer:
defer

a_sub:
+ require acl = a_none foo bar baz barf
require acl = a_deny "new arg1" $acl_arg1

# End