From: Wietse Venema
Use a dedicated transport for all secure-channel deliveries.
+Use a dedicated transport that does not cache SMTP +connections. Otherwise, the hostname from the SMTP connection cache +overrides the hostname that Postfix uses for TLS policy lookup and +server certificate verification.
Eliminate MX lookups. Specify local transport(5) table -entries for sensitive domains with explicit smtp:[mailhost] -or smtp:[mailhost]:port destinations (you can assure -security of this table unlike DNS); in the smtp_tls_per_site -table, specify the value "MUST" for the key [mailhost] or -smtp:[mailhost]:port. This prevents false hostname -information in DNS MX records from changing Postfix's notion of the -server hostname that is used for TLS policy lookup and server certificate -verification.
+entries for sensitive domains with explicit securetls:[mailhost] +or securetls:[mailhost]:port destinations (you can +assure security of this table unlike DNS). This prevents false +hostname information in DNS MX records from changing Postfix's +notion of the server hostname that is used for TLS policy lookup +and server certificate verification. The "securetls" transport is +configured to enforce TLS with peername verification, and to disable +the SMTP connection cache which could interfere with enforcement +of smtp_tls_per_site policies.Disallow CNAME hostname overrides. In main.cf, specify "smtp_cname_overrides_servername = no". This prevents false hostname diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index b485dc1d8..cf3ea6b11 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -8229,7 +8229,13 @@ use smtp_tls_policy_maps inst discouraged. Always use the full destination nexthop (enclosed in [] with a possible ":port" suffix). A recipient domain or MX-enabled transport next-hop with no port suffix may look like a bare hostname, -but is still a suitable destination.
+but is still a suitable destination. The hostname lookup key +may not behave as you expect when SMTP connection caching is enabled +(see smtp_connection_cache_destinations and +smtp_connection_cache_on_demand). Different hostnames may resolve +to the same IP address, and the hostname from the SMTP connection +cache overrides the hostname that Postfix uses for TLS policy lookup +and server certificate verification.Specify a next-hop destination or server hostname on the left-hand side; no wildcards are allowed. The next-hop destination is either diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 8484d0216..4a085fda4 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -4683,7 +4683,13 @@ Use of the bare hostname as the per-site table lookup key is discouraged. Always use the full destination nexthop (enclosed in [] with a possible ":port" suffix). A recipient domain or MX-enabled transport next-hop with no port suffix may look like a bare hostname, -but is still a suitable \fIdestination\fR. +but is still a suitable \fIdestination\fR. The hostname lookup key +may not behave as you expect when SMTP connection caching is enabled +(see smtp_connection_cache_destinations and +smtp_connection_cache_on_demand). Different hostnames may resolve +to the same IP address, and the hostname from the SMTP connection +cache overrides the hostname that Postfix uses for TLS policy lookup +and server certificate verification. .PP Specify a next-hop destination or server hostname on the left-hand side; no wildcards are allowed. The next-hop destination is either diff --git a/postfix/proto/TLS_README.html b/postfix/proto/TLS_README.html index 7247efedc..00e7cbd93 100644 --- a/postfix/proto/TLS_README.html +++ b/postfix/proto/TLS_README.html @@ -1839,10 +1839,16 @@ the following information:
Use a dedicated transport for all secure-channel deliveries.
+Use a dedicated transport that does not cache SMTP +connections. Otherwise, the hostname from the SMTP connection cache +overrides the hostname that Postfix uses for TLS policy lookup and +server certificate verification.
Eliminate MX lookups. Specify local transport(5) table -entries for sensitive domains with explicit smtp:[mailhost] -or smtp:[mailhost]:port destinations (you can assure -security of this table unlike DNS); in the smtp_tls_per_site -table, specify the value "MUST" for the key [mailhost] or -smtp:[mailhost]:port. This prevents false hostname -information in DNS MX records from changing Postfix's notion of the -server hostname that is used for TLS policy lookup and server certificate -verification.
+entries for sensitive domains with explicit securetls:[mailhost] +or securetls:[mailhost]:port destinations (you can +assure security of this table unlike DNS). This prevents false +hostname information in DNS MX records from changing Postfix's +notion of the server hostname that is used for TLS policy lookup +and server certificate verification. The "securetls" transport is +configured to enforce TLS with peername verification, and to disable +the SMTP connection cache which could interfere with enforcement +of smtp_tls_per_site policies.Disallow CNAME hostname overrides. In main.cf, specify "smtp_cname_overrides_servername = no". This prevents false hostname diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 0918f8db9..b0e109933 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -8670,7 +8670,13 @@ use smtp_tls_policy_maps instead.
discouraged. Always use the full destination nexthop (enclosed in [] with a possible ":port" suffix). A recipient domain or MX-enabled transport next-hop with no port suffix may look like a bare hostname, -but is still a suitable destination. +but is still a suitable destination. The hostname lookup key +may not behave as you expect when SMTP connection caching is enabled +(see smtp_connection_cache_destinations and +smtp_connection_cache_on_demand). Different hostnames may resolve +to the same IP address, and the hostname from the SMTP connection +cache overrides the hostname that Postfix uses for TLS policy lookup +and server certificate verification.Specify a next-hop destination or server hostname on the left-hand side; no wildcards are allowed. The next-hop destination is either diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index edd0ad650..aefe5c413 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 "20060719" +#define MAIL_RELEASE_DATE "20060720" #define MAIL_VERSION_NUMBER "2.4" #ifdef SNAPSHOT diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index 8566d882e..711f1015a 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -488,7 +488,7 @@ static void milter8_close_stream(MILTER8 *milter) /* milter8_read_resp - receive command code now, receive data later */ static int milter8_read_resp(MILTER8 *milter, int event, unsigned char *command, - ssize_t *data_len) + ssize_t *data_len) { UINT32_TYPE len; ssize_t pkt_len; @@ -963,6 +963,10 @@ static const char *milter8_event(MILTER8 *milter, int event, #define IN_CONNECT_EVENT(e) ((e) == SMFIC_CONNECT || (e) == SMFIC_HELO) for (;;) { + char *cp; + char *rp; + char ch; + if (milter8_read_resp(milter, event, &cmd, &data_size) != 0) return (milter->def_reply); if (msg_verbose) @@ -1081,6 +1085,11 @@ static const char *milter8_event(MILTER8 *milter, int event, * Decision: "ddd d.d+.d+ text". This decision is final (i.e. * Sendmail 8 changes receiver state). Note: the reply may be in * multi-line SMTP format. + * + * XXX Sendmail compatibility: sendmail 8 uses the reply as a format + * string; therefore any '%' characters in the reply are doubled. + * Postfix doesn't use replies as format strings; we replace '%%' + * by '%', and remove single (i.e. invalid) '%' characters. */ case SMFIR_REPLYCODE: if (milter8_read_data(milter, data_size, @@ -1097,6 +1106,15 @@ static const char *milter8_event(MILTER8 *milter, int event, milter8_conf_error(milter); return (milter->def_reply); } + if ((rp = cp = strchr(STR(milter->buf), '%')) != 0) { + for (;;) { + if ((ch = *cp++) == '%') + ch = *cp++; + *rp++ = ch; + if (ch == 0) + break; + } + } if (IN_CONNECT_EVENT(event)) { #ifdef LIBMILTER_AUTO_DISCONNECT milter8_close_stream(milter); diff --git a/postfix/src/milter/test-list b/postfix/src/milter/test-list index 70ea9a4c5..62c4bb6b3 100644 --- a/postfix/src/milter/test-list +++ b/postfix/src/milter/test-list @@ -1,12 +1,12 @@ # Reject with text -./test-milter -C 1 -a "554 5.7.1 Rejected" -c connect -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c helo -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c mail -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c rcpt -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c header -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c eoh -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c body -p inet:9999@127.0.0.1 -./test-milter -C 1 -a "554 5.7.1 Rejected" -c eom -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c connect -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c helo -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c mail -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c rcpt -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c header -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c eoh -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c body -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 1% 2%% 3%%%" -c eom -p inet:9999@127.0.0.1 # Tempfail tests ./test-milter -C 1 -a tempfail -c connect -p inet:9999@127.0.0.1 diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index d617499d3..ad76eb800 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -328,30 +328,36 @@ int main(int argc, char **argv) exit(1); } break; -#ifdef SMFIR_INSHEADER case 'i': +#ifdef SMFIR_INSHEADER if (ins_hdr) { fprintf(stderr, "too many -i options\n"); exit(1); } parse_hdr_info(optarg, &ins_idx, &ins_hdr, &ins_val); - break; +#else + fprintf(stderr, "no libmilter support to insert header\n"); + exit(1); #endif + break; case 'p': if (smfi_setconn(optarg) == MI_FAILURE) { fprintf(stderr, "smfi_setconn failed\n"); exit(1); } break; -#ifdef SMFIR_CHGHEADER case 'r': +#ifdef SMFIR_CHGHEADER if (chg_hdr) { fprintf(stderr, "too many -r options\n"); exit(1); } parse_hdr_info(optarg, &chg_idx, &chg_hdr, &chg_val); - break; +#else + fprintf(stderr, "no libmilter support to change header\n"); + exit(1); #endif + break; case 'v': verbose++; break;