From f42ce7db52f3c84fc7390a969ab758f0ab1d3aa1 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Tue, 13 Jan 2015 00:00:00 -0500 Subject: [PATCH] postfix-2.12-20150113-nonprod --- postfix/HISTORY | 33 ++++++++-- postfix/WISHLIST | 11 ---- postfix/src/bounce/bounce.c | 16 +++-- postfix/src/cleanup/cleanup_init.c | 3 +- postfix/src/cleanup/cleanup_masquerade.c | 3 +- postfix/src/flush/flush.c | 2 +- postfix/src/global/addr_match_list.c | 6 +- postfix/src/global/addr_match_list.h | 4 +- postfix/src/global/db_common.c | 3 +- postfix/src/global/debug_peer.c | 2 +- postfix/src/global/domain_list.c | 6 +- postfix/src/global/domain_list.h | 3 +- postfix/src/global/flush_clnt.c | 2 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/match_parent_style.c | 3 +- postfix/src/global/namadr_list.c | 5 +- postfix/src/global/namadr_list.h | 4 +- postfix/src/global/namadr_list.ref | 18 ++--- postfix/src/global/resolve_local.c | 3 +- postfix/src/global/resolve_local.ref | 2 +- postfix/src/global/server_acl.c | 10 +-- postfix/src/global/server_acl.ref | 2 +- postfix/src/global/string_list.c | 5 +- postfix/src/global/string_list.h | 3 +- postfix/src/global/user_acl.c | 9 ++- postfix/src/global/user_acl.h | 2 +- postfix/src/postdrop/postdrop.c | 3 +- postfix/src/postqueue/postqueue.c | 12 ++-- postfix/src/postscreen/postscreen.c | 6 +- postfix/src/qmqpd/qmqpd.c | 2 +- postfix/src/sendmail/sendmail.c | 6 +- postfix/src/smtp/smtp.c | 4 +- postfix/src/smtp/smtp_sasl_glue.c | 3 +- postfix/src/smtpd/smtpd.c | 21 ++++-- postfix/src/smtpd/smtpd_check.c | 39 ++++++----- postfix/src/smtpd/smtpd_error.ref | 6 +- postfix/src/trivial-rewrite/resolve.c | 8 ++- postfix/src/util/casefold.c | 51 ++++++++++----- postfix/src/util/casefold_test.in | 3 + postfix/src/util/casefold_test.ref | 83 +++++++++++++----------- postfix/src/util/dict_utf8.c | 8 +-- postfix/src/util/match_list.c | 83 ++++++++++++++++-------- postfix/src/util/match_list.h | 4 +- postfix/src/util/match_ops.c | 16 ++--- postfix/src/util/printable.c | 2 +- 45 files changed, 317 insertions(+), 205 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 6126f4ba9..f990bedc3 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -21348,11 +21348,34 @@ Apologies for any names omitted. 20150112 - Support for UTF-8 casefolding in match_lists. Instead of - using strcasecmp(), casefold all string constant patterns - during initialization, and casefold a search string at the - beginning of the search, and use strcmp() for comparison. - Files: util/casefold.c util/dict.h, util/dict_utf8.c, + Infrastructure: support for UTF-8 casefolding in match_lists. + Instead of using strcasecmp(), casefold all fixed-string + patterns during initialization, casefold a search string + at the beginning of the search, and use strcmp() for + comparison. Files: util/casefold.c util/dict.h, util/dict_utf8.c, util/match_list.c, util/match_list.h, util/match_ops.c, util/stringops.h, global/addr_match_list.c, global/domain_list.c, global/namadr_list.c, global/string_list.c. + +20150113 + + Cleanup: show the configuration parameter name in error + messages while parsing or searching match_list-based features + such as mydestination, relay_domains and a few dozen more. + Files: cleanup/cleanup_init.c, flush/flush.c, + global/addr_match_list.c, global/debug_peer.c, + global/domain_list.c, global/flush_clnt.c, + global/match_parent_style.c, global/namadr_list.c, + global/resolve_local.c, global/string_list.c, global/user_acl.[hc], + postdrop/postdrop.c, postqueue/postqueue.c, + postscreen/postscreen.c, qmqpd/qmqpd.c, sendmail/sendmail.c., + smtp/smtp.c, smtp/smtp_sasl_glue.c, smtpd/smtpd.c, + smtpd/smtpd_check.c, trivial-rewrite/resolve.c, + util/match_list.[hc], util/match_ops.c. + + Cleanup: apply printable() to all bounce(8) service + string-valued protocol fields. File: bounce/bounce.c. + + Apparenly the UCI 4.8 ucasemap_utf8FoldCase() function does + not complain about UTF-8 syntax errors, so we add our own + redundant check. File: util/casefold.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 26f80b1d1..b83e5f0f3 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -8,17 +8,6 @@ Wish list: Things to do after the stable release: - Add context argument for better match_list diagnostics. - - Expose UTF8 flag in server_acl API. Some applications such - as postscreen don't need UTF8 support. - - Expose UTF8 flag in match_list API. Some applications - such as address lists don't need UTF8 support. - - Implement UTF8 casefolding in match_list for non-table - patterns. - UTF8 DNS[BW]L domain name. Consolidate maps flags in mail_params.h instead of having diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index b33fefc4c..3b067cb61 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -319,7 +319,9 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } - printable(STR(dsn_envid), '?'); + VS_NEUTER(encoding); + VS_NEUTER(sender); + VS_NEUTER(dsn_envid); if (msg_verbose) msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x", myname, flags, service_name, STR(queue_name), STR(queue_id), @@ -380,10 +382,12 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client) msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } - printable(STR(dsn_envid), '?'); + VS_NEUTER(encoding); + VS_NEUTER(sender); + VS_NEUTER(dsn_envid); + VS_NEUTER(verp_delims); if (strlen(STR(verp_delims)) != 2) { - msg_warn("malformed verp delimiter string: %s", - printable(STR(verp_delims), '?')); + msg_warn("malformed verp delimiter string: %s", STR(verp_delims)); return (-1); } if (msg_verbose) @@ -460,7 +464,9 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } - printable(STR(dsn_envid), '?'); + VS_NEUTER(encoding); + VS_NEUTER(sender); + VS_NEUTER(dsn_envid); VS_NEUTER(rcpt_buf->address); VS_NEUTER(rcpt_buf->orig_addr); VS_NEUTER(rcpt_buf->dsn_orcpt); diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index f43f34f2c..cf9381518 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -379,7 +379,8 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv) maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK); if (*var_masq_exceptions) cleanup_masq_exceptions = - string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions); + string_list_init(VAR_MASQ_EXCEPTIONS, MATCH_FLAG_RETURN, + var_masq_exceptions); if (*var_masq_classes) cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table, var_masq_classes); diff --git a/postfix/src/cleanup/cleanup_masquerade.c b/postfix/src/cleanup/cleanup_masquerade.c index e81bc188c..58053c063 100644 --- a/postfix/src/cleanup/cleanup_masquerade.c +++ b/postfix/src/cleanup/cleanup_masquerade.c @@ -206,7 +206,8 @@ int main(int argc, char **argv) var_masq_exceptions = argv[1]; cleanup_masq_exceptions = - string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions); + string_list_init(VAR_MASQ_EXCEPTIONS, MATCH_FLAG_RETURN, + var_masq_exceptions); masq_domains = argv_split(argv[2], CHARS_COMMA_SP); addr = vstring_alloc(1); if (strchr(argv[3], '@') == 0) diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index 52603cb46..fccb61cd7 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -805,7 +805,7 @@ 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_RETURN + flush_domains = domain_list_init(VAR_FFLUSH_DOMAINS, MATCH_FLAG_RETURN | match_parent_style(VAR_FFLUSH_DOMAINS), var_fflush_domains); } diff --git a/postfix/src/global/addr_match_list.c b/postfix/src/global/addr_match_list.c index fdc95d012..de3d3f967 100644 --- a/postfix/src/global/addr_match_list.c +++ b/postfix/src/global/addr_match_list.c @@ -81,13 +81,14 @@ #ifdef TEST -#include #include #include #include +#include #include #include #include +#include #include /* util_utf8_enable */ static void usage(char *progname) @@ -116,7 +117,8 @@ int main(int argc, char **argv) usage(argv[0]); dict_allow_surrogate = 1; util_utf8_enable = 1; - list = addr_match_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]); + list = addr_match_list_init("command line", MATCH_FLAG_PARENT + | MATCH_FLAG_RETURN, argv[optind]); addr = argv[optind + 1]; if (strcmp(addr, "-") == 0) { VSTRING *buf = vstring_alloc(100); diff --git a/postfix/src/global/addr_match_list.h b/postfix/src/global/addr_match_list.h index 67c7e2316..f03c09d95 100644 --- a/postfix/src/global/addr_match_list.h +++ b/postfix/src/global/addr_match_list.h @@ -21,8 +21,8 @@ */ #define ADDR_MATCH_LIST MATCH_LIST -#define addr_match_list_init(f, p) \ - match_list_init((f), (p), 1, match_hostaddr) +#define addr_match_list_init(o, f, p) \ + match_list_init((o), (f), (p), 1, match_hostaddr) #define addr_match_list_match(l, a) \ match_list_match((l), (a)) #define addr_match_list_free match_list_free diff --git a/postfix/src/global/db_common.c b/postfix/src/global/db_common.c index 1e5a1d4ed..491a72690 100644 --- a/postfix/src/global/db_common.c +++ b/postfix/src/global/db_common.c @@ -256,7 +256,8 @@ void db_common_parse_domain(CFG_PARSER *parser, void *ctxPtr) domainlist = cfg_get_str(parser, "domain", "", 0, 0); if (*domainlist) { - ctx->domain = string_list_init(MATCH_FLAG_RETURN, domainlist); + ctx->domain = string_list_init(parser->name, MATCH_FLAG_RETURN, + domainlist); if (ctx->domain == 0) /* diff --git a/postfix/src/global/debug_peer.c b/postfix/src/global/debug_peer.c index 023e1ffda..06fcfc863 100644 --- a/postfix/src/global/debug_peer.c +++ b/postfix/src/global/debug_peer.c @@ -99,7 +99,7 @@ void debug_peer_init(void) */ if (*var_debug_peer_list) debug_peer_list = - namadr_list_init(MATCH_FLAG_RETURN + namadr_list_init(VAR_DEBUG_PEER_LIST, MATCH_FLAG_RETURN | match_parent_style(VAR_DEBUG_PEER_LIST), var_debug_peer_list); } diff --git a/postfix/src/global/domain_list.c b/postfix/src/global/domain_list.c index c64f4de38..2bcd38d2d 100644 --- a/postfix/src/global/domain_list.c +++ b/postfix/src/global/domain_list.c @@ -83,11 +83,12 @@ #ifdef TEST -#include #include #include +#include #include #include +#include #include /* util_utf8_enable */ static void usage(char *progname) @@ -116,7 +117,8 @@ int main(int argc, char **argv) usage(argv[0]); dict_allow_surrogate = 1; util_utf8_enable = 1; - list = domain_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]); + list = domain_list_init("command line", MATCH_FLAG_PARENT + | MATCH_FLAG_RETURN, argv[optind]); host = argv[optind + 1]; vstream_printf("%s: %s\n", host, domain_list_match(list, host) ? "YES" : list->error == 0 ? "NO" : "ERROR"); diff --git a/postfix/src/global/domain_list.h b/postfix/src/global/domain_list.h index 8612219d9..b0dfaec1f 100644 --- a/postfix/src/global/domain_list.h +++ b/postfix/src/global/domain_list.h @@ -21,7 +21,8 @@ */ #define DOMAIN_LIST MATCH_LIST -#define domain_list_init(f, p) match_list_init((f), (p), 1, match_hostname) +#define domain_list_init(o, f, p)\ + match_list_init((o), (f), (p), 1, match_hostname) #define domain_list_match match_list_match #define domain_list_free match_list_free diff --git a/postfix/src/global/flush_clnt.c b/postfix/src/global/flush_clnt.c index 07985dc20..7accaa98a 100644 --- a/postfix/src/global/flush_clnt.c +++ b/postfix/src/global/flush_clnt.c @@ -103,7 +103,7 @@ static DOMAIN_LIST *flush_domains; void flush_init(void) { - flush_domains = domain_list_init(MATCH_FLAG_RETURN + flush_domains = domain_list_init(VAR_FFLUSH_DOMAINS, MATCH_FLAG_RETURN | match_parent_style(VAR_FFLUSH_DOMAINS), var_fflush_domains); } diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index c97ed8e87..04eb716b0 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20150112" +#define MAIL_RELEASE_DATE "20150113" #define MAIL_VERSION_NUMBER "2.12" #ifdef SNAPSHOT diff --git a/postfix/src/global/match_parent_style.c b/postfix/src/global/match_parent_style.c index b07a4fdcd..c3c9db66f 100644 --- a/postfix/src/global/match_parent_style.c +++ b/postfix/src/global/match_parent_style.c @@ -60,7 +60,8 @@ int match_parent_style(const char *name) */ if (match_par_dom_list == 0) match_par_dom_list = - string_list_init(MATCH_FLAG_NONE, var_par_dom_match); + string_list_init(VAR_PAR_DOM_MATCH, MATCH_FLAG_NONE, + var_par_dom_match); /* * Look up the parent domain matching policy. diff --git a/postfix/src/global/namadr_list.c b/postfix/src/global/namadr_list.c index eebfa68db..1be7d54c9 100644 --- a/postfix/src/global/namadr_list.c +++ b/postfix/src/global/namadr_list.c @@ -89,9 +89,9 @@ #ifdef TEST -#include #include #include +#include #include #include #include @@ -124,7 +124,8 @@ int main(int argc, char **argv) usage(argv[0]); dict_allow_surrogate = 1; util_utf8_enable = 1; - list = namadr_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]); + list = namadr_list_init("command line", MATCH_FLAG_PARENT + | MATCH_FLAG_RETURN, argv[optind]); host = argv[optind + 1]; addr = argv[optind + 2]; vstream_printf("%s/%s: %s\n", host, addr, diff --git a/postfix/src/global/namadr_list.h b/postfix/src/global/namadr_list.h index b2322edf8..e327784a3 100644 --- a/postfix/src/global/namadr_list.h +++ b/postfix/src/global/namadr_list.h @@ -21,8 +21,8 @@ */ #define NAMADR_LIST MATCH_LIST -#define namadr_list_init(f, p) \ - match_list_init((f), (p), 2, match_hostname, match_hostaddr) +#define namadr_list_init(o, f, p) \ + match_list_init((o), (f), (p), 2, match_hostname, match_hostaddr) #define namadr_list_match match_list_match #define namadr_list_free match_list_free diff --git a/postfix/src/global/namadr_list.ref b/postfix/src/global/namadr_list.ref index b21fe54ea..7df05be91 100644 --- a/postfix/src/global/namadr_list.ref +++ b/postfix/src/global/namadr_list.ref @@ -2,18 +2,18 @@ dummy/168.100.189.2: YES dummy/168.100.189.2: NO dummy/168.100.189.3: YES dummy/168.100.189.16: NO -./namadr_list: warning: bad net/mask pattern: "168.100.189.0/98" +./namadr_list: warning: command line: bad net/mask pattern: "168.100.189.0/98" dummy/168.100.189.16: ERROR -./namadr_list: warning: bad net/mask pattern: "168.100.589.0/28" +./namadr_list: warning: command line: bad net/mask pattern: "168.100.589.0/28" dummy/168.100.189.16: ERROR dummy/168.100.989.16: NO ./namadr_list: error: unsupported dictionary type: 2001 ./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7 is unavailable. unsupported dictionary type: 2001 -./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7: table lookup problem +./namadr_list: warning: command line: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7: table lookup problem dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: ERROR dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO -./namadr_list: warning: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead +./namadr_list: warning: command line: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: ERROR dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: YES dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: NO @@ -32,10 +32,10 @@ foo/168.100.189.3: YES bar/168.100.189.3: NO baz/168.100.189.3: YES x.x.x/127.0.0.1: NO -./namadr_list: warning: bad net/mask pattern: "be/be" +./namadr_list: warning: command line: bad net/mask pattern: "be/be" x.x.x/127.0.0.1: ERROR x.x.x/127.0.0.1: NO -./namadr_list: warning: bad address pattern: "be:be" +./namadr_list: warning: command line: bad address pattern: "be:be" x.x.x/::1: ERROR foo/168.100.189.3: YES bar/168.100.189.3: NO @@ -43,11 +43,11 @@ foo/168.100.189.3: NO bar/168.100.189.3: NO foo/168.100.189.3: YES bar/168.100.189.3: NO -./namadr_list: warning: fail:1: table lookup problem +./namadr_list: warning: command line: fail:1: table lookup problem bar/168.100.189.3: ERROR -./namadr_list: warning: fail:1: table lookup problem +./namadr_list: warning: command line: fail:1: table lookup problem bar/168.100.189.3: ERROR ./namadr_list: error: open file /tmp/nosuchfile: No such file or directory ./namadr_list: warning: non-existent:/tmp/nosuchfile is unavailable. open file /tmp/nosuchfile: No such file or directory -./namadr_list: warning: non-existent:/tmp/nosuchfile: table lookup problem +./namadr_list: warning: command line: non-existent:/tmp/nosuchfile: table lookup problem bar/168.100.189.3: ERROR diff --git a/postfix/src/global/resolve_local.c b/postfix/src/global/resolve_local.c index 98d04b2a8..c6ef84808 100644 --- a/postfix/src/global/resolve_local.c +++ b/postfix/src/global/resolve_local.c @@ -69,7 +69,8 @@ void resolve_local_init(void) /* Allow on-the-fly update to make testing easier. */ if (resolve_local_list) string_list_free(resolve_local_list); - resolve_local_list = string_list_init(MATCH_FLAG_RETURN, var_mydest); + resolve_local_list = string_list_init(VAR_MYDEST, MATCH_FLAG_RETURN, + var_mydest); } /* resolve_local - match domain against list of local destinations */ diff --git a/postfix/src/global/resolve_local.ref b/postfix/src/global/resolve_local.ref index ce46b616f..e77146999 100644 --- a/postfix/src/global/resolve_local.ref +++ b/postfix/src/global/resolve_local.ref @@ -1,6 +1,6 @@ mydestination=example.com destination=example.com YES mydestination=example.net destination=example.com NO -unknown: warning: fail:1_resolve_local: table lookup problem +unknown: warning: mydestination: fail:1_resolve_local: table lookup problem mydestination=fail:1_resolve_local destination=example.com ERROR mydestination=fail:1_resolve_local destination=example.com.. NO mydestination=fail:1_resolve_local destination= NO diff --git a/postfix/src/global/server_acl.c b/postfix/src/global/server_acl.c index 2caf063c8..daa2c3ec2 100644 --- a/postfix/src/global/server_acl.c +++ b/postfix/src/global/server_acl.c @@ -102,12 +102,12 @@ void server_acl_pre_jail_init(const char *mynetworks, const char *origin) addr_match_list_free(server_acl_mynetworks_host); } server_acl_mynetworks = - addr_match_list_init(MATCH_FLAG_RETURN | match_parent_style(origin), - mynetworks); + addr_match_list_init(origin, MATCH_FLAG_RETURN + | match_parent_style(origin), mynetworks); if (warn_compat_break_mynetworks_style) server_acl_mynetworks_host = - addr_match_list_init(MATCH_FLAG_RETURN | match_parent_style(origin), - mynetworks_host()); + addr_match_list_init(origin, MATCH_FLAG_RETURN + | match_parent_style(origin), mynetworks_host()); } /* server_acl_parse - parse access list */ @@ -279,7 +279,7 @@ int main(void) } else if (STREQ(cmd, VAR_SERVER_ACL)) { UPDATE_VAR(var_server_acl, value); } else if (STREQ(cmd, "address")) { - server_acl_pre_jail_init(var_mynetworks, VAR_SERVER_ACL); + server_acl_pre_jail_init(var_mynetworks, VAR_MYNETWORKS); argv = server_acl_parse(var_server_acl, VAR_SERVER_ACL); ret = server_acl_eval(value, argv, VAR_SERVER_ACL); argv_free(argv); diff --git a/postfix/src/global/server_acl.ref b/postfix/src/global/server_acl.ref index 442fda128..b70f3c654 100644 --- a/postfix/src/global/server_acl.ref +++ b/postfix/src/global/server_acl.ref @@ -9,7 +9,7 @@ 168.100.189.3: permit > mynetworks=fail:1 > address=168.100.189.4 -unknown: warning: fail:1: table lookup problem +unknown: warning: mynetworks: fail:1: table lookup problem unknown: warning: server_acl: permit_mynetworks: mynetworks lookup error -- ignoring the remainder of this access list 168.100.189.4: error > server_acl=fail:1,reject diff --git a/postfix/src/global/string_list.c b/postfix/src/global/string_list.c index b5dda32e8..076556783 100644 --- a/postfix/src/global/string_list.c +++ b/postfix/src/global/string_list.c @@ -75,12 +75,13 @@ #ifdef TEST -#include #include #include +#include #include #include #include +#include #include /* util_utf8_enable */ static void usage(char *progname) @@ -109,7 +110,7 @@ int main(int argc, char **argv) usage(argv[0]); dict_allow_surrogate = 1; util_utf8_enable = 1; - list = string_list_init(MATCH_FLAG_RETURN, argv[optind]); + list = string_list_init("command line", MATCH_FLAG_RETURN, argv[optind]); string = argv[optind + 1]; vstream_printf("%s: %s\n", string, string_list_match(list, string) ? "YES" : list->error == 0 ? "NO" : "ERROR"); diff --git a/postfix/src/global/string_list.h b/postfix/src/global/string_list.h index 0a96bacfe..1079a7623 100644 --- a/postfix/src/global/string_list.h +++ b/postfix/src/global/string_list.h @@ -21,7 +21,8 @@ */ #define STRING_LIST MATCH_LIST -#define string_list_init(f, p) match_list_init((f), (p), 1, match_string) +#define string_list_init(o, f, p) \ + match_list_init((o), (f), (p), 1, match_string) #define string_list_match match_list_match #define string_list_free match_list_free diff --git a/postfix/src/global/user_acl.c b/postfix/src/global/user_acl.c index 9dd19c0f7..ecdde9f15 100644 --- a/postfix/src/global/user_acl.c +++ b/postfix/src/global/user_acl.c @@ -6,7 +6,8 @@ /* SYNOPSIS /* #include /* -/* const char *check_user_acl_byuid(acl, uid) +/* const char *check_user_acl_byuid(pname, acl, uid) +/* cobnst char *pname; /* const char *acl; /* uid_t uid; /* DESCRIPTION @@ -20,6 +21,8 @@ /* calls. /* /* Arguments: +/* .IP pname +/* The parameter name of the acl. /* .IP acl /* Authorized user name list suitable for input to string_list_init(3). /* .IP uid @@ -59,7 +62,7 @@ /* check_user_acl_byuid - check user authorization */ -const char *check_user_acl_byuid(char *acl, uid_t uid) +const char *check_user_acl_byuid(const char *pname, const char *acl, uid_t uid) { struct mypasswd *mypwd; STRING_LIST *list; @@ -101,7 +104,7 @@ const char *check_user_acl_byuid(char *acl, uid_t uid) name = mypwd->pw_name; } - list = string_list_init(MATCH_FLAG_NONE, acl); + list = string_list_init(pname, MATCH_FLAG_NONE, acl); if ((matched = string_list_match(list, name)) == 0) { if (!who) who = vstring_alloc(10); diff --git a/postfix/src/global/user_acl.h b/postfix/src/global/user_acl.h index 8a9afb2b7..4e36fbfcb 100644 --- a/postfix/src/global/user_acl.h +++ b/postfix/src/global/user_acl.h @@ -25,7 +25,7 @@ /* * External interface */ -extern const char *check_user_acl_byuid(char *, uid_t); +extern const char *check_user_acl_byuid(const char *, const char *, uid_t); /* AUTHOR(S) /* Wietse Venema diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 9c435fbf5..1a4096c7c 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -315,7 +315,8 @@ int main(int argc, char **argv) * or in the daemon process? */ mail_dict_init(); - if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0) + if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl, + uid)) != 0) msg_fatal("User %s(%ld) is not allowed to submit mail", errstr, (long) uid); diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index caa0e059b..c90285db7 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -270,7 +270,8 @@ static void show_queue(void) uid_t uid = getuid(); if (uid != 0 && uid != var_owner_uid - && (errstr = check_user_acl_byuid(var_showq_acl, uid)) != 0) + && (errstr = check_user_acl_byuid(VAR_SHOWQ_ACL, var_showq_acl, + uid)) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to view the mail queue", errstr, (long) uid); @@ -344,7 +345,8 @@ static void flush_queue(void) uid_t uid = getuid(); if (uid != 0 && uid != var_owner_uid - && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0) + && (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl, + uid)) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to flush the mail queue", errstr, (long) uid); @@ -370,7 +372,8 @@ static void flush_site(const char *site) uid_t uid = getuid(); if (uid != 0 && uid != var_owner_uid - && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0) + && (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl, + uid)) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to flush the mail queue", errstr, (long) uid); @@ -404,7 +407,8 @@ static void flush_file(const char *queue_id) uid_t uid = getuid(); if (uid != 0 && uid != var_owner_uid - && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0) + && (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl, + uid)) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to flush the mail queue", errstr, (long) uid); diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c index d7dbaaa94..e4bf8e486 100644 --- a/postfix/src/postscreen/postscreen.c +++ b/postfix/src/postscreen/postscreen.c @@ -852,7 +852,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv) psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL); /* Ignore smtpd_forbid_cmds lookup errors. Non-critical feature. */ if (*var_psc_forbid_cmds) - psc_forbid_cmds = string_list_init(MATCH_FLAG_RETURN, + psc_forbid_cmds = string_list_init(VAR_PSC_FORBID_CMDS, + MATCH_FLAG_RETURN, var_psc_forbid_cmds); if (*var_psc_dnsbl_reply) psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY, @@ -998,7 +999,8 @@ static void post_jail_init(char *unused_name, char **unused_argv) msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION, var_psc_barlf_action); /* Fail "closed" on error. */ - psc_wlist_if = addr_match_list_init(MATCH_FLAG_RETURN, var_psc_wlist_if); + psc_wlist_if = addr_match_list_init(VAR_PSC_WLIST_IF, MATCH_FLAG_RETURN, + var_psc_wlist_if); /* * Start the cache maintenance pseudo thread last. Early cleanup makes diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index d1864ab2d..2f1347187 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -785,7 +785,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv) { debug_peer_init(); qmqpd_clients = - namadr_list_init(MATCH_FLAG_RETURN + namadr_list_init(VAR_QMQPD_CLIENTS, MATCH_FLAG_RETURN | match_parent_style(VAR_QMQPD_CLIENTS), var_qmqpd_clients); } diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index f8ce7dfdb..4a91aa48e 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -646,7 +646,8 @@ static void enqueue(const int flags, const char *encoding, * Access control is enforced in the postdrop command. The code here * merely produces a more user-friendly interface. */ - if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0) + if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, + var_submit_acl, uid)) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to submit mail", errstr, (long) uid); @@ -1404,7 +1405,8 @@ int main(int argc, char **argv) msg_fatal_status(EX_USAGE, "stand-alone mode requires no recipient"); /* The actual enforcement happens in the postdrop command. */ - if ((errstr = check_user_acl_byuid(var_submit_acl, uid = getuid())) != 0) + if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl, + uid = getuid())) != 0) msg_fatal_status(EX_NOPERM, "User %s(%ld) is not allowed to submit mail", errstr, (long) uid); diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index 45961764c..c48735876 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -1186,7 +1186,9 @@ static void pre_init(char *unused_name, char **unused_argv) * Session cache domain list. */ if (*var_smtp_cache_dest) - smtp_cache_dest = string_list_init(MATCH_FLAG_RETURN, var_smtp_cache_dest); + smtp_cache_dest = string_list_init(VAR_SMTP_CACHE_DEST, + MATCH_FLAG_RETURN, + var_smtp_cache_dest); /* * EHLO keyword filter. diff --git a/postfix/src/smtp/smtp_sasl_glue.c b/postfix/src/smtp/smtp_sasl_glue.c index 09ef734c8..d2c1c3c59 100644 --- a/postfix/src/smtp/smtp_sasl_glue.c +++ b/postfix/src/smtp/smtp_sasl_glue.c @@ -246,7 +246,8 @@ void smtp_sasl_initialize(void) * Initialize optional supported mechanism matchlist */ if (*var_smtp_sasl_mechs) - smtp_sasl_mechs = string_list_init(MATCH_FLAG_NONE, + smtp_sasl_mechs = string_list_init(VAR_SMTP_SASL_MECHS, + MATCH_FLAG_NONE, var_smtp_sasl_mechs); /* diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index d9312f9dd..566bc3b2f 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -5246,12 +5246,18 @@ static void pre_jail_init(char *unused_name, char **unused_argv) * Initialize blacklist/etc. patterns before entering the chroot jail, in * case they specify a filename pattern. */ - smtpd_noop_cmds = string_list_init(MATCH_FLAG_RETURN, var_smtpd_noop_cmds); - smtpd_forbid_cmds = string_list_init(MATCH_FLAG_RETURN, var_smtpd_forbid_cmds); - verp_clients = namadr_list_init(MATCH_FLAG_RETURN, var_verp_clients); - xclient_hosts = namadr_list_init(MATCH_FLAG_RETURN, var_xclient_hosts); - xforward_hosts = namadr_list_init(MATCH_FLAG_RETURN, var_xforward_hosts); - hogger_list = namadr_list_init(MATCH_FLAG_RETURN + smtpd_noop_cmds = string_list_init(VAR_SMTPD_NOOP_CMDS, MATCH_FLAG_RETURN, + var_smtpd_noop_cmds); + smtpd_forbid_cmds = string_list_init(VAR_SMTPD_FORBID_CMDS, + MATCH_FLAG_RETURN, + var_smtpd_forbid_cmds); + verp_clients = namadr_list_init(VAR_VERP_CLIENTS, MATCH_FLAG_RETURN, + var_verp_clients); + xclient_hosts = namadr_list_init(VAR_XCLIENT_HOSTS, MATCH_FLAG_RETURN, + var_xclient_hosts); + xforward_hosts = namadr_list_init(VAR_XFORWARD_HOSTS, MATCH_FLAG_RETURN, + var_xforward_hosts); + hogger_list = namadr_list_init(VAR_SMTPD_HOGGERS, MATCH_FLAG_RETURN | match_parent_style(VAR_SMTPD_HOGGERS), var_smtpd_hoggers); @@ -5276,7 +5282,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv) if (*var_smtpd_sasl_exceptions_networks) sasl_exceptions_networks = - namadr_list_init(MATCH_FLAG_RETURN, + namadr_list_init(VAR_SMTPD_SASL_EXCEPTIONS_NETWORKS, + MATCH_FLAG_RETURN, var_smtpd_sasl_exceptions_networks); #else msg_warn("%s is true, but SASL support is not compiled in", diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 27de37bf2..5286ba86d 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -706,16 +706,17 @@ void smtpd_check_init(void) * Pre-open access control lists before going to jail. */ mynetworks_curr = - namadr_list_init(MATCH_FLAG_RETURN | match_parent_style(VAR_MYNETWORKS), - var_mynetworks); + namadr_list_init(VAR_MYNETWORKS, MATCH_FLAG_RETURN + | match_parent_style(VAR_MYNETWORKS), var_mynetworks); mynetworks_new = - namadr_list_init(MATCH_FLAG_RETURN | match_parent_style(VAR_MYNETWORKS), - mynetworks_host()); + namadr_list_init(VAR_MYNETWORKS, MATCH_FLAG_RETURN + | match_parent_style(VAR_MYNETWORKS), mynetworks_host()); relay_domains = - domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + domain_list_init(VAR_RELAY_DOMAINS, + match_parent_style(VAR_RELAY_DOMAINS), var_relay_domains); perm_mx_networks = - namadr_list_init(MATCH_FLAG_RETURN + namadr_list_init(VAR_PERM_MX_NETWORKS, MATCH_FLAG_RETURN | match_parent_style(VAR_PERM_MX_NETWORKS), var_perm_mx_networks); #ifdef USE_TLS @@ -747,8 +748,10 @@ void smtpd_check_init(void) | DICT_FLAG_UTF8_REQUEST); #ifdef TEST - virt_alias_doms = string_list_init(MATCH_FLAG_NONE, var_virt_alias_doms); - virt_mailbox_doms = string_list_init(MATCH_FLAG_NONE, var_virt_mailbox_doms); + virt_alias_doms = string_list_init(VAR_VIRT_ALIAS_DOMS, MATCH_FLAG_NONE, + var_virt_alias_doms); + virt_mailbox_doms = string_list_init(VAR_VIRT_MAILBOX_DOMS, MATCH_FLAG_NONE, + var_virt_mailbox_doms); #endif access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS); @@ -889,7 +892,8 @@ void smtpd_check_init(void) /* * Optional permit logging. */ - smtpd_acl_perm_log = string_list_init(MATCH_FLAG_RETURN, + smtpd_acl_perm_log = string_list_init(VAR_SMTPD_ACL_PERM_LOG, + MATCH_FLAG_RETURN, var_smtpd_acl_perm_log); } @@ -5975,9 +5979,9 @@ int main(int argc, char **argv) #define UPDATE_MAPS(ptr, var, val, lock) \ { if (ptr) maps_free(ptr); ptr = maps_create(var, val, lock); } -#define UPDATE_LIST(ptr, val) \ +#define UPDATE_LIST(ptr, var, val) \ { if (ptr) string_list_free(ptr); \ - ptr = string_list_init(MATCH_FLAG_NONE, val); } + ptr = string_list_init(var, MATCH_FLAG_NONE, val); } case 2: if (strcasecmp(args->argv[0], VAR_MYDEST) == 0) { @@ -5997,7 +6001,8 @@ int main(int argc, char **argv) } if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_DOMS) == 0) { UPDATE_STRING(var_virt_alias_doms, args->argv[1]); - UPDATE_LIST(virt_alias_doms, var_virt_alias_doms); + UPDATE_LIST(virt_alias_doms, VAR_VIRT_ALIAS_DOMS, + var_virt_alias_doms); smtpd_resolve_init(100); resp = 0; break; @@ -6012,7 +6017,8 @@ int main(int argc, char **argv) } if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_DOMS) == 0) { UPDATE_STRING(var_virt_mailbox_doms, args->argv[1]); - UPDATE_LIST(virt_mailbox_doms, var_virt_mailbox_doms); + UPDATE_LIST(virt_mailbox_doms, VAR_VIRT_MAILBOX_DOMS, + var_virt_mailbox_doms); smtpd_resolve_init(100); resp = 0; break; @@ -6053,7 +6059,7 @@ int main(int argc, char **argv) /* NOT: UPDATE_STRING */ namadr_list_free(mynetworks_curr); mynetworks_curr = - namadr_list_init(MATCH_FLAG_RETURN + namadr_list_init(VAR_MYNETWORKS, MATCH_FLAG_RETURN | match_parent_style(VAR_MYNETWORKS), args->argv[1]); smtpd_resolve_init(100); @@ -6064,7 +6070,8 @@ int main(int argc, char **argv) /* NOT: UPDATE_STRING */ domain_list_free(relay_domains); relay_domains = - domain_list_init(match_parent_style(VAR_RELAY_DOMAINS), + domain_list_init(VAR_RELAY_DOMAINS, + match_parent_style(VAR_RELAY_DOMAINS), args->argv[1]); smtpd_resolve_init(100); resp = 0; @@ -6074,7 +6081,7 @@ int main(int argc, char **argv) UPDATE_STRING(var_perm_mx_networks, args->argv[1]); domain_list_free(perm_mx_networks); perm_mx_networks = - namadr_list_init(MATCH_FLAG_RETURN + namadr_list_init(VAR_PERM_MX_NETWORKS, MATCH_FLAG_RETURN | match_parent_style(VAR_PERM_MX_NETWORKS), args->argv[1]); resp = 0; diff --git a/postfix/src/smtpd/smtpd_error.ref b/postfix/src/smtpd/smtpd_error.ref index 2316ac54a..0f2e2fac3 100644 --- a/postfix/src/smtpd/smtpd_error.ref +++ b/postfix/src/smtpd/smtpd_error.ref @@ -57,7 +57,7 @@ OK >>> recipient_restrictions permit_mynetworks OK >>> rcpt reject@dunno.domain -./smtpd_check: warning: fail:1_mynetworks: table lookup problem +./smtpd_check: warning: mynetworks: fail:1_mynetworks: table lookup problem ./smtpd_check: : reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 : Temporary lookup failure; from= to= proto=SMTP helo= 451 4.3.0 : Temporary lookup failure >>> # @@ -69,7 +69,7 @@ OK >>> # Expect REJECT (server configuration error) >>> # >>> rcpt reject@dunno.domain -./smtpd_check: warning: non-null host address bits in "168.100.189.1/27", perhaps you should use "168.100.189.0/27" instead +./smtpd_check: warning: mynetworks: non-null host address bits in "168.100.189.1/27", perhaps you should use "168.100.189.0/27" instead ./smtpd_check: : reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 : Temporary lookup failure; from= to= proto=SMTP helo= 451 4.3.0 : Temporary lookup failure >>> # @@ -119,7 +119,7 @@ OK >>> mydestination fail:1_mydestination OK >>> rcpt user@example.com -./smtpd_check: warning: fail:1_mydestination: table lookup problem +./smtpd_check: warning: mydestination: fail:1_mydestination: table lookup problem ./smtpd_check: : reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 : Temporary lookup failure; from=<> to= proto=SMTP helo= 451 4.3.0 : Temporary lookup failure >>> # diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index 5291b1216..f7c5a6a63 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -795,15 +795,17 @@ void resolve_init(void) if (*var_virt_alias_doms) virt_alias_doms = - string_list_init(MATCH_FLAG_RETURN, var_virt_alias_doms); + string_list_init(VAR_VIRT_ALIAS_DOMS, MATCH_FLAG_RETURN, + var_virt_alias_doms); if (*var_virt_mailbox_doms) virt_mailbox_doms = - string_list_init(MATCH_FLAG_RETURN, var_virt_mailbox_doms); + string_list_init(VAR_VIRT_MAILBOX_DOMS, MATCH_FLAG_RETURN, + var_virt_mailbox_doms); if (*var_relay_domains) relay_domains = - domain_list_init(MATCH_FLAG_RETURN + domain_list_init(VAR_RELAY_DOMAINS, MATCH_FLAG_RETURN | match_parent_style(VAR_RELAY_DOMAINS), var_relay_domains); diff --git a/postfix/src/util/casefold.c b/postfix/src/util/casefold.c index 99acf7572..072c14e3b 100644 --- a/postfix/src/util/casefold.c +++ b/postfix/src/util/casefold.c @@ -31,7 +31,8 @@ /* /* Arguments: /* .IP utf8_request -/* Perform UTF-8 case folding. +/* Boolean parameter that enables UTF-8 case folding. This is +/* ignored when compiled without EAI support. /* .IP src /* Null-terminated input string. /* .IP dest @@ -78,7 +79,7 @@ char *casefold(int utf8_req, VSTRING *dest, const char *src, #ifdef NO_EAI /* - * ASCII mode only + * ASCII mode only. */ vstring_strcpy(dest, src); return (lowercase(STR(dest))); @@ -93,13 +94,24 @@ char *casefold(int utf8_req, VSTRING *dest, const char *src, int n; /* - * All-ASCII input. + * All-ASCII input, or ASCII mode only. */ if (utf8_req == 0 || allascii(src)) { vstring_strcpy(dest, src); return (lowercase(STR(dest))); } + /* + * ICU 4.8 ucasemap_utf8FoldCase() does not complain about UTF-8 syntax + * errors. XXX Is this behavior guaranteed or accidental? We don't know, + * therefore must check it here. + */ + if (valid_utf8_string(src, strlen(src)) == 0) { + if (err) + *err = "malformed UTF-8 or invalid codepoint"; + return (0); + } + /* * One-time initialization. With ICU 4.8 this works while chrooted. */ @@ -130,7 +142,9 @@ char *casefold(int utf8_req, VSTRING *dest, const char *src, /* * Report the result. With ICU 4.8, there are no casefolding errors for * the entire RFC 3629 Unicode range (code points U+0000..U+10FFFF - * including surrogates). + * including surrogates), nor are there casefolding errors for bad UTF-8 + * input. XXX Is this behavior guaranteed or accidental? We don't know, + * therefore we have the UTF-8 syntax check (and range check) above. */ if (U_SUCCESS(error) == 0) { if (err) @@ -200,7 +214,7 @@ int main(int argc, char **argv) while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { bp = STR(buffer); - msg_info("> %s", bp); + vstream_printf("> %s\n", bp); cmd = mystrtok(&bp, CHARS_SPACE); if (cmd == 0 || *cmd == '#') continue; @@ -212,9 +226,9 @@ int main(int argc, char **argv) */ if (strcmp(cmd, "fold") == 0) { if ((conv_res = casefold(utf8_req, dest, bp, &fold_err)) != 0) - msg_info("\"%s\" ->fold \"%s\"", bp, conv_res); + vstream_printf("\"%s\" ->fold \"%s\"\n", bp, conv_res); else - msg_warn("cannot casefold \"%s\": %s", bp, fold_err); + vstream_printf("cannot casefold \"%s\": %s\n", bp, fold_err); } /* @@ -225,20 +239,20 @@ int main(int argc, char **argv) && first <= last) { for (codepoint = first; codepoint <= last; codepoint++) { if (codepoint >= 0xD800 && codepoint <= 0xDFFF) { - msg_warn("skipping surrogate range"); + vstream_printf("skipping surrogate range\n"); codepoint = 0xDFFF; } else { encode_utf8(buffer, codepoint); if (msg_verbose) - msg_info("U+%X -> %s", codepoint, STR(buffer)); + vstream_printf("U+%X -> %s\n", codepoint, STR(buffer)); if (valid_utf8_string(STR(buffer), LEN(buffer)) == 0) - msg_fatal("bad utf-8 encoding for U+%X", codepoint); + msg_fatal("bad utf-8 encoding for U+%X\n", codepoint); if (casefold(utf8_req, dest, STR(buffer), &fold_err) == 0) - msg_warn("casefold error for U+%X: %s", - codepoint, fold_err); + vstream_printf("casefold error for U+%X: %s\n", + codepoint, fold_err); } } - msg_info("range completed: 0x%x..0x%x", first, last); + vstream_printf("range completed: 0x%x..0x%x\n", first, last); } /* @@ -248,10 +262,10 @@ int main(int argc, char **argv) && sscanf(bp, "%255s", STR(buffer)) == 1) { if (geteuid() == 0) { if (chdir(STR(buffer)) < 0) - msg_fatal("chdir(%s): %m", STR(buffer)); + msg_fatal("chdir(%s): %m\n", STR(buffer)); if (chroot(STR(buffer)) < 0) - msg_fatal("chroot(%s): %m", STR(buffer)); - msg_info("chroot %s completed", STR(buffer)); + msg_fatal("chroot(%s): %m\n", STR(buffer)); + vstream_printf("chroot %s completed\n", STR(buffer)); } } @@ -267,9 +281,10 @@ int main(int argc, char **argv) * Usage */ else { - msg_info("Usage: %s chroot | fold | range | verbose ", - argv[0]); + vstream_printf("Usage: %s chroot | fold | range | verbose \n", + argv[0]); } + vstream_fflush(VSTREAM_OUT); } exit(0); } diff --git a/postfix/src/util/casefold_test.in b/postfix/src/util/casefold_test.in index f1a0098fd..9b50e22e2 100644 --- a/postfix/src/util/casefold_test.in +++ b/postfix/src/util/casefold_test.in @@ -17,3 +17,6 @@ fold HeLlO.ExAmPlE.CoM fold x。example.com fold x.example.com fold x。example.com +# Bad UTF-8 +fold yyy€€€ +fold €€€xxx diff --git a/postfix/src/util/casefold_test.ref b/postfix/src/util/casefold_test.ref index 18c6b6c54..00d6f8d1f 100644 --- a/postfix/src/util/casefold_test.ref +++ b/postfix/src/util/casefold_test.ref @@ -1,39 +1,44 @@ -./casefold: > # Ignored when not running as root. -./casefold: > chroot /tmp -./casefold: > # Casefold U+0000 .. U+10FFFF excluding surrogates. -./casefold: > range 0x0 0xD7FF -./casefold: range completed: 0x0..0xd7ff -./casefold: > range 0xD800 0xD800 -./casefold: warning: skipping surrogate range -./casefold: range completed: 0xd800..0xd800 -./casefold: > range 0xDFFF 0xDFFF -./casefold: warning: skipping surrogate range -./casefold: range completed: 0xdfff..0xdfff -./casefold: > range 0xE000 0x10FFFF -./casefold: range completed: 0xe000..0x10ffff -./casefold: > # Demonstrate that range is not a noop. -./casefold: > verbose 1 -./casefold: > range 0xE000 0xE007 -./casefold: U+E000 ->  -./casefold: U+E001 ->  -./casefold: U+E002 ->  -./casefold: U+E003 ->  -./casefold: U+E004 ->  -./casefold: U+E005 ->  -./casefold: U+E006 ->  -./casefold: U+E007 ->  -./casefold: range completed: 0xe000..0xe007 -./casefold: > verbose 0 -./casefold: > # Upper-case greek -> lower-case greek. -./casefold: > fold Δημοσθένους.example.com -./casefold: "Δημοσθένους.example.com" ->fold "δημοσθένουσ.example.com" -./casefold: > # Upper-case ASCII -> lower-case ASCII. -./casefold: > fold HeLlO.ExAmPlE.CoM -./casefold: "HeLlO.ExAmPlE.CoM" ->fold "hello.example.com" -./casefold: > # Folding does not change aliases for '.'. -./casefold: > fold x。example.com -./casefold: "x。example.com" ->fold "x。example.com" -./casefold: > fold x.example.com -./casefold: "x.example.com" ->fold "x.example.com" -./casefold: > fold x。example.com -./casefold: "x。example.com" ->fold "x。example.com" +> # Ignored when not running as root. +> chroot /tmp +> # Casefold U+0000 .. U+10FFFF excluding surrogates. +> range 0x0 0xD7FF +range completed: 0x0..0xd7ff +> range 0xD800 0xD800 +skipping surrogate range +range completed: 0xd800..0xd800 +> range 0xDFFF 0xDFFF +skipping surrogate range +range completed: 0xdfff..0xdfff +> range 0xE000 0x10FFFF +range completed: 0xe000..0x10ffff +> # Demonstrate that range is not a noop. +> verbose 1 +> range 0xE000 0xE007 +U+E000 ->  +U+E001 ->  +U+E002 ->  +U+E003 ->  +U+E004 ->  +U+E005 ->  +U+E006 ->  +U+E007 ->  +range completed: 0xe000..0xe007 +> verbose 0 +> # Upper-case greek -> lower-case greek. +> fold Δημοσθένους.example.com +"Δημοσθένους.example.com" ->fold "δημοσθένουσ.example.com" +> # Upper-case ASCII -> lower-case ASCII. +> fold HeLlO.ExAmPlE.CoM +"HeLlO.ExAmPlE.CoM" ->fold "hello.example.com" +> # Folding does not change aliases for '.'. +> fold x。example.com +"x。example.com" ->fold "x。example.com" +> fold x.example.com +"x.example.com" ->fold "x.example.com" +> fold x。example.com +"x。example.com" ->fold "x。example.com" +> # Bad UTF-8 +> fold yyy€€€ +cannot casefold "yyy€€€": malformed UTF-8 or invalid codepoint +> fold €€€xxx +cannot casefold "€€€xxx": malformed UTF-8 or invalid codepoint diff --git a/postfix/src/util/dict_utf8.c b/postfix/src/util/dict_utf8.c index 9a6c7b68d..17fe06131 100644 --- a/postfix/src/util/dict_utf8.c +++ b/postfix/src/util/dict_utf8.c @@ -8,7 +8,7 @@ /* /* DICT *dict_utf8_activate( /* DICT *dict) -/* +/* AUXILIARY FUNCTIONS /* char *dict_utf8_check_fold( /* DICT *dict, /* const char *string, @@ -29,9 +29,9 @@ /* paths in application code). Attempts to store non-UTF-8 /* keys or values are skipped while reporting a non-error /* status, attempts to look up or delete non-UTF-8 keys are -/* skipped while reporting a non-error status, and attempts -/* to look up a non-UTF-8 value are flagged while reporting a -/* configuration error. +/* skipped while reporting a non-error status, and lookup +/* results that contain a non-UTF-8 value are blocked while +/* reporting a configuration error. /* /* The dict_utf8_check* functions may be invoked to perform /* UTF-8 validity checks when util_utf8_enable is non-zero. diff --git a/postfix/src/util/match_list.c b/postfix/src/util/match_list.c index f0a3f90ab..36ee0902a 100644 --- a/postfix/src/util/match_list.c +++ b/postfix/src/util/match_list.c @@ -6,7 +6,8 @@ /* SYNOPSIS /* #include /* -/* MATCH_LIST *match_list_init(flags, pattern_list, count, func,...) +/* MATCH_LIST *match_list_init(pname, flags, pattern_list, count, func,...) +/* const char *pname; /* int flags; /* const char *pattern_list; /* int count; @@ -19,41 +20,59 @@ /* void match_list_free(list) /* MATCH_LIST *list; /* DESCRIPTION -/* This module implements a framework for tests for list membership. -/* The actual tests are done by user-supplied functions. With -/* util_utf8_enable non-zero, string comparison supports UTF-8. +/* This module implements a framework for tests for list +/* membership. The actual tests are done by user-supplied +/* functions. /* /* Patterns are separated by whitespace and/or commas. A pattern /* is either a string, a file name (in which case the contents /* of the file are substituted for the file name) or a type:name -/* lookup table specification. In order to reverse the result of -/* a pattern match, precede a pattern with an exclamation point (!). +/* lookup table specification. In order to reverse the result +/* of a pattern match, precede a pattern with an exclamation +/* point (!). /* -/* match_list_init() performs initializations. The flags argument -/* specifies the bit-wise OR of zero or more of the following: +/* match_list_init() performs initializations. When the global +/* util_utf8_enable variable is non-zero, and when the code +/* is compiled with EAI support, string comparison will use +/* caseless UTF-8 mode. Otherwise, only ASCII characters will +/* be casefolded. +/* +/* match_list_match() matches strings against the specified +/* pattern list, passing the first string to the first function +/* given to match_list_init(), the second string to the second +/* function, and so on. +/* +/* match_list_free() releases storage allocated by match_list_init(). +/* +/* Arguments: +/* .IP pname +/* Parameter name or other identiying information that is +/* prepended to error messages. +/* .IP flags +/* Specifies the bit-wise OR of zero or more of the following: /* .RS /* .IP MATCH_FLAG_PARENT -/* The hostname pattern foo.com matches any name within 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. +/* The hostname pattern foo.com matches any name within 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. /* .IP MATCH_FLAG_RETURN /* Request that match_list_match() logs a warning and returns /* zero (with list->error set to a non-zero dictionary error /* code) instead of raising a fatal run-time error. /* .RE /* Specify MATCH_FLAG_NONE to request none of the above. -/* The pattern_list argument specifies a list of patterns. The third -/* argument specifies how many match functions follow. -/* -/* match_list_match() matches strings against the specified pattern -/* list, passing the first string to the first function given to -/* match_list_init(), the second string to the second function, and -/* so on. -/* -/* match_list_free() releases storage allocated by match_list_init(). +/* .IP pattern_list +/* A list of patterns. +/* .IP count +/* Specifies how many match functions follow. +/* .IP list +/* Pattern list produced by match_list_init(). +/* .IP string +/* Search string. /* DIAGNOSTICS /* Fatal error: unable to open or read a match_list file; invalid -/* match_list pattern. +/* match_list pattern; casefold error (UTF-8 mode only). /* SEE ALSO /* host_match(3) match hosts by name or by address /* LICENSE @@ -110,9 +129,11 @@ static ARGV *match_list_parse(MATCH_LIST *match_list, ARGV *pat_list, const char *utf8_err; /* - * No DICT_FLAG_FOLD_FIX here, because we casefold the search string at - * the beginning of a search. String constant patterns are casefolded - * during match_list initialization. + * We do not use DICT_FLAG_FOLD_FIX, because we casefold the search + * string at the beginning of a search, and we use strcmp() for string + * comparison. This works because string patterns are casefolded during + * match_list initialization, and databases are supposed to fold case + * upon creation. */ #define OPEN_FLAGS O_RDONLY #define DICT_FLAGS (DICT_FLAG_LOCK | DICT_FLAG_UTF8_REQUEST) @@ -128,15 +149,17 @@ static ARGV *match_list_parse(MATCH_LIST *match_list, ARGV *pat_list, while ((start = mystrtokq(&bp, delim, CHARS_BRACE)) != 0) { if (*start == '#') { msg_warn("%s: comment at end of line is not supported: %s %s", - myname, start, bp); + match_list->pname, start, bp); break; } for (match = init_match, item = start; *item == '!'; item++) match = !match; if (*item == 0) - msg_fatal("%s: no pattern after '!'", myname); + /* No graceful degradation for this... */ + msg_fatal("%s: no pattern after '!'", match_list->pname); if (*item == '/') { /* /file/name */ if ((fp = vstream_fopen(item, O_RDONLY, 0)) == 0) { + /* Replace unusable pattern with pseudo table. */ vstring_sprintf(buf, "%s:%s", DICT_TYPE_NOFILE, item); if (dict_handle(STR(buf)) == 0) dict_register(STR(buf), @@ -164,11 +187,12 @@ static ARGV *match_list_parse(MATCH_LIST *match_list, ARGV *pat_list, if (casefold(util_utf8_enable, match_list->fold_buf, match ? item : STR(vstring_sprintf(buf, "!%s", item)), &utf8_err) == 0) { + /* Replace unusable pattern with pseudo table. */ vstring_sprintf(match_list->fold_buf, "%s:%s", DICT_TYPE_NOUTF8, item); if (dict_handle(STR(match_list->fold_buf)) == 0) dict_register(STR(match_list->fold_buf), - dict_surrogate(DICT_TYPE_NOFILE, item, + dict_surrogate(DICT_TYPE_NOUTF8, item, OPEN_FLAGS, DICT_FLAGS, "casefold error: %s", utf8_err)); @@ -182,7 +206,8 @@ static ARGV *match_list_parse(MATCH_LIST *match_list, ARGV *pat_list, /* match_list_init - initialize pattern list */ -MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,...) +MATCH_LIST *match_list_init(const char *pname, int flags, + const char *patterns, int match_count,...) { MATCH_LIST *list; char *saved_patterns; @@ -193,6 +218,7 @@ MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,... msg_panic("match_list_init: bad flags 0x%x", flags); list = (MATCH_LIST *) mymalloc(sizeof(*list)); + list->pname = mystrdup(pname); list->flags = flags; list->match_count = match_count; list->match_func = @@ -264,6 +290,7 @@ int match_list_match(MATCH_LIST *list,...) void match_list_free(MATCH_LIST *list) { /* XXX Should decrement map refcounts. */ + myfree(list->pname); argv_free(list->patterns); myfree((void *) list->match_func); myfree((void *) list->match_args); diff --git a/postfix/src/util/match_list.h b/postfix/src/util/match_list.h index c08475cd3..d8b779430 100644 --- a/postfix/src/util/match_list.h +++ b/postfix/src/util/match_list.h @@ -25,6 +25,7 @@ typedef struct MATCH_LIST MATCH_LIST; typedef int (*MATCH_LIST_FN) (MATCH_LIST *, const char *, const char *); struct MATCH_LIST { + char *pname; /* used in error messages */ int flags; /* processing options */ ARGV *patterns; /* one pattern each */ int match_count; /* match function/argument count */ @@ -39,7 +40,7 @@ struct MATCH_LIST { #define MATCH_FLAG_RETURN (1<<1) #define MATCH_FLAG_ALL (MATCH_FLAG_PARENT | MATCH_FLAG_RETURN) -extern MATCH_LIST *match_list_init(int, const char *, int,...); +extern MATCH_LIST *match_list_init(const char *, int, const char *, int,...); extern int match_list_match(MATCH_LIST *,...); extern void match_list_free(MATCH_LIST *); @@ -63,4 +64,3 @@ extern int match_hostaddr(MATCH_LIST *, const char *, const char *); /*--*/ #endif - diff --git a/postfix/src/util/match_ops.c b/postfix/src/util/match_ops.c index f49b13865..6542f4910 100644 --- a/postfix/src/util/match_ops.c +++ b/postfix/src/util/match_ops.c @@ -99,9 +99,9 @@ static int match_error(MATCH_LIST *list, const char *fmt,...) vstring_vsprintf(buf, fmt, ap); va_end(ap); if (list->flags & MATCH_FLAG_RETURN) { - msg_warn("%s", vstring_str(buf)); + msg_warn("%s: %s", list->pname, vstring_str(buf)); } else { - msg_fatal("%s", vstring_str(buf)); + msg_fatal("%s: %s", list->pname, vstring_str(buf)); } vstring_free(buf); return (0); @@ -115,7 +115,7 @@ int match_string(MATCH_LIST *list, const char *string, const char *pattern) DICT *dict; if (msg_verbose) - msg_info("%s: %s ~? %s", myname, string, pattern); + msg_info("%s: %s: %s ~? %s", myname, list->pname, string, pattern); /* * Try dictionary lookup: exact match. @@ -157,7 +157,7 @@ int match_hostname(MATCH_LIST *list, const char *name, const char *pattern) DICT *dict; if (msg_verbose) - msg_info("%s: %s ~? %s", myname, name, pattern); + msg_info("%s: %s: %s ~? %s", myname, list->pname, name, pattern); /* * Try dictionary lookup: exact match and parent domains. @@ -172,9 +172,9 @@ int match_hostname(MATCH_LIST *list, const char *name, const char *pattern) if (entry == name || (dict->flags & DICT_FLAG_FIXED)) { match = (dict_get(dict, entry) != 0); if (msg_verbose > 1) - msg_info("%s: lookup %s:%s %s: %s", - myname, dict->type, dict->name, entry, - match ? "found" : "notfound"); + msg_info("%s: %s: lookup %s:%s %s: %s", + myname, list->pname, dict->type, dict->name, + entry, match ? "found" : "notfound"); if (match != 0) break; if ((list->error = dict->error) != 0) @@ -227,7 +227,7 @@ int match_hostaddr(MATCH_LIST *list, const char *addr, const char *pattern) int rc; if (msg_verbose) - msg_info("%s: %s ~? %s", myname, addr, pattern); + msg_info("%s: %s: %s ~? %s", myname, list->pname, addr, pattern); #define V4_ADDR_STRING_CHARS "01234567890." #define V6_ADDR_STRING_CHARS V4_ADDR_STRING_CHARS "abcdefABCDEF:" diff --git a/postfix/src/util/printable.c b/postfix/src/util/printable.c index ff2ac63b3..a37ff6306 100644 --- a/postfix/src/util/printable.c +++ b/postfix/src/util/printable.c @@ -16,7 +16,7 @@ /* in its input with the given replacement. /* /* util_utf8_enable controls whether UTF8 is considered printable. -/* By default, non-ASCII text is replaced. +/* With util_utf8_enable equal to zero, non-ASCII text is replaced. /* /* Arguments: /* .IP buffer -- 2.47.3