From 723c72e64c04d3b7bdf03b26c65761c1ae569312 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 11 Jun 2012 22:00:11 +0100 Subject: [PATCH] Add ${acl {name}{arg}} expansion item. --- doc/doc-docbook/spec.xfpt | 14 ++++++++++++ doc/doc-txt/ChangeLog | 2 ++ doc/doc-txt/NewStuff | 4 ++++ src/src/expand.c | 42 +++++++++++++++++++++++++++++++++++- src/src/globals.c | 7 +++--- src/src/macros.h | 4 +++- test/confs/0002 | 8 +++++++ test/scripts/0000-Basic/0002 | 11 ++++++++++ test/stdout/0002 | 11 ++++++++++ 9 files changed, 98 insertions(+), 5 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index dcf6b6cfb..cde80a17c 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -8758,6 +8758,20 @@ string easier to understand. This item inserts &"basic"& header lines. It is described with the &%header%& expansion item below. + +.vitem "&*${acl{*&<&'name'&>&*}{*&<&'string'&>&*}}*&" +.cindex "expansion" "calling an acl" +.cindex "&%acl%&" "call from expansion" +The name and <&'string'&> are first expanded separately. The expanded +<&'string'&> is assigned to the &$address_data$& variable. If {<&'string'&>} +is omitted, &$address_data$& is made empty. The named ACL (see chapter +&<>&) is called and may use &$address_data$&. If the ACL sets +a value using a "message =" modifier and returns accept, 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. + + .vitem "&*${dlfunc{*&<&'file'&>&*}{*&<&'function'&>&*}{*&<&'arg'&>&*}&&& {*&<&'arg'&>&*}...}*&" .cindex &%dlfunc%& diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 34521098e..4a2215956 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -44,6 +44,8 @@ NM/01 Bugzilla 1197 - Spec typo JH/03 Add expansion operators ${listnamed:name} and ${listcount:string} +JH/04 Add expansion item ${acl {name}{argument}} + Exim version 4.80 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 6d64faa00..b13a5a0f2 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -87,6 +87,10 @@ 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}{argument}} to call an ACL. The argument can + be accessed by the ACL in $address_data. The expansion result is set by + a "message =" modifier and an "accept" return from the ACL. + Version 4.80 ------------ diff --git a/src/src/expand.c b/src/src/expand.c index 965842611..16d5d74ab 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -102,6 +102,7 @@ bcrypt ({CRYPT}$2a$). alphabetical order. */ static uschar *item_table[] = { + US"acl", US"dlfunc", US"extract", US"filter", @@ -124,6 +125,7 @@ static uschar *item_table[] = { US"tr" }; enum { + EITEM_ACL, EITEM_DLFUNC, EITEM_EXTRACT, EITEM_FILTER, @@ -3641,6 +3643,45 @@ while (*s != 0) switch(item_type) { + /* Call an ACL from an expansion. We feed data in via $address_data. + If the ACL returns acceptance 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: + { + int rc; + uschar *sub[2]; + uschar *new_yield; + uschar *user_msg; + uschar *log_msg; + switch(read_subs(sub, 2, 1, &s, skipping, TRUE, US"acl")) + { + case 1: goto EXPAND_FAILED_CURLY; + case 2: + case 3: goto EXPAND_FAILED; + } + if (skipping) continue; + + DEBUG(D_expand) + debug_printf("expanding: acl: %s arg: %s\n", sub[0], sub[1]?sub[1]:US""); + + deliver_address_data = sub[1]; + switch(rc = acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], &user_msg, &log_msg)) + { + case OK: + if (user_msg) + yield = string_cat(yield, &size, &ptr, user_msg, Ustrlen(user_msg)); + continue; + case DEFER: + continue; + default: + expand_string_message = string_sprintf("acl \"%s\" did not accept", 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 @@ -5533,7 +5574,6 @@ while (*s != 0) goto EXPAND_FAILED; } - if (skipping) continue; list = ((namedlist_block *)(t->data.ptr))->string; while ((item = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) diff --git a/src/src/globals.c b/src/src/globals.c index 97c7166ab..3ad38d39d 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -192,7 +192,6 @@ uschar *acl_not_smtp = NULL; uschar *acl_not_smtp_mime = NULL; #endif uschar *acl_not_smtp_start = NULL; - uschar *acl_smtp_auth = NULL; uschar *acl_smtp_connect = NULL; uschar *acl_smtp_data = NULL; @@ -240,7 +239,8 @@ uschar *acl_wherenames[] = { US"RCPT", US"NOTQUIT", US"QUIT", US"STARTTLS", - US"VRFY" + US"VRFY", + US"expansion" }; uschar *acl_wherecodes[] = { US"550", /* RCPT */ @@ -260,7 +260,8 @@ uschar *acl_wherecodes[] = { US"550", /* RCPT */ US"0", /* NOTQUIT; not relevant */ US"0", /* QUIT; not relevant */ US"550", /* STARTTLS */ - US"252" /* VRFY */ + US"252", /* VRFY */ + US"0" /* unknown; not relevant */ }; BOOL active_local_from_check = FALSE; diff --git a/src/src/macros.h b/src/src/macros.h index b17a80e10..d25071aae 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -820,7 +820,9 @@ enum { ACL_WHERE_RCPT, /* Some controls are for RCPT only */ ACL_WHERE_NOTQUIT, ACL_WHERE_QUIT, ACL_WHERE_STARTTLS, - ACL_WHERE_VRFY + ACL_WHERE_VRFY, + + ACL_WHERE_EXPANSION /* Currently used by a ${acl:name} expansion */ }; /* Situations for spool_write_header() */ diff --git a/test/confs/0002 b/test/confs/0002 index 6983fd87f..317c4a27d 100644 --- a/test/confs/0002 +++ b/test/confs/0002 @@ -44,4 +44,12 @@ check_data: warn logwrite = Subject is: "$h_subject:" deny message = reply_address=<$reply_address> +a_ret: + accept message = [$address_data] + +a_none: + accept + +a_deny: + # End diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002 index 652891615..d567f8486 100644 --- a/test/scripts/0000-Basic/0002 +++ b/test/scripts/0000-Basic/0002 @@ -86,6 +86,17 @@ reduce: ${reduce {<\x7f 1\x7f2\177 3}{0}{${eval:$value+$item}}} # Operators +acl: ${acl +acl: ${acl} +acl: ${acl {a_bad}} +acl: ${acl {a_ret}} +acl: ${acl {a_ret}{person@dom.ain}} +acl: ${acl {a_none}} +acl: ${acl {a_none}{person@dom.ain}} +acl: ${acl {a_deny}} +acl: ${acl {a_deny}{person@dom.ain}} +acl: ${reduce {1:2:3:4} {} {$value ${acl {a_ret}{$item}}}} + addrss: ${address:local-part@dom.ain} addrss: ${address:Exim Person (that's me)} domain: ${domain:local-part@dom.ain} diff --git a/test/stdout/0002 b/test/stdout/0002 index de67f99fc..377fe02cd 100644 --- a/test/stdout/0002 +++ b/test/stdout/0002 @@ -78,6 +78,17 @@ > > # Operators > +> Failed: missing or misplaced { or } +> Failed: missing or misplaced { or } +> Failed: acl "a_bad" did not accept +> acl: [] +> acl: [person@dom.ain] +> acl: +> acl: +> Failed: acl "a_deny" did not accept +> Failed: acl "a_deny" did not accept +> acl: [1] [2] [3] [4] +> > addrss: local-part@dom.ain > addrss: local-part@dom.ain > domain: dom.ain -- 2.25.1