Postfix 1.1 patch 09 brings you the usual minor fixes that also appeared in recent snapshots, plus a change that closes an obscure relaying loophole with user@domain@postfix-style.virtual.domain addresses for virtual domains with @domain.name catch-all patterns. This change introduces a new parameter, with backwards compatible default settings. To allow Postfix to receive user@domain@domain addresses, specify "resolve_dequoted_address = no" in main.cf (quote the address localpart as per RFC 822, don't look for @ etc. inside the address localpart). Although this is technically more correct, it also opens opportunities for mail relay attacks when Postfix provides backup MX service for Sendmail systems. For the other minor changes, see the HISTORY file differences below. Prereq: "1.1.8" diff -cr --new-file /tmp/postfix-1.1.8/src/global/mail_version.h ./src/global/mail_version.h *** /tmp/postfix-1.1.8/src/global/mail_version.h Sat May 4 09:45:01 2002 --- ./src/global/mail_version.h Sun May 12 20:15:31 2002 *************** *** 21,34 **** * release date only, unless they include the same bugfix as a patch release. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "1.1.8" extern char *var_mail_version; /* * Release date. */ #define VAR_MAIL_RELEASE "mail_release_date" ! #define DEF_MAIL_RELEASE "20020504" extern char *var_mail_release; /* LICENSE --- 21,34 ---- * release date only, unless they include the same bugfix as a patch release. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "1.1.9" extern char *var_mail_version; /* * Release date. */ #define VAR_MAIL_RELEASE "mail_release_date" ! #define DEF_MAIL_RELEASE "20020513" extern char *var_mail_release; /* LICENSE diff -cr --new-file /tmp/postfix-1.1.8/HISTORY ./HISTORY *** /tmp/postfix-1.1.8/HISTORY Sat May 4 20:10:52 2002 --- ./HISTORY Mon May 13 16:10:41 2002 *************** *** 6249,6254 **** --- 6249,6306 ---- Portability: run-time test to avoid GDBM trouble. File: util/dict_dbm.c. + 20020508 + + 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: + global/mail_addr_map.c. + + Bugfix: for address localpart quoting, now quote @ as a + special character everywhere, except when resolving addresses. + Previously, the @ was nowhere quoted as a special character, + not even in SMTP commands. Files: global/quote_82[12]_local.c + and some 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. + + 20020512 + + Cleanup: the SMTP client logged and bounced the CNAME + expanded recipient address, and thereby complicated trouble + shooting. File: src/smtp_proto.c. + + Bugfix: the SMTP and LMTP clients bounced the quoted + recipient address, resulting in too much quoting in bounce + reports. Files: src/smtp_proto.c, lmtp/lmtp_proto.c. + + 20020513 + + Bugfix: the LDAP client used the "wrong" @ character in + addresses with multiple @. LaMont Jones, HP. File: + util/dict_ldap.c. + + Compatibility: forwards "postqueue -r" compatibility with + the additional queue file records that are stored by snapshot + 20050512. + + Cleanup: specify "resolve_dequoted_address = no" to prevent + Postfix from looking inside quotes for extra @ etc. characters + when resolving an address. This behavior is technically + more correct, but it opens a mail relay loophole with "user + @domain"@domain when relaying mail to a Sendmail system. + Open problems: Low: sendmail does not store null command-line recipients. diff -cr --new-file /tmp/postfix-1.1.8/RELEASE_NOTES ./RELEASE_NOTES *** /tmp/postfix-1.1.8/RELEASE_NOTES Tue Mar 26 16:11:22 2002 --- ./RELEASE_NOTES Mon May 13 16:11:12 2002 *************** *** 12,17 **** --- 12,39 ---- date. Snapshots change only the release date, unless they include the same bugfix as a patch release. + Incompatible changes with Postfix version 1.1.9 (released 20020513) + =================================================================== + + 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. + + To allow such addresses, specify "resolve_dequoted_address = no" + in main.cf (quote the address localpart as per RFC 822, and don't + look for @ or % or ! characters inside the address localpart). + However, this opens opportunities for obscure mail relay attacks + when Postfix provides backup MX service for Sendmail systems. + + The appearance of user@domain1@domain2 addresses has changed. In + mail headers, such addresses are now properly quoted as + "user@domain1"@domain2. As a side effect, 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 version 1.1.6 (released 20020326) =================================================================== diff -cr --new-file /tmp/postfix-1.1.8/conf/sample-misc.cf ./conf/sample-misc.cf *** /tmp/postfix-1.1.8/conf/sample-misc.cf Mon Dec 31 12:35:15 2001 --- ./conf/sample-misc.cf Mon May 13 17:45:26 2002 *************** *** 362,367 **** --- 362,383 ---- #relocated_maps = hash:/etc/postfix/relocated relocated_maps = + # The resolve_dequoted_address parameter controls how Postfix + # resolves addresses. + # + # By default, the Postfix address resolver does not quote the address + # localpart as per RFC 822, so that additional @ or % or ! operators + # remain visible. This behavior is safe but it is also technically + # incorrect. + # + # If you specify "resolve_dequoted_address = no", then the Postfix + # resolver will not know about additional @ etc. operators in the + # address localpart. This opens opportunities for obscure mail relay + # attacks with user@domain@domain addresses when Postfix provides + # backup MX service for Sendmail systems. + # + resolve_dequoted_address = no + # The syslog_facility parameter controls where Postfix logging is # sent by the syslog daemon. Specify a logging facility as defined # in syslog.conf(5). The default logging facility is "mail". diff -cr --new-file /tmp/postfix-1.1.8/html/pickup.8.html ./html/pickup.8.html *** /tmp/postfix-1.1.8/html/pickup.8.html Sun Dec 30 15:46:33 2001 --- ./html/pickup.8.html Mon May 13 15:40:41 2002 *************** *** 1,5 ****
- 
  PICKUP(8)                                               PICKUP(8)
  
  NAME
--- 1,4 ----
***************
*** 80,85 ****
         P.O. Box 704
         Yorktown Heights, NY 10598, USA
  
!                                                                 1
! 
  
--- 79,83 ---- P.O. Box 704 Yorktown Heights, NY 10598, USA ! PICKUP(8) diff -cr --new-file /tmp/postfix-1.1.8/html/trivial-rewrite.8.html ./html/trivial-rewrite.8.html *** /tmp/postfix-1.1.8/html/trivial-rewrite.8.html Thu Jan 17 11:24:55 2002 --- ./html/trivial-rewrite.8.html Mon May 13 16:20:26 2002 *************** *** 1,5 ****
- 
  TRIVIAL-REWRITE(8)                             TRIVIAL-REWRITE(8)
  
  NAME
