X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/130e9641fd8700ee9ac18a3f2e42a4e8f743a8e9..184e88237dea64ce48076cdd0184612d057cbafd:/src/src/routers/redirect.c diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c index 2173923ec..74aba2065 100644 --- a/src/src/routers/redirect.c +++ b/src/src/routers/redirect.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/routers/redirect.c,v 1.12 2005/05/24 08:50:36 ph10 Exp $ */ +/* $Cambridge: exim/src/src/routers/redirect.c,v 1.20 2007/01/08 10:50:20 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2007 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -39,6 +39,8 @@ optionlist redirect_router_options[] = { (void *)offsetof(redirect_router_options_block, file) }, { "file_transport", opt_stringptr, (void *)offsetof(redirect_router_options_block, file_transport_name) }, + { "filter_prepend_home",opt_bit | (RDON_PREPEND_HOME << 16), + (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_blackhole", opt_bit | (RDON_BLACKHOLE << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_exim_filter", opt_bit | (RDON_EXIM_FILTER << 16), @@ -69,6 +71,8 @@ optionlist redirect_router_options[] = { (void *)offsetof(redirect_router_options_block, forbid_pipe) }, { "forbid_sieve_filter",opt_bit | (RDON_SIEVE_FILTER << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, + { "forbid_smtp_code", opt_bool, + (void *)offsetof(redirect_router_options_block, forbid_smtp_code) }, { "hide_child_in_errmsg", opt_bool, (void *)offsetof(redirect_router_options_block, hide_child_in_errmsg) }, { "ignore_eacces", opt_bit | (RDON_EACCES << 16), @@ -160,13 +164,14 @@ redirect_router_options_block redirect_router_option_defaults = { NULL, /* srs_dbselect */ #endif 022, /* modemask */ - RDO_REWRITE, /* bit_options */ + RDO_REWRITE | RDO_PREPEND_HOME, /* bit_options */ FALSE, /* check_ancestor */ TRUE_UNSET, /* check_owner */ TRUE_UNSET, /* check_group */ FALSE, /* forbid_file */ FALSE, /* forbid_filter_reply */ FALSE, /* forbid_pipe */ + FALSE, /* forbid_smtp_code */ FALSE, /* hide_child_in_errmsg */ FALSE, /* one_time */ FALSE, /* qualify_preserve_domain */ @@ -258,7 +263,7 @@ passed on must have the original errors_address value. Arguments: rblock the router control block addr the address being routed - verify true if verifying + verify v_none/v_recipient/v_sender/v_expn addr_prop point to the propagated block, which is where the new values are to be placed @@ -268,7 +273,7 @@ Returns: the result of rf_get_errors_address() or rf_get_munge_headers(), static int sort_errors_and_headers(router_instance *rblock, address_item *addr, - BOOL verify, address_item_propagated *addr_prop) + int verify, address_item_propagated *addr_prop) { int frc = rf_get_errors_address(addr, rblock, verify, &(addr_prop->errors_address)); @@ -329,6 +334,9 @@ while (generated != NULL) next->parent = addr; orflag(next, addr, af_ignore_error); next->start_router = rblock->redirect_router; + if (addr->child_count == SHRT_MAX) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router generated more than %d " + "child addresses for <%s>", rblock->name, SHRT_MAX, addr->address); addr->child_count++; next->next = *addr_new; @@ -499,7 +507,7 @@ int redirect_router_entry( router_instance *rblock, /* data for this instantiation */ address_item *addr, /* address we are working on */ struct passwd *pw, /* passwd entry after check_local_user */ - BOOL verify, /* TRUE when verifying */ + int verify, /* v_none/v_recipient/v_sender/v_expn */ address_item **addr_local, /* add it to this if it's local */ address_item **addr_remote, /* add it to this if it's remote */ address_item **addr_new, /* put new addresses on here */ @@ -539,7 +547,7 @@ addr_prop.srs_sender = NULL; /* When verifying and testing addresses, the "logwrite" command in filters must be bypassed. */ -if (!verify && !address_test_mode) options |= RDO_REALLOG; +if (verify == v_none && !address_test_mode) options |= RDO_REALLOG; /* Sort out the fixed or dynamic uid/gid. This uid is used (a) for reading the file (and interpreting a filter) and (b) for running the transports for @@ -573,7 +581,7 @@ if (!ugid.gid_set && pw != NULL) if(usesrs) { - int srs_action, n_srs; + int srs_action = 0, n_srs; uschar *res; uschar *usedomain; @@ -618,7 +626,8 @@ if (!ugid.gid_set && pw != NULL) /* Forward SRS */ /* No point in actually performing SRS if we are just verifying a recipient */ - if((srs_action & 1) && !verify && (sender_address ? sender_address[0] != 0 : FALSE)) + if((srs_action & 1) && verify == v_none && + (sender_address ? sender_address[0] != 0 : FALSE)) { srs_orig_sender = sender_address; @@ -708,26 +717,39 @@ switch (frc) break; /* FF_DEFER and FF_FAIL can arise only as a result of explicit commands - (:fail: in an alias file or "fail" in a filter). If a configured message was - supplied, allow it to be included in an SMTP response after verifying. */ + (:defer: or :fail: in an alias file or "fail" in a filter). If a configured + message was supplied, allow it to be included in an SMTP response after + verifying. Remove any SMTP code if it is not allowed. */ case FF_DEFER: - if (addr->message == NULL) addr->message = US"forced defer"; - else addr->user_message = addr->message; - return DEFER; + yield = DEFER; + goto SORT_MESSAGE; case FF_FAIL: if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK) return xrc; add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw); + yield = FAIL; + + SORT_MESSAGE: if (addr->message == NULL) - addr->message = US"forced rejection"; + 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) + { + 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->user_message = addr->message; setflag(addr, af_pass_message); } - return FAIL; + return yield; /* As in the case of a system filter, a freeze does not happen after a manual thaw. In case deliveries were set up by the filter, we set the child count @@ -801,12 +823,12 @@ dealing with it, the router declines. */ if (eblock != NULL) { if (!moan_skipped_syntax_errors( - rblock->name, /* For message content */ - eblock, /* Ditto */ - (verify || address_test_mode)? - NULL : ob->syntax_errors_to, /* Who to mail */ - generated != NULL, /* True if not all failed */ - ob->syntax_errors_text)) /* Custom message */ + rblock->name, /* For message content */ + eblock, /* Ditto */ + (verify != v_none || address_test_mode)? + NULL : ob->syntax_errors_to, /* Who to mail */ + generated != NULL, /* True if not all failed */ + ob->syntax_errors_text)) /* Custom message */ return DEFER; if (filtertype != FILTER_FORWARD || generated == NULL) @@ -835,7 +857,7 @@ generated anything. Log what happened to this address, and return DISCARD. */ if (frc == FF_DELIVERED) { - if (generated == NULL && !verify && !address_test_mode) + if (generated == NULL && verify == v_none && !address_test_mode) { log_write(0, LOG_MAIN, "=> %s <%s> R=%s", discarded, addr->address, rblock->name);