*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions concerned with routing, and the list of generic router options. */
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] == '*')
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;
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;
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
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 */
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)
{
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;
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
/* 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);
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, FALSE);
addr->local_part += plen;
DEBUG(D_route) debug_printf("stripped prefix %s\n", addr->prefix);
}
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, slen);
+ 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;
- deliver_localpart_verified = NULL;
deliver_set_expansions(addr);
/* For convenience, the pre-router checks are in a separate function, which