From: Wietse Venema Date: Thu, 9 May 2002 05:00:00 +0000 (-0500) Subject: postfix-1.1.9-20020509 X-Git-Tag: v2.0.0~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78a1cda2a79497559ac34c9aae8c3de08115b42e;p=thirdparty%2Fpostfix.git postfix-1.1.9-20020509 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 1e41483b4..6f3bce6f1 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -6353,9 +6353,10 @@ Apologies for any names omitted. 20020508 - Bugfix: close an obscure source routing relaying loophole - involving postfix-style virtual domains. Problem reported - by Victor Duchovny. File: smtpd/smtpd_check.c. + Bugfix: close user@domain@postfix-style.virtual.domain + source routing relaying loophole involving postfix-style + virtual domains with @virtual.domain catch-all patterns. + Problem reported by Victor Duchovny. File: smtpd/smtpd_check.c. Bugfix: mail_addr_map() used the "wrong" @ character in addresses with multiple @. Victor Duchovny. File: @@ -6367,8 +6368,31 @@ Apologies for any names omitted. not even in SMTP commands. Files: global/quote_82[12]_local.c and clients. +20020509 + + Safety: don't allow an OK access rule lookup result for + user@domain@postfix-style.virtual.domain. Suggested by + Victor Duchovny, Morgan Stanley. File: smtpd/smtpd_check.c. + + Bugfix: quote unquoted address localparts that need quoting. + Files: global/tok822_parse.c, global/quote_82[12]_local.c. + + Documentation: simplified the advanced content filtering + example, and included a more advanced example for those + who want to squeeze out more performance without running + multiple Postfix instances. Text by Victor Duchovny, Morgan + Stanley. File: README_FILES/FILTER_README. + Open problems: + Low: smtpd should reply with the original recipient address, + or it should at least externalize it. + + Low: all table lookups should consistently use internalized + (unquoted) or externalized (quoted) forms as lookup keys. + smtpd, qmgr, local, etc. use internalized forms as keys. + cleanup uses externalized forms. + Low: sendmail does not store null command-line recipients. Low: have a configurable list of errno values for mailbox diff --git a/postfix/README_FILES/FILTER_README b/postfix/README_FILES/FILTER_README index d1bc3b085..71db5573b 100644 --- a/postfix/README_FILES/FILTER_README +++ b/postfix/README_FILES/FILTER_README @@ -137,24 +137,22 @@ We will set up a content filtering program that receives SMTP mail via localhost port 10025, and that submits SMTP mail back into Postfix via localhost port 10026. - ................................... - : Postfix : - ----->smtpd \ : - : -cleanup-\ /local----> - ---->pickup / -queue- : - : cleanup2/ | \smtp-----> - : ^ v : - : | v : - : smtpd smtp : - : 10026 | : - .......................|........... - ^ | - | v - ....|............. - : | 10025 : - : filter : - : : - .................. + .................................. + : Postfix : + ----->smtpd \ /local----> + : -cleanup->queue- : + ---->pickup / ^ | \smtp-----> + : | v : + : smtpd smtp : + : 10026 | : + ......................|........... + ^ | + | v + ....|............ + : | 10025 : + : filter : + : : + ................. To enable content filtering in this manner, specify in main.cf a new parameter: @@ -216,11 +214,11 @@ a dedicated listener on port localhost 10026: -o content_filter= -o local_recipient_maps= -o myhostname=localhost.domain.name - -o disable_dns_lookups=yes - -o cleanup_service=cleanup2 - cleanup2 unix n - n - 0 cleanup - -o header_checks= - -o body_checks= + -o smtpd_helo_restrictions= + -o smtpd_client_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject + -o mynetworks=127.0.0.0/8 This is just another SMTP server. The "-o content_filter=" requests no content filtering for incoming mail. The server has the same @@ -234,13 +232,164 @@ The "-o myhostname=localhost.domain.name" avoids a possible problem if the content filter is picky about the hostname that Postfix sends in SMTP server replies. -The "-o disable_dns_lookups=yes" turns off unnecessary DNS lookups -that would only slow things down. +The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8" +turn off UCE controls that would only waste time here. + +Squeezing out more performance +============================== + +Many refinements are possible, such as running a specially-configured +smtp delivery agent for feeding mail into the content filter, and +turning off address rewriting before or after content filtering. + +As the example below shows, things quickly become very complex, +because a lot of main.cf like information gets listed in the +master.cf file. This makes the system hard to understand. + +If you need to squeeze out more performance, it is probably simpler +to run multiple Postfix instances, one before and one after the +content filter. That way, each instance can have simple main.cf +and master.cf files, and the system will be easier to understand. + +As before, we will set up a content filtering program that receives +SMTP mail via localhost port 10025, and that submits SMTP mail back +into Postfix via localhost port 10026. + + ................................... + : Postfix : + ----->smtpd \ : + : -cleanup-\ /local----> + ---->pickup / -queue- : + : cleanup2/ | \smtp-----> + : ^ v : + : | v : + : smtpd smtp : + : 10026 | : + .......................|........... + ^ | + | v + ....|............. + : | 10025 : + : filter : + : : + .................. + +To enable content filtering in this manner, specify in main.cf a +new parameter: + +/etc/postfix/main.cf: + content_filter = scan:localhost:10025 + +/etc/postfix/master.cf: +# +# This is the usual input "smtpd" already present in master.cf +# +smtp inet n - n - - smtpd +# +# This is the cleanup daemon that handles messages in front of +# the content filter, it does header_checks and body_checks (if +# any), but does not do any address rewriting. +# +# The address rewriting happens in the second cleanup phase after +# the content filter. This gives the content_filter access to +# *largely* unmodified addresses for maximum flexibility. +# +# The trivial-rewrite daemon handles the logic of append_myorigin +# and append_dot_mydomain, turning these off requires two +# trivial-rewrite services, by which point (if you are not +# already) you are much better off with two complete Postfix +# instances one in front of and one behind the content filter. +# +# Note that some sites may specifically want to do the opposite: +# perform rewrites in front of the content_filter which would +# then see only cleaned up addresses, in this case the parameter +# settings below should be moved to the second "cleanup" +# instance. +# +cleanup unix n - n - 0 cleanup + -o canonical_maps= + -o sender_canonical_maps= + -o recipient_canonical_maps= + -o masquerade_domains= + -o virtual_maps= +# +# This is the delivery agent that injects mail into the content +# filter. It is tuned for low latency and low concurrency, most +# content filters burn CPU and high concurrency causes thrashing. +# The process limit of 10 reenforces the effect of +# $default_destination_concurrency_limit, even without an +# explicit process limit, the concurrency is bounded because all +# messages heading into the content filter have the same +# destination. The "disable_dns_lookups" setting prevents the +# delivery agent from consuming precious "bandwidth" in the +# narrow deliver channel waiting for slow DNS responses. It also +# ensures that the original envelope recipient is seen by the +# content filter. +# +scan unix n - n - 10 smtp + -o disable_dns_lookups=yes +# +# This is the SMTP listener that receives filtered messages from +# the content filter. It *MUST* clear the content_filter +# parameter to avoid loops, and use a different hostname to avoid +# triggering the Postfix SMTP loop detection code. +# +# +# Since all recipients have been validated by the first "smtpd", +# clear local_recipient_maps, virtual_maps and +# virtual_mailbox_maps. +# +# This "smtpd" uses a separate cleanup that does no header or +# body checks, but does do the various address rewrites disabled +# in the first cleanup. +# +# The parameters from mynetworks onward disable all access +# control other than insisting on connections from one of the IP +# addresses of the host. This is typically overkill, but can +# reduce resource usage, if the default restrictions use lots of +# tables. +# +localhost:10026 inet n - n - - smtpd + -o content_filter= + -o myhostname=localhost.domain.name + -o local_recipient_maps= + -o virtual_maps= + -o virtual_mailbox_maps= + -o cleanup_service=cleanup2 + -o mynetworks=127.0.0.0/8 + -o mynetworks_style=host + -o smtpd_restriction_classes= + -o smtpd_client_restrictions= + -o smtpd_helo_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject +# +# This is the second cleanup daemon. No header or body checks. +# If preferable, enable rewrites in the first cleanup daemon, and +# disable them here. +# +cleanup2 unix n - n - 0 cleanup + -o header_checks= + -o body_checks= +# +# The normal "smtp" delivery agent for contrast with "scan". +# Definitely do not set "disable_dns_lookups = yes" here if you +# send mail to the Internet. +# +smtp unix n - n - - smtp + +This causes Postfix to add one extra content filtering record to +each incoming mail message, with content scan:localhost:10025. +You can use the same syntax as in the right-hand side of a Postfix +transport table. The content filtering records are added by the +smtpd and pickup servers. -The "-o cleanup_service=cleanup2" specifies that mail received via -the secondary SMTP server should be send into the cleanup2 service. +The "scan" transport is a dedicated instance of the "smtp" delivery +agent for injecting messages into the SMTP content filter. Using +a dedicated "smtp" transport allows one to tune it for the specific +task of delivering mail to a local content filter (low latency, +low concurrency, throughput dependent on predictably low latency). -As the master.cf entry above shows, the cleanup2 service is like -the normal cleanup server, but with some features turned off: no -processing of header patterns, and no processing of body message -patterns. This can save you some precious CPU cycles. +See the previous example for setting up the content filter with +the Postfix spawn service; you can of course use any server that +can be run stand-alone outside the Postfix environment. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 8964d11bd..69e7921d2 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -12,6 +12,30 @@ snapshot release). Patches change the patchlevel and the release date. Snapshots change only the release date, unless they include the same bugfixes as a patch release. +Incompatible changes with Postfix snapshot 1.1.9-20020509 +========================================================= + +The Postfix SMTP server no longer honors OK access rules for +user@domain@postfix-style.virtual.domain, to close a relaying +loophole with postfix-style virtual domains that have @domain.name +catch-all patterns. + +The appearance of user@domain1@domain2 addresses has changed. In +mail headers, such addresses are now properly quoted as +"user@domain1"@domain2. This quoted form is now also expected on +the left-hand side of virtual and canonical lookup tables, but only +by some of the Postfix components. For now, it is better not to +use user@domain1@domain2 address forms on the left-hand side of +lookup tables. + +Incompatible changes with Postfix snapshot 1.1.8-20020508 +========================================================= + +The Postfix SMTP server by default no longer accepts mail for +user@domain@postfix-style.virtual.domain, to close a relaying +loophole with postfix-style virtual domains that have @domain.name +catch-all patterns. + Incompatible changes with Postfix snapshot 1.1.8-20020505 ========================================================= diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index f1ce60526..d46805638 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -1,5 +1,4 @@
-
 CLEANUP(8)                                             CLEANUP(8)
 
 NAME
