diff --git a/postfix/HISTORY b/postfix/HISTORY index e49e852ae..821d64f63 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -15487,3 +15487,14 @@ Apologies for any names omitted. caused by an incomplete API change; refined the queue space check; release scratch space immediately after delivering mail to the before-queue filter. Files: smtpd.c, smtpd_proxy.c. + +20091110 + + Workaround: specify "smtp_tls_block_early_mail_reply = yes" + to detect a mail hijacking attack based on a TLS protocol + vulnerability (CVE-2009-3555). The attack involves prepending + malicious HELO/MAIL/RCPT/DATA commands to a Postfix SMTP + client TLS session. The attack would succeed with non-Postfix + SMTP servers that reply to the malicious commands after + negotiating the Postfix SMTP client TLS session. File: + smtp/smtp_proto.c. diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index f6e9232a9..4114cf4b1 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -534,29 +534,37 @@ SMTP(8) SMTP(8) File with the Postfix SMTP client ECDSA private key in PEM format. + Available in Postfix version 2.7 and later: + + smtp_tls_block_early_mail_reply (no) + Try to detect a mail hijacking attack based on a + TLS protocol vulnerability (CVE-2009-3555), where + an attacker prepends malicious HELO/MAIL/RCPT/DATA + commands to a Postfix client TLS session. + OBSOLETE STARTTLS CONTROLS - The following configuration parameters exist for compati- + The following configuration parameters exist for compati- bility with Postfix versions before 2.3. Support for these will be removed in a future release. smtp_use_tls (no) - Opportunistic mode: use TLS when a remote SMTP - server announces STARTTLS support, otherwise send + Opportunistic mode: use TLS when a remote SMTP + server announces STARTTLS support, otherwise send the mail in the clear. smtp_enforce_tls (no) - Enforcement mode: require that remote SMTP servers - use TLS encryption, and never send mail in the + Enforcement mode: require that remote SMTP servers + use TLS encryption, and never send mail in the clear. smtp_tls_enforce_peername (yes) - With mandatory TLS encryption, require that the + With mandatory TLS encryption, require that the remote SMTP server hostname matches the information in the remote SMTP server certificate. smtp_tls_per_site (empty) Optional lookup tables with the Postfix SMTP client - TLS usage policy by next-hop destination and by + TLS usage policy by next-hop destination and by remote SMTP server hostname. smtp_tls_cipherlist (empty) @@ -566,27 +574,27 @@ SMTP(8) SMTP(8) RESOURCE AND RATE CONTROLS smtp_destination_concurrency_limit ($default_destina- tion_concurrency_limit) - The maximal number of parallel deliveries to the - same destination via the smtp message delivery + The maximal number of parallel deliveries to the + same destination via the smtp message delivery transport. smtp_destination_recipient_limit ($default_destina- tion_recipient_limit) - The maximal number of recipients per message for + The maximal number of recipients per message for the smtp message delivery transport. smtp_connect_timeout (30s) - The SMTP client time limit for completing a TCP + The SMTP client time limit for completing a TCP connection, or zero (use the operating system built-in time limit). smtp_helo_timeout (300s) - The SMTP client time limit for sending the HELO or - EHLO command, and for receiving the initial server + The SMTP client time limit for sending the HELO or + EHLO command, and for receiving the initial server response. lmtp_lhlo_timeout (300s) - The LMTP client time limit for sending the LHLO + The LMTP client time limit for sending the LHLO command, and for receiving the initial server response. @@ -595,30 +603,30 @@ SMTP(8) SMTP(8) command, and for receiving the server response. smtp_mail_timeout (300s) - The SMTP client time limit for sending the MAIL - FROM command, and for receiving the server + The SMTP client time limit for sending the MAIL + FROM command, and for receiving the server response. smtp_rcpt_timeout (300s) - The SMTP client time limit for sending the SMTP - RCPT TO command, and for receiving the server + The SMTP client time limit for sending the SMTP + RCPT TO command, and for receiving the server response. smtp_data_init_timeout (120s) - The SMTP client time limit for sending the SMTP - DATA command, and for receiving the server + The SMTP client time limit for sending the SMTP + DATA command, and for receiving the server response. smtp_data_xfer_timeout (180s) - The SMTP client time limit for sending the SMTP + The SMTP client time limit for sending the SMTP message content. smtp_data_done_timeout (600s) - The SMTP client time limit for sending the SMTP + The SMTP client time limit for sending the SMTP ".", and for receiving the server response. smtp_quit_timeout (300s) - The SMTP client time limit for sending the QUIT + The SMTP client time limit for sending the QUIT command, and for receiving the server response. Available in Postfix version 2.1 and later: @@ -629,12 +637,12 @@ SMTP(8) SMTP(8) lookups, or zero (no limit). smtp_mx_session_limit (2) - The maximal number of SMTP sessions per delivery - request before giving up or delivering to a fall- + The maximal number of SMTP sessions per delivery + request before giving up or delivering to a fall- back relay host, or zero (no limit). smtp_rset_timeout (20s) - The SMTP client time limit for sending the RSET + The SMTP client time limit for sending the RSET command, and for receiving the server response. Available in Postfix version 2.2 and earlier: @@ -646,11 +654,11 @@ SMTP(8) SMTP(8) Available in Postfix version 2.2 and later: smtp_connection_cache_destinations (empty) - Permanently enable SMTP connection caching for the + Permanently enable SMTP connection caching for the specified destinations. smtp_connection_cache_on_demand (yes) - Temporarily enable SMTP connection caching while a + Temporarily enable SMTP connection caching while a destination has a high volume of mail in the active queue. @@ -660,62 +668,62 @@ SMTP(8) SMTP(8) smtp_connection_cache_time_limit (2s) When SMTP connection caching is enabled, the amount - of time that an unused SMTP client socket is kept + of time that an unused SMTP client socket is kept open before it is closed. Available in Postfix version 2.3 and later: connection_cache_protocol_timeout (5s) - Time limit for connection cache connect, send or + Time limit for connection cache connect, send or receive operations. TROUBLE SHOOTING CONTROLS debug_peer_level (2) - The increment in verbose logging level when a - remote client or server matches a pattern in the + The increment in verbose logging level when a + remote client or server matches a pattern in the debug_peer_list parameter. debug_peer_list (empty) - Optional list of remote client or server hostname - or network address patterns that cause the verbose - logging level to increase by the amount specified + Optional list of remote client or server hostname + or network address patterns that cause the verbose + logging level to increase by the amount specified in $debug_peer_level. error_notice_recipient (postmaster) - The recipient of postmaster notifications about - mail delivery problems that are caused by policy, + The recipient of postmaster notifications about + mail delivery problems that are caused by policy, resource, software or protocol errors. internal_mail_filter_classes (empty) - What categories of Postfix-generated mail are sub- - ject to before-queue content inspection by + What categories of Postfix-generated mail are sub- + ject to before-queue content inspection by non_smtpd_milters, header_checks and body_checks. notify_classes (resource, software) - The list of error classes that are reported to the + The list of error classes that are reported to the postmaster. MISCELLANEOUS CONTROLS best_mx_transport (empty) - Where the Postfix SMTP client should deliver mail + Where the Postfix SMTP client should deliver mail when it detects a "mail loops back to myself" error condition. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to - handle a request before it is terminated by a + How much time a Postfix daemon process may take to + handle a request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal + The maximal number of digits after the decimal point when logging sub-second delay values. disable_dns_lookups (no) - Disable DNS lookups in the Postfix SMTP and LMTP + Disable DNS lookups in the Postfix SMTP and LMTP clients. inet_interfaces (all) @@ -723,7 +731,7 @@ SMTP(8) SMTP(8) tem receives mail on. inet_protocols (ipv4) - The Internet protocols Postfix will attempt to use + The Internet protocols Postfix will attempt to use when making or accepting connections. ipc_timeout (3600s) @@ -731,81 +739,81 @@ SMTP(8) SMTP(8) over an internal communication channel. lmtp_assume_final (no) - When an LMTP server announces no DSN support, + When an LMTP server announces no DSN support, assume that the server performs final delivery, and - send "delivered" delivery status notifications + send "delivered" delivery status notifications instead of "relayed". lmtp_tcp_port (24) - The default TCP port that the Postfix LMTP client + The default TCP port that the Postfix LMTP client connects to. max_idle (100s) - The maximum amount of time that an idle Postfix - daemon process waits for an incoming connection + The maximum amount of time that an idle Postfix + daemon process waits for an incoming connection before terminating voluntarily. max_use (100) - The maximal number of incoming connections that a - Postfix daemon process will service before termi- + The maximal number of incoming connections that a + Postfix daemon process will service before termi- nating voluntarily. process_id (read-only) - The process ID of a Postfix command or daemon + The process ID of a Postfix command or daemon process. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. proxy_interfaces (empty) The network interface addresses that this mail sys- - tem receives mail on by way of a proxy or network + tem receives mail on by way of a proxy or network address translation unit. smtp_bind_address (empty) - An optional numerical network address that the - Postfix SMTP client should bind to when making an + An optional numerical network address that the + Postfix SMTP client should bind to when making an IPv4 connection. smtp_bind_address6 (empty) - An optional numerical network address that the - Postfix SMTP client should bind to when making an + An optional numerical network address that the + Postfix SMTP client should bind to when making an IPv6 connection. smtp_helo_name ($myhostname) - The hostname to send in the SMTP EHLO or HELO com- + The hostname to send in the SMTP EHLO or HELO com- mand. lmtp_lhlo_name ($myhostname) The hostname to send in the LMTP LHLO command. smtp_host_lookup (dns) - What mechanisms when the Postfix SMTP client uses - to look up a host's IP address. + What mechanisms the Postfix SMTP client uses to + look up a host's IP address. smtp_randomize_addresses (yes) - Randomize the order of equal-preference MX host + Randomize the order of equal-preference MX host addresses. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - The mail system name that is prepended to the - process name in syslog records, so that "smtpd" + The mail system name that is prepended to the + process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". Available with Postfix 2.2 and earlier: fallback_relay (empty) - Optional list of relay hosts for SMTP destinations + Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. Available with Postfix 2.3 and later: smtp_fallback_relay ($fallback_relay) - Optional list of relay hosts for SMTP destinations + Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. SEE ALSO @@ -826,7 +834,7 @@ SMTP(8) SMTP(8) TLS_README, Postfix STARTTLS howto LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 779f6ddf0..637d2a58f 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -9236,6 +9236,21 @@ must be inside the chroot jail.
This feature is available in Postfix 2.2 and later.
+ + +Try to detect a mail hijacking attack based on a TLS protocol +vulnerability (CVE-2009-3555), where an attacker prepends malicious +HELO/MAIL/RCPT/DATA commands to a Postfix client TLS session. The +attack would succeed with non-Postfix SMTP servers that reply to +the malicious HELO/MAIL/RCPT/DATA commands after negotiating the +Postfix SMTP client TLS session.
+ +This feature is available in Postfix 2.7.
+ +This feature is available in Postfix 2.7.
+ +%PARAM smtp_tls_block_early_mail_reply no + +Try to detect a mail hijacking attack based on a TLS protocol +vulnerability (CVE-2009-3555), where an attacker prepends malicious +HELO/MAIL/RCPT/DATA commands to a Postfix client TLS session. The +attack would succeed with non-Postfix SMTP servers that reply to +the malicious HELO/MAIL/RCPT/DATA commands after negotiating the +Postfix SMTP client TLS session.
+ +This feature is available in Postfix 2.7.
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 6a1fa321c..548cbef93 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1465,6 +1465,12 @@ extern char *var_smtp_tls_sec_cmatch; #define DEF_LMTP_TLS_FPT_CMATCH "" extern char *var_smtp_tls_fpt_cmatch; +#define VAR_SMTP_TLS_BLK_EARLY_MAIL_REPLY "smtp_tls_block_early_mail_reply" +#define DEF_SMTP_TLS_BLK_EARLY_MAIL_REPLY 0 +#define VAR_LMTP_TLS_BLK_EARLY_MAIL_REPLY "lmtp_tls_block_early_mail_reply" +#define DEF_LMTP_TLS_BLK_EARLY_MAIL_REPLY 0 +extern bool var_smtp_tls_blk_early_mail_reply; + /* * SASL authentication support, SMTP server side. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index e0c2c22a3..bb091f28c 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 "20091109" +#define MAIL_RELEASE_DATE "20091110" #define MAIL_VERSION_NUMBER "2.7" #ifdef SNAPSHOT diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c index dbadd98bc..ad6b0b15a 100644 --- a/postfix/src/smtp/lmtp_params.c +++ b/postfix/src/smtp/lmtp_params.c @@ -99,6 +99,7 @@ #ifdef USE_TLS VAR_LMTP_TLS_ENFORCE_PN, DEF_LMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername, VAR_LMTP_TLS_NOTEOFFER, DEF_LMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer, + VAR_LMTP_TLS_BLK_EARLY_MAIL_REPLY, DEF_LMTP_TLS_BLK_EARLY_MAIL_REPLY, &var_smtp_tls_blk_early_mail_reply, #endif VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth, VAR_LMTP_CNAME_OVERR, DEF_LMTP_CNAME_OVERR, &var_smtp_cname_overr, diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index d43625434..06469e21d 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -400,6 +400,12 @@ /* File with the Postfix SMTP client ECDSA certificate in PEM format. /* .IP "\fBsmtp_tls_eckey_file ($smtp_tls_eccert_file)\fR" /* File with the Postfix SMTP client ECDSA private key in PEM format. +/* .PP +/* Available in Postfix version 2.7 and later: +/* .IP "\fBsmtp_tls_block_early_mail_reply (no)\fR" +/* Try to detect a mail hijacking attack based on a TLS protocol +/* vulnerability (CVE-2009-3555), where an attacker prepends malicious +/* HELO/MAIL/RCPT/DATA commands to a Postfix client TLS session. /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -572,7 +578,7 @@ /* .IP "\fBlmtp_lhlo_name ($myhostname)\fR" /* The hostname to send in the LMTP LHLO command. /* .IP "\fBsmtp_host_lookup (dns)\fR" -/* What mechanisms when the Postfix SMTP client uses to look up a host's IP +/* What mechanisms the Postfix SMTP client uses to look up a host's IP /* address. /* .IP "\fBsmtp_randomize_addresses (yes)\fR" /* Randomize the order of equal-preference MX host addresses. @@ -769,6 +775,7 @@ char *var_smtp_tls_proto; char *var_smtp_tls_ciph; char *var_smtp_tls_eccert_file; char *var_smtp_tls_eckey_file; +bool var_smtp_tls_blk_early_mail_reply; #endif diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index d1ecf37fe..3e5e24172 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -119,6 +119,7 @@ typedef struct SMTP_STATE { #define SMTP_FEATURE_PIX_NO_ESMTP (1<<16) /* PIX smtp fixup mode */ #define SMTP_FEATURE_PIX_DELAY_DOTCRLF (1<<17) /* PIX smtp fixup mode */ #define SMTP_FEATURE_XFORWARD_PORT (1<<18) +#define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */ /* * Features that passivate under the endpoint. diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c index 4c8afe881..f0bf35736 100644 --- a/postfix/src/smtp/smtp_params.c +++ b/postfix/src/smtp/smtp_params.c @@ -103,6 +103,7 @@ #ifdef USE_TLS VAR_SMTP_TLS_ENFORCE_PN, DEF_SMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername, VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer, + VAR_SMTP_TLS_BLK_EARLY_MAIL_REPLY, DEF_SMTP_TLS_BLK_EARLY_MAIL_REPLY, &var_smtp_tls_blk_early_mail_reply, #endif VAR_SMTP_SENDER_AUTH, DEF_SMTP_SENDER_AUTH, &var_smtp_sender_auth, VAR_SMTP_CNAME_OVERR, DEF_SMTP_CNAME_OVERR, &var_smtp_cname_overr, diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index c74b5fbce..e9586c844 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -1292,6 +1292,36 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, && (session->features & SMTP_FEATURE_AUTH)) vstring_strcat(next_command, " AUTH=<>"); #endif + + /* + * CVE-2009-3555 (TLS renegotiation). Try to detect a mail + * hijacking attack that prepends malicious EHLO/MAIL/RCPT/DATA + * commands to our TLS session. + * + * For the attack to succeed, the remote SMTP server must reply to + * the malicious EHLO/MAIL/RCPT/DATA commands after completing + * TLS (re)negotiation, so that the replies arrive in our TLS + * session (otherwise the Postfix SMTP client would time out + * waiting for an answer). With some luck we can detect this + * specific attack as a server MAIL reply that arrives before we + * send our own MAIL command. + * + * We don't apply this test to the HELO command because the result + * would be very timing sensitive, and we don't apply this test + * to RCPT and DATA replies because these may be pipelined for + * legitimate reasons. + */ +#ifdef USE_TLS + if (var_smtp_tls_blk_early_mail_reply + && (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) != 0 + && (vstream_peek(session->stream) > 0 + || peekfd(vstream_fileno(session->stream)) > 0)) + session->features |= SMTP_FEATURE_EARLY_TLS_MAIL_REPLY; +#endif + + /* + * We now return to our regular broadcast. + */ next_state = SMTP_STATE_RCPT; break; @@ -1512,6 +1542,32 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, xfer_request[SMTP_STATE_MAIL]); mail_from_rejected = 1; } + + /* + * CVE-2009-3555 (TLS renegotiation). Whatever it was + * that arrived before we sent our MAIL FROM command, it + * was not a fatal-level TLS alert message. It could be a + * warning-level TLS alert message, or a ChangeCipherSpec + * message, but such messages are not normally sent in + * the middle of a TLS session. We disconnect and try + * again later. + */ +#ifdef USE_TLS + if (var_smtp_tls_blk_early_mail_reply + && (session->features & SMTP_FEATURE_EARLY_TLS_MAIL_REPLY)) { + smtp_site_fail(state, DSN_BY_LOCAL_MTA, + SMTP_RESP_FAKE(&fake, "4.7.0"), + "unexpected server message"); + msg_warn("server %s violates %s policy", + session->namaddr, + VAR_SMTP_TLS_BLK_EARLY_MAIL_REPLY); + mail_from_rejected = 1; + } +#endif + + /* + * We now return to our regular broadcast. + */ recv_state = SMTP_STATE_RCPT; break; diff --git a/postfix/src/util/inet_addr_local.c b/postfix/src/util/inet_addr_local.c index 1ebf3fc6e..a54a84899 100644 --- a/postfix/src/util/inet_addr_local.c +++ b/postfix/src/util/inet_addr_local.c @@ -183,6 +183,9 @@ static int ial_getifaddrs(INET_ADDR_LIST *addr_list, for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (!(ifa->ifa_flags & IFF_UP) || ifa->ifa_addr == 0) continue; + /* XXX Should we cons up a default mask instead? */ + if (ifa->ifa_netmask == 0) + continue; sa = ifa->ifa_addr; sam = ifa->ifa_netmask; if (af != AF_UNSPEC && sa->sa_family != af)