--- 1,4 ----
***************
*** 80,85 ****
--- 79,92 ----
                The domain that locally-posted mail appears to come
                from.
  
+        resolve_unquoted_address
+               When resolving an address, do not quote the address
+               localpart as per RFC 822, so that additional  @,  %
+               or  !   characters  remain visible. This is techni-
+               cally  incorrect,  but  allows  us  to  stop  relay
+               attacks  when forwarding mail to a Sendmail primary
+               MX host.
+ 
  Rewriting
         allow_percent_hack
                Rewrite user%domain to user@domain.
***************
*** 95,105 ****
  
  Routing
         local_transport
!               Where  to  deliver mail for destinations that match
!               $mydestination or  $inet_interfaces.   The  default
                transport is local.
  
!               Syntax  is  transport:nexthop; see transport(5) for
                details. The :nexthop part is optional.
  
         default_transport
--- 102,112 ----
  
  Routing
         local_transport
!               Where to deliver mail for destinations  that  match
!               $mydestination  or  $inet_interfaces.   The default
                transport is local.
  
!               Syntax is transport:nexthop; see  transport(5)  for
                details. The :nexthop part is optional.
  
         default_transport
***************
*** 107,129 ****
                is explicitly given in the transport(5) table.  The
                default transport is smtp.
  
!               Syntax is transport:nexthop; see  transport(5)  for
                details. The :nexthop part is optional.
  
         parent_domain_matches_subdomains
!               List  of Postfix features that use domain.name pat-
                terns  to  match  sub.domain.name  (as  opposed  to
                requiring .domain.name patterns).
  
         relayhost
!               The  default host to send non-local mail to when no
                entry is matched in the transport(5) table.
  
!               When no relayhost  is  specified,  mail  is  routed
                directly to the destination's mail exchanger.
  
         transport_maps
!               List  of tables with domain to (transport, nexthop)
                mappings.
  
  SEE ALSO
--- 114,136 ----
                is explicitly given in the transport(5) table.  The
                default transport is smtp.
  
!               Syntax  is  transport:nexthop; see transport(5) for
                details. The :nexthop part is optional.
  
         parent_domain_matches_subdomains
!               List of Postfix features that use domain.name  pat-
                terns  to  match  sub.domain.name  (as  opposed  to
                requiring .domain.name patterns).
  
         relayhost
!               The default host to send non-local mail to when  no
                entry is matched in the transport(5) table.
  
!               When  no  relayhost  is  specified,  mail is routed
                directly to the destination's mail exchanger.
  
         transport_maps
!               List of tables with domain to (transport,  nexthop)
                mappings.
  
  SEE ALSO
***************
*** 132,138 ****
         transport(5) transport table format
  
  LICENSE
!        The Secure Mailer license must be  distributed  with  this
         software.
  
  AUTHOR(S)
--- 139,145 ----
         transport(5) transport table format
  
  LICENSE
!        The  Secure  Mailer  license must be distributed with this
         software.
  
  AUTHOR(S)
***************
*** 141,146 ****
         P.O. Box 704
         Yorktown Heights, NY 10598, USA
  
!                                                                 1
! 
  
