X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Frouters%2Fredirect.c;h=944fb6743a8e98c966f8bd3529e636478d65d1b6;hb=3d0a6e0fcf175e8416f344939b60c918c0f0f418;hp=9be15ede4142336a519f4e9ffb929cd498118f2a;hpb=fd6de02e0406522ba0cfff43d6be5b0201200b95;p=exim.git diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c index 9be15ede4..944fb6743 100644 --- a/src/src/routers/redirect.c +++ b/src/src/routers/redirect.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/routers/redirect.c,v 1.14 2005/09/12 15:09:55 ph10 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -39,6 +37,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 +69,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), @@ -97,6 +99,8 @@ optionlist redirect_router_options[] = { (void *)offsetof(redirect_router_options_block, 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, @@ -129,6 +133,21 @@ address can appear in the tables drtables.c. */ int redirect_router_options_count = sizeof(redirect_router_options)/sizeof(optionlist); + +#ifdef MACRO_PREDEF + +/* Dummy entries */ +redirect_router_options_block redirect_router_option_defaults = {0}; +void redirect_router_init(router_instance *rblock) {} +int redirect_router_entry(router_instance *rblock, address_item *addr, + struct passwd *pw, int verify, address_item **addr_local, + address_item **addr_remote, address_item **addr_new, + address_item **addr_succeed) {return 0;} + +#else /*!MACRO_PREDEF*/ + + + /* Default private options block for the redirect router. */ redirect_router_options_block redirect_router_option_defaults = { @@ -147,6 +166,7 @@ redirect_router_options_block redirect_router_option_defaults = { NULL, /* sieve_subaddress */ NULL, /* sieve_useraddress */ NULL, /* sieve_vacation_directory */ + NULL, /* sieve_enotify_mailto_owner */ NULL, /* syntax_errors_text */ NULL, /* syntax_errors_to */ NULL, /* qualify_domain */ @@ -160,13 +180,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 */ @@ -202,11 +223,11 @@ than false, there is likely to be a problem. */ if (ob->one_time) { ob->forbid_pipe = ob->forbid_file = ob->forbid_filter_reply = TRUE; - if (rblock->extra_headers != NULL || rblock->remove_headers != NULL) + if (rblock->extra_headers || rblock->remove_headers) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "\"headers_add\" and \"headers_remove\" are not permitted with " "\"one_time\"", rblock->name); - if (rblock->unseen || rblock->expand_unseen != NULL) + if (rblock->unseen || rblock->expand_unseen) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "\"unseen\" may not be used with \"one_time\"", rblock->name); } @@ -218,7 +239,7 @@ or if owngroups is set. */ if (ob->check_owner == TRUE_UNSET) ob->check_owner = rblock->check_local_user || - (ob->owners != NULL && ob->owners[0] != 0); + (ob->owners && ob->owners[0] != 0); if (ob->check_group == TRUE_UNSET) ob->check_group = (rblock->check_local_user && (ob->modemask & 020) == 0) || @@ -226,7 +247,7 @@ if (ob->check_group == TRUE_UNSET) /* If explicit qualify domain set, the preserve option is locked out */ -if (ob->qualify_domain != NULL && ob->qualify_preserve_domain) +if (ob->qualify_domain && ob->qualify_preserve_domain) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "only one of \"qualify_domain\" or \"qualify_preserve_domain\" must be set", rblock->name); @@ -271,11 +292,11 @@ sort_errors_and_headers(router_instance *rblock, address_item *addr, int verify, address_item_propagated *addr_prop) { int frc = rf_get_errors_address(addr, rblock, verify, - &(addr_prop->errors_address)); + &addr_prop->errors_address); if (frc != OK) return frc; -addr->p.errors_address = addr_prop->errors_address; -return rf_get_munge_headers(addr, rblock, &(addr_prop->extra_headers), - &(addr_prop->remove_headers)); +addr->prop.errors_address = addr_prop->errors_address; +return rf_get_munge_headers(addr, rblock, &addr_prop->extra_headers, + &addr_prop->remove_headers); } @@ -319,16 +340,18 @@ add_generated(router_instance *rblock, address_item **addr_new, redirect_router_options_block *ob = (redirect_router_options_block *)(rblock->options_block); -while (generated != NULL) +while (generated) { address_item *parent; address_item *next = generated; - uschar *errors_address = next->p.errors_address; + uschar *errors_address = next->prop.errors_address; generated = next->next; next->parent = addr; - orflag(next, addr, af_ignore_error); next->start_router = rblock->redirect_router; + if (addr->child_count == USHRT_MAX) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router generated more than %d " + "child addresses for <%s>", rblock->name, USHRT_MAX, addr->address); addr->child_count++; next->next = *addr_new; @@ -338,7 +361,7 @@ while (generated != NULL) if (ob->one_time && !queue_2stage) { - for (parent = addr; parent->parent != NULL; parent = parent->parent); + for (parent = addr; parent->parent; parent = parent->parent) ; next->onetime_parent = parent->address; } @@ -349,28 +372,27 @@ while (generated != NULL) unless the ancestor was routed by a case-sensitive router. */ if (ob->check_ancestor) - { - for (parent = addr; parent != NULL; parent = parent->parent) - { - if (((parent->router != NULL && parent->router->caseful_local_part)? - Ustrcmp(next->address, parent->address) - : - strcmpic(next->address, parent->address) + for (parent = addr; parent; parent = parent->parent) + if ((parent->router && parent->router->caseful_local_part + ? Ustrcmp(next->address, parent->address) + : strcmpic(next->address, parent->address) ) == 0) { DEBUG(D_route) debug_printf("generated parent replaced by child\n"); next->address = string_copy(addr->address); break; } - } - } /* A user filter may, under some circumstances, set up an errors address. If so, we must take care to re-instate it when we copy in the propagated data so that it overrides any errors_to setting on the router. */ - next->p = *addr_prop; - if (errors_address != NULL) next->p.errors_address = errors_address; + { + BOOL ignore_error = next->prop.ignore_error; + next->prop = *addr_prop; + next->prop.ignore_error = ignore_error || addr->prop.ignore_error; + } + if (errors_address) next->prop.errors_address = errors_address; /* For pipes, files, and autoreplies, record this router as handling them, because they don't go through the routing process again. Then set up uid, @@ -442,13 +464,19 @@ while (generated != NULL) } } +#ifdef SUPPORT_I18N + if (!next->prop.utf8_msg) + next->prop.utf8_msg = string_is_utf8(next->address) + || (sender_address && string_is_utf8(sender_address)); +#endif + DEBUG(D_route) { debug_printf("%s router generated %s\n %serrors_to=%s transport=%s\n", rblock->name, next->address, testflag(next, af_pfr)? "pipe, file, or autoreply\n " : "", - next->p.errors_address, + next->prop.errors_address, (next->transport == NULL)? US"NULL" : next->transport->name); if (testflag(next, af_uid_set)) @@ -461,6 +489,10 @@ while (generated != NULL) else debug_printf("gid=unset "); +#ifdef SUPPORT_I18N + if (next->prop.utf8_msg) debug_printf("utf8 "); +#endif + debug_printf("home=%s\n", next->home_dir); } } @@ -508,7 +540,7 @@ int redirect_router_entry( redirect_router_options_block *ob = (redirect_router_options_block *)(rblock->options_block); address_item *generated = NULL; -uschar *save_qualify_domain_recipient = qualify_domain_recipient; +const uschar *save_qualify_domain_recipient = qualify_domain_recipient; uschar *discarded = US"discarded"; address_item_propagated addr_prop; error_block *eblock = NULL; @@ -535,6 +567,12 @@ addr_prop.remove_headers = NULL; #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; +addr_prop.utf8_downcvt_maybe = addr->prop.utf8_downcvt_maybe; +#endif + /* When verifying and testing addresses, the "logwrite" command in filters must be bypassed. */ @@ -631,8 +669,8 @@ if (!ugid.gid_set && pw != NULL) // eximsrs_db_set(FALSE, NULL); */ - if(ob->srs_alias != NULL ? (usedomain = expand_string(ob->srs_alias)) == NULL : 1) - usedomain = deliver_domain; + 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) { @@ -685,10 +723,10 @@ else } frc = rda_interpret(&redirect, options, ob->include_directory, - ob->sieve_vacation_directory, ob->sieve_useraddress, ob->sieve_subaddress, - &ugid, &generated, &(addr->message), ob->skip_syntax_errors? &eblock : NULL, - &filtertype, string_sprintf("%s router (recipient is %s)", rblock->name, - addr->address)); + 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, + string_sprintf("%s router (recipient is %s)", rblock->name, addr->address)); qualify_domain_recipient = save_qualify_domain_recipient; @@ -709,26 +747,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 @@ -865,11 +916,9 @@ else next->next = *addr_new; *addr_new = next; - /* Copy relevant flags (af_propagate is a name for the set), and set the - data that propagates. */ + /* Set the data that propagates. */ - copyflag(next, addr, af_propagate); - next->p = addr_prop; + next->prop = addr_prop; DEBUG(D_route) debug_printf("%s router autogenerated %s\n%s%s%s", rblock->name, @@ -889,4 +938,5 @@ addr->next = *addr_succeed; return yield; } +#endif /*!MACRO_PREDEF*/ /* End of routers/redirect.c */