@@ -169,6 +168,5 @@ CLEANUP(8)                                             CLEANUP(8)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
-                                                                1
-
+                                                       CLEANUP(8)
 
diff --git a/postfix/src/cleanup/cleanup_map1n.c b/postfix/src/cleanup/cleanup_map1n.c index 51f5be9c0..0a181e463 100644 --- a/postfix/src/cleanup/cleanup_map1n.c +++ b/postfix/src/cleanup/cleanup_map1n.c @@ -10,6 +10,7 @@ /* char *addr; /* DESCRIPTION /* This module implements one-to-many table mapping via table lookup. +/* Table lookups are done with quoted (externalized) address forms. /* The process is recursive. The recursion terminates when the /* left-hand side appears in its own expansion, or when a maximal /* nesting level is reached. diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index f1ce8a9f6..a267086de 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -1047,6 +1047,8 @@ tok822_parse.o: ../../include/sys_defs.h tok822_parse.o: ../../include/vstring.h tok822_parse.o: ../../include/vbuf.h tok822_parse.o: ../../include/msg.h +tok822_parse.o: quote_822_local.h +tok822_parse.o: quote_flags.h tok822_parse.o: tok822.h tok822_parse.o: resolve_clnt.h tok822_resolve.o: tok822_resolve.c diff --git a/postfix/src/global/domain_list.c b/postfix/src/global/domain_list.c index d4ea536b2..b067fb895 100644 --- a/postfix/src/global/domain_list.c +++ b/postfix/src/global/domain_list.c @@ -82,6 +82,7 @@ #include #include +#include #include #include @@ -90,7 +91,7 @@ static void usage(char *progname) msg_fatal("usage: %s [-v] patterns hostname", progname); } -main(int argc, char **argv) +int main(int argc, char **argv) { DOMAIN_LIST *list; char *host; diff --git a/postfix/src/global/dot_lockfile.c b/postfix/src/global/dot_lockfile.c index 9d0a2bef3..94681bf00 100644 --- a/postfix/src/global/dot_lockfile.c +++ b/postfix/src/global/dot_lockfile.c @@ -154,7 +154,7 @@ void dot_unlockfile(const char *path) #include #include -main(int argc, char **argv) +int main(int argc, char **argv) { VSTRING *why = vstring_alloc(100); diff --git a/postfix/src/global/mail_date.c b/postfix/src/global/mail_date.c index ca20f99a1..93edfe9c2 100644 --- a/postfix/src/global/mail_date.c +++ b/postfix/src/global/mail_date.c @@ -131,7 +131,7 @@ const char *mail_date(time_t when) #include -main(void) +int main(void) { vstream_printf("%s\n", mail_date(time((time_t *) 0))); vstream_fflush(VSTREAM_OUT); diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 0fb33c85a..051405c8c 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,10 +20,10 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20020508" +#define MAIL_RELEASE_DATE "20020509" #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "1.1.8-" MAIL_RELEASE_DATE +#define DEF_MAIL_VERSION "1.1.9-" MAIL_RELEASE_DATE extern char *var_mail_version; /* diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c index 7fd51ff57..98979e142 100644 --- a/postfix/src/global/maps.c +++ b/postfix/src/global/maps.c @@ -217,7 +217,7 @@ MAPS *maps_free(MAPS *maps) #include #include -main(int argc, char **argv) +int main(int argc, char **argv) { VSTRING *buf = vstring_alloc(100); MAPS *maps; diff --git a/postfix/src/global/namadr_list.c b/postfix/src/global/namadr_list.c index c5169d87e..3388023b3 100644 --- a/postfix/src/global/namadr_list.c +++ b/postfix/src/global/namadr_list.c @@ -88,6 +88,7 @@ #include #include +#include #include #include @@ -96,7 +97,7 @@ static void usage(char *progname) msg_fatal("usage: %s [-v] pattern_list hostname address", progname); } -main(int argc, char **argv) +int main(int argc, char **argv) { NAMADR_LIST *list; char *host; diff --git a/postfix/src/global/quote_821_local.c b/postfix/src/global/quote_821_local.c index d91d1897e..2fa6bd526 100644 --- a/postfix/src/global/quote_821_local.c +++ b/postfix/src/global/quote_821_local.c @@ -27,6 +27,8 @@ /* In violation with RFCs, treat 8-bit text as ordinary text. /* .IP QUOTE_FLAG_EXPOSE_AT /* In violation with RFCs, treat `@' as an ordinary character. +/* .IP QUOTE_FLAG_APPEND +/* Append to the result buffer, instead of overwriting it. /* .RE /* STANDARDS /* RFC 821 (SMTP protocol) @@ -100,7 +102,8 @@ static int is_821_dot_string(char *local_part, char *end, int flags) /* make_821_quoted_string - make quoted-string from local-part */ -static VSTRING *make_821_quoted_string(VSTRING *dst, char *local_part, char *end) +static VSTRING *make_821_quoted_string(VSTRING *dst, char *local_part, + char *end, int flags) { char *cp; int ch; @@ -109,10 +112,10 @@ static VSTRING *make_821_quoted_string(VSTRING *dst, char *local_part, char *end * Put quotes around the result, and prepend a backslash to characters * that need quoting when they occur in a quoted-string. */ - VSTRING_RESET(dst); VSTRING_ADDCH(dst, '"'); for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { - if (ch > 127 || ch == '\r' || ch == '\n' || ch == '"' || ch == '\\') + if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN)) + || ch == '\r' || ch == '\n' || ch == '"' || ch == '\\') VSTRING_ADDCH(dst, '\\'); VSTRING_ADDCH(dst, ch); } @@ -134,10 +137,12 @@ VSTRING *quote_821_local(VSTRING *dst, char *addr, int flags) */ if ((at = strrchr(addr, '@')) == 0) /* just in case */ at = addr + strlen(addr); /* should not happen */ + if ((flags & QUOTE_FLAG_APPEND) == 0) + VSTRING_RESET(dst); if (is_821_dot_string(addr, at, flags)) { - return (vstring_strcpy(dst, addr)); + return (vstring_strcat(dst, addr)); } else { - make_821_quoted_string(dst, addr, at); + make_821_quoted_string(dst, addr, at, flags & QUOTE_FLAG_8BITCLEAN); return (vstring_strcat(dst, at)); } } @@ -152,14 +157,15 @@ VSTRING *quote_821_local(VSTRING *dst, char *addr, int flags) #include #include "quote_821_local.h" -main(void) +int main(void) { VSTRING *src = vstring_alloc(100); VSTRING *dst = vstring_alloc(100); while (vstring_fgets_nonl(src, VSTREAM_IN)) { vstream_fprintf(VSTREAM_OUT, "%s\n", - vstring_str(quote_821_local(dst, vstring_str(src)))); + vstring_str(quote_821_local(dst, vstring_str(src), + QUOTE_FLAG_8BITCLEAN))); vstream_fflush(VSTREAM_OUT); } exit(0); diff --git a/postfix/src/global/quote_822_local.c b/postfix/src/global/quote_822_local.c index 93607feb2..54392805d 100644 --- a/postfix/src/global/quote_822_local.c +++ b/postfix/src/global/quote_822_local.c @@ -35,6 +35,8 @@ /* In violation with RFCs, treat 8-bit text as ordinary text. /* .IP QUOTE_FLAG_EXPOSE_AT /* In violation with RFCs, treat `@' as an ordinary character. +/* .IP QUOTE_FLAG_APPEND +/* Append to the result buffer, instead of overwriting it. /* .RE /* STANDARDS /* RFC 822 (ARPA Internet Text Messages) @@ -114,7 +116,7 @@ static int is_822_dot_string(const char *local_part, const char *end, int flags) /* make_822_quoted_string - make quoted-string from local-part */ static VSTRING *make_822_quoted_string(VSTRING *dst, const char *local_part, - const char *end) + const char *end, int flags) { const char *cp; int ch; @@ -125,7 +127,8 @@ static VSTRING *make_822_quoted_string(VSTRING *dst, const char *local_part, */ VSTRING_ADDCH(dst, '"'); for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { - if ( /* ch > 127 || */ ch == '"' || ch == '\\' || ch == '\r') + if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN)) + || ch == '"' || ch == '\\' || ch == '\r') VSTRING_ADDCH(dst, '\\'); VSTRING_ADDCH(dst, ch); } @@ -153,11 +156,13 @@ VSTRING *quote_822_local(VSTRING *dst, const char *mbox, int flags) start = mbox; if ((end = strrchr(start, '@')) == 0) end = start + strlen(start); + if ((flags & QUOTE_FLAG_APPEND) == 0) + VSTRING_RESET(dst); if (is_822_dot_string(start, end, flags)) { - return (vstring_strcpy(dst, mbox)); + return (vstring_strcat(dst, mbox)); } else { - vstring_strncpy(dst, mbox, start - mbox); - make_822_quoted_string(dst, start, end); + vstring_strncat(dst, mbox, start - mbox); + make_822_quoted_string(dst, start, end, flags & QUOTE_FLAG_8BITCLEAN); return (vstring_strcat(dst, end)); } } @@ -215,7 +220,7 @@ int main(int unused_argc, char **unused_argv) VSTRING *unquoted = vstring_alloc(100); while (vstring_fgets_nonl(raw, VSTREAM_IN)) { - quote_822_local(quoted, STR(raw)); + quote_822_local(quoted, STR(raw), QUOTE_FLAG_8BITCLEAN); vstream_printf("quoted: %s\n", STR(quoted)); unquote_822_local(unquoted, STR(quoted)); vstream_printf("unquoted: %s\n", STR(unquoted)); diff --git a/postfix/src/global/quote_flags.h b/postfix/src/global/quote_flags.h index 2c62cf0d8..df0e0b837 100644 --- a/postfix/src/global/quote_flags.h +++ b/postfix/src/global/quote_flags.h @@ -13,6 +13,7 @@ */ #define QUOTE_FLAG_8BITCLEAN (1<<0) /* be 8-bit clean */ #define QUOTE_FLAG_EXPOSE_AT (1<<1) /* @ is ordinary text */ +#define QUOTE_FLAG_APPEND (1<<2) /* append, not overwrite */ /* LICENSE /* .ad diff --git a/postfix/src/global/rec2stream.c b/postfix/src/global/rec2stream.c index 0e392cf0b..8188f1f6e 100644 --- a/postfix/src/global/rec2stream.c +++ b/postfix/src/global/rec2stream.c @@ -35,7 +35,7 @@ #include #include -main(void) +int main(void) { VSTRING *buf = vstring_alloc(100); int type; diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index 4c884309f..c506f4939 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -230,7 +230,7 @@ static void resolve(char *addr, RESOLVE_REPLY *reply) vstream_fflush(VSTREAM_OUT); } -main(int argc, char **argv) +int main(int argc, char **argv) { RESOLVE_REPLY reply; int ch; diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c index 5b1285a14..5cff7e0ba 100644 --- a/postfix/src/global/rewrite_clnt.c +++ b/postfix/src/global/rewrite_clnt.c @@ -197,7 +197,7 @@ static void rewrite(char *rule, char *addr, VSTRING *reply) vstream_fflush(VSTREAM_OUT); } -main(int argc, char **argv) +int main(int argc, char **argv) { VSTRING *reply; int ch; diff --git a/postfix/src/global/stream2rec.c b/postfix/src/global/stream2rec.c index 99f40eef2..a7da5c5ea 100644 --- a/postfix/src/global/stream2rec.c +++ b/postfix/src/global/stream2rec.c @@ -35,7 +35,7 @@ #include #include -main(void) +int main(void) { VSTRING *buf = vstring_alloc(150); int type; diff --git a/postfix/src/global/string_list.c b/postfix/src/global/string_list.c index 522ff26a1..bed30deab 100644 --- a/postfix/src/global/string_list.c +++ b/postfix/src/global/string_list.c @@ -70,6 +70,7 @@ #include #include +#include #include #include #include @@ -79,7 +80,7 @@ static void usage(char *progname) msg_fatal("usage: %s [-v] patterns string", progname); } -main(int argc, char **argv) +int main(int argc, char **argv) { STRING_LIST *list; char *string; diff --git a/postfix/src/global/tok822_parse.c b/postfix/src/global/tok822_parse.c index 997a03554..097b4c351 100644 --- a/postfix/src/global/tok822_parse.c +++ b/postfix/src/global/tok822_parse.c @@ -107,6 +107,7 @@ /* Global library. */ +#include "quote_822_local.h" #include "tok822.h" /* @@ -221,6 +222,7 @@ VSTRING *tok822_internalize(VSTRING *vp, TOK822 *tree, int flags) VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags) { + VSTRING *tmp; TOK822 *tp; if (flags & TOK822_STR_WIPE) @@ -235,8 +237,20 @@ VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags) continue; } break; + + /* + * XXX In order to correctly externalize an address, it is not + * sufficient to quote individual atoms. There are higher-level + * rules that say when an address localpart needs to be quoted. + * We wing it with the quote_822_local() routine, which ignores + * the issue of atoms in the domain part that would need quoting. + */ case TOK822_ADDR: - tok822_externalize(vp, tp->head, TOK822_STR_NONE); + tmp = vstring_alloc(100); + tok822_internalize(tmp, tp->head, TOK822_STR_NONE); + quote_822_local(vp, vstring_str(tmp), + QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND); + vstring_free(tmp); break; case TOK822_ATOM: case TOK822_COMMENT: diff --git a/postfix/src/global/tok822_parse.ref b/postfix/src/global/tok822_parse.ref index 169957ac4..53521f3b5 100644 --- a/postfix/src/global/tok822_parse.ref +++ b/postfix/src/global/tok822_parse.ref @@ -259,26 +259,21 @@ Externalized, newlines inserted: named group: foo@bar, baz@barf; ->>>wietse@foo (wietse - venema)<<< +>>>wietse@foo (wietse venema)<<< Parse tree: address atom "wietse" OP "@" atom "foo" - comment "(wietse - venema)" + comment "(wietse venema)" Internalized: -wietse@foo (wietse - venema) +wietse@foo (wietse venema) Externalized, no newlines inserted: -wietse@foo (wietse - venema) +wietse@foo (wietse venema) Externalized, newlines inserted: -wietse@foo (wietse - venema) +wietse@foo (wietse venema) diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index e53157fc1..9ccd01eeb 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -339,7 +339,7 @@ static void qmqpd_write_content(QMQPD_STATE *state) "\tid %s; %s", state->queue_id, mail_date(state->time)); } #ifdef RECEIVED_ENVELOPE_FROM - quote_822_local(state->buf, state->sender); + quote_822_local(state->buf, state->sender, QUOTE_FLAG_8BITCLEAN); rec_fprintf(state->cleanup, REC_TYPE_NORM, "\t(envelope-from <%s>)", STR(state->buf)); #endif diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 497907ea8..fdd063caf 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -312,6 +312,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -939,9 +940,9 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) "\tby %s (%s) with %s id %s", var_myhostname, var_mail_name, state->protocol, state->queue_id); - /* XXX Should RFC 822 externalize recipient address */ + quote_822_local(state->buffer, state->recipient, QUOTE_FLAG_8BITCLEAN); rec_fprintf(state->cleanup, REC_TYPE_NORM, - "\tfor <%s>; %s", state->recipient, mail_date(state->time)); + "\tfor <%s>; %s", STR(state->buffer), mail_date(state->time)); } else { rec_fprintf(state->cleanup, REC_TYPE_NORM, "\tby %s (%s) with %s", @@ -950,9 +951,9 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) "\tid %s; %s", state->queue_id, mail_date(state->time)); } #ifdef RECEIVED_ENVELOPE_FROM - /* XXX Should RFC 822 externalize sender address */ + quote_822_local(state->buffer, state->sender, QUOTE_FLAG_8BITCLEAN); rec_fprintf(state->cleanup, REC_TYPE_NORM, - "\t(envelope-from %s)", state->sender); + "\t(envelope-from %s)", STR(state->buffer)); #endif smtpd_chat_reply(state, "354 End data with ."); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 8e85d5723..19bcf4ade 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -1760,16 +1760,15 @@ static int check_mail_access(SMTPD_STATE *state, const char *table, { if (bare_addr) myfree(bare_addr); return(x); } /* - * Source-routed, non-local, recipient addresses are too suspicious for - * returning an "OK" result. The complicated expression below was brought - * to you by the keyboard of Victor Duchovni, Morgan Stanley and hacked - * up a bit by Wietse. + * Source-routed (non-local or virtual) recipient addresses are too + * suspicious for returning an "OK" result. The complicated expression + * below was brought to you by the keyboard of Victor Duchovni, Morgan + * Stanley and hacked up a bit by Wietse. */ #define SUSPICIOUS(domain, reply, state, reply_name, reply_class) \ (var_allow_untrust_route == 0 \ && (reply->flags & RESOLVE_FLAG_ROUTED) \ - && strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0 \ - && !resolve_final(state, reply_name, domain)) + && strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0) /* * Look up user+foo@domain if the address has an extension, user@domain