X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/13a4b4c1810a1a9f3c956f1e92807a0d86c6f5bf..1d28cc061677bd07d9bed48dd84bd5c590247043:/src/src/route.c diff --git a/src/src/route.c b/src/src/route.c index a1426d58f..82d51bc68 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -2,8 +2,10 @@ * Exim - an Internet mail transport agent * *************************************************/ +/* Copyright (c) The Exim Maintainers 2020 - 2022 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* 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. */ @@ -287,7 +289,12 @@ for (router_instance * r = routers; r; r = r->next) /* 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 */ @@ -335,19 +342,20 @@ wildcard. Arguments: local_part the local part to check prefixes the list of prefixes + vp if set, pointer to place for size of wildcard portion Returns: length of matching prefix or zero */ int -route_check_prefix(const uschar *local_part, const uschar *prefixes) +route_check_prefix(const uschar * local_part, const uschar * prefixes, + unsigned * vp) { int sep = 0; uschar *prefix; const uschar *listptr = prefixes; -uschar prebuf[64]; -while ((prefix = string_nextinlist(&listptr, &sep, prebuf, sizeof(prebuf)))) +while ((prefix = string_nextinlist(&listptr, &sep, NULL, 0))) { int plen = Ustrlen(prefix); if (prefix[0] == '*') @@ -355,10 +363,19 @@ while ((prefix = string_nextinlist(&listptr, &sep, prebuf, sizeof(prebuf)))) prefix++; for (const uschar * p = local_part + Ustrlen(local_part) - (--plen); p >= local_part; p--) - if (strncmpic(prefix, p, plen) == 0) return plen + p - local_part; + if (strncmpic(prefix, p, plen) == 0) + { + unsigned vlen = p - local_part; + if (vp) *vp = vlen; + return plen + vlen; + } } else - if (strncmpic(prefix, local_part, plen) == 0) return plen; + if (strncmpic(prefix, local_part, plen) == 0) + { + if (vp) *vp = 0; + return plen; + } } return 0; @@ -377,31 +394,40 @@ is a wildcard. Arguments: local_part the local part to check suffixes the list of suffixes + vp if set, pointer to place for size of wildcard portion Returns: length of matching suffix or zero */ int -route_check_suffix(const uschar *local_part, const uschar *suffixes) +route_check_suffix(const uschar * local_part, const uschar * suffixes, + unsigned * vp) { int sep = 0; int alen = Ustrlen(local_part); uschar *suffix; const uschar *listptr = suffixes; -uschar sufbuf[64]; -while ((suffix = string_nextinlist(&listptr, &sep, sufbuf, sizeof(sufbuf)))) +while ((suffix = string_nextinlist(&listptr, &sep, NULL, 0))) { int slen = Ustrlen(suffix); if (suffix[slen-1] == '*') { - const uschar *pend = local_part + alen - (--slen) + 1; + const uschar * pend = local_part + alen - (--slen) + 1; for (const uschar * p = local_part; p < pend; p++) - if (strncmpic(suffix, p, slen) == 0) return alen - (p - local_part); + if (strncmpic(suffix, p, slen) == 0) + { + int tlen = alen - (p - local_part); + if (vp) *vp = tlen - slen; + return tlen; + } } else if (alen > slen && strncmpic(suffix, local_part + alen - slen, slen) == 0) + { + if (vp) *vp = 0; return slen; + } } return 0; @@ -587,14 +613,13 @@ gid_t gid = 0; /* For picky compilers */ BOOL ugid_set = FALSE; const uschar *listptr; uschar *check; -uschar buffer[1024]; if (!s) return OK; DEBUG(D_route) debug_printf("checking require_files\n"); listptr = s; -while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer)))) +while ((check = string_nextinlist(&listptr, &sep, NULL, 0))) { int rc; int eacces_code = 0; @@ -717,7 +742,7 @@ while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer)))) otherwise. Save the old state for resetting on the wait. */ oldsignal = signal(SIGCHLD, SIG_DFL); - pid = fork(); + pid = exim_fork(US"require-files"); /* If fork() fails, reinstate the original error and behave as if this block of code were not present. This is the same behaviour as happens @@ -740,9 +765,9 @@ while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer)))) exim_setugid(uid, gid, TRUE, string_sprintf("require_files check, file=%s", ss)); if (route_check_access(ss, uid, gid, 4)) - exim_underbar_exit(0); + exim_underbar_exit(EXIT_SUCCESS); DEBUG(D_route) debug_printf("route_check_access() failed\n"); - exim_underbar_exit(1); + exim_underbar_exit(EXIT_FAILURE); } /* In the parent, wait for the child to finish */ @@ -928,7 +953,7 @@ if ((rc = route_check_dls(r->name, US"local_parts", r->local_parts, login of a local user. Note: the third argument to route_finduser() must be NULL here, to prevent a numeric string being taken as a numeric uid. If the user is found, set deliver_home to the home directory, and also set -local_user_{uid,gid} and local_part_verified. */ +local_user_{uid,gid} and local_part_data. */ if (r->check_local_user) { @@ -939,7 +964,8 @@ if (r->check_local_user) r->name, addr->local_part); return SKIP; } - deliver_localpart_verified = string_copy(US (*pw)->pw_name); + addr->prop.localpart_data = + deliver_localpart_data = string_copy(US (*pw)->pw_name); deliver_home = string_copy(US (*pw)->pw_dir); local_user_gid = (*pw)->pw_gid; local_user_uid = (*pw)->pw_uid; @@ -953,22 +979,19 @@ confusing. */ if (r->router_home_directory) { - uschar *router_home = expand_string(r->router_home_directory); - if (!router_home) - { - if (!f.expand_string_forcedfail) - { - *perror = string_sprintf("failed to expand \"%s\" for " - "router_home_directory: %s", r->router_home_directory, - expand_string_message); - return DEFER; - } - } - else + uschar * router_home = expand_string(r->router_home_directory); + if (router_home) { setflag(addr, af_home_expanded); /* Note set from router_home_directory */ deliver_home = router_home; } + else if (!f.expand_string_forcedfail) + { + *perror = string_sprintf("failed to expand \"%s\" for " + "router_home_directory: %s", r->router_home_directory, + expand_string_message); + return DEFER; + } } /* Skip if the sender condition is not met. We leave this one till after the @@ -1477,7 +1500,7 @@ for (uschar * ele; (ele = string_nextinlist(&varlist, &sep, NULL, 0)); ) 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); } @@ -1620,9 +1643,9 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) /* Default no affixes and select whether to use a caseful or caseless local part in this router. */ - addr->prefix = addr->suffix = NULL; - addr->local_part = r->caseful_local_part? - addr->cc_local_part : addr->lc_local_part; + addr->prefix = addr->prefix_v = addr->suffix = addr->suffix_v = NULL; + addr->local_part = r->caseful_local_part + ? addr->cc_local_part : addr->lc_local_part; DEBUG(D_route) debug_printf("local_part=%s domain=%s\n", addr->local_part, addr->domain); @@ -1633,10 +1656,22 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) if (r->prefix) { - int plen = route_check_prefix(addr->local_part, r->prefix); + unsigned vlen; + int plen = route_check_prefix(addr->local_part, r->prefix, &vlen); if (plen > 0) { - addr->prefix = string_copyn(addr->local_part, plen); + /* If the variable-part is zero-length then the prefix was not + wildcarded and we can detaint-copy it since it matches the + (non-expandable) router option. Otherwise copy the (likely) tainted match + and the variable-part of the match from the local_part. */ + + if (vlen) + { + addr->prefix = string_copyn(addr->local_part, plen); + addr->prefix_v = string_copyn(addr->local_part, vlen); + } + else + 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); } @@ -1652,11 +1687,15 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) if (r->suffix) { - int slen = route_check_suffix(addr->local_part, r->suffix); + unsigned vlen; + int slen = route_check_suffix(addr->local_part, r->suffix, &vlen); if (slen > 0) { int lplen = Ustrlen(addr->local_part) - slen; - addr->suffix = addr->local_part + lplen; + addr->suffix = vlen + ? addr->local_part + lplen + : 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); } @@ -1672,7 +1711,8 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) the local part sorted. */ router_name = r->name; - deliver_localpart_verified = NULL; + driver_srcfile = r->srcfile; + driver_srcline = r->srcline; deliver_set_expansions(addr); /* For convenience, the pre-router checks are in a separate function, which @@ -1680,7 +1720,7 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) 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; @@ -1731,7 +1771,7 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) { 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; } @@ -1783,7 +1823,7 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) 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) { @@ -2011,10 +2051,23 @@ if (yield == DEFER && addr->message) 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 */