X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Frouters%2Fredirect.c;h=c2e2a21fe061212a0fb160d264851a8142a9f426;hb=d515a9174a5ea517bc3d27bc4d40223b24d7a47f;hp=e33a5fe49fec8adbd424f1f6adedb88685c5ad64;hpb=0756eb3cb50d73a77b486e47528f7cb1bffdb299;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c index e33a5fe49..c2e2a21fe 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.1 2004/10/07 13:10:02 ph10 Exp $ */ +/* $Cambridge: exim/src/src/routers/redirect.c,v 1.15 2006/02/07 11:19:02 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2006 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -41,18 +41,20 @@ optionlist redirect_router_options[] = { (void *)offsetof(redirect_router_options_block, file_transport_name) }, { "forbid_blackhole", opt_bit | (RDON_BLACKHOLE << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, + { "forbid_exim_filter", opt_bit | (RDON_EXIM_FILTER << 16), + (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_file", opt_bool, (void *)offsetof(redirect_router_options_block, forbid_file) }, + { "forbid_filter_dlfunc", opt_bit | (RDON_DLFUNC << 16), + (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_filter_existstest", opt_bit | (RDON_EXISTS << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_filter_logwrite",opt_bit | (RDON_LOG << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_filter_lookup", opt_bit | (RDON_LOOKUP << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, - #ifdef EXIM_PERL { "forbid_filter_perl", opt_bit | (RDON_PERL << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, - #endif { "forbid_filter_readfile", opt_bit | (RDON_READFILE << 16), (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_filter_readsocket", opt_bit | (RDON_READSOCK << 16), @@ -65,6 +67,8 @@ optionlist redirect_router_options[] = { (void *)offsetof(redirect_router_options_block, bit_options) }, { "forbid_pipe", opt_bool, (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) }, { "hide_child_in_errmsg", opt_bool, (void *)offsetof(redirect_router_options_block, hide_child_in_errmsg) }, { "ignore_eacces", opt_bit | (RDON_EACCES << 16), @@ -93,10 +97,26 @@ 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_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, @@ -124,12 +144,21 @@ redirect_router_options_block redirect_router_option_defaults = { NULL, /* include_directory */ NULL, /* pipe_transport_name */ NULL, /* reply_transport_name */ + NULL, /* sieve_subaddress */ + NULL, /* sieve_useraddress */ NULL, /* sieve_vacation_directory */ NULL, /* syntax_errors_text */ NULL, /* syntax_errors_to */ 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, /* bit_options */ FALSE, /* check_ancestor */ @@ -165,7 +194,10 @@ if ((ob->file == NULL) == (ob->data == NULL)) "%sone of \"file\" or \"data\" must be specified", rblock->name, (ob->file == NULL)? "" : "only "); -/* Onetime aliases can only be real addresses. Headers can't be manipulated. */ +/* Onetime aliases can only be real addresses. Headers can't be manipulated. +The combination of one_time and unseen is not allowed. We can't check the +expansion of "unseen" here, but we assume that if it is set to anything other +than false, there is likely to be a problem. */ if (ob->one_time) { @@ -174,6 +206,9 @@ if (ob->one_time) 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) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " + "\"unseen\" may not be used with \"one_time\"", rblock->name); } /* The defaults for check_owner and check_group depend on other settings. The @@ -223,7 +258,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 @@ -233,7 +268,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)); @@ -464,7 +499,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 */ @@ -497,10 +532,14 @@ addr_prop.errors_address = NULL; addr_prop.extra_headers = NULL; addr_prop.remove_headers = NULL; +#ifdef EXPERIMENTAL_SRS +addr_prop.srs_sender = NULL; +#endif + /* 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 @@ -522,6 +561,95 @@ if (!ugid.gid_set && pw != NULL) 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(ob->srs_alias != NULL ? (usedomain = expand_string(ob->srs_alias)) == NULL : 1) + usedomain = 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 @@ -557,9 +685,10 @@ else } frc = rda_interpret(&redirect, options, ob->include_directory, - ob->sieve_vacation_directory, &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_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; @@ -592,8 +721,13 @@ switch (frc) 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); - if (addr->message == NULL) addr->message = US"forced rejection"; - else addr->user_message = addr->message; + if (addr->message == NULL) + addr->message = US"forced rejection"; + else + { + addr->user_message = addr->message; + setflag(addr, af_pass_message); + } return FAIL; /* As in the case of a system filter, a freeze does not happen after a manual @@ -668,12 +802,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) @@ -702,7 +836,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);