* Exim - an Internet mail transport agent *
*************************************************/
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Functions concerned with routing, and the list of generic router options. */
/* Build a host list if fallback hosts is set. */
- host_build_hostlist(&(r->fallback_hostlist), r->fallback_hosts, FALSE);
+ {
+ int old_pool = store_pool;
+ store_pool = POOL_PERM;
+ host_build_hostlist(&r->fallback_hostlist, r->fallback_hosts, FALSE);
+ store_pool = old_pool;
+ }
/* Check redirect_router and pass_router are valid */
*/
static BOOL
-check_router_conditions(router_instance *r, address_item *addr, int verify,
- struct passwd **pw, uschar **perror)
+check_router_conditions(router_instance * r, address_item * addr, int verify,
+ struct passwd ** pw, uschar ** perror)
{
int rc;
-uschar *check_local_part;
-unsigned int *localpart_cache;
+uschar * check_local_part;
+unsigned int * localpart_cache;
/* Reset variables to hold a home directory and data from lookup of a domain or
local part, and ensure search_find_defer is unset, in case there aren't any
required. Also, we only use the match cache for local parts that have not had
a prefix or suffix stripped. */
+check_local_part = string_copy(addr->cc_local_part);
if (!addr->prefix && !addr->suffix)
- {
localpart_cache = addr->localpart_cache;
- check_local_part = addr->cc_local_part;
- }
else
{
localpart_cache = NULL;
- check_local_part = string_copy(addr->cc_local_part);
if (addr->prefix)
check_local_part += Ustrlen(addr->prefix);
if (addr->suffix)
{
addr->message = string_sprintf("expansion of \"%s\" failed "
"in %s router: %s", ele, r->name, expand_string_message);
- return DEFER;
+ /* Caller will replace that for logging, if a DB lookup, to avoid exposing
+ passwords */
+ DEBUG(D_route) debug_printf("%s\n", addr->message);
+ if (!f.search_find_defer)
+ return f.search_find_defer ? DEFER : FAIL;
}
if (!(node = tree_search(*root, name)))
{ /* name should never be tainted */
- node = store_get(sizeof(tree_node) + Ustrlen(name), FALSE);
+ node = store_get(sizeof(tree_node) + Ustrlen(name), GET_UNTAINTED);
Ustrcpy(node->name, name);
(void)tree_insertnode(root, node);
}
{
int yield = OK;
BOOL unseen;
-router_instance *r, *nextr;
-const uschar *old_domain = addr->domain;
+router_instance * r, * nextr;
+const uschar * old_domain = addr->domain;
HDEBUG(D_route)
{
for (r = addr->start_router ? addr->start_router : routers; r; r = nextr)
{
- uschar *error;
- struct passwd *pw = NULL;
+ uschar * error;
+ struct passwd * pw = NULL;
struct passwd pwcopy;
BOOL loop_detected = FALSE;
BOOL more;
addr->prefix_v = string_copyn(addr->local_part, vlen);
}
else
- addr->prefix = string_copyn_taint(addr->local_part, plen, FALSE);
+ addr->prefix = string_copyn_taint(addr->local_part, plen, GET_UNTAINTED);
addr->local_part += plen;
DEBUG(D_route) debug_printf("stripped prefix %s\n", addr->prefix);
}
int lplen = Ustrlen(addr->local_part) - slen;
addr->suffix = vlen
? addr->local_part + lplen
- : string_copy_taint(addr->local_part + lplen, slen);
+ : string_copy_taint(addr->local_part + lplen, GET_UNTAINTED);
addr->suffix_v = addr->suffix + Ustrlen(addr->suffix) - vlen;
addr->local_part = string_copyn(addr->local_part, lplen);
DEBUG(D_route) debug_printf("stripped suffix %s\n", addr->suffix);
the local part sorted. */
router_name = r->name;
+ driver_srcfile = r->srcfile;
+ driver_srcline = r->srcline;
deliver_set_expansions(addr);
/* For convenience, the pre-router checks are in a separate function, which
if ((rc = check_router_conditions(r, addr, verify, &pw, &error)) != OK)
{
- router_name = NULL;
+ driver_srcfile = router_name = NULL; driver_srcline = 0;
if (rc == SKIP) continue;
addr->message = error;
yield = rc;
router traversal. On the addr string they are held as a variable tree, so
as to maintain the post-expansion taints separate. */
- switch (set_router_vars(addr, r))
+ switch (rc = set_router_vars(addr, r))
{
case OK: break;
case PASS: continue; /* with next router */
- default: goto ROUTE_EXIT;
+ default: yield = rc; goto ROUTE_EXIT;
}
/* Finally, expand the address_data field in the router. Forced failure
{
DEBUG(D_route)
debug_printf("\"more\"=false: skipping remaining routers\n");
- router_name = NULL;
+ driver_srcfile = router_name = NULL; driver_srcline = 0;
r = NULL;
break;
}
yield = (r->info->code)(r, addr, pw, verify, paddr_local, paddr_remote,
addr_new, addr_succeed);
- router_name = NULL;
+ driver_srcfile = router_name = NULL; driver_srcline = 0;
if (yield == FAIL)
{
addr->message = expand_hide_passwords(addr->message);
deliver_set_expansions(NULL);
-router_name = NULL;
+driver_srcfile = router_name = NULL; driver_srcline = 0;
f.disable_logging = FALSE;
return yield;
}
+
+
+/* For error messages, a string describing the config location associated
+with current processing. NULL if we are not in a router. */
+/* Name only, for now */
+
+uschar *
+router_current_name(void)
+{
+if (!router_name) return NULL;
+return string_sprintf(" (router %s, %s %d)", router_name, driver_srcfile, driver_srcline);
+}
+
#endif /*!MACRO_PREDEF*/
/* End of route.c */