--- 148,152 ---- P.O. Box 704 Yorktown Heights, NY 10598, USA ! TRIVIAL-REWRITE(8) diff -cr --new-file /tmp/postfix-1.1.8/man/man8/trivial-rewrite.8 ./man/man8/trivial-rewrite.8 *** /tmp/postfix-1.1.8/man/man8/trivial-rewrite.8 Thu Jan 17 11:24:54 2002 --- ./man/man8/trivial-rewrite.8 Mon May 13 16:20:25 2002 *************** *** 80,85 **** --- 80,91 ---- List of domains that this machine considers local. .IP \fBmyorigin\fR The domain that locally-posted mail appears to come from. + .IP \fBresolve_unquoted_address\fR + When resolving an address, do not quote the address localpart as + per RFC 822, so that additional \fB@\fR, \fB%\fR or \fB!\fR + characters remain visible. This is technically incorrect, but + allows us to stop relay attacks when forwarding mail to a Sendmail + primary MX host. .SH Rewriting .ad .fi diff -cr --new-file /tmp/postfix-1.1.8/src/bounce/Makefile.in ./src/bounce/Makefile.in *** /tmp/postfix-1.1.8/src/bounce/Makefile.in Fri Jan 25 09:11:46 2002 --- ./src/bounce/Makefile.in Mon May 13 12:43:03 2002 *************** *** 83,88 **** --- 83,89 ---- bounce_append_service.o: ../../include/stringops.h bounce_append_service.o: ../../include/mail_queue.h bounce_append_service.o: ../../include/quote_822_local.h + bounce_append_service.o: ../../include/quote_flags.h bounce_append_service.o: ../../include/deliver_flock.h bounce_append_service.o: ../../include/myflock.h bounce_append_service.o: bounce_service.h *************** *** 123,128 **** --- 124,130 ---- bounce_notify_util.o: ../../include/line_wrap.h bounce_notify_util.o: ../../include/mail_queue.h bounce_notify_util.o: ../../include/quote_822_local.h + bounce_notify_util.o: ../../include/quote_flags.h bounce_notify_util.o: ../../include/mail_params.h bounce_notify_util.o: ../../include/is_header.h bounce_notify_util.o: ../../include/record.h diff -cr --new-file /tmp/postfix-1.1.8/src/cleanup/Makefile.in ./src/cleanup/Makefile.in *** /tmp/postfix-1.1.8/src/cleanup/Makefile.in Sun Mar 24 14:47:01 2002 --- ./src/cleanup/Makefile.in Mon May 13 12:42:31 2002 *************** *** 184,189 **** --- 184,190 ---- cleanup_map11.o: ../../include/mail_addr_map.h cleanup_map11.o: ../../include/maps.h cleanup_map11.o: ../../include/quote_822_local.h + cleanup_map11.o: ../../include/quote_flags.h cleanup_map11.o: cleanup.h cleanup_map11.o: ../../include/tok822.h cleanup_map11.o: ../../include/resolve_clnt.h *************** *** 203,208 **** --- 204,210 ---- cleanup_map1n.o: ../../include/maps.h cleanup_map1n.o: ../../include/cleanup_user.h cleanup_map1n.o: ../../include/quote_822_local.h + cleanup_map1n.o: ../../include/quote_flags.h cleanup_map1n.o: ../../include/been_here.h cleanup_map1n.o: cleanup.h cleanup_map1n.o: ../../include/tok822.h *************** *** 222,227 **** --- 224,230 ---- cleanup_masquerade.o: ../../include/tok822.h cleanup_masquerade.o: ../../include/resolve_clnt.h cleanup_masquerade.o: ../../include/quote_822_local.h + cleanup_masquerade.o: ../../include/quote_flags.h cleanup_masquerade.o: cleanup.h cleanup_masquerade.o: ../../include/vstream.h cleanup_masquerade.o: ../../include/maps.h *************** *** 245,250 **** --- 248,254 ---- cleanup_message.o: ../../include/resolve_clnt.h cleanup_message.o: ../../include/header_opts.h cleanup_message.o: ../../include/quote_822_local.h + cleanup_message.o: ../../include/quote_flags.h cleanup_message.o: ../../include/mail_params.h cleanup_message.o: ../../include/mail_date.h cleanup_message.o: ../../include/mail_addr.h *************** *** 301,306 **** --- 305,311 ---- cleanup_rewrite.o: ../../include/resolve_clnt.h cleanup_rewrite.o: ../../include/rewrite_clnt.h cleanup_rewrite.o: ../../include/quote_822_local.h + cleanup_rewrite.o: ../../include/quote_flags.h cleanup_rewrite.o: cleanup.h cleanup_rewrite.o: ../../include/vstream.h cleanup_rewrite.o: ../../include/argv.h diff -cr --new-file /tmp/postfix-1.1.8/src/global/Makefile.in ./src/global/Makefile.in *** /tmp/postfix-1.1.8/src/global/Makefile.in Fri Jan 25 09:10:26 2002 --- ./src/global/Makefile.in Mon May 13 12:41:51 2002 *************** *** 57,63 **** 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 \ ! match_parent_style.h TESTSRC = rec2stream.c stream2rec.c recdump.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ --- 57,63 ---- 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 \ ! match_parent_style.h quote_flags.h TESTSRC = rec2stream.c stream2rec.c recdump.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ *************** *** 579,584 **** --- 579,585 ---- mail_copy.o: ../../include/vstring_vstream.h mail_copy.o: ../../include/stringops.h mail_copy.o: quote_822_local.h + mail_copy.o: quote_flags.h mail_copy.o: record.h mail_copy.o: rec_type.h mail_copy.o: mail_queue.h *************** *** 884,894 **** --- 885,897 ---- quote_821_local.o: ../../include/vstring.h quote_821_local.o: ../../include/vbuf.h quote_821_local.o: quote_821_local.h + quote_821_local.o: quote_flags.h quote_822_local.o: quote_822_local.c quote_822_local.o: ../../include/sys_defs.h quote_822_local.o: ../../include/vstring.h quote_822_local.o: ../../include/vbuf.h quote_822_local.o: quote_822_local.h + quote_822_local.o: quote_flags.h rec2stream.o: rec2stream.c rec2stream.o: ../../include/sys_defs.h rec2stream.o: ../../include/vstring.h *************** *** 968,973 **** --- 971,977 ---- rewrite_clnt.o: ../../include/events.h rewrite_clnt.o: ../../include/iostuff.h rewrite_clnt.o: quote_822_local.h + rewrite_clnt.o: quote_flags.h rewrite_clnt.o: mail_proto.h rewrite_clnt.o: ../../include/attr.h rewrite_clnt.o: mail_params.h *************** *** 1036,1041 **** --- 1040,1047 ---- 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 -cr --new-file /tmp/postfix-1.1.8/src/global/mail_addr_map.c ./src/global/mail_addr_map.c *** /tmp/postfix-1.1.8/src/global/mail_addr_map.c Sun Oct 7 17:55:23 2001 --- ./src/global/mail_addr_map.c Sun May 12 20:01:18 2002 *************** *** 94,100 **** */ if (*string == '@') { buffer = vstring_alloc(100); ! if ((ratsign = strchr(address, '@')) != 0) vstring_strncpy(buffer, address, ratsign - address); else vstring_strcpy(buffer, address); --- 94,100 ---- */ if (*string == '@') { buffer = vstring_alloc(100); ! if ((ratsign = strrchr(address, '@')) != 0) vstring_strncpy(buffer, address, ratsign - address); else vstring_strcpy(buffer, address); diff -cr --new-file /tmp/postfix-1.1.8/src/global/mail_params.h ./src/global/mail_params.h *** /tmp/postfix-1.1.8/src/global/mail_params.h Mon Mar 25 08:22:11 2002 --- ./src/global/mail_params.h Mon May 13 15:29:47 2002 *************** *** 1415,1420 **** --- 1415,1431 ---- #define DEF_README_DIR "no" #endif + /* + * Safety: resolve the unquoted address (technically incorrect), instead of + * resolving the quoted address (technically incorrect). This prevents mail + * relay loopholes with "user@domain"@domain when you're relaying mail for a + * Sendmail system or when receiving mail for a local virtual domain with an + * @domain catch-all rule. + */ + #define VAR_RESOLVE_DEQUOTED "resolve_dequoted_address" + #define DEF_RESOLVE_DEQUOTED 1 + extern bool var_resolve_dequoted; + /* LICENSE /* .ad /* .fi diff -cr --new-file /tmp/postfix-1.1.8/src/global/quote_821_local.c ./src/global/quote_821_local.c *** /tmp/postfix-1.1.8/src/global/quote_821_local.c Fri Oct 27 08:29:41 2000 --- ./src/global/quote_821_local.c Sun May 12 19:53:39 2002 *************** *** 9,24 **** /* VSTRING *quote_821_local(dst, src) /* VSTRING *dst; /* char *src; /* DESCRIPTION /* quote_821_local() quotes the local part of a mailbox address and /* returns a result that can be used in SMTP commands as specified ! /* by RFC 821. /* /* Arguments: /* .IP dst /* The result. /* .IP src /* The input address. /* STANDARDS /* RFC 821 (SMTP protocol) /* BUGS --- 9,41 ---- /* VSTRING *quote_821_local(dst, src) /* VSTRING *dst; /* char *src; + /* + /* VSTRING *quote_821_local_flags(dst, src, flags) + /* VSTRING *dst; + /* char *src; + /* int flags; /* DESCRIPTION /* quote_821_local() quotes the local part of a mailbox address and /* returns a result that can be used in SMTP commands as specified ! /* by RFC 821. It implements an 8-bit clean version of RFC 821. ! /* ! /* quote_821_local_flags() provides finer control. /* /* Arguments: /* .IP dst /* The result. /* .IP src /* The input address. + /* .IP flags + /* Bit-wise OR of zero or more of the following. + /* .RS + /* .IP QUOTE_FLAG_8BITCLEAN + /* 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) /* BUGS *************** *** 55,61 **** /* is_821_dot_string - is this local-part an rfc 821 dot-string? */ ! static int is_821_dot_string(char *local_part, char *end) { char *cp; int ch; --- 72,78 ---- /* is_821_dot_string - is this local-part an rfc 821 dot-string? */ ! static int is_821_dot_string(char *local_part, char *end, int flags) { char *cp; int ch; *************** *** 70,76 **** for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == '.' && cp[1] == '.') return (NO); ! if (ch > 127) return (NO); if (ch == ' ') return (NO); --- 87,93 ---- for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == '.' && cp[1] == '.') return (NO); ! if (ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN)) return (NO); if (ch == ' ') return (NO); *************** *** 81,87 **** || ch == '[' || ch == ']' || ch == '\\' || ch == ',' || ch == ';' || ch == ':' ! /* || ch == '@' */ || ch == '"') return (NO); } if (cp[-1] == '.') --- 98,104 ---- || ch == '[' || ch == ']' || ch == '\\' || ch == ',' || ch == ';' || ch == ':' ! || (ch == '@' && !(flags & QUOTE_FLAG_EXPOSE_AT)) || ch == '"') return (NO); } if (cp[-1] == '.') *************** *** 91,97 **** /* make_821_quoted_string - make quoted-string from local-part */ ! static VSTRING *make_821_quoted_string(VSTRING *dst, char *local_part, char *end) { char *cp; int ch; --- 108,115 ---- /* make_821_quoted_string - make quoted-string from local-part */ ! static VSTRING *make_821_quoted_string(VSTRING *dst, char *local_part, ! char *end, int flags) { char *cp; int ch; *************** *** 100,109 **** * 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 == '\\') VSTRING_ADDCH(dst, '\\'); VSTRING_ADDCH(dst, ch); } --- 118,127 ---- * Put quotes around the result, and prepend a backslash to characters * that need quoting when they occur in a quoted-string. */ VSTRING_ADDCH(dst, '"'); for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { ! if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN)) ! || ch == '\r' || ch == '\n' || ch == '"' || ch == '\\') VSTRING_ADDCH(dst, '\\'); VSTRING_ADDCH(dst, ch); } *************** *** 112,120 **** return (dst); } ! /* quote_821_local - quote local part of address according to rfc 821 */ ! VSTRING *quote_821_local(VSTRING *dst, char *addr) { char *at; --- 130,138 ---- return (dst); } ! /* quote_821_local_flags - quote local part of address according to rfc 821 */ ! VSTRING *quote_821_local_flags(VSTRING *dst, char *addr, int flags) { char *at; *************** *** 125,134 **** */ if ((at = strrchr(addr, '@')) == 0) /* just in case */ at = addr + strlen(addr); /* should not happen */ ! if (is_821_dot_string(addr, at)) { ! return (vstring_strcpy(dst, addr)); } else { ! make_821_quoted_string(dst, addr, at); return (vstring_strcat(dst, at)); } } --- 143,154 ---- */ 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_strcat(dst, addr)); } else { ! make_821_quoted_string(dst, addr, at, flags & QUOTE_FLAG_8BITCLEAN); return (vstring_strcat(dst, at)); } } diff -cr --new-file /tmp/postfix-1.1.8/src/global/quote_821_local.h ./src/global/quote_821_local.h *** /tmp/postfix-1.1.8/src/global/quote_821_local.h Mon Jan 18 15:11:49 1999 --- ./src/global/quote_821_local.h Sun May 12 19:46:03 2002 *************** *** 14,22 **** #include /* * External interface. */ ! extern VSTRING *quote_821_local(VSTRING *, char *); /* LICENSE /* .ad --- 14,29 ---- #include /* + * Global library. + */ + #include + + /* * External interface. */ ! extern VSTRING *quote_821_local_flags(VSTRING *, char *, int); ! #define quote_821_local(dst, src) \ ! quote_821_local_flags((dst), (src), QUOTE_FLAG_8BITCLEAN) /* LICENSE /* .ad diff -cr --new-file /tmp/postfix-1.1.8/src/global/quote_822_local.c ./src/global/quote_822_local.c *** /tmp/postfix-1.1.8/src/global/quote_822_local.c Fri Oct 27 08:30:17 2000 --- ./src/global/quote_822_local.c Sun May 12 20:10:49 2002 *************** *** 10,15 **** --- 10,20 ---- /* VSTRING *dst; /* const char *src; /* + /* VSTRING *quote_822_local_flags(dst, src, flags) + /* VSTRING *dst; + /* const char *src; + /* int flags; + /* /* VSTRING *unquote_822_local(dst, src) /* VSTRING *dst; /* const char *src; *************** *** 17,23 **** /* quote_822_local() quotes the local part of a mailbox and /* returns a result that can be used in message headers as /* specified by RFC 822 (actually, an 8-bit clean version of ! /* RFC 822). /* /* unquote_822_local() transforms the local part of a mailbox /* address to unquoted (internal) form. --- 22,30 ---- /* quote_822_local() quotes the local part of a mailbox and /* returns a result that can be used in message headers as /* specified by RFC 822 (actually, an 8-bit clean version of ! /* RFC 822). It implements an 8-bit clean version of RFC 822. ! /* ! /* quote_822_local_flags() provides finer control. /* /* unquote_822_local() transforms the local part of a mailbox /* address to unquoted (internal) form. *************** *** 27,32 **** --- 34,49 ---- /* The result. /* .IP src /* The input address. + /* .IP flags + /* Bit-wise OR of zero or more of the following. + /* .RS + /* .IP QUOTE_FLAG_8BITCLEAN + /* 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) /* BUGS *************** *** 65,71 **** /* is_822_dot_string - is this local-part an rfc 822 dot-string? */ ! static int is_822_dot_string(const char *local_part, const char *end) { const char *cp; int ch; --- 82,88 ---- /* is_822_dot_string - is this local-part an rfc 822 dot-string? */ ! static int is_822_dot_string(const char *local_part, const char *end, int flags) { const char *cp; int ch; *************** *** 83,99 **** for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == '.' && (cp + 1) < end && cp[1] == '.') return (NO); ! #if 0 ! if (ch > 127) return (NO); - #endif if (ch == ' ') return (NO); if (ISCNTRL(ch)) return (NO); if (ch == '(' || ch == ')' || ch == '<' || ch == '>' ! /* || ch == '@' */ || ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || ch == '[' || ch == ']') --- 100,114 ---- for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == '.' && (cp + 1) < end && cp[1] == '.') return (NO); ! if (ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN)) return (NO); if (ch == ' ') return (NO); if (ISCNTRL(ch)) return (NO); if (ch == '(' || ch == ')' || ch == '<' || ch == '>' ! || (ch == '@' && !(flags & QUOTE_FLAG_EXPOSE_AT)) || ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || ch == '[' || ch == ']') *************** *** 107,113 **** /* 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 *cp; int ch; --- 122,128 ---- /* 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, int flags) { const char *cp; int ch; *************** *** 118,124 **** */ VSTRING_ADDCH(dst, '"'); for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { ! if ( /* ch > 127 || */ ch == '"' || ch == '\\' || ch == '\r') VSTRING_ADDCH(dst, '\\'); VSTRING_ADDCH(dst, ch); } --- 133,140 ---- */ VSTRING_ADDCH(dst, '"'); for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { ! if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN)) ! || ch == '"' || ch == '\\' || ch == '\r') VSTRING_ADDCH(dst, '\\'); VSTRING_ADDCH(dst, ch); } *************** *** 126,134 **** return (dst); } ! /* quote_822_local - quote local part of mailbox according to rfc 822 */ ! VSTRING *quote_822_local(VSTRING *dst, const char *mbox) { const char *start; /* first byte of localpart */ const char *end; /* first byte after localpart */ --- 142,150 ---- return (dst); } ! /* quote_822_local_flags - quote local part of mailbox according to rfc 822 */ ! VSTRING *quote_822_local_flags(VSTRING *dst, const char *mbox, int flags) { const char *start; /* first byte of localpart */ const char *end; /* first byte after localpart */ *************** *** 146,156 **** start = mbox; if ((end = strrchr(start, '@')) == 0) end = start + strlen(start); ! if (is_822_dot_string(start, end)) { ! return (vstring_strcpy(dst, mbox)); } else { ! vstring_strncpy(dst, mbox, start - mbox); ! make_822_quoted_string(dst, start, end); return (vstring_strcat(dst, end)); } } --- 162,174 ---- 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_strcat(dst, mbox)); } else { ! vstring_strncat(dst, mbox, start - mbox); ! make_822_quoted_string(dst, start, end, flags & QUOTE_FLAG_8BITCLEAN); return (vstring_strcat(dst, end)); } } diff -cr --new-file /tmp/postfix-1.1.8/src/global/quote_822_local.h ./src/global/quote_822_local.h *** /tmp/postfix-1.1.8/src/global/quote_822_local.h Fri Dec 11 13:55:21 1998 --- ./src/global/quote_822_local.h Sun May 12 19:47:13 2002 *************** *** 17,26 **** #include /* * External interface. */ ! extern VSTRING *quote_822_local(VSTRING *, const char *); extern VSTRING *unquote_822_local(VSTRING *, const char *); /* LICENSE /* .ad --- 17,33 ---- #include /* + * Global library. + */ + #include + + /* * External interface. */ ! extern VSTRING *quote_822_local_flags(VSTRING *, const char *, int); extern VSTRING *unquote_822_local(VSTRING *, const char *); + #define quote_822_local(dst, src) \ + quote_822_local_flags((dst), (src), QUOTE_FLAG_8BITCLEAN) /* LICENSE /* .ad diff -cr --new-file /tmp/postfix-1.1.8/src/global/quote_flags.h ./src/global/quote_flags.h *** /tmp/postfix-1.1.8/src/global/quote_flags.h Wed Dec 31 19:00:00 1969 --- ./src/global/quote_flags.h Thu May 9 16:29:51 2002 *************** *** 0 **** --- 1,27 ---- + /*++ + /* NAME + /* quote_flags 3h + /* SUMMARY + /* quote rfc 821/822 local part + /* SYNOPSIS + /* #include "quote_flags.h" + /* DESCRIPTION + /* .nf + + /* + * External interface. + */ + #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 + /* .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 + /*--*/ diff -cr --new-file /tmp/postfix-1.1.8/src/global/rec_type.h ./src/global/rec_type.h *** /tmp/postfix-1.1.8/src/global/rec_type.h Sun Dec 23 19:27:06 2001 --- ./src/global/rec_type.h Sun May 12 19:35:14 2002 *************** *** 58,64 **** */ #define REC_TYPE_ENVELOPE "MCTFILSDROWVA" #define REC_TYPE_CONTENT "XLN" ! #define REC_TYPE_EXTRACT "EDROPre" /* NOT A */ #define REC_TYPE_NOEXTRACT "E" /* --- 58,64 ---- */ #define REC_TYPE_ENVELOPE "MCTFILSDROWVA" #define REC_TYPE_CONTENT "XLN" ! #define REC_TYPE_EXTRACT "EDROPreA" #define REC_TYPE_NOEXTRACT "E" /* diff -cr --new-file /tmp/postfix-1.1.8/src/global/tok822_parse.c ./src/global/tok822_parse.c *** /tmp/postfix-1.1.8/src/global/tok822_parse.c Sun Dec 23 18:19:39 2001 --- ./src/global/tok822_parse.c Sun May 12 19:58:32 2002 *************** *** 107,112 **** --- 107,113 ---- /* Global library. */ + #include "quote_822_local.h" #include "tok822.h" /* *************** *** 221,226 **** --- 222,228 ---- VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags) { + VSTRING *tmp; TOK822 *tp; if (flags & TOK822_STR_WIPE) *************** *** 235,242 **** continue; } break; case TOK822_ADDR: ! tok822_externalize(vp, tp->head, TOK822_STR_NONE); break; case TOK822_ATOM: case TOK822_COMMENT: --- 237,256 ---- 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: ! tmp = vstring_alloc(100); ! tok822_internalize(tmp, tp->head, TOK822_STR_NONE); ! quote_822_local_flags(vp, vstring_str(tmp), ! QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND); ! vstring_free(tmp); break; case TOK822_ATOM: case TOK822_COMMENT: diff -cr --new-file /tmp/postfix-1.1.8/src/lmtp/Makefile.in ./src/lmtp/Makefile.in *** /tmp/postfix-1.1.8/src/lmtp/Makefile.in Fri Jan 25 09:11:18 2002 --- ./src/lmtp/Makefile.in Mon May 13 12:42:48 2002 *************** *** 162,167 **** --- 162,168 ---- lmtp_proto.o: ../../include/off_cvt.h lmtp_proto.o: ../../include/mark_corrupt.h lmtp_proto.o: ../../include/quote_821_local.h + lmtp_proto.o: ../../include/quote_flags.h lmtp_proto.o: lmtp.h lmtp_proto.o: ../../include/argv.h lmtp_proto.o: lmtp_sasl.h diff -cr --new-file /tmp/postfix-1.1.8/src/lmtp/lmtp_proto.c ./src/lmtp/lmtp_proto.c *** /tmp/postfix-1.1.8/src/lmtp/lmtp_proto.c Fri Dec 21 20:09:32 2001 --- ./src/lmtp/lmtp_proto.c Sun May 12 20:03:56 2002 *************** *** 294,305 **** * Macros for readability. XXX Aren't LMTP addresses supposed to be case * insensitive? */ ! #define REWRITE_ADDRESS(addr) do { \ ! if (*(addr)) { \ ! quote_821_local(state->scratch, addr); \ ! myfree(addr); \ ! addr = mystrdup(vstring_str(state->scratch)); \ ! lowercase(addr); \ } \ } while (0) --- 294,305 ---- * Macros for readability. XXX Aren't LMTP addresses supposed to be case * insensitive? */ ! #define REWRITE_ADDRESS(dst, src) do { \ ! if (*(src)) { \ ! quote_821_local(dst, src); \ ! lowercase(vstring_str(dst)); \ ! } else { \ ! vstring_strcpy(dst, src); \ } \ } while (0) *************** *** 357,366 **** * Build the MAIL FROM command. */ case LMTP_STATE_MAIL: ! if (*request->sender) ! REWRITE_ADDRESS(request->sender); ! vstring_sprintf(next_command, "MAIL FROM:<%s>", request->sender); ! if (state->features & LMTP_FEATURE_SIZE) vstring_sprintf_append(next_command, " SIZE=%lu", request->data_size); next_state = LMTP_STATE_RCPT; --- 357,366 ---- * Build the MAIL FROM command. */ case LMTP_STATE_MAIL: ! REWRITE_ADDRESS(state->scratch, request->sender); ! vstring_sprintf(next_command, "MAIL FROM:<%s>", ! vstring_str(state->scratch)); ! if (state->features & LMTP_FEATURE_SIZE) /* RFC 1652 */ vstring_sprintf_append(next_command, " SIZE=%lu", request->data_size); next_state = LMTP_STATE_RCPT; *************** *** 372,379 **** */ case LMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; ! REWRITE_ADDRESS(rcpt->address); ! vstring_sprintf(next_command, "RCPT TO:<%s>", rcpt->address); if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len) next_state = LMTP_STATE_DATA; break; --- 372,380 ---- */ case LMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; ! REWRITE_ADDRESS(state->scratch, rcpt->address); ! vstring_sprintf(next_command, "RCPT TO:<%s>", ! vstring_str(state->scratch)); if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len) next_state = LMTP_STATE_DATA; break; diff -cr --new-file /tmp/postfix-1.1.8/src/local/Makefile.in ./src/local/Makefile.in *** /tmp/postfix-1.1.8/src/local/Makefile.in Fri Jan 25 09:11:08 2002 --- ./src/local/Makefile.in Mon May 13 12:42:41 2002 *************** *** 139,144 **** --- 139,145 ---- delivered.o: ../../include/rec_type.h delivered.o: ../../include/is_header.h delivered.o: ../../include/quote_822_local.h + delivered.o: ../../include/quote_flags.h delivered.o: ../../include/header_opts.h delivered.o: local.h delivered.o: ../../include/been_here.h diff -cr --new-file /tmp/postfix-1.1.8/src/pickup/pickup.c ./src/pickup/pickup.c *** /tmp/postfix-1.1.8/src/pickup/pickup.c Fri Dec 28 12:58:57 2001 --- ./src/pickup/pickup.c Sun May 12 19:36:22 2002 *************** *** 181,186 **** --- 181,188 ---- info->rcpt = mystrdup(vstring_str(buf)); if (type == REC_TYPE_TIME) continue; + if (type == REC_TYPE_ATTR) + continue; if (type == REC_TYPE_FILT && *expected == REC_TYPE_ENVELOPE[0]) continue; else { diff -cr --new-file /tmp/postfix-1.1.8/src/pipe/Makefile.in ./src/pipe/Makefile.in *** /tmp/postfix-1.1.8/src/pipe/Makefile.in Fri Jan 25 09:11:49 2002 --- ./src/pipe/Makefile.in Mon May 13 12:43:05 2002 *************** *** 83,86 **** --- 83,87 ---- pipe.o: ../../include/split_addr.h pipe.o: ../../include/off_cvt.h pipe.o: ../../include/quote_822_local.h + pipe.o: ../../include/quote_flags.h pipe.o: ../../include/mail_server.h diff -cr --new-file /tmp/postfix-1.1.8/src/qmqpd/Makefile.in ./src/qmqpd/Makefile.in *** /tmp/postfix-1.1.8/src/qmqpd/Makefile.in Fri Jan 25 09:12:27 2002 --- ./src/qmqpd/Makefile.in Mon May 13 12:43:26 2002 *************** *** 92,97 **** --- 92,98 ---- qmqpd.o: ../../include/match_list.h qmqpd.o: ../../include/match_ops.h qmqpd.o: ../../include/quote_822_local.h + qmqpd.o: ../../include/quote_flags.h qmqpd.o: ../../include/match_parent_style.h qmqpd.o: ../../include/mail_server.h qmqpd.o: qmqpd.h diff -cr --new-file /tmp/postfix-1.1.8/src/showq/Makefile.in ./src/showq/Makefile.in *** /tmp/postfix-1.1.8/src/showq/Makefile.in Fri Jan 25 09:11:51 2002 --- ./src/showq/Makefile.in Mon May 13 12:43:07 2002 *************** *** 75,79 **** --- 75,82 ---- showq.o: ../../include/mail_conf.h showq.o: ../../include/record.h showq.o: ../../include/rec_type.h + showq.o: ../../include/quote_822_local.h + showq.o: ../../include/quote_flags.h + showq.o: ../../include/mail_addr.h showq.o: ../../include/bounce_log.h showq.o: ../../include/mail_server.h diff -cr --new-file /tmp/postfix-1.1.8/src/smtp/Makefile.in ./src/smtp/Makefile.in *** /tmp/postfix-1.1.8/src/smtp/Makefile.in Fri Jan 25 09:11:37 2002 --- ./src/smtp/Makefile.in Mon May 13 12:42:59 2002 *************** *** 166,171 **** --- 166,172 ---- smtp_proto.o: ../../include/off_cvt.h smtp_proto.o: ../../include/mark_corrupt.h smtp_proto.o: ../../include/quote_821_local.h + smtp_proto.o: ../../include/quote_flags.h smtp_proto.o: smtp.h smtp_proto.o: ../../include/argv.h smtp_proto.o: smtp_sasl.h diff -cr --new-file /tmp/postfix-1.1.8/src/smtp/smtp_proto.c ./src/smtp/smtp_proto.c *** /tmp/postfix-1.1.8/src/smtp/smtp_proto.c Sat May 4 09:38:59 2002 --- ./src/smtp/smtp_proto.c Sun May 12 20:04:37 2002 *************** *** 303,322 **** /* * Macros for readability. */ ! #define REWRITE_ADDRESS(addr) do { \ ! if (*(addr)) { \ ! quote_821_local(state->scratch, addr); \ ! smtp_unalias_addr(state->scratch2, vstring_str(state->scratch)); \ ! myfree(addr); \ ! addr = mystrdup(vstring_str(state->scratch2)); \ } \ } while (0) ! #define QUOTE_ADDRESS(addr) do { \ ! if (*(addr)) { \ ! quote_821_local(state->scratch, addr); \ ! myfree(addr); \ ! addr = mystrdup(vstring_str(state->scratch)); \ } \ } while (0) --- 303,322 ---- /* * Macros for readability. */ ! #define REWRITE_ADDRESS(dst, mid, src) do { \ ! if (*(src)) { \ ! quote_821_local(mid, src); \ ! smtp_unalias_addr(dst, vstring_str(mid)); \ ! } else { \ ! vstring_strcpy(dst, src); \ } \ } while (0) ! #define QUOTE_ADDRESS(dst, src) do { \ ! if (*(src)) { \ ! quote_821_local(dst, src); \ ! } else { \ ! vstring_strcpy(dst, src); \ } \ } while (0) *************** *** 408,419 **** */ case SMTP_STATE_MAIL: if (var_disable_dns == 0) { ! REWRITE_ADDRESS(request->sender); } else { ! QUOTE_ADDRESS(request->sender); } ! vstring_sprintf(next_command, "MAIL FROM:<%s>", request->sender); ! if (state->features & SMTP_FEATURE_SIZE) vstring_sprintf_append(next_command, " SIZE=%lu", request->data_size); next_state = SMTP_STATE_RCPT; --- 408,421 ---- */ case SMTP_STATE_MAIL: if (var_disable_dns == 0) { ! REWRITE_ADDRESS(state->scratch, state->scratch2, ! request->sender); } else { ! QUOTE_ADDRESS(state->scratch, request->sender); } ! vstring_sprintf(next_command, "MAIL FROM:<%s>", ! vstring_str(state->scratch)); ! if (state->features & SMTP_FEATURE_SIZE) /* RFC 1652 */ vstring_sprintf_append(next_command, " SIZE=%lu", request->data_size); next_state = SMTP_STATE_RCPT; *************** *** 426,436 **** case SMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; if (var_disable_dns == 0) { ! REWRITE_ADDRESS(rcpt->address); } else { ! QUOTE_ADDRESS(rcpt->address); } ! vstring_sprintf(next_command, "RCPT TO:<%s>", rcpt->address); if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len) next_state = SMTP_STATE_DATA; break; --- 428,440 ---- case SMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; if (var_disable_dns == 0) { ! REWRITE_ADDRESS(state->scratch, state->scratch2, ! rcpt->address); } else { ! QUOTE_ADDRESS(state->scratch, rcpt->address); } ! vstring_sprintf(next_command, "RCPT TO:<%s>", ! vstring_str(state->scratch)); if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len) next_state = SMTP_STATE_DATA; break; diff -cr --new-file /tmp/postfix-1.1.8/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c *** /tmp/postfix-1.1.8/src/smtpd/smtpd_check.c Mon Mar 18 15:10:27 2002 --- ./src/smtpd/smtpd_check.c Mon May 13 13:51:26 2002 *************** *** 1021,1026 **** --- 1021,1032 ---- domain += 1; /* + * Skip source-routed non-local or virtual mail (uncertain destination). + */ + if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED)) + return (SMTPD_CHECK_DUNNO); + + /* * Permit final delivery: the destination matches mydestination, * virtual_maps, or virtual_mailbox_maps. */ *************** *** 1028,1039 **** return (SMTPD_CHECK_OK); /* - * Skip source-routed mail (uncertain destination). - */ - if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED)) - return (SMTPD_CHECK_DUNNO); - - /* * Permit if the destination matches the relay_domains list. */ if (domain_list_match(relay_domains, domain)) --- 1034,1039 ---- *************** *** 1760,1775 **** { 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. */ ! #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)) /* * Look up user+foo@domain if the address has an extension, user@domain --- 1760,1774 ---- { if (bare_addr) myfree(bare_addr); return(x); } /* ! * 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(reply, reply_class) \ (var_allow_untrust_route == 0 \ && (reply->flags & RESOLVE_FLAG_ROUTED) \ ! && strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0) /* * Look up user+foo@domain if the address has an extension, user@domain *************** *** 1779,1785 **** found, reply_name, reply_class, def_acl)) != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(domain, reply, state, reply_name, reply_class) ? SMTPD_CHECK_DUNNO : status); /* --- 1778,1784 ---- found, reply_name, reply_class, def_acl)) != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(reply, reply_class) ? SMTPD_CHECK_DUNNO : status); /* *************** *** 1790,1796 **** found, reply_name, reply_class, def_acl)) != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(domain, reply, state, reply_name, reply_class) ? SMTPD_CHECK_DUNNO : status); /* --- 1789,1795 ---- found, reply_name, reply_class, def_acl)) != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(reply, reply_class) ? SMTPD_CHECK_DUNNO : status); /* *************** *** 1800,1806 **** found, reply_name, reply_class, def_acl)) != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(domain, reply, state, reply_name, reply_class) ? SMTPD_CHECK_DUNNO : status); /* --- 1799,1805 ---- found, reply_name, reply_class, def_acl)) != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(reply, reply_class) ? SMTPD_CHECK_DUNNO : status); /* *************** *** 1814,1820 **** myfree(local_at); if (status != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(domain, reply, state, reply_name, reply_class) ? SMTPD_CHECK_DUNNO : status); /* --- 1813,1819 ---- myfree(local_at); if (status != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(reply, reply_class) ? SMTPD_CHECK_DUNNO : status); /* *************** *** 1828,1834 **** myfree(local_at); if (status != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(domain, reply, state, reply_name, reply_class) ? SMTPD_CHECK_DUNNO : status); } --- 1827,1833 ---- myfree(local_at); if (status != 0 || *found) CHECK_MAIL_ACCESS_RETURN(status == SMTPD_CHECK_OK ! && SUSPICIOUS(reply, reply_class) ? SMTPD_CHECK_DUNNO : status); } diff -cr --new-file /tmp/postfix-1.1.8/src/trivial-rewrite/Makefile.in ./src/trivial-rewrite/Makefile.in *** /tmp/postfix-1.1.8/src/trivial-rewrite/Makefile.in Fri Jan 25 09:11:24 2002 --- ./src/trivial-rewrite/Makefile.in Mon May 13 12:42:51 2002 *************** *** 76,81 **** --- 76,82 ---- resolve.o: ../../include/resolve_local.h resolve.o: ../../include/mail_conf.h resolve.o: ../../include/quote_822_local.h + resolve.o: ../../include/quote_flags.h resolve.o: ../../include/tok822.h resolve.o: ../../include/resolve_clnt.h resolve.o: trivial-rewrite.h diff -cr --new-file /tmp/postfix-1.1.8/src/trivial-rewrite/resolve.c ./src/trivial-rewrite/resolve.c *** /tmp/postfix-1.1.8/src/trivial-rewrite/resolve.c Fri Nov 2 19:51:23 2001 --- ./src/trivial-rewrite/resolve.c Mon May 13 16:08:57 2002 *************** *** 97,105 **** /* * The address is in internalized (unquoted) form, so we must externalize * it first before we can parse it. */ ! quote_822_local(addr_buf, addr); ! tree = tok822_scan_addr(vstring_str(addr_buf)); /* * Preliminary resolver: strip off all instances of the local domain. --- 97,113 ---- /* * The address is in internalized (unquoted) form, so we must externalize * it first before we can parse it. + * + * But practically, we have to look at the unquoted form so that routing + * characters like @ remain visible, in order to stop user@domain@domain + * relay attempts when forwarding mail to a primary Sendmail MX host. */ ! if (var_resolve_dequoted) { ! tree = tok822_scan_addr(addr); ! } else { ! quote_822_local(addr_buf, addr); ! tree = tok822_scan_addr(vstring_str(addr_buf)); ! } /* * Preliminary resolver: strip off all instances of the local domain. diff -cr --new-file /tmp/postfix-1.1.8/src/trivial-rewrite/trivial-rewrite.c ./src/trivial-rewrite/trivial-rewrite.c *** /tmp/postfix-1.1.8/src/trivial-rewrite/trivial-rewrite.c Thu Jan 17 11:20:46 2002 --- ./src/trivial-rewrite/trivial-rewrite.c Mon May 13 16:08:09 2002 *************** *** 64,69 **** --- 64,75 ---- /* List of domains that this machine considers local. /* .IP \fBmyorigin\fR /* The domain that locally-posted mail appears to come from. + /* .IP \fBresolve_unquoted_address\fR + /* When resolving an address, do not quote the address localpart as + /* per RFC 822, so that additional \fB@\fR, \fB%\fR or \fB!\fR + /* characters remain visible. This is technically incorrect, but + /* allows us to stop relay attacks when forwarding mail to a Sendmail + /* primary MX host. /* .SH Rewriting /* .ad /* .fi *************** *** 167,172 **** --- 173,179 ---- bool var_append_at_myorigin; bool var_percent_hack; char *var_local_transport; + int var_resolve_dequoted; /* rewrite_service - read request and send reply */ *************** *** 234,239 **** --- 241,247 ---- VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain, VAR_APP_AT_MYORIGIN, DEF_APP_AT_MYORIGIN, &var_append_at_myorigin, VAR_PERCENT_HACK, DEF_PERCENT_HACK, &var_percent_hack, + VAR_RESOLVE_DEQUOTED, DEF_RESOLVE_DEQUOTED, &var_resolve_dequoted, 0, }; diff -cr --new-file /tmp/postfix-1.1.8/src/util/Makefile.in ./src/util/Makefile.in *** /tmp/postfix-1.1.8/src/util/Makefile.in Sat Feb 23 18:45:59 2002 --- ./src/util/Makefile.in Mon May 13 12:41:14 2002 *************** *** 1062,1067 **** --- 1062,1069 ---- stat_as.o: msg.h stat_as.o: set_eugid.h stat_as.o: stat_as.h + strcasecmp.o: strcasecmp.c + strcasecmp.o: sys_defs.h stream_connect.o: stream_connect.c stream_connect.o: sys_defs.h stream_connect.o: msg.h diff -cr --new-file /tmp/postfix-1.1.8/src/util/dict_ldap.c ./src/util/dict_ldap.c *** /tmp/postfix-1.1.8/src/util/dict_ldap.c Thu Jan 17 12:55:29 2002 --- ./src/util/dict_ldap.c Mon May 13 11:05:25 2002 *************** *** 586,592 **** */ if (*(sub) == '%') { char *u = vstring_str(escaped_name); ! char *p = strchr(u, '@'); switch (*(sub + 1)) { case 'd': --- 586,592 ---- */ if (*(sub) == '%') { char *u = vstring_str(escaped_name); ! char *p = strrchr(u, '@'); switch (*(sub + 1)) { case 'd':