From: Wietse Venema Date: Fri, 13 Dec 2002 05:00:00 +0000 (-0500) Subject: postfix-1.1.12-20021213 X-Git-Tag: v2.0.0~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac8e713e627d114357e0e362f507a566bb9ba755;p=thirdparty%2Fpostfix.git postfix-1.1.12-20021213 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 9203896ac..14f135d59 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7401,6 +7401,23 @@ Apologies for any names omitted. shooting a little easier. Files: smtpd/smtpd_check.c, trivial-rewrite/resolve.c. +20021213 + + Cleanup: transport map entries with null nexthop ignored + relayhost settings. Making the code simpler also made it + more correct. Files: trivial-rewrite/resolve.c, + trivial-rewrite/transport.c. + + Feature: "helpful_warnings" (default: yes) that can be + turned off if you really know what you're doing and want + to eliminate some unnecessary work. + + Feature: enforcement of master.cf process limits for + processes such as qmgr and pickup that must run alone, and + processes such as cleanup and bounce that must run without + explicit process count limit. If an incorrect process limit + is specified in master.cf the service aborts. + Open problems: Low: after successful delivery, per-queue window += 1/window, diff --git a/postfix/html/faq.html b/postfix/html/faq.html index c6226e548..68accfa7b 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -604,7 +604,7 @@ href="transport.5.html">transport table lookups.

-Important: do not specify a relayhost entry, or else mail for +Important: do not specify a relayhost in main.cf, or else mail for internal destinations will still be given to the relayhost.

diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index 0e33b3d2b..83a0273ab 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -443,5 +443,6 @@ int main(int argc, char **argv) MAIL_SERVER_STR_TABLE, str_table, MAIL_SERVER_TIME_TABLE, time_table, MAIL_SERVER_POST_INIT, post_jail_init, + MAIL_SERVER_UNLIMITED, 0); } diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 21438aa5b..1dd7f9881 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -338,5 +338,6 @@ int main(int argc, char **argv) MAIL_SERVER_POST_INIT, cleanup_post_jail, MAIL_SERVER_PRE_ACCEPT, pre_accept, MAIL_SERVER_IN_FLOW_DELAY, + MAIL_SERVER_UNLIMITED, 0); } diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index c4517a492..c55c5ddbd 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -675,5 +675,6 @@ int main(int argc, char **argv) single_server_main(argc, argv, flush_service, MAIL_SERVER_TIME_TABLE, time_table, MAIL_SERVER_PRE_INIT, pre_jail_init, + MAIL_SERVER_UNLIMITED, 0); } diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index fd27b82d4..62c849a82 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -14,6 +14,7 @@ /* char *var_transit_origin; /* char *var_transit_dest; /* char *var_mail_name; +/* int var_helpful_warnings; /* char *var_syslog_name; /* char *var_mail_owner; /* uid_t var_owner_uid; @@ -167,6 +168,7 @@ char *var_relayhost; char *var_transit_origin; char *var_transit_dest; char *var_mail_name; +int var_helpful_warnings; char *var_syslog_name; char *var_mail_owner; uid_t var_owner_uid; @@ -511,6 +513,7 @@ void mail_params_init() VAR_STRICT_ENCODING, DEF_STRICT_ENCODING, &var_strict_encoding, VAR_DISABLE_MIME_INPUT, DEF_DISABLE_MIME_INPUT, &var_disable_mime_input, VAR_DISABLE_MIME_OCONV, DEF_DISABLE_MIME_OCONV, &var_disable_mime_oconv, + VAR_HELPFUL_WARNINGS, DEF_HELPFUL_WARNINGS, &var_helpful_warnings, 0, }; const char *cp; diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index e9f43b83a..937224a27 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -23,6 +23,13 @@ typedef int bool; #define DEF_MAIL_NAME "Postfix" extern char *var_mail_name; + /* + * You want to be helped or not. + */ +#define VAR_HELPFUL_WARNINGS "helpful_warnings" +#define DEF_HELPFUL_WARNINGS 1 +extern bool var_helpful_warnings; + /* * What problem classes should be reported to the postmaster via email. * Default is bad problems only. See mail_error(3). Even when mail notices diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index e9cd06f5c..1405ab088 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20021212" +#define MAIL_RELEASE_DATE "20021213" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "1.1.12-" MAIL_RELEASE_DATE diff --git a/postfix/src/master/mail_server.h b/postfix/src/master/mail_server.h index 47b8cfeee..068354d5d 100644 --- a/postfix/src/master/mail_server.h +++ b/postfix/src/master/mail_server.h @@ -27,6 +27,8 @@ #define MAIL_SERVER_LOOP 12 #define MAIL_SERVER_EXIT 13 #define MAIL_SERVER_PRE_ACCEPT 14 +#define MAIL_SERVER_SOLITARY 15 +#define MAIL_SERVER_UNLIMITED 16 #define MAIL_SERVER_IN_FLOW_DELAY 20 diff --git a/postfix/src/master/master_ent.c b/postfix/src/master/master_ent.c index 89aac56ab..4412dff3b 100644 --- a/postfix/src/master/master_ent.c +++ b/postfix/src/master/master_ent.c @@ -402,6 +402,8 @@ MASTER_SERV *get_master_ent() argv_add(serv->args, command, (char *) 0); if (serv->max_proc == 1) argv_add(serv->args, "-l", (char *) 0); + if (serv->max_proc == 0) + argv_add(serv->args, "-z", (char *) 0); if (strcmp(basename(command), name) != 0) argv_add(serv->args, "-n", name, (char *) 0); argv_add(serv->args, "-t", transport, (char *) 0); diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 927aa94d2..4275c0c65 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -98,6 +98,10 @@ /* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)" /* Pause $in_flow_delay seconds when no "mail flow control token" /* is available. A token is consumed for each connection request. +/* .IP MAIL_SERVER_SOLITARY +/* This service must be configured with process limit of 1. +/* .IP MAIL_SERVER_UNLIMITED +/* This service must be configured with process limit of 0. /* .PP /* multi_server_disconnect() should be called by the application /* when a client disconnects. @@ -388,6 +392,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) char *lock_path; VSTRING *why; int alone = 0; + int zerolimit = 0; WATCHDOG *watchdog; char *oval; @@ -436,7 +441,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) * stderr, because no-one is going to see them. */ opterr = 0; - while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) { + while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uvz")) > 0) { switch (c) { case 'c': root_dir = "setme"; @@ -477,6 +482,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) case 'v': msg_verbose++; break; + case 'z': + zerolimit = 1; + break; default: msg_fatal("invalid option: %c", c); break; @@ -527,6 +535,16 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) case MAIL_SERVER_IN_FLOW_DELAY: multi_server_in_flow_delay = 1; break; + case MAIL_SERVER_SOLITARY: + if (!alone) + msg_fatal("service %s requires a process limit of 1", + service_name); + break; + case MAIL_SERVER_UNLIMITED: + if (!zerolimit) + msg_fatal("service %s requires a process limit of 0", + service_name); + break; default: msg_panic("%s: unknown argument type: %d", myname, key); } diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index d110e4010..077d8cc70 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -95,6 +95,10 @@ /* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)" /* Pause $in_flow_delay seconds when no "mail flow control token" /* is available. A token is consumed for each connection request. +/* .IP MAIL_SERVER_SOLITARY +/* This service must be configured with process limit of 1. +/* .IP MAIL_SERVER_UNLIMITED +/* This service must be configured with process limit of 0. /* .PP /* The var_use_limit variable limits the number of clients that /* a server can service before it commits suicide. @@ -235,7 +239,7 @@ static void single_server_wakeup(int fd) close_on_exec(fd, CLOSE_ON_EXEC); stream = vstream_fdopen(fd, O_RDWR); tmp = concatenate(single_server_name, " socket", (char *) 0); - vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); + vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); myfree(tmp); timed_ipc_setup(stream); if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0) @@ -344,6 +348,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) char *lock_path; VSTRING *why; int alone = 0; + int zerolimit = 0; WATCHDOG *watchdog; char *oval; @@ -392,7 +397,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) * stderr, because no-one is going to see them. */ opterr = 0; - while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) { + while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uvz")) > 0) { switch (c) { case 'c': root_dir = "setme"; @@ -433,6 +438,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) case 'v': msg_verbose++; break; + case 'z': + zerolimit = 1; + break; default: msg_fatal("invalid option: %c", c); break; @@ -483,6 +491,16 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) case MAIL_SERVER_IN_FLOW_DELAY: single_server_in_flow_delay = 1; break; + case MAIL_SERVER_SOLITARY: + if (!alone) + msg_fatal("service %s requires a process limit of 1", + service_name); + break; + case MAIL_SERVER_UNLIMITED: + if (!zerolimit) + msg_fatal("service %s requires a process limit of 0", + service_name); + break; default: msg_panic("%s: unknown argument type: %d", myname, key); } diff --git a/postfix/src/master/trigger_server.c b/postfix/src/master/trigger_server.c index c84b8a8b5..08d42bf18 100644 --- a/postfix/src/master/trigger_server.c +++ b/postfix/src/master/trigger_server.c @@ -102,6 +102,10 @@ /* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)" /* Pause $in_flow_delay seconds when no "mail flow control token" /* is available. A token is consumed for each connection request. +/* .IP MAIL_SERVER_SOLITARY +/* This service must be configured with process limit of 1. +/* .IP MAIL_SERVER_UNLIMITED +/* This service must be configured with process limit of 0. /* .PP /* The var_use_limit variable limits the number of clients that /* a server can service before it commits suicide. @@ -340,6 +344,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. char *lock_path; VSTRING *why; int alone = 0; + int zerolimit = 0; WATCHDOG *watchdog; char *oval; @@ -388,7 +393,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. * stderr, because no-one is going to see them. */ opterr = 0; - while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) { + while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uvz")) > 0) { switch (c) { case 'c': root_dir = "setme"; @@ -429,6 +434,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. case 'v': msg_verbose++; break; + case 'z': + zerolimit = 1; + break; default: msg_fatal("invalid option: %c", c); break; @@ -479,6 +487,16 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. case MAIL_SERVER_IN_FLOW_DELAY: trigger_server_in_flow_delay = 1; break; + case MAIL_SERVER_SOLITARY: + if (!alone) + msg_fatal("service %s requires a process limit of 1", + service_name); + break; + case MAIL_SERVER_UNLIMITED: + if (!zerolimit) + msg_fatal("service %s requires a process limit of 0", + service_name); + break; default: msg_panic("%s: unknown argument type: %d", myname, key); } diff --git a/postfix/src/nqmgr/qmgr.c b/postfix/src/nqmgr/qmgr.c index f0a5135ab..cd1e72b1e 100644 --- a/postfix/src/nqmgr/qmgr.c +++ b/postfix/src/nqmgr/qmgr.c @@ -569,5 +569,6 @@ int main(int argc, char **argv) MAIL_SERVER_POST_INIT, qmgr_post_init, MAIL_SERVER_LOOP, qmgr_loop, MAIL_SERVER_PRE_ACCEPT, pre_accept, + MAIL_SERVER_SOLITARY, 0); } diff --git a/postfix/src/nqmgr/qmgr_entry.c b/postfix/src/nqmgr/qmgr_entry.c index 45c8b7f61..5032a4556 100644 --- a/postfix/src/nqmgr/qmgr_entry.c +++ b/postfix/src/nqmgr/qmgr_entry.c @@ -290,7 +290,7 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_PEER *peer, QMGR_MESSAGE *message) * XXX This code does not detect the case that the active queue is being * starved because incoming mail is pounding the disk. */ - if (var_qmgr_clog_warn_time > 0) { + if (var_helpful_warnings && var_qmgr_clog_warn_time > 0) { int queue_length = queue->todo_refcount + queue->busy_refcount; time_t now; QMGR_TRANSPORT *transport; diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index e798de07c..40e1ab714 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -521,5 +521,6 @@ int main(int argc, char **argv) trigger_server_main(argc, argv, pickup_service, MAIL_SERVER_STR_TABLE, str_table, MAIL_SERVER_POST_INIT, drop_privileges, + MAIL_SERVER_SOLITARY, 0); } diff --git a/postfix/src/qmgr/qmgr.c b/postfix/src/qmgr/qmgr.c index ab91a0fe4..9ecfa116b 100644 --- a/postfix/src/qmgr/qmgr.c +++ b/postfix/src/qmgr/qmgr.c @@ -515,5 +515,6 @@ int main(int argc, char **argv) MAIL_SERVER_POST_INIT, qmgr_post_init, MAIL_SERVER_LOOP, qmgr_loop, MAIL_SERVER_PRE_ACCEPT, pre_accept, + MAIL_SERVER_SOLITARY, 0); } diff --git a/postfix/src/qmgr/qmgr_entry.c b/postfix/src/qmgr/qmgr_entry.c index 1c0772dbe..57de8ebd6 100644 --- a/postfix/src/qmgr/qmgr_entry.c +++ b/postfix/src/qmgr/qmgr_entry.c @@ -229,7 +229,7 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_QUEUE *queue, QMGR_MESSAGE *message) * XXX This code does not detect the case that the active queue is being * starved because incoming mail is pounding the disk. */ - if (var_qmgr_clog_warn_time > 0) { + if (var_helpful_warnings && var_qmgr_clog_warn_time > 0) { int queue_length = queue->todo_refcount + queue->busy_refcount; time_t now; QMGR_TRANSPORT *transport; diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index 11872996d..69edaaafb 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -230,9 +230,18 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop, * With virtual, relay, or other non-local destinations, give the highest * precedence to delivery transport associated next-hop information. * + * XXX With the virtual mailbox transport, set the nexthop information to + * $myhostname, so that in default configurations the virtual delivery + * agent will not use separate queues for every $virtual_mailbox_domains + * domain name. That prevents anomalies where many low-traffic domains + * starve a high-traffic domain. + * * XXX Nag if the domain is listed in multiple domain lists. The effect is * implementation defined, and may break when internals change. */ +#define VIRT_ALIAS_TRANSPORT var_error_transport +#define VIRT_ALIAS_NEXTHOP "User unknown in virtual alias table" + dict_errno = 0; if (domain != 0) { tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL); @@ -242,12 +251,13 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop, *flags |= RESOLVE_FLAG_ERROR; if (virt_alias_doms && string_list_match(virt_alias_doms, STR(nexthop))) { - if (virt_mailbox_doms + if (var_helpful_warnings + && virt_mailbox_doms && string_list_match(virt_mailbox_doms, STR(nexthop))) msg_warn("do not list domain %s in BOTH %s and %s", STR(nexthop), VAR_VIRT_ALIAS_DOMS, VAR_VIRT_MAILBOX_DOMS); - vstring_strcpy(channel, var_error_transport); - vstring_strcpy(nexthop, "User unknown in virtual alias table"); + vstring_strcpy(channel, VIRT_ALIAS_TRANSPORT); + vstring_strcpy(nexthop, VIRT_ALIAS_NEXTHOP); blame = VAR_ERROR_TRANSPORT; *flags |= RESOLVE_CLASS_ALIAS; } else if (dict_errno != 0) { @@ -256,6 +266,7 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop, } else if (virt_mailbox_doms && string_list_match(virt_mailbox_doms, STR(nexthop))) { vstring_strcpy(channel, var_virt_transport); + vstring_strcpy(nexthop, var_myhostname); blame = VAR_VIRT_TRANSPORT; *flags |= RESOLVE_CLASS_VIRTUAL; } else if (dict_errno != 0) { @@ -275,28 +286,38 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop, blame = VAR_DEF_TRANSPORT; *flags |= RESOLVE_CLASS_DEFAULT; } - if (*var_relayhost) + if (*var_relayhost) { vstring_strcpy(nexthop, var_relayhost); + lowercase(STR(nexthop)); + } } - if ((destination = split_at(STR(channel), ':')) != 0 && *destination) + if ((destination = split_at(STR(channel), ':')) != 0 && *destination) { vstring_strcpy(nexthop, destination); + lowercase(STR(nexthop)); + } } /* * Local delivery. Set up the default local transport and the default * next-hop hostname (myself). * + * XXX Set the nexthop information to myhostname, so that the local delivery + * agent does not get a queue for every domain name in $mydestination or + * for every network address in $inet_interfaces. + * * XXX Nag if the domain is listed in multiple domain lists. The effect is * implementation defined, and may break when internals change. */ else { if ((rcpt_domain = strrchr(STR(nextrcpt), '@')) != 0) { rcpt_domain++; - if (virt_alias_doms + if (var_helpful_warnings + && virt_alias_doms && string_list_match(virt_alias_doms, rcpt_domain)) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_MYDEST, VAR_VIRT_ALIAS_DOMS); - if (virt_mailbox_doms + if (var_helpful_warnings + && virt_mailbox_doms && string_list_match(virt_mailbox_doms, rcpt_domain)) msg_warn("do not list domain %s in BOTH %s and %s", rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS); @@ -337,6 +358,20 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop, } } + /* + * Kludge for virtual alias domains. Their next-hop info is arbitrary + * text that must not be passed on to regular delivery agents. So, if the + * transport was changed, but the nexthop was not, copy over the local + * hostname instead. + */ +#define STREQ(x, y) (strcmp((x), (y)) == 0) + + if ((*flags & RESOLVE_FLAG_FAIL) == 0 + && (*flags & RESOLVE_CLASS_ALIAS) != 0 + && !STREQ(STR(channel), VIRT_ALIAS_TRANSPORT) + && STREQ(STR(nexthop), VIRT_ALIAS_NEXTHOP)) + vstring_strcpy(nexthop, var_myhostname); + /* * Bounce recipients that have moved, regardless of domain address class. * The downside of doing this here is that this table has no effect on @@ -345,13 +380,13 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop, */ #define IGNORE_ADDR_EXTENSION ((char **) 0) - if ((*flags & RESOLVE_FLAG_FAIL) == 0 && *var_relocated_maps != 0) { + if ((*flags & RESOLVE_FLAG_FAIL) == 0 && relocated_maps != 0) { const char *newloc; if ((newloc = mail_addr_find(relocated_maps, STR(nextrcpt), IGNORE_ADDR_EXTENSION)) != 0) { vstring_strcpy(channel, var_error_transport); - vstring_sprintf(nexthop, "user has moved to %s", newloc); + vstring_sprintf(nexthop, "User has moved to %s", newloc); } else if (dict_errno != 0) { msg_warn("%s lookup failure", VAR_RELOCATED_MAPS); *flags |= RESOLVE_FLAG_FAIL; diff --git a/postfix/src/trivial-rewrite/transport.c b/postfix/src/trivial-rewrite/transport.c index e67d9818c..d0c6211d0 100644 --- a/postfix/src/trivial-rewrite/transport.c +++ b/postfix/src/trivial-rewrite/transport.c @@ -75,6 +75,15 @@ static int transport_match_parent_style; static VSTRING *wildcard_channel; static VSTRING *wildcard_nexthop; +#define STR(x) vstring_str(x) + + /* + * Macro for consistent updates of the transport and nexthop results. + */ +#define UPDATE_IF_SPECIFIED(dst, src) do { \ + if ((src) && *(src)) vstring_strcpy((dst), (src)); \ + } while (0) + /* transport_init - pre-jail initialization */ void transport_init(void) @@ -84,14 +93,12 @@ void transport_init(void) transport_path = maps_create("transport", var_transport_maps, DICT_FLAG_LOCK); transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS); - } /* find_transport_entry - look up and parse transport table entry */ static int find_transport_entry(const char *key, int flags, - VSTRING *channel, VSTRING *nexthop, - const char *def_nexthop) + VSTRING *channel, VSTRING *nexthop) { char *saved_value; const char *host; @@ -115,27 +122,14 @@ static int find_transport_entry(const char *key, int flags, } /* - * Can't do transport:user@domain until we have a way to pass the - * recipient back to the application, and until we have verified that - * this does not open security holes via, for example, regexp maps. - * Nothing is supposed to trust a transport name, envelope recipient - * address or next-hop hostname, but to be on the safe side we probably - * should add some syntax sanity checks. + * Can't do transport:user@domain because the right-hand side can have + * arbitrary content (especially in the case of the error mailer). */ else { saved_value = mystrdup(value); - if ((host = split_at(saved_value, ':')) != 0 && *host != 0) { -#if 0 - if ((ratsign = strrchr(host, '@'))) { - vstring_strcpy(recipient, host); - vstring_strcpy(nexthop, ratsign + 1); - } else -#endif - vstring_strcpy(nexthop, host); - } else if (def_nexthop != 0) - vstring_strcpy(nexthop, def_nexthop); - if (*saved_value != 0) - vstring_strcpy(channel, saved_value); + host = split_at(saved_value, ':'); + UPDATE_IF_SPECIFIED(nexthop, host); + UPDATE_IF_SPECIFIED(channel, saved_value); myfree(saved_value); return (FOUND); } @@ -148,11 +142,21 @@ void transport_wildcard_init(void) VSTRING *channel = vstring_alloc(10); VSTRING *nexthop = vstring_alloc(10); + /* + * Technically, the wildcard lookup pattern is redundant. A static map + * (keys always match, result is fixed string) could achieve the same: + * + * transport_maps = hash:/etc/postfix/transport static:xxx:yyy + * + * But the user interface of such an approach would be less intuitive. We + * tolerate the continued existence of wildcard lookup patterns because + * of human interface considerations. + */ #define WILDCARD "*" #define FULL 0 #define PARTIAL DICT_FLAG_FIXED - if (find_transport_entry(WILDCARD, FULL, channel, nexthop, (char *) 0)) { + if (find_transport_entry(WILDCARD, FULL, channel, nexthop)) { wildcard_channel = channel; wildcard_nexthop = nexthop; if (msg_verbose) @@ -174,7 +178,6 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) const char *name; const char *next; int found; - const char *def_nexthop = 0; #define STREQ(x,y) (strcmp((x), (y)) == 0) #define DISCARD_EXTENSION ((char **) 0) @@ -193,7 +196,7 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) * string. Specify the FULL flag to include regexp maps in the query. */ if (STREQ(full_addr, var_xport_null_key)) { - if (find_transport_entry(full_addr, FULL, channel, nexthop, def_nexthop)) + if (find_transport_entry(full_addr, FULL, channel, nexthop)) RETURN_FREE(FOUND); RETURN_FREE(NOTFOUND); } @@ -205,9 +208,7 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) if ((ratsign = strrchr(full_addr, '@')) == 0 || ratsign[1] == 0) msg_panic("transport_lookup: bad address: \"%s\"", full_addr); - def_nexthop = ratsign + 1; - - if (find_transport_entry(full_addr, FULL, channel, nexthop, def_nexthop)) + if (find_transport_entry(full_addr, FULL, channel, nexthop)) RETURN_FREE(FOUND); /* @@ -217,8 +218,8 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) */ if ((stripped_addr = strip_addr(full_addr, DISCARD_EXTENSION, *var_rcpt_delim)) != 0) { - if (find_transport_entry(stripped_addr, PARTIAL, channel, nexthop, - def_nexthop)) { + if (find_transport_entry(stripped_addr, PARTIAL, + channel, nexthop)) { myfree(stripped_addr); RETURN_FREE(FOUND); } else { @@ -243,7 +244,7 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) * with regular expressions. */ for (found = 0, name = ratsign + 1; /* void */ ; name = next) { - if (find_transport_entry(name, PARTIAL, channel, nexthop, def_nexthop)) + if (find_transport_entry(name, PARTIAL, channel, nexthop)) RETURN_FREE(FOUND); if ((next = strchr(name + 1, '.')) == 0) break; @@ -255,10 +256,8 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) * Fall back to the wild-card entry. */ if (wildcard_channel) { - if (*vstring_str(wildcard_channel)) - vstring_strcpy(channel, vstring_str(wildcard_channel)); - if (*vstring_str(wildcard_nexthop)) - vstring_strcpy(nexthop, vstring_str(wildcard_nexthop)); + UPDATE_IF_SPECIFIED(channel, STR(wildcard_channel)); + UPDATE_IF_SPECIFIED(nexthop, STR(wildcard_nexthop)); RETURN_FREE(FOUND); }