From faa05a9388f4efb82db4e7ea20ae746ab62f578a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 29 Oct 2012 22:14:16 +0000 Subject: [PATCH] Track ACL context through ${acl expansions. Bug 1305. Rather than pass "where" around all the string-expansion calls I've used a global; and unpleasant mismatch with the existing "where" tracking done for nested ACL calls. --- src/src/acl.c | 37 ++++++++++++++++++++++++++++++++++++- src/src/deliver.c | 5 +++++ src/src/expand.c | 3 ++- src/src/functions.h | 1 + src/src/globals.c | 4 +++- src/src/macros.h | 3 ++- 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/src/acl.c b/src/src/acl.c index 00ff83854..c1eebf655 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -4006,6 +4006,39 @@ return search_find_defer?DEFER:ERROR; * Check access using an ACL * *************************************************/ +/* Alternate interface for ACL, used by expansions */ +int +acl_eval(int where, uschar *recipient, uschar *s, uschar **user_msgptr, + uschar **log_msgptr) +{ +int rc; +address_item adb; +address_item *addr = NULL; + +*user_msgptr = *log_msgptr = NULL; +sender_verified_failed = NULL; +ratelimiters_cmd = NULL; +log_reject_target = LOG_MAIN|LOG_REJECT; + +if (where == ACL_WHERE_RCPT) + { + adb = address_defaults; + addr = &adb; + addr->address = recipient; + if (deliver_split_address(addr) == DEFER) + { + *log_msgptr = US"defer in percent_hack_domains check"; + return DEFER; + } + deliver_domain = addr->domain; + deliver_localpart = addr->local_part; + } + +return acl_check_internal(where, addr, s, 0, user_msgptr, log_msgptr); +} + + + /* This is the external interface for ACL checks. It sets up an address and the expansions for $domain and $local_part when called after RCPT, then calls acl_check_internal() to do the actual work. @@ -4024,6 +4057,7 @@ Returns: OK access is granted by an ACCEPT verb DEFER can't tell at the moment ERROR disaster */ +int acl_where = ACL_WHERE_UNKNOWN; int acl_check(int where, uschar *recipient, uschar *s, uschar **user_msgptr, @@ -4052,7 +4086,9 @@ if (where == ACL_WHERE_RCPT) deliver_localpart = addr->local_part; } +acl_where = where; rc = acl_check_internal(where, addr, s, 0, user_msgptr, log_msgptr); +acl_where = ACL_WHERE_UNKNOWN; /* Cutthrough - if requested, and WHERE_RCPT and not yet opened conn as result of recipient-verify, @@ -4135,7 +4171,6 @@ return rc; } - /************************************************* * Create ACL variable * *************************************************/ diff --git a/src/src/deliver.c b/src/src/deliver.c index 55a27b023..02329d272 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -4515,6 +4515,7 @@ FILE *jread; int process_recipients = RECIP_ACCEPT; open_db dbblock; open_db *dbm_file; +extern int acl_where; uschar *info = (queue_run_pid == (pid_t)0)? string_sprintf("delivering %s", id) : @@ -4565,6 +4566,9 @@ message_size = 0; update_spool = FALSE; remove_journal = TRUE; +/* Set a known context for any ACLs we call via expansions */ +acl_where = ACL_WHERE_DELIVERY; + /* Reset the random number generator, so that if several delivery processes are started from a queue runner that has already used random numbers (for sorting), they don't all get the same sequence. */ @@ -7034,6 +7038,7 @@ expand_check_condition) to do a lookup. We must therefore be sure everything is released. */ search_tidyup(); +acl_where = ACL_WHERE_UNKNOWN; return final_yield; } diff --git a/src/src/expand.c b/src/src/expand.c index 6d5471f98..786d4279c 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1869,6 +1869,7 @@ int i; uschar *tmp; int sav_narg = acl_narg; int ret; +extern int acl_where; if(--nsub > sizeof(acl_arg)/sizeof(*acl_arg)) nsub = sizeof(acl_arg)/sizeof(*acl_arg); for (i = 0; i < nsub && sub[i+1]; i++) @@ -1890,7 +1891,7 @@ DEBUG(D_expand) acl_narg>0 ? sub[1] : US"", acl_narg>1 ? " +more" : ""); -ret = acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], user_msgp, &tmp); +ret = acl_eval(acl_where, NULL, sub[0], user_msgp, &tmp); for (i = 0; i < nsub; i++) acl_arg[i] = sub[i+1]; /* restore old args */ diff --git a/src/src/functions.h b/src/src/functions.h index 034ef196d..d6f4f68fd 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -49,6 +49,7 @@ extern BOOL tls_openssl_options_parse(uschar *, long *); extern acl_block *acl_read(uschar *(*)(void), uschar **); extern int acl_check(int, uschar *, uschar *, uschar **, uschar **); +extern int acl_eval(int, uschar *, uschar *, uschar **, uschar **); extern tree_node *acl_var_create(uschar *); extern void acl_var_write(uschar *, uschar *, void *); diff --git a/src/src/globals.c b/src/src/globals.c index ba6c8c6ba..5dff0ee4b 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -245,7 +245,8 @@ uschar *acl_wherenames[] = { US"RCPT", US"QUIT", US"STARTTLS", US"VRFY", - US"expansion" + US"delivery", + US"unknown" }; uschar *acl_wherecodes[] = { US"550", /* RCPT */ @@ -266,6 +267,7 @@ uschar *acl_wherecodes[] = { US"550", /* RCPT */ US"0", /* QUIT; not relevant */ US"550", /* STARTTLS */ US"252", /* VRFY */ + US"0", /* delivery; not relevant */ US"0" /* unknown; not relevant */ }; diff --git a/src/src/macros.h b/src/src/macros.h index 305200211..c9d990ada 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -826,7 +826,8 @@ enum { ACL_WHERE_RCPT, /* Some controls are for RCPT only */ ACL_WHERE_STARTTLS, ACL_WHERE_VRFY, - ACL_WHERE_EXPANSION /* Currently used by a ${acl:name} expansion */ + ACL_WHERE_DELIVERY, + ACL_WHERE_UNKNOWN /* Currently used by a ${acl:name} expansion */ }; /* Situations for spool_write_header() */ -- 2.30.2