* 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-only */
#include "../exim.h"
/* Options specific to the redirect router. */
+#define LOFF(field) OPT_OFF(redirect_router_options_block, field)
optionlist redirect_router_options[] = {
{ "allow_defer", opt_bit | (RDON_DEFER << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "allow_fail", opt_bit | (RDON_FAIL << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "allow_filter", opt_bit | (RDON_FILTER << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "allow_freeze", opt_bit | (RDON_FREEZE << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
- { "check_ancestor", opt_bool,
- (void *)offsetof(redirect_router_options_block, check_ancestor) },
- { "check_group", opt_bool,
- (void *)offsetof(redirect_router_options_block, check_group) },
- { "check_owner", opt_bool,
- (void *)offsetof(redirect_router_options_block, check_owner) },
- { "data", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, data) },
- { "directory_transport",opt_stringptr,
- (void *)offsetof(redirect_router_options_block, directory_transport_name) },
- { "file", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, file) },
- { "file_transport", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, file_transport_name) },
+ LOFF(bit_options) },
+ { "check_ancestor", opt_bool, LOFF(check_ancestor) },
+ { "check_group", opt_bool, LOFF(check_group) },
+ { "check_owner", opt_bool, LOFF(check_owner) },
+ { "data", opt_stringptr, LOFF(data) },
+ { "directory_transport",opt_stringptr, LOFF(directory_transport_name) },
+ { "file", opt_stringptr, LOFF(file) },
+ { "file_transport", opt_stringptr, LOFF(file_transport_name) },
+
{ "filter_prepend_home",opt_bit | (RDON_PREPEND_HOME << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_blackhole", opt_bit | (RDON_BLACKHOLE << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_exim_filter", opt_bit | (RDON_EXIM_FILTER << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_file", opt_bool,
- (void *)offsetof(redirect_router_options_block, forbid_file) },
+ LOFF(forbid_file) },
{ "forbid_filter_dlfunc", opt_bit | (RDON_DLFUNC << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_existstest", opt_bit | (RDON_EXISTS << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_logwrite",opt_bit | (RDON_LOG << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_lookup", opt_bit | (RDON_LOOKUP << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_perl", opt_bit | (RDON_PERL << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_readfile", opt_bit | (RDON_READFILE << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_readsocket", opt_bit | (RDON_READSOCK << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_filter_reply",opt_bool,
- (void *)offsetof(redirect_router_options_block, forbid_filter_reply) },
+ LOFF(forbid_filter_reply) },
{ "forbid_filter_run", opt_bit | (RDON_RUN << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_include", opt_bit | (RDON_INCLUDE << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_pipe", opt_bool,
- (void *)offsetof(redirect_router_options_block, forbid_pipe) },
+ LOFF(forbid_pipe) },
{ "forbid_sieve_filter",opt_bit | (RDON_SIEVE_FILTER << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "forbid_smtp_code", opt_bool,
- (void *)offsetof(redirect_router_options_block, forbid_smtp_code) },
+ LOFF(forbid_smtp_code) },
{ "hide_child_in_errmsg", opt_bool,
- (void *)offsetof(redirect_router_options_block, hide_child_in_errmsg) },
+ LOFF( hide_child_in_errmsg) },
{ "ignore_eacces", opt_bit | (RDON_EACCES << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
+ LOFF(bit_options) },
{ "ignore_enotdir", opt_bit | (RDON_ENOTDIR << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
- { "include_directory", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, include_directory) },
- { "modemask", opt_octint,
- (void *)offsetof(redirect_router_options_block, modemask) },
- { "one_time", opt_bool,
- (void *)offsetof(redirect_router_options_block, one_time) },
- { "owners", opt_uidlist,
- (void *)offsetof(redirect_router_options_block, owners) },
- { "owngroups", opt_gidlist,
- (void *)offsetof(redirect_router_options_block, owngroups) },
- { "pipe_transport", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, pipe_transport_name) },
- { "qualify_domain", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, qualify_domain) },
- { "qualify_preserve_domain", opt_bool,
- (void *)offsetof(redirect_router_options_block, qualify_preserve_domain) },
- { "repeat_use", opt_bool | opt_public,
- (void *)offsetof(router_instance, repeat_use) },
- { "reply_transport", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, reply_transport_name) },
+ LOFF(bit_options) },
+
+ { "include_directory", opt_stringptr, LOFF( include_directory) },
+ { "modemask", opt_octint, LOFF(modemask) },
+ { "one_time", opt_bool, LOFF(one_time) },
+ { "owners", opt_uidlist, LOFF(owners) },
+ { "owngroups", opt_gidlist, LOFF(owngroups) },
+ { "pipe_transport", opt_stringptr, LOFF(pipe_transport_name) },
+ { "qualify_domain", opt_stringptr, LOFF(qualify_domain) },
+ { "qualify_preserve_domain", opt_bool, LOFF(qualify_preserve_domain) },
+ { "repeat_use", opt_bool | opt_public, OPT_OFF(router_instance, repeat_use) },
+ { "reply_transport", opt_stringptr, LOFF(reply_transport_name) },
+
{ "rewrite", opt_bit | (RDON_REWRITE << 16),
- (void *)offsetof(redirect_router_options_block, bit_options) },
- { "sieve_enotify_mailto_owner", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, sieve_enotify_mailto_owner) },
- { "sieve_subaddress", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, sieve_subaddress) },
- { "sieve_useraddress", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, sieve_useraddress) },
- { "sieve_vacation_directory", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, sieve_vacation_directory) },
- { "skip_syntax_errors", opt_bool,
- (void *)offsetof(redirect_router_options_block, skip_syntax_errors) },
-#ifdef EXPERIMENTAL_SRS
- { "srs", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, srs) },
- { "srs_alias", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, srs_alias) },
- { "srs_condition", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, srs_condition) },
- { "srs_dbinsert", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, srs_dbinsert) },
- { "srs_dbselect", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, srs_dbselect) },
-#endif
- { "syntax_errors_text", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, syntax_errors_text) },
- { "syntax_errors_to", opt_stringptr,
- (void *)offsetof(redirect_router_options_block, syntax_errors_to) }
+ LOFF(bit_options) },
+
+ { "sieve_enotify_mailto_owner", opt_stringptr, LOFF(sieve_enotify_mailto_owner) },
+ { "sieve_subaddress", opt_stringptr, LOFF(sieve_subaddress) },
+ { "sieve_useraddress", opt_stringptr, LOFF(sieve_useraddress) },
+ { "sieve_vacation_directory", opt_stringptr, LOFF(sieve_vacation_directory) },
+ { "skip_syntax_errors", opt_bool, LOFF(skip_syntax_errors) },
+ { "syntax_errors_text", opt_stringptr, LOFF(syntax_errors_text) },
+ { "syntax_errors_to", opt_stringptr, LOFF(syntax_errors_to) }
};
/* Size of the options list. An extern variable has to be used so that its
NULL, /* qualify_domain */
NULL, /* owners */
NULL, /* owngroups */
-#ifdef EXPERIMENTAL_SRS
- NULL, /* srs */
- NULL, /* srs_alias */
- NULL, /* srs_condition */
- NULL, /* srs_dbinsert */
- NULL, /* srs_dbselect */
-#endif
022, /* modemask */
RDO_REWRITE | RDO_PREPEND_HOME, /* bit_options */
FALSE, /* check_ancestor */
if (next->address[0] == '|')
{
address_pipe = next->address;
- if (rf_get_transport(ob->pipe_transport_name, &(ob->pipe_transport),
+ if (rf_get_transport(ob->pipe_transport_name, &ob->pipe_transport,
next, rblock->name, US"pipe_transport"))
next->transport = ob->pipe_transport;
address_pipe = NULL;
}
else if (next->address[0] == '>')
{
- if (rf_get_transport(ob->reply_transport_name, &(ob->reply_transport),
+ if (rf_get_transport(ob->reply_transport_name, &ob->reply_transport,
next, rblock->name, US"reply_transport"))
next->transport = ob->reply_transport;
}
next->transport = ob->directory_transport;
}
else
- {
- if (rf_get_transport(ob->file_transport_name, &(ob->file_transport),
+ if (rf_get_transport(ob->file_transport_name, &ob->file_transport,
next, rblock->name, US"file_transport"))
next->transport = ob->file_transport;
- }
+
address_file = NULL;
}
}
int frc = 0;
int xrc = 0;
-addr_local = addr_local; /* Keep picky compilers happy */
-addr_remote = addr_remote;
-
/* Initialize the data to be propagated to the children */
addr_prop.address_data = deliver_address_data;
addr_prop.variables = NULL;
tree_dup((tree_node **)&addr_prop.variables, addr->prop.variables);
-#ifdef EXPERIMENTAL_SRS
-addr_prop.srs_sender = NULL;
-#endif
#ifdef SUPPORT_I18N
addr_prop.utf8_msg = addr->prop.utf8_msg;
addr_prop.utf8_downcvt = addr->prop.utf8_downcvt;
ugid.gid_set = TRUE;
}
-#ifdef EXPERIMENTAL_SRS
- /* Perform SRS on recipient/return-path as required */
-
- if(ob->srs != NULL)
- {
- BOOL usesrs = TRUE;
-
- if(ob->srs_condition != NULL)
- usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
-
- if(usesrs)
- {
- int srs_action = 0, n_srs;
- uschar *res;
- uschar *usedomain;
-
- /* What are we doing? */
- if(Ustrcmp(ob->srs, "forward") == 0)
- srs_action = 1;
- else if(Ustrcmp(ob->srs, "reverseandforward") == 0)
- {
- srs_action = 3;
-
- if((ob->srs_dbinsert == NULL) ^ (ob->srs_dbselect == NULL))
- return DEFER;
- }
- else if(Ustrcmp(ob->srs, "reverse") == 0)
- srs_action = 2;
-
- /* Reverse SRS */
- if(srs_action & 2)
- {
- srs_orig_recipient = addr->address;
-
- eximsrs_init();
- if(ob->srs_dbselect)
- eximsrs_db_set(TRUE, ob->srs_dbselect);
-/* Comment this out for now...
-// else
-// eximsrs_db_set(TRUE, NULL);
-*/
-
- if((n_srs = eximsrs_reverse(&res, addr->address)) == OK)
- {
- srs_recipient = res;
- DEBUG(D_any)
- debug_printf("SRS (reverse): Recipient '%s' rewritten to '%s'\n", srs_orig_recipient, srs_recipient);
- }
-
- eximsrs_done();
-
- if(n_srs != OK)
- return n_srs;
- }
-
- /* Forward SRS */
- /* No point in actually performing SRS if we are just verifying a recipient */
- if((srs_action & 1) && verify == v_none &&
- (sender_address ? sender_address[0] != 0 : FALSE))
- {
-
- srs_orig_sender = sender_address;
- eximsrs_init();
- if(ob->srs_dbinsert)
- eximsrs_db_set(FALSE, ob->srs_dbinsert);
-/* Comment this out for now...
-// else
-// eximsrs_db_set(FALSE, NULL);
-*/
-
- if (!(usedomain = ob->srs_alias ? expand_string(ob->srs_alias) : NULL))
- usedomain = string_copy(deliver_domain);
-
- if((n_srs = eximsrs_forward(&res, sender_address, usedomain)) == OK)
- {
- addr_prop.srs_sender = res;
- DEBUG(D_any)
- debug_printf("SRS (forward): Sender '%s' rewritten to '%s'\n", srs_orig_sender, res);
- }
-
- eximsrs_done();
-
- if(n_srs != OK)
- return n_srs;
- }
- }
- }
-#endif
-
/* Call the function that interprets redirection data, either inline or from a
file. This is a separate function so that the system filter can use it. It will
run the function in a subprocess if necessary. If qualify_preserve_domain is
frc = rda_interpret(&redirect, options, ob->include_directory,
ob->sieve_vacation_directory, ob->sieve_enotify_mailto_owner,
ob->sieve_useraddress, ob->sieve_subaddress, &ugid, &generated,
- &(addr->message), ob->skip_syntax_errors? &eblock : NULL, &filtertype,
+ &addr->message, ob->skip_syntax_errors? &eblock : NULL, &filtertype,
string_sprintf("%s router (recipient is %s)", rblock->name, addr->address));
qualify_domain_recipient = save_qualify_domain_recipient;
addr->message = yield == FAIL ? US"forced rejection" : US"forced defer";
else
{
- int ovector[3];
- if (ob->forbid_smtp_code &&
- pcre_exec(regex_smtp_code, NULL, CS addr->message,
- Ustrlen(addr->message), 0, PCRE_EOPT,
- ovector, sizeof(ovector)/sizeof(int)) >= 0)
+ uschar * matched;
+ if ( ob->forbid_smtp_code
+ && regex_match(regex_smtp_code, addr->message, -1, &matched))
{
DEBUG(D_route) debug_printf("SMTP code at start of error message "
"is ignored because forbid_smtp_code is set\n");
- addr->message += ovector[1];
+ addr->message += Ustrlen(matched);
}
addr->user_message = addr->message;
setflag(addr, af_pass_message);
if (filtertype != FILTER_FORWARD && ob->skip_syntax_errors)
{
- eblock = store_get(sizeof(error_block), FALSE);
+ eblock = store_get(sizeof(error_block), GET_UNTAINTED);
eblock->next = NULL;
eblock->text1 = addr->message;
eblock->text2 = NULL;