alphabetical order. */
static uschar *item_table[] = {
+ US"acl",
US"dlfunc",
US"extract",
US"filter",
US"tr" };
enum {
+ EITEM_ACL,
EITEM_DLFUNC,
EITEM_EXTRACT,
EITEM_FILTER,
US"==", /* Backward compatibility */
US">",
US">=",
+ US"acl",
US"and",
US"bool",
US"bool_lax",
ECOND_NUM_EE,
ECOND_NUM_G,
ECOND_NUM_GE,
+ ECOND_ACL,
ECOND_AND,
ECOND_BOOL,
ECOND_BOOL_LAX,
static var_entry var_table[] = {
/* WARNING: Do not invent variables whose names start acl_c or acl_m because
they will be confused with user-creatable ACL variables. */
+ { "acl_arg1", vtype_stringptr, &acl_arg[0] },
+ { "acl_arg2", vtype_stringptr, &acl_arg[1] },
+ { "acl_arg3", vtype_stringptr, &acl_arg[2] },
+ { "acl_arg4", vtype_stringptr, &acl_arg[3] },
+ { "acl_arg5", vtype_stringptr, &acl_arg[4] },
+ { "acl_arg6", vtype_stringptr, &acl_arg[5] },
+ { "acl_arg7", vtype_stringptr, &acl_arg[6] },
+ { "acl_arg8", vtype_stringptr, &acl_arg[7] },
+ { "acl_arg9", vtype_stringptr, &acl_arg[8] },
+ { "acl_narg", vtype_int, &acl_narg },
{ "acl_verify_message", vtype_stringptr, &acl_verify_message },
{ "address_data", vtype_stringptr, &deliver_address_data },
{ "address_file", vtype_stringptr, &address_file },
return s;
+ /* call ACL (in a conditional context). Accept true, deny false.
+ Defer is a forced-fail. Anything set by message= goes to $value.
+ See also the expansion-item version EITEM_ACL. */
+
+ case ECOND_ACL:
+ /* ${if acl {name arg1 arg2...} {yes}{no}}
+ {
+ uschar *nameargs;
+ uschar *user_msg;
+ uschar *log_msg;
+ BOOL cond = FALSE;
+ int size = 0;
+
+ while (isspace(*s)) s++;
+ if (*s++ != '{') goto COND_FAILED_CURLY_START;
+ if (!(nameargs = expand_string_internal(s, TRUE, &s, FALSE, FALSE)) return NULL;
+ if (*s++ != '}') goto COND_FAILED_CURLY_END;
+
+ switch(acl_check_args(ACL_WHERE_EXPANSION, NULL, nameargs, &user_msg, &log_msg))
+ {
+ case OK:
+ cond = TRUE;
+ case FAIL:
+ if (user_msg)
+ lookup_value = string_cat(NULL, &size, &ptr, user_msg, Ustrlen(user_msg));
+ if (yield != NULL) *yield = cond;
+ return s;
+
+ case DEFER:
+ expand_string_forcedfail = TRUE;
+ default:
+ expand_string_message = string_sprintf("error from acl \"%s\"", nameargs);
+ return NULL;
+ }
+ }
+ return s;
+
+
/* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
${if saslauthd {{username}{password}{service}{realm}} {yes}[no}}
However, the last two are optional. That is why the whole set is enclosed
- in their own set or braces. */
+ in their own set of braces. */
case ECOND_SASLAUTHD:
#ifndef CYRUS_SASLAUTHD_SOCKET
switch(item_type)
{
+ /* Call an ACL from an expansion. We feed data in via $acl_arg1 - $acl_arg9.
+ If the ACL returns accept or reject we return content set by "message ="
+ There is currently no limit on recursion; this would have us call
+ acl_check_internal() directly and get a current level from somewhere.
+ */
+
+ case EITEM_ACL:
+ /* ${acl {name} {arg1}{arg2}...} */
+ {
+ int i;
+ uschar *sub[10]; /* name + arg1-arg9 (which must match number of acl_arg[]) */
+ uschar *user_msg;
+ uschar *log_msg;
+
+ switch(read_subs(sub, 10, 1, &s, skipping, TRUE, US"acl"))
+ {
+ case 1: goto EXPAND_FAILED_CURLY;
+ case 2:
+ case 3: goto EXPAND_FAILED;
+ }
+ if (skipping) continue;
+
+ for (i = 1; i < sizeof(sub)/sizeof(*sub) && sub[i]; i++)
+ acl_arg[i-1] = sub[i];
+ acl_narg = i-1;
+ while (i < sizeof(sub)/sizeof(*sub))
+ acl_arg[i++ - 1] = NULL;
+
+ DEBUG(D_expand)
+ debug_printf("expanding: acl: %s arg: %s%s\n",
+ sub[0],
+ acl_narg>0 ? sub[1] : US"<none>",
+ acl_narg>1 ? " +more" : "");
+
+ switch(acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], &user_msg, &log_msg))
+ {
+ case OK:
+ case FAIL:
+ if (user_msg)
+ yield = string_cat(yield, &size, &ptr, user_msg, Ustrlen(user_msg));
+ continue;
+
+ case DEFER:
+ expand_string_forcedfail = TRUE;
+ default:
+ expand_string_message = string_sprintf("error from acl \"%s\"", sub[0]);
+ goto EXPAND_FAILED;
+ }
+ }
+
/* Handle conditionals - preserve the values of the numerical expansion
variables in case they get changed by a regular expression match in the
condition. If not, they retain their external settings. At the end
goto EXPAND_FAILED;
}
- if (skipping) continue;
list = ((namedlist_block *)(t->data.ptr))->string;
while ((item = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)