TRUE; otherwise its default is FALSE. */
if (r->retry_use_local_part == TRUE_UNSET)
- r->retry_use_local_part = r->check_local_user;
+ r->retry_use_local_part =
+ r->check_local_user || r->local_parts || r->condition || r->prefix || r->suffix || r->senders || r->require_files;
/* Build a host list if fallback hosts is set. */
{
exim_setugid(uid, gid, TRUE,
string_sprintf("require_files check, file=%s", ss));
- if (route_check_access(ss, uid, gid, 4)) _exit(0);
+ if (route_check_access(ss, uid, gid, 4))
+ exim_underbar_exit(0);
DEBUG(D_route) debug_printf("route_check_access() failed\n");
- _exit(1);
+ exim_underbar_exit(1);
}
/* In the parent, wait for the child to finish */
while (waitpid(pid, &status, 0) < 0)
- {
if (errno != EINTR) /* unexpected error, interpret as failure */
{
status = 1;
break;
}
- }
signal(SIGCHLD, oldsignal); /* restore */
if ((status == 0) == invert) return SKIP;
BOOL cache_set = (Ustrcmp(lastname, s) == 0);
DEBUG(D_uid) debug_printf("seeking password data for user \"%s\": %s\n", s,
- cache_set? "using cached result" : "cache not available");
+ cache_set ? "using cached result" : "cache not available");
if (!cache_set)
{
return TRUE;
}
- (void)string_format(lastname, sizeof(lastname), "%s", s);
+ string_format_nt(lastname, sizeof(lastname), "%s", s);
/* Force failure if string length is greater than given maximum */
{
const uschar * varlist = r->set;
tree_node ** root = (tree_node **) &addr->prop.variables;
-int sep = 0;
+int sep = ';';
if (!varlist) return OK;
/* Variable name must exist and start "r_". */
if (!name || name[0] != 'r' || name[1] != '_' || !name[2])
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "bad router variable name '%s' in router '%s'\n", name, r->name);
return FAIL;
+ }
name += 2;
+ while (isspace(*assignment)) assignment++;
+
if (!(val = expand_string(US assignment)))
if (f.expand_string_forcedfail)
{
}
if (!(node = tree_search(*root, name)))
- {
- node = store_get(sizeof(tree_node) + Ustrlen(name));
+ { /* name should never be tainted */
+ node = store_get(sizeof(tree_node) + Ustrlen(name), FALSE);
Ustrcpy(node->name, name);
(void)tree_insertnode(root, node);
}
node->data.ptr = US val;
- DEBUG(D_route) debug_printf("set r_%s = '%s'\n", name, val);
+ DEBUG(D_route) debug_printf("set r_%s%s = '%s'%s\n",
+ name, is_tainted(name)?" (tainted)":"",
+ val, is_tainted(val)?" (tainted)":"");
+
+ /* All expansions after this point need visibility of that variable */
+ router_var = *root;
}
return OK;
}
router traversal. On the addr string they are held as a variable tree, so
as to maintain the post-expansion taints separate. */
- if ((yield = set_router_vars(addr, r)) != OK)
- if (yield == PASS)
- continue; /* with next router */
- else
- goto ROUTE_EXIT;
-
-#ifdef notdef
- if (r->set)
+ switch (set_router_vars(addr, r))
{
- const uschar * list = r->set;
- int sep = 0;
- for (uschar * ele; (ele = string_nextinlist(&list, &sep, NULL, 0)); )
- {
- uschar * ee;
- if (!(ee = expand_string(ele)))
- if (f.expand_string_forcedfail)
- {
- DEBUG(D_route) debug_printf("forced failure in expansion of \"%s\" "
- "(router variable): decline action taken\n", ele);
-
- /* Expand "more" if necessary; DEFER => an expansion failed */
-
- yield = exp_bool(addr, US"router", r->name, D_route,
- US"more", r->more, r->expand_more, &more);
- if (yield != OK) goto ROUTE_EXIT;
-
- if (!more)
- {
- DEBUG(D_route)
- debug_printf("\"more\"=false: skipping remaining routers\n");
- router_name = NULL;
- r = NULL;
- break;
- }
- else continue; /* With next router */
- }
- else
- {
- addr->message = string_sprintf("expansion of \"%s\" failed "
- "in %s router: %s", ele, r->name, expand_string_message);
- yield = DEFER;
- goto ROUTE_EXIT;
- }
-
- addr->prop.set = string_append_listele(addr->prop.set, ':', ee);
- }
+ case OK: break;
+ case PASS: continue; /* with next router */
+ default: goto ROUTE_EXIT;
}
-#endif
/* Finally, expand the address_data field in the router. Forced failure
behaves as if the router declined. Any other failure is more serious. On
/* If succeeded while verifying but fail_verify is set, convert into
a failure, and take it off the local or remote delivery list. */
- if (((verify == v_sender && r->fail_verify_sender) ||
- (verify == v_recipient && r->fail_verify_recipient)) &&
- (yield == OK || yield == PASS))
+ if ( ( verify == v_sender && r->fail_verify_sender
+ || verify == v_recipient && r->fail_verify_recipient
+ )
+ && (yield == OK || yield == PASS))
{
addr->message = string_sprintf("%s router forced verify failure", r->name);
if (*paddr_remote == addr) *paddr_remote = addr->next;
HDEBUG(D_route)
{
debug_printf("%s router %s for %s\n", r->name,
- (yield == PASS)? "passed" : "declined", addr->address);
+ yield == PASS ? "passed" : "declined", addr->address);
if (Ustrcmp(old_domain, addr->domain) != 0)
debug_printf("domain %s rewritten\n", old_domain);
}
if (yield == DEFER)
{
- HDEBUG(D_route)
- {
- debug_printf("%s router: defer for %s\n", r->name, addr->address);
- debug_printf(" message: %s\n", (addr->message == NULL)?
- US"<none>" : addr->message);
- }
+ HDEBUG(D_route) debug_printf("%s router: defer for %s\n message: %s\n",
+ r->name, addr->address, addr->message ? addr->message : US"<none>");
goto ROUTE_EXIT;
}