diff --git a/postfix/HISTORY b/postfix/HISTORY index cd8ce6ed0..4f38f958a 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5600,7 +5600,7 @@ Apologies for any names omitted. Feature: configurable parent domain matching for domain and hostname/address match lists: either .domain or the - domain name itself. + domain name itself. Files: util/match_ops.c util/match_list.c Feature: added pretend-to-be-behind-PIX mode to the smtp-sink test program, in order to stress test some PIX bug workaround @@ -5620,6 +5620,11 @@ Apologies for any names omitted. 20011115 + Feature: mailbox_command_maps no longer requires that every + user has an entry. If the user does not have a command + entry, the local delivery agent tries the other delivery + methods instead. File: local/mailbox.c. + Bugfix: reset the smtpd command transaction log between non-deliveries. File: smtpd/smtpd.c. @@ -5629,6 +5634,31 @@ Apologies for any names omitted. and eliminated one missing reset (Victor Duchovny, Morgan Stanley). File: smtpd/smtpd.c. +20011118 + + Cleanup: replaced unnecessary wrapper code by macros. Files: + global/{string,domain,namadr}_list.[hc]. + +20011119 + + Feature: configurable parent domain matching strategy for + transport map lookups. File: trivial-rewrite/transport.c. + + New parent_domain_matches_subdomains parameter. This lists + all the Postfix features where a domain name matches itself + and all its subdomains (instead of requiring ".domain.name" + for subdomain matches). Planning for future backwards + compatibility :-) File: global/match_parent_style.c. + + Workaround: simplified the PIX "." bug to always + sleep for 10 seconds. File: smtp/smtp_proto.c. + +20011120 + + Workaround: disable attribute string length restriction so + that trivial-rewrite does not refuse to rewrite broken mail + headers. Files: util/attr_scan*.c. + Open problems: Medium: need in-process caching for map lookups. LDAP diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index d4fae5c2e..8e0bbc130 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,7 +1,31 @@ -Snapshot 20011103 introduces a negligible amount of features and -is all about revision of Postfix internals. With more than 70 pages -of context diffs compared to the previous snapshot, this release -is a baseline for upcoming feature changes. +Incompatible changes with snapshot-20011121 +=========================================== + +The internal protocols have changed again, so you must "postfix +reload" if upgrading from a previous release. The change is from +base64 encoded strings to null-terminated strings. + +Major changes with snapshot-20011121 +==================================== + +With host/domain name wildcard matching, the parent domain matching +behavior is now configurable (that is, does "sub.domain.name" match +the pattern "domain.name" or does it match the pattern ".domain.name"). +The new configuration parameter "parent_domain_matches_subdomains" +specifies what Postfix features use the "sub.domain.name matches +domain.name" approach. It is expected that eventually, all Postfix +features will use ".domain.name" subdomain matching. + +New "warn_if_reject" smtpd pseudo restriction that only warns if +a restriction would reject mail. + +Disgusting workaround for a well-known CISCO PIX firewall bug that +causes the .LF> at the end of mail to be lost. The workaround +has no effect for other mail deliveries. + +mailbox_command_maps allows you to configure the external delivery +command per user (local delivery agent only). This feature has +precedence over mailbox_command and home_mailbox settings. Major changes with snapshot-20011103 ==================================== diff --git a/postfix/src/flush/Makefile.in b/postfix/src/flush/Makefile.in index 31cf38158..835aea378 100644 --- a/postfix/src/flush/Makefile.in +++ b/postfix/src/flush/Makefile.in @@ -80,4 +80,5 @@ flush.o: ../../include/maps.h flush.o: ../../include/domain_list.h flush.o: ../../include/match_list.h flush.o: ../../include/match_ops.h +flush.o: ../../include/match_parent_style.h flush.o: ../../include/mail_server.h diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index 4f81dd302..ce8f95bd2 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -160,6 +160,7 @@ #include #include #include +#include /* Single server skeleton. */ @@ -636,7 +637,8 @@ static void flush_service(VSTREAM *client_stream, char *unused_service, static void pre_jail_init(char *unused_name, char **unused_argv) { - flush_domains = domain_list_init(MATCH_FLAG_PARENT, var_fflush_domains); + flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS), + var_fflush_domains); } /* main - pass control to the single-threaded skeleton */ diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 8bda43b3a..92773fe68 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -19,7 +19,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \ timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \ tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \ - verp_sender.c + verp_sender.c match_parent_style.c OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ debug_peer.o debug_process.o defer.o deliver_completed.o \ deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \ @@ -40,7 +40,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \ tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \ - verp_sender.o + verp_sender.o match_parent_style.o HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ config.h debug_peer.h debug_process.h defer.h deliver_completed.h \ deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \ @@ -56,7 +56,8 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ recipient_list.h record.h resolve_clnt.h resolve_local.h \ rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \ sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \ - mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h + mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \ + match_parent_style.h TESTSRC = rec2stream.c stream2rec.c recdump.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ @@ -321,6 +322,7 @@ debug_peer.o: namadr_list.h debug_peer.o: ../../include/match_list.h debug_peer.o: ../../include/match_ops.h debug_peer.o: debug_peer.h +debug_peer.o: match_parent_style.h debug_process.o: debug_process.c debug_process.o: ../../include/sys_defs.h debug_process.o: ../../include/msg.h @@ -723,6 +725,13 @@ mark_corrupt.o: ../../include/vbuf.h mark_corrupt.o: mail_queue.h mark_corrupt.o: ../../include/vstring.h mark_corrupt.o: mark_corrupt.h +match_parent_style.o: match_parent_style.c +match_parent_style.o: ../../include/sys_defs.h +match_parent_style.o: string_list.h +match_parent_style.o: ../../include/match_list.h +match_parent_style.o: ../../include/match_ops.h +match_parent_style.o: mail_params.h +match_parent_style.o: match_parent_style.h mbox_conf.o: mbox_conf.c mbox_conf.o: ../../include/sys_defs.h mbox_conf.o: ../../include/name_mask.h @@ -942,6 +951,7 @@ resolve_local.o: ../../include/match_ops.h resolve_local.o: mail_params.h resolve_local.o: own_inet_addr.h resolve_local.o: resolve_local.h +resolve_local.o: match_parent_style.h rewrite_clnt.o: rewrite_clnt.c rewrite_clnt.o: ../../include/sys_defs.h rewrite_clnt.o: ../../include/msg.h diff --git a/postfix/src/global/debug_peer.c b/postfix/src/global/debug_peer.c index 75280476b..c7096c973 100644 --- a/postfix/src/global/debug_peer.c +++ b/postfix/src/global/debug_peer.c @@ -69,6 +69,7 @@ #include #include #include +#include /* Application-specific. */ @@ -97,8 +98,9 @@ void debug_peer_init(void) * Finally. */ if (*var_debug_peer_list) - debug_peer_list = namadr_list_init(MATCH_FLAG_PARENT, - var_debug_peer_list); + debug_peer_list = + namadr_list_init(match_parent_style(VAR_DEBUG_PEER_LIST), + var_debug_peer_list); } /* debug_peer_check - see if this peer needs verbose logging */ diff --git a/postfix/src/global/domain_list.c b/postfix/src/global/domain_list.c index 10f3d2312..d4ea536b2 100644 --- a/postfix/src/global/domain_list.c +++ b/postfix/src/global/domain_list.c @@ -38,11 +38,8 @@ /* .RS /* .IP MATCH_FLAG_PARENT /* The hostname pattern foo.com matches itself and any name below -/* the domain foo.com. -/* .IP MATCH_FLAG_DOTPARENT -/* The hostname pattern foo.com matches itself only. -/* The hostname pattern .foo.com matches any name below the domain -/* foo.com. +/* the domain foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. /* The second argument is a list of domain patterns, or the name of @@ -112,7 +109,7 @@ main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = domain_list_init(argv[optind]); + list = domain_list_init(MATCH_FLAG_PARENT, argv[optind]); host = argv[optind + 1]; vstream_printf("%s: %s\n", host, domain_list_match(list, host) ? "YES" : "NO"); diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 98da1b2d7..803996ffc 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -64,6 +64,7 @@ /* char *var_mynetworks_style; /* char *var_verp_delims; /* char *var_verp_filter; +/* char *var_par_dom_match; /* /* char *var_import_environ; /* char *var_export_environ; @@ -187,6 +188,7 @@ char *var_mynetworks_style; char *var_verp_delims; char *var_verp_filter; int var_in_flow_delay; +char *var_par_dom_match; char *var_import_environ; char *var_export_environ; @@ -312,6 +314,7 @@ void mail_params_init() VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0, VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2, VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0, + VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0, 0, }; static CONFIG_STR_FN_TABLE function_str_defaults_2[] = { diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 89c8c7885..c65cee5ee 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1321,6 +1321,21 @@ extern bool var_verp_bounce_off; #define DEF_IN_FLOW_DELAY "1s" extern int var_in_flow_delay; + /* + * Backwards compatibility: foo.com matches itself and names below foo.com. + */ +#define VAR_PAR_DOM_MATCH "parent_domain_matches_subdomains" +#define DEF_PAR_DOM_MATCH VAR_DEBUG_PEER_LIST "," \ + VAR_FFLUSH_DOMAINS "," \ + VAR_MYNETWORKS "," \ + VAR_PERM_MX_NETWORKS "," \ + VAR_QMQPD_CLIENTS "," \ + VAR_RELAY_DOMAINS "," \ + SMTPD_ACCESS_MAPS +extern char *var_par_dom_match; + +#define SMTPD_ACCESS_MAPS "smtpd_access_maps" + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f9aa03559..ca13fbf0b 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20011118" +#define DEF_MAIL_VERSION "Snapshot-20011119" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/global/match_parent_style.c b/postfix/src/global/match_parent_style.c new file mode 100644 index 000000000..a914f616f --- /dev/null +++ b/postfix/src/global/match_parent_style.c @@ -0,0 +1,72 @@ +/*++ +/* NAME +/* match_parent_style 3 +/* SUMMARY +/* parent domain matching control +/* SYNOPSIS +/* #include +/* +/* int match_parent_style(name) +/* const char *name; +/* DESCRIPTION +/* This module queries configuration parameters for the policy that +/* controls how wild-card parent domain names are used by various +/* postfix lookup mechanisms. +/* +/* match_parent_style() looks up "name" in the +/* parent_domain_matches_subdomain configuration parameter +/* and returns either MATCH_FLAG_PARENT or MATCH_PARENT_NONE. +/* DIAGNOSTICS +/* Fatal error: out of memory, name listed under both parent wild card +/* matching policies. +/* SEE ALSO +/* string_list(3) plain string matching +/* domain_list(3) match host name patterns +/* namadr_list(3) match host name/address patterns +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include + +/* Utility library. */ + +/* Global library. */ + +#include +#include +#include + +/* Application-specific. */ + +static STRING_LIST *match_par_dom_list; + +int match_parent_style(const char *name) +{ + int result; + + /* + * Initialize on the fly. + */ + if (match_par_dom_list == 0) + match_par_dom_list = + string_list_init(MATCH_FLAG_NONE, var_par_dom_match); + + /* + * Look up the parent domain matching policy. + */ + if (string_list_match(match_par_dom_list, name)) + result = MATCH_FLAG_PARENT; + else + result = 0; + return (result); +} diff --git a/postfix/src/global/match_parent_style.h b/postfix/src/global/match_parent_style.h new file mode 100644 index 000000000..7b51eddf7 --- /dev/null +++ b/postfix/src/global/match_parent_style.h @@ -0,0 +1,35 @@ +#ifndef _MATCH_PARENT_STYLE_H_INCLUDED_ +#define _MATCH_PARENT_STYLE_H_INCLUDED_ + +/*++ +/* NAME +/* match_parent_style 3h +/* SUMMARY +/* parent domain matching control +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +extern int match_parent_style(const char *); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/global/namadr_list.c b/postfix/src/global/namadr_list.c index b527ba37d..c5169d87e 100644 --- a/postfix/src/global/namadr_list.c +++ b/postfix/src/global/namadr_list.c @@ -39,16 +39,13 @@ /* pattern. The matching process is case insensitive. /* /* namadr_list_init() performs initializations. The first -/* argument is the bit-wise OR of zero or mor of the +/* argument is the bit-wise OR of zero or more of the /* following: /* .RS /* .IP MATCH_FLAG_PARENT -/* The hostname pattern foo.com matches itself and any name below -/* the domain foo.com. -/* .IP MATCH_FLAG_DOTPARENT -/* The hostname pattern foo.com matches itself only. -/* The hostname pattern .foo.com matches any name below the domain -/* foo.com. +/* The hostname pattern foo.com matches itself and any name below +/* the domain foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. /* The second argument is a list of patterns, or the absolute @@ -109,22 +106,22 @@ main(int argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); while ((ch = GETOPT(argc, argv, "v")) > 0) { - switch (ch) { - case 'v': - msg_verbose++; - break; - default: - usage(argv[0]); - } + switch (ch) { + case 'v': + msg_verbose++; + break; + default: + usage(argv[0]); + } } if (argc != optind + 3) - usage(argv[0]); - list = namadr_list_init(argv[optind]); + usage(argv[0]); + list = namadr_list_init(MATCH_FLAG_PARENT, argv[optind]); host = argv[optind + 1]; addr = argv[optind + 2]; vstream_printf("%s/%s: %s\n", host, addr, - namadr_list_match(list, host, addr) ? - "YES" : "NO"); + namadr_list_match(list, host, addr) ? + "YES" : "NO"); vstream_fflush(VSTREAM_OUT); namadr_list_free(list); } diff --git a/postfix/src/global/resolve_local.c b/postfix/src/global/resolve_local.c index 66730c713..94a5a4dbf 100644 --- a/postfix/src/global/resolve_local.c +++ b/postfix/src/global/resolve_local.c @@ -58,6 +58,7 @@ #include #include #include +#include /* Application-specific */ diff --git a/postfix/src/global/string_list.c b/postfix/src/global/string_list.c index c2890faa2..522ff26a1 100644 --- a/postfix/src/global/string_list.c +++ b/postfix/src/global/string_list.c @@ -98,7 +98,7 @@ main(int argc, char **argv) } if (argc != optind + 2) usage(argv[0]); - list = string_list_init(argv[optind]); + list = string_list_init(MATCH_FLAG_NONE, argv[optind]); string = argv[optind + 1]; vstream_printf("%s: %s\n", string, string_list_match(list, string) ? "YES" : "NO"); diff --git a/postfix/src/qmqpd/Makefile.in b/postfix/src/qmqpd/Makefile.in index e03398ee1..5e923c5b0 100644 --- a/postfix/src/qmqpd/Makefile.in +++ b/postfix/src/qmqpd/Makefile.in @@ -92,6 +92,7 @@ qmqpd.o: ../../include/namadr_list.h qmqpd.o: ../../include/match_list.h qmqpd.o: ../../include/match_ops.h qmqpd.o: ../../include/quote_822_local.h +qmqpd.o: ../../include/match_parent_style.h qmqpd.o: ../../include/mail_server.h qmqpd.o: qmqpd.h qmqpd_peer.o: qmqpd_peer.c diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index e17eed0f1..cb23d5a16 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -135,6 +135,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -643,7 +644,9 @@ static void pre_accept(char *unused_name, char **unused_argv) static void pre_jail_init(char *unused_name, char **unused_argv) { debug_peer_init(); - qmqpd_clients = namadr_list_init(MATCH_FLAG_PARENT, var_qmqpd_clients); + qmqpd_clients = + namadr_list_init(match_parent_style(VAR_QMQPD_CLIENTS), + var_qmqpd_clients); } /* main - the main program */ diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 3267d5eae..3a8f4d1df 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -663,8 +663,7 @@ int smtp_xfer(SMTP_STATE *state) smtp_fputs("", 0, session->stream); if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0) { vstream_fflush(session->stream);/* hurts performance */ - sock_empty_wait(vstream_fileno(session->stream), - session->stream->timeout / 2); + sleep(10); /* not to mention this */ } if (vstream_ferror(state->src)) msg_fatal("queue file read error"); diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 57016b95c..f94336be3 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -189,6 +189,7 @@ smtpd_check.o: ../../include/own_inet_addr.h smtpd_check.o: ../../include/mail_conf.h smtpd_check.o: ../../include/maps.h smtpd_check.o: ../../include/mail_addr_find.h +smtpd_check.o: ../../include/match_parent_style.h smtpd_check.o: smtpd.h smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: smtpd_sasl_glue.h diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 83b213dd2..6bd641706 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -289,6 +289,7 @@ #include #include #include +#include /* Application-specific. */ @@ -339,6 +340,11 @@ static DOMAIN_LIST *relay_domains; static NAMADR_LIST *mynetworks; static NAMADR_LIST *perm_mx_networks; + /* + * How to do parent domain wildcard matching, if any. + */ +static int access_parent_style; + /* * Pre-parsed restriction lists. */ @@ -456,10 +462,9 @@ static int has_required(ARGV *restrictions, char **required) rest += 1; continue; } - for (reqd = required; *reqd; reqd++) { + for (reqd = required; *reqd; reqd++) if (strcmp(*rest, *reqd) == 0) return (1); - } if ((expansion = (ARGV *) htable_find(smtpd_rest_classes, *rest)) != 0) if (has_required(expansion, required)) return (1); @@ -486,8 +491,8 @@ static void fail_required(char *name, char **required) */ example = vstring_alloc(10); for (reqd = required; *reqd; reqd++) - vstring_sprintf_append(example, "%s%s", *reqd, - reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", "); + vstring_sprintf_append(example, "%s%s", *reqd, + reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", "); msg_fatal("parameter \"%s\": specify at least one working instance of: %s", name, STR(example)); } @@ -510,9 +515,15 @@ void smtpd_check_init(void) /* * Pre-open access control lists before going to jail. */ - mynetworks = namadr_list_init(MATCH_FLAG_PARENT, var_mynetworks); - relay_domains = domain_list_init(MATCH_FLAG_PARENT, var_relay_domains); - perm_mx_networks = namadr_list_init(MATCH_FLAG_PARENT, var_perm_mx_networks); + mynetworks = + namadr_list_init(match_parent_style(VAR_MYNETWORKS), + var_mynetworks); + relay_domains = + domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + var_relay_domains); + perm_mx_networks = + namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS), + var_perm_mx_networks); /* * Pre-parse and pre-open the recipient maps. @@ -530,6 +541,8 @@ void smtpd_check_init(void) relocated_maps = maps_create(VAR_RELOCATED_MAPS, var_relocated_maps, DICT_FLAG_LOCK); + access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS); + /* * error_text is used for returning error responses. */ @@ -1562,7 +1575,7 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, if ((dict = dict_handle(table)) == 0) msg_panic("%s: dictionary not found: %s", myname, table); - for (name = low_domain; /* void */ ; name = next + 1) { + for (name = low_domain; /* void */ ; name = next) { if (flags == 0 || (flags & dict->flags) != 0) { if ((value = dict_get(dict, name)) != 0) CHK_DOMAIN_RETURN(check_table_result(state, table, value, @@ -1571,8 +1584,10 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, if (dict_errno != 0) msg_fatal("%s: table lookup problem", table); } - if ((next = strchr(name, '.')) == 0) + if ((next = strchr(name + 1, '.')) == 0) break; + if (access_parent_style == MATCH_FLAG_PARENT) + next += 1; flags = PARTIAL; } CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED); @@ -2456,6 +2471,7 @@ char *var_virt_mailbox_maps; char *var_relocated_maps; char *var_local_rcpt_maps; char *var_perm_mx_networks; +char *var_par_dom_match; typedef struct { char *name; @@ -2477,7 +2493,8 @@ static STRING_TABLE string_table[] = { VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, - VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 0, 0, + VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, + VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, }; @@ -2815,13 +2832,17 @@ int main(int argc, char **argv) } if (strcasecmp(args->argv[0], "mynetworks") == 0) { namadr_list_free(mynetworks); - mynetworks = namadr_list_init(MATCH_FLAG_PARENT, args->argv[1]); + mynetworks = + namadr_list_init(match_parent_style(VAR_MYNETWORKS), + args->argv[1]); resp = 0; break; } if (strcasecmp(args->argv[0], "relay_domains") == 0) { domain_list_free(relay_domains); - relay_domains = domain_list_init(MATCH_FLAG_PARENT, args->argv[1]); + relay_domains = + domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + args->argv[1]); resp = 0; break; } diff --git a/postfix/src/trivial-rewrite/transport.c b/postfix/src/trivial-rewrite/transport.c index baf55f699..379e2395f 100644 --- a/postfix/src/trivial-rewrite/transport.c +++ b/postfix/src/trivial-rewrite/transport.c @@ -62,12 +62,14 @@ #include #include +#include /* Application-specific. */ #include "transport.h" static MAPS *transport_path; +static int transport_match_parent_style; /* transport_init - pre-jail initialization */ @@ -77,6 +79,7 @@ void transport_init(void) msg_panic("transport_init: repeated call"); transport_path = maps_create("transport", var_transport_maps, DICT_FLAG_LOCK); + transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS); } /* transport_lookup - map a transport domain */ @@ -85,6 +88,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop) { char *low_domain = lowercase(mystrdup(domain)); const char *name; + const char *next; const char *value; const char *host; char *saved_value; @@ -113,7 +117,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop) * Specify if a key is partial or full, to avoid matching partial keys with * regular expressions. */ - for (name = low_domain; name != 0; name = strchr(name + 1, '.')) { + for (name = low_domain; /* void */; name = next) { if ((value = maps_find(transport_path, name, maps_flag)) != 0) { saved_value = mystrdup(value); if ((host = split_at(saved_value, ':')) == 0 || *host == 0) @@ -132,6 +136,10 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop) } else if (dict_errno != 0) { msg_fatal("transport table lookup problem"); } + if ((next = strchr(name + 1, '.')) == 0) + break; + if (transport_match_parent_style == MATCH_FLAG_PARENT) + next++; maps_flag = PARTIAL; } myfree(low_domain); diff --git a/postfix/src/util/attr_print.c b/postfix/src/util/attr_print.c deleted file mode 100644 index fe38ea6fd..000000000 --- a/postfix/src/util/attr_print.c +++ /dev/null @@ -1,227 +0,0 @@ -/*++ -/* NAME -/* attr_print 3 -/* SUMMARY -/* send attributes over byte stream -/* SYNOPSIS -/* #include -/* -/* int attr_print(fp, flags, type, name, ...) -/* VSTREAM fp; -/* int flags; -/* int type; -/* char *name; -/* -/* int attr_vprint(fp, flags, ap) -/* VSTREAM fp; -/* int flags; -/* va_list ap; -/* DESCRIPTION -/* attr_print() takes zero or more (name, value) simple attributes -/* or (name, count, value) list attributes, and converts its input -/* to a byte stream that can be recovered with attr_scan(). The stream -/* is not flushed. -/* -/* attr_vprint() provides an alternate interface that is convenient -/* for calling from within variadoc functions. -/* -/* Attributes are sent in the requested order as specified with the -/* attr_print() argument list. This routine satisfies the formatting -/* rules as outlined in attr_scan(3). -/* -/* Arguments: -/* .IP fp -/* Stream to write the result to. -/* .IP flags -/* The bit-wise OR of zero or more of the following. -/* .RS -/* .IP ATTR_FLAG_MORE -/* After sending the requested attributes, leave the output stream in -/* a state that is usable for more attribute sending operations on -/* the same output attribute list. -/* By default, attr_print() automatically appends an attribute list -/* terminator when it has sent the last requested attribute. -/* .RE -/* .IP type -/* The type determines the arguments that follow. -/* .RS -/* .IP "ATTR_TYPE_NUM (char *, int)" -/* This argument is followed by an attribute name and an integer. -/* .IP "ATTR_TYPE_STR (char *, char *)" -/* This argument is followed by an attribute name and a null-terminated -/* string. -/* .IP "ATTR_TYPE_HASH (HTABLE *)" -/* The content of the hash table is sent as a sequence of string-valued -/* attributes with names equal to the hash table lookup key. -/* .IP ATTR_TYPE_END -/* This terminates the attribute list. -/* .RE -/* DIAGNOSTICS -/* The result value is 0 in case of success, VSTREAM_EOF in case -/* of trouble. -/* -/* Panic: interface violation. All system call errors are fatal. -/* SEE ALSO -/* attr_scan(3) recover attributes from byte stream -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System library. */ - -#include -#include - -/* Utility library. */ - -#include -#include -#include -#include -#include -#include - -#define STR(x) vstring_str(x) -#define LEN(x) VSTRING_LEN(x) - -/* attr_print_str - encode and send attribute information */ - -static void attr_print_str(VSTREAM *fp, const char *str, int len) -{ - static VSTRING *base64_buf; - - if (base64_buf == 0) - base64_buf = vstring_alloc(10); - - base64_encode(base64_buf, str, len); - vstream_fputs(STR(base64_buf), fp); -} - -static void attr_print_num(VSTREAM *fp, unsigned num) -{ - static VSTRING *plain; - - if (plain == 0) - plain = vstring_alloc(10); - - vstring_sprintf(plain, "%u", num); - attr_print_str(fp, STR(plain), LEN(plain)); -} - -/* attr_vprint - send attribute list to stream */ - -int attr_vprint(VSTREAM *fp, int flags, va_list ap) -{ - const char *myname = "attr_print"; - int attr_type; - char *attr_name; - unsigned int_val; - char *str_val; - HTABLE_INFO **ht_info_list; - HTABLE_INFO **ht; - - /* - * Sanity check. - */ - if (flags & ~ATTR_FLAG_ALL) - msg_panic("%s: bad flags: 0x%x", myname, flags); - - /* - * Iterate over all (type, name, value) triples, and produce output on - * the fly. - */ - while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { - switch (attr_type) { - case ATTR_TYPE_NUM: - attr_name = va_arg(ap, char *); - attr_print_str(fp, attr_name, strlen(attr_name)); - int_val = va_arg(ap, int); - VSTREAM_PUTC(':', fp); - attr_print_num(fp, (unsigned) int_val); - if (msg_verbose) - msg_info("send attr %s = %u", attr_name, int_val); - break; - case ATTR_TYPE_STR: - attr_name = va_arg(ap, char *); - attr_print_str(fp, attr_name, strlen(attr_name)); - str_val = va_arg(ap, char *); - VSTREAM_PUTC(':', fp); - attr_print_str(fp, str_val, strlen(str_val)); - if (msg_verbose) - msg_info("send attr %s = %s", attr_name, str_val); - break; - case ATTR_TYPE_HASH: - ht_info_list = htable_list(va_arg(ap, HTABLE *)); - for (ht = ht_info_list; *ht; ht++) { - attr_print_str(fp, ht[0]->key, strlen(ht[0]->key)); - VSTREAM_PUTC(':', fp); - attr_print_str(fp, ht[0]->value, strlen(ht[0]->value)); - if (msg_verbose) - msg_info("send attr name %s value %s", - ht[0]->key, ht[0]->value); - if (ht[1] != 0) - VSTREAM_PUTC('\n', fp); - } - myfree((char *) ht_info_list); - break; - default: - msg_panic("%s: unknown type code: %d", myname, attr_type); - } - VSTREAM_PUTC('\n', fp); - } - if ((flags & ATTR_FLAG_MORE) == 0) - VSTREAM_PUTC('\n', fp); - return (vstream_ferror(fp)); -} - -int attr_print(VSTREAM *fp, int flags,...) -{ - va_list ap; - int ret; - - va_start(ap, flags); - ret = attr_vprint(fp, flags, ap); - va_end(ap); - return (ret); -} - -#ifdef TEST - - /* - * Proof of concept test program. Mirror image of the attr_scan test - * program. - */ -#include - -int main(int unused_argc, char **argv) -{ - HTABLE *table = htable_create(1); - - msg_vstream_init(argv[0], VSTREAM_ERR); - msg_verbose = 1; - htable_enter(table, "foo-name", mystrdup("foo-value")); - htable_enter(table, "bar-name", mystrdup("bar-value")); - attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, - ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", - ATTR_TYPE_HASH, table, - ATTR_TYPE_END); - attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, - ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", - ATTR_TYPE_END); - if (vstream_fflush(VSTREAM_OUT) != 0) - msg_fatal("write error: %m"); - - htable_free(table, myfree); - return (0); -} - -#endif diff --git a/postfix/src/util/attr_scan.c b/postfix/src/util/attr_scan.c deleted file mode 100644 index afcf3c99c..000000000 --- a/postfix/src/util/attr_scan.c +++ /dev/null @@ -1,460 +0,0 @@ -/*++ -/* NAME -/* attr_scan 3 -/* SUMMARY -/* recover attributes from byte stream -/* SYNOPSIS -/* #include -/* -/* int attr_scan(fp, flags, type, name, ...) -/* VSTREAM fp; -/* int flags; -/* int type; -/* char *name; -/* -/* int attr_vscan(fp, flags, ap) -/* VSTREAM fp; -/* int flags; -/* va_list ap; -/* DESCRIPTION -/* attr_scan() takes zero or more (name, value) request attributes -/* and recovers the attribute values from the byte stream that was -/* possibly generated by attr_print(). -/* -/* attr_vscan() provides an alternative interface that is convenient -/* for calling from within a variadic function. -/* -/* The input stream is formatted as follows, where (item)* stands -/* for zero or more instances of the specified item, and where -/* (item1 | item2) stands for choice: -/* -/* .in +5 -/* attr-list :== simple-attr* newline -/* .br -/* simple-attr :== attr-name colon attr-value newline -/* .br -/* attr-name :== any base64 encoded string -/* .br -/* attr-value :== any base64 encoded string -/* .br -/* colon :== the ASCII colon character -/* .br -/* newline :== the ASCII newline character -/* .in -/* -/* All attribute names and attribute values are sent as base64-encoded -/* strings. Each base64 encoding must be no longer than 2*var_line_limit -/* characters. The formatting rules aim to make implementations in PERL -/* and other languages easy. -/* -/* Normally, attributes must be received in the sequence as specified with -/* the attr_scan() argument list. The input stream may contain additional -/* attributes at any point in the input stream, including additional -/* instances of requested attributes. -/* -/* Additional input attributes or input attribute instances are silently -/* skipped over, unless the ATTR_FLAG_EXTRA processing flag is specified -/* (see below). This allows for some flexibility in the evolution of -/* protocols while still providing the option of being strict where -/* this is desirable. -/* -/* Arguments: -/* .IP fp -/* Stream to recover the input attributes from. -/* .IP flags -/* The bit-wise OR of zero or more of the following. -/* .RS -/* .IP ATTR_FLAG_MISSING -/* Log a warning when the input attribute list terminates before all -/* requested attributes are recovered. It is always an error when the -/* input stream ends without the newline attribute list terminator. -/* .IP ATTR_FLAG_EXTRA -/* Log a warning and stop attribute recovery when the input stream -/* contains an attribute that was not requested. This includes the -/* case of additional instances of a requested attribute. -/* .IP ATTR_FLAG_MORE -/* After recovering the requested attributes, leave the input stream -/* in a state that is usable for more attr_scan() operations from the -/* same input attribute list. -/* By default, attr_scan() skips forward past the input attribute list -/* terminator. -/* .IP ATTR_FLAG_STRICT -/* For convenience, this value combines both ATTR_FLAG_MISSING and -/* ATTR_FLAG_EXTRA. -/* .IP ATTR_FLAG_NONE -/* For convenience, this value requests none of the above. -/* .RE -/* .IP type -/* The type argument determines the arguments that follow. -/* .RS -/* .IP "ATTR_TYPE_NUM (char *, int *)" -/* This argument is followed by an attribute name and an integer pointer. -/* .IP "ATTR_TYPE_STR (char *, VSTRING *)" -/* This argument is followed by an attribute name and a VSTRING pointer. -/* .IP "ATTR_TYPE_HASH (HTABLE *)" -/* All further input attributes are processed as string attributes. -/* No specific attribute sequence is enforced. -/* All attributes up to the attribute list terminator are read, -/* but only the first instance of each attribute is stored. -/* .sp -/* The attribute string values are stored in the hash table under -/* keys equal to the attribute name (obtained from the input stream). -/* Values from the input stream are added to the hash table. Existing -/* hash table entries are not replaced. -/* .sp -/* N.B. This construct must be followed by an ATTR_TYPE_END argument. -/* .IP ATTR_TYPE_END -/* This argument terminates the requested attribute list. -/* .RE -/* BUGS -/* ATTR_TYPE_HASH accepts attributes with arbitrary names from possibly -/* untrusted sources. This is unsafe, unless the resulting table is -/* queried only with known to be good attribute names. -/* DIAGNOSTICS -/* attr_scan() and attr_vscan() return -1 when malformed input is -/* detected (string too long, incomplete line, missing end marker). -/* Otherwise, the result value is the number of attributes that were -/* successfully recovered from the input stream (a hash table counts -/* as the number of entries stored into the table). -/* -/* Panic: interface violation. All system call errors are fatal. -/* SEE ALSO -/* attr_print(3) send attributes over byte stream. -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System library. */ - -#include -#include -#include - -/* Utility library. */ - -#include -#include -#include -#include -#include -#include -#include - -/* Application specific. */ - -#define STR(x) vstring_str(x) -#define LEN(x) VSTRING_LEN(x) - -/* attr_scan_string - pull a string from the input stream */ - -static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context) -{ - static VSTRING *base64_buf = 0; - extern int var_line_limit; /* XXX */ - int limit = var_line_limit * 2; - int ch; - - if (base64_buf == 0) - base64_buf = vstring_alloc(10); - - VSTRING_RESET(base64_buf); - while ((ch = VSTREAM_GETC(fp)) != ':' && ch != '\n') { - if (ch == VSTREAM_EOF) { - msg_warn("premature end-of-input from %s while reading %s", - VSTREAM_PATH(fp), context); - return (-1); - } - VSTRING_ADDCH(base64_buf, ch); - if (LEN(base64_buf) > limit) { - msg_warn("string length > %d characters from %s while reading %s", - limit, VSTREAM_PATH(fp), context); - return (-1); - } - } - VSTRING_TERMINATE(base64_buf); - if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) { - msg_warn("malformed base64 data from %s: %.100s", - VSTREAM_PATH(fp), STR(base64_buf)); - return (-1); - } - if (msg_verbose) - msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)"); - return (ch); -} - -/* attr_scan_number - pull a number from the input stream */ - -static int attr_scan_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf, - const char *context) -{ - char junk = 0; - int ch; - - if ((ch = attr_scan_string(fp, str_buf, context)) < 0) - return (-1); - if (sscanf(STR(str_buf), "%u%c", ptr, &junk) != 1 || junk != 0) { - msg_warn("malformed numerical data from %s while reading %s: %.100s", - VSTREAM_PATH(fp), context, STR(str_buf)); - return (-1); - } - return (ch); -} - -/* attr_vscan - receive attribute list from stream */ - -int attr_vscan(VSTREAM *fp, int flags, va_list ap) -{ - const char *myname = "attr_scan"; - static VSTRING *str_buf = 0; - static VSTRING *name_buf = 0; - int wanted_type = -1; - char *wanted_name; - unsigned int *number; - VSTRING *string; - HTABLE *hash_table; - int ch; - int conversions; - - /* - * Sanity check. - */ - if (flags & ~ATTR_FLAG_ALL) - msg_panic("%s: bad flags: 0x%x", myname, flags); - - /* - * Initialize. - */ - if (str_buf == 0) { - str_buf = vstring_alloc(10); - name_buf = vstring_alloc(10); - } - - /* - * Iterate over all (type, name, value) triples. - */ - for (conversions = 0; /* void */ ; conversions++) { - - /* - * Determine the next attribute type and attribute name on the - * caller's wish list. - * - * If we're reading into a hash table, we already know that the - * attribute value is string-valued, and we get the attribute name - * from the input stream instead. This is secure only when the - * resulting table is queried with known to be good attribute names. - */ - if (wanted_type != ATTR_TYPE_HASH) { - wanted_type = va_arg(ap, int); - if (wanted_type == ATTR_TYPE_END) { - if ((flags & ATTR_FLAG_MORE) != 0) - return (conversions); - wanted_name = "(list terminator)"; - } else if (wanted_type == ATTR_TYPE_HASH) { - wanted_name = "(any attribute name or list terminator)"; - hash_table = va_arg(ap, HTABLE *); - if (va_arg(ap, int) !=ATTR_TYPE_END) - msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END", - myname); - } else { - wanted_name = va_arg(ap, char *); - } - } - - /* - * Locate the next attribute of interest in the input stream. - */ - for (;;) { - - /* - * Get the name of the next attribute. Hitting EOF is always bad. - * Hitting the end-of-input early is OK if the caller is prepared - * to deal with missing inputs. - */ - if (msg_verbose) - msg_info("%s: wanted attribute: %s", - VSTREAM_PATH(fp), wanted_name); - if ((ch = attr_scan_string(fp, name_buf, - "input attribute name")) == VSTREAM_EOF) - return (-1); - if (ch == '\n' && LEN(name_buf) == 0) { - if (wanted_type == ATTR_TYPE_END - || wanted_type == ATTR_TYPE_HASH) - return (conversions); - if ((flags & ATTR_FLAG_MISSING) != 0) - msg_warn("missing attribute %s in input from %s", - wanted_name, VSTREAM_PATH(fp)); - return (conversions); - } - - /* - * See if the caller asks for this attribute. - */ - if (wanted_type == ATTR_TYPE_HASH - || (wanted_type != ATTR_TYPE_END - && strcmp(wanted_name, STR(name_buf)) == 0)) - break; - if ((flags & ATTR_FLAG_EXTRA) != 0) { - msg_warn("spurious attribute %s in input from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (conversions); - } - - /* - * Skip over this attribute. The caller does not ask for it. - */ - while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n') - /* void */ ; - } - - /* - * Do the requested conversion. If the target attribute is a - * non-array type, disallow sending a multi-valued attribute, and - * disallow sending no value. If the target attribute is an array - * type, allow the sender to send a zero-element array (i.e. no value - * at all). XXX Need to impose a bound on the number of array - * elements. - */ - switch (wanted_type) { - case ATTR_TYPE_NUM: - if (ch != ':') { - msg_warn("missing value for number attribute %s from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (-1); - } - number = va_arg(ap, unsigned int *); - if ((ch = attr_scan_number(fp, number, str_buf, - "input attribute value")) < 0) - return (-1); - if (ch != '\n') { - msg_warn("multiple values for attribute %s from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (-1); - } - break; - case ATTR_TYPE_STR: - if (ch != ':') { - msg_warn("missing value for string attribute %s from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (-1); - } - string = va_arg(ap, VSTRING *); - if ((ch = attr_scan_string(fp, string, - "input attribute value")) < 0) - return (-1); - if (ch != '\n') { - msg_warn("multiple values for attribute %s from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (-1); - } - break; - case ATTR_TYPE_HASH: - if (ch != ':') { - msg_warn("missing value for string attribute %s from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (-1); - } - if ((ch = attr_scan_string(fp, str_buf, - "input attribute value")) < 0) - return (-1); - if (ch != '\n') { - msg_warn("multiple values for attribute %s from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (-1); - } - if (htable_locate(hash_table, STR(name_buf)) != 0) { - if ((flags & ATTR_FLAG_EXTRA) != 0) { - msg_warn("duplicate attribute %s in input from %s", - STR(name_buf), VSTREAM_PATH(fp)); - return (conversions); - } - } else { - htable_enter(hash_table, STR(name_buf), - mystrdup(STR(str_buf))); - } - break; - default: - msg_panic("%s: unknown type code: %d", myname, wanted_type); - } - } -} - -/* attr_scan - read attribute list from stream */ - -int attr_scan(VSTREAM *fp, int flags,...) -{ - va_list ap; - int ret; - - va_start(ap, flags); - ret = attr_vscan(fp, flags, ap); - va_end(ap); - return (ret); -} - -#ifdef TEST - - /* - * Proof of concept test program. Mirror image of the attr_scan test - * program. - */ -#include - -int var_line_limit = 2048; - -int main(int unused_argc, char **used_argv) -{ - VSTRING *str_val = vstring_alloc(1); - HTABLE *table = htable_create(1); - HTABLE_INFO **ht_info_list; - HTABLE_INFO **ht; - int int_val; - int ret; - - msg_verbose = 1; - msg_vstream_init(used_argv[0], VSTREAM_ERR); - if ((ret = attr_scan(VSTREAM_IN, - ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, - ATTR_TYPE_STR, ATTR_NAME_STR, str_val, - ATTR_TYPE_HASH, table, - ATTR_TYPE_END)) > 2) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); - vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); - ht_info_list = htable_list(table); - for (ht = ht_info_list; *ht; ht++) - vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value); - myfree((char *) ht_info_list); - } else { - vstream_printf("return: %d\n", ret); - } - if ((ret = attr_scan(VSTREAM_IN, - ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, - ATTR_TYPE_STR, ATTR_NAME_STR, str_val, - ATTR_TYPE_END)) == 2) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); - vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); - ht_info_list = htable_list(table); - for (ht = ht_info_list; *ht; ht++) - vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value); - myfree((char *) ht_info_list); - } else { - vstream_printf("return: %d\n", ret); - } - if (vstream_fflush(VSTREAM_OUT) != 0) - msg_fatal("write error: %m"); - - vstring_free(str_val); - htable_free(table, myfree); - - return (0); -} - -#endif diff --git a/postfix/src/util/attr_scan0.c b/postfix/src/util/attr_scan0.c index 85bab44b5..e788f0c05 100644 --- a/postfix/src/util/attr_scan0.c +++ b/postfix/src/util/attr_scan0.c @@ -157,7 +157,7 @@ static int attr_scan0_string(VSTREAM *fp, VSTRING *plain_buf, const char *contex int limit = var_line_limit * 2; int ch; - if ((ch = vstring_get_null_bound(plain_buf, fp, limit)) == VSTREAM_EOF) { + if ((ch = vstring_get_null(plain_buf, fp)) == VSTREAM_EOF) { msg_warn("premature end-of-input from %s while reading %s", VSTREAM_PATH(fp), context); return (-1); diff --git a/postfix/src/util/attr_scan64.c b/postfix/src/util/attr_scan64.c index 8ad10847b..ea30f4a2a 100644 --- a/postfix/src/util/attr_scan64.c +++ b/postfix/src/util/attr_scan64.c @@ -172,11 +172,13 @@ static int attr_scan64_string(VSTREAM *fp, VSTRING *plain_buf, const char *conte return (-1); } VSTRING_ADDCH(base64_buf, ch); +#if 0 if (LEN(base64_buf) > limit) { msg_warn("string length > %d characters from %s while reading %s", limit, VSTREAM_PATH(fp), context); return (-1); } +#endif } VSTRING_TERMINATE(base64_buf); if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) { diff --git a/postfix/src/util/inet_trigger.c b/postfix/src/util/inet_trigger.c index 980c22df1..dddbcb62a 100644 --- a/postfix/src/util/inet_trigger.c +++ b/postfix/src/util/inet_trigger.c @@ -107,6 +107,7 @@ int inet_trigger(const char *service, const char *buf, int len, int timeout) msg_warn("%s: connect to %s: %m", myname, service); return (-1); } + close_on_exec(fd, CLOSE_ON_EXEC); ip = (struct inet_trigger *) mymalloc(sizeof(*ip)); ip->fd = fd; ip->service = mystrdup(service); diff --git a/postfix/src/util/make_dirs.c b/postfix/src/util/make_dirs.c index 31efea03e..ad1b451de 100644 --- a/postfix/src/util/make_dirs.c +++ b/postfix/src/util/make_dirs.c @@ -54,7 +54,7 @@ int make_dirs(const char *path, int perms) int saved_ch; struct stat st; int ret; - mode_t saved_mode; + mode_t saved_mode = 0; /* * Initialize. Make a copy of the path that we can safely clobber. diff --git a/postfix/src/util/match_list.c b/postfix/src/util/match_list.c index 993dc324f..3d9e71c3f 100644 --- a/postfix/src/util/match_list.c +++ b/postfix/src/util/match_list.c @@ -34,10 +34,8 @@ /* .RS /* .IP MATCH_FLAG_PARENT /* The hostname pattern foo.com matches any name within the domain -/* foo.com. -/* .IP MATCH_FLAG_DOTPARENT -/* The hostname pattern .foo.com matches any name under foo.com. -/* The pattern foo.com matches itself only. +/* foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. /* The pattern_list argument specifies a list of patterns. The third diff --git a/postfix/src/util/match_ops.c b/postfix/src/util/match_ops.c index 4f018d2cb..1bde84abd 100644 --- a/postfix/src/util/match_ops.c +++ b/postfix/src/util/match_ops.c @@ -34,10 +34,9 @@ /* of the named host. The flags argument specifies the bit-wise OR /* of zero or more of the following: /* .IP MATCH_FLAG_PARENT -/* The pattern foo.com matches any name within the domain foo.com. -/* .IP MATCH_FLAG_DOTPARENT -/* The pattern .foo.com matches any name under foo.com. The pattern -/* foo.com matches itself only. +/* The hostname pattern foo.com matches itself and any name below +/* the domain foo.com. If this flag is cleared, foo.com matches itself +/* only, and .foo.com matches any name below the domain foo.com. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. /* @@ -140,25 +139,15 @@ int match_hostname(int flags, const char *name, const char *pattern) if (strchr(pattern, ':') != 0) { temp = lowercase(mystrdup(name)); match = 0; - if (flags & MATCH_FLAG_PARENT) { - for (entry = temp; /* void */ ; entry = next + 1) { - if ((match = (dict_lookup(pattern, entry) != 0)) != 0) - break; - if (dict_errno != 0) - msg_fatal("%s: table lookup problem", pattern); - if ((next = strchr(entry, '.')) == 0) - break; - } - } - if (flags & MATCH_FLAG_DOTPARENT) { - for (entry = temp; /* void */ ; entry = next) { - if ((match = (dict_lookup(pattern, entry) != 0)) != 0) - break; - if (dict_errno != 0) - msg_fatal("%s: table lookup problem", pattern); - if ((next = strchr(entry, '.')) == 0) - break; - } + for (entry = temp; /* void */ ; entry = next) { + if ((match = (dict_lookup(pattern, entry) != 0)) != 0) + break; + if (dict_errno != 0) + msg_fatal("%s: table lookup problem", pattern); + if ((next = strchr(entry + 1, '.')) == 0) + break; + if (flags & MATCH_FLAG_PARENT) + next += 1; } myfree(temp); return (match); @@ -179,10 +168,9 @@ int match_hostname(int flags, const char *name, const char *pattern) pd = name + strlen(name) - strlen(pattern); if (pd > name && pd[-1] == '.' && strcasecmp(pd, pattern) == 0) return (1); - } - if (flags & MATCH_FLAG_DOTPARENT) { + } else if (pattern[0] == '.') { pd = name + strlen(name) - strlen(pattern); - if (pd > name && pd[-1] == '.' && strcasecmp(pd - 1, pattern) == 0) + if (pd > name && strcasecmp(pd, pattern) == 0) return (1); } } diff --git a/postfix/src/util/match_ops.h b/postfix/src/util/match_ops.h index 9a66c74ef..e147f7b50 100644 --- a/postfix/src/util/match_ops.h +++ b/postfix/src/util/match_ops.h @@ -15,8 +15,7 @@ #define MATCH_FLAG_NONE 0 #define MATCH_FLAG_PARENT (1<<0) -#define MATCH_FLAG_DOTPARENT (1<<1) -#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT|MATCH_FLAG_DOTPARENT) +#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT) extern int match_string(int, const char *, const char *); extern int match_hostname(int, const char *, const char *); diff --git a/postfix/src/util/stream_trigger.c b/postfix/src/util/stream_trigger.c index 31b4dae0a..9cb57e513 100644 --- a/postfix/src/util/stream_trigger.c +++ b/postfix/src/util/stream_trigger.c @@ -103,6 +103,7 @@ int stream_trigger(const char *service, const char *buf, int len, int timeou msg_warn("%s: connect to %s: %m", myname, service); return (-1); } + close_on_exec(fd, CLOSE_ON_EXEC); /* * Stash away context. diff --git a/postfix/src/util/unix_trigger.c b/postfix/src/util/unix_trigger.c index d4a341d75..6a3b19160 100644 --- a/postfix/src/util/unix_trigger.c +++ b/postfix/src/util/unix_trigger.c @@ -104,6 +104,7 @@ int unix_trigger(const char *service, const char *buf, int len, int timeout) msg_warn("%s: connect to %s: %m", myname, service); return (-1); } + close_on_exec(fd, CLOSE_ON_EXEC); /* * Stash away context.