diff --git a/postfix/HISTORY b/postfix/HISTORY index 19eef1a2e..50274e0f3 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -16337,5 +16337,15 @@ Apologies for any names omitted. TLS <=> plaintext for postscreen(8). One tlsproxy(8) process can translate traffic for multiple remote SMTP clients. With early testing feedback from Victor Duchovni and Christian - Roessner. Files: util/nbbio.c, tlsproxy/starttlsd.c, - tlsproxy/starttlsd_state.c. + Roessner. Files: util/nbbio.[hc], tlsproxy/*.[hc], + postscreen/postscreen_starttlsd.c, postscreen/postscreen_smtpd.c. + +20101103 + + Cleanup: missing tls_level support in tlsproxy (it has no + way to send plaintext, but perhaps an informative error + message is in order anyway). File: tlsproxy/tlsproxy.c. + + Cleanup: simplified the handling of throttled output (i.e. + output that can't be sent because the receiver tries to be + nasty). File: postscreen/postscreen_send.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 3092ca6fc..016482248 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -4,7 +4,12 @@ Wish list: anvil rate limit for sasl_username. - encapsulate nbbio buffer access and update by tlsproxy. + Encapsulate nbbio buffer access and update by tlsproxy. + + Full-duplex support for tlsproxy(8). This requires updating + events(3) and nbbio(3). + + Register automagic destructor for object attached to VSTREAM. smtpd xclient option for sasl_username. diff --git a/postfix/html/postscreen.8.html b/postfix/html/postscreen.8.html index a4ab206fc..4f7250d7e 100644 --- a/postfix/html/postscreen.8.html +++ b/postfix/html/postscreen.8.html @@ -60,98 +60,101 @@ POSTSCREEN(8) POSTSCREEN(8) RFC 3207 (STARTTLS command) RFC 3461 (SMTP DSN Extension) RFC 3463 (Enhanced Status Codes) - RFC 5321 (SMTP protocol, including multi-line 220 greetings) + RFC 5321 (SMTP protocol, including multi-line 220 banners) DIAGNOSTICS Problems and transactions are logged to syslogd(8). BUGS - The postscreen(8) built-in SMTP protocol engine currently - does not announce support for AUTH, XCLIENT or XFORWARD. - Support for AUTH may be added in the future. In the mean + The postscreen(8) server does not yet implement the + soft_bounce feature. + + The postscreen(8) built-in SMTP protocol engine currently + does not announce support for AUTH, XCLIENT or XFORWARD. + Support for AUTH may be added in the future. In the mean time, if you need to make these services available on port - 25, then do not enable the optional "after 220 server + 25, then do not enable the optional "after 220 server greeting" tests. - The optional "after 220 server greeting" tests involve - postscreen(8)'s built-in SMTP protocol engine. When these + The optional "after 220 server greeting" tests involve + postscreen(8)'s built-in SMTP protocol engine. When these tests succeed, postscreen(8) adds the client to the tempo- - rary whitelist but it cannot not hand off the "live" con- - nection to a Postfix SMTP server process in the middle of - a session. Instead, postscreen(8) defers attempts to - deliver mail with a 4XX status, and waits for the client - to disconnect. The next time a good client connects, it - will be allowed to talk to a Postfix SMTP server process - to deliver mail. postscreen(8) mitigates the impact of - this limitation by giving such tests a long expiration + rary whitelist but it cannot not hand off the "live" con- + nection to a Postfix SMTP server process in the middle of + a session. Instead, postscreen(8) defers attempts to + deliver mail with a 4XX status, and waits for the client + to disconnect. The next time a good client connects, it + will be allowed to talk to a Postfix SMTP server process + to deliver mail. postscreen(8) mitigates the impact of + this limitation by giving such tests a long expiration time. CONFIGURATION PARAMETERS - Changes to main.cf are not picked up automatically, as - postscreen(8) processes may run for several hours. Use + Changes to main.cf are not picked up automatically, as + postscreen(8) processes may run for several hours. Use the command "postfix reload" after a configuration change. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. NOTE: Some postscreen(8) parameters implement stress- - dependent behavior. This is supported only when the - default parameter value is stress-dependent (that is, it - looks like ${stress?X}${stress:Y}, or it is the $name of + dependent behavior. This is supported only when the + default parameter value is stress-dependent (that is, it + looks like ${stress?X}${stress:Y}, or it is the $name of an smtpd parameter with a stress-dependent default). - Other parameters always evaluate as if the stress parame- + Other parameters always evaluate as if the stress parame- ter value is the empty string. COMPATIBILITY CONTROLS postscreen_discard_ehlo_keyword_address_maps ($smtpd_dis- card_ehlo_keyword_address_maps) - Lookup tables, indexed by the remote SMTP client - address, with case insensitive lists of EHLO key- - words (pipelining, starttls, auth, etc.) that the - postscreen(8) server will not send in the EHLO + Lookup tables, indexed by the remote SMTP client + address, with case insensitive lists of EHLO key- + words (pipelining, starttls, auth, etc.) that the + postscreen(8) server will not send in the EHLO response to a remote SMTP client. postscreen_discard_ehlo_keywords ($smtpd_discard_ehlo_key- words) - A case insensitive list of EHLO keywords (pipelin- - ing, starttls, auth, etc.) that the postscreen(8) - server will not send in the EHLO response to a + A case insensitive list of EHLO keywords (pipelin- + ing, starttls, auth, etc.) that the postscreen(8) + server will not send in the EHLO response to a remote SMTP client. TRIAGE PARAMETERS postscreen_bare_newline_action (ignore) - The action that postscreen(8) takes when an SMTP - client sends a bare newline character, that is, a + The action that postscreen(8) takes when an SMTP + client sends a bare newline character, that is, a newline not preceded by carriage return. postscreen_bare_newline_enable (no) - Enable "bare newline" SMTP protocol tests in the + Enable "bare newline" SMTP protocol tests in the postscreen(8) server. postscreen_blacklist_action (ignore) - The action that postscreen(8) takes when an SMTP - client is permanently blacklisted with the + The action that postscreen(8) takes when an SMTP + client is permanently blacklisted with the postscreen_blacklist_networks parameter. postscreen_blacklist_networks (empty) Network addresses that are permanently blacklisted; - see the postscreen_blacklist_action parameter for + see the postscreen_blacklist_action parameter for possible actions. postscreen_disable_vrfy_command ($disable_vrfy_command) - Disable the SMTP VRFY command in the postscreen(8) + Disable the SMTP VRFY command in the postscreen(8) daemon. postscreen_dnsbl_action (ignore) - The action that postscreen(8) takes when an SMTP + The action that postscreen(8) takes when an SMTP client's combined DNSBL score is equal to or - greater than a threshold (as defined with the + greater than a threshold (as defined with the postscreen_dnsbl_sites and postscreen_dnsbl_thresh- old parameters). postscreen_dnsbl_reply_map (empty) - A mapping from actual DNSBL domain name which - includes a secret password, to the DNSBL domain + A mapping from actual DNSBL domain name which + includes a secret password, to the DNSBL domain name that postscreen will reply with when it rejects mail. @@ -160,16 +163,16 @@ POSTSCREEN(8) POSTSCREEN(8) weight factors. postscreen_dnsbl_threshold (1) - The inclusive lower bound for blocking an SMTP + The inclusive lower bound for blocking an SMTP client, based on its combined DNSBL score as - defined with the postscreen_dnsbl_sites parameter. + defined with the postscreen_dnsbl_sites parameter. postscreen_forbidden_commands ($smtpd_forbidden_commands) List of commands that the postscreen(8) server con- siders in violation of the SMTP protocol. postscreen_greet_action (ignore) - The action that postscreen(8) takes when an SMTP + The action that postscreen(8) takes when an SMTP client speaks before its turn within the time spec- ified with the postscreen_greet_wait parameter. @@ -177,151 +180,151 @@ POSTSCREEN(8) POSTSCREEN(8) The text in the optional "220-text..." server response that postscreen(8) sends ahead of the real Postfix SMTP server's "220 text..." response, in an - attempt to confuse bad SMTP clients so that they + attempt to confuse bad SMTP clients so that they speak before their turn (pre-greet). postscreen_greet_wait (${stress?2}${stress:6}s) The amount of time that postscreen(8) will wait for - an SMTP client to send a command before its turn, - and for DNS blocklist lookup results to arrive - (default: up to 2 seconds under stress, up to 6 + an SMTP client to send a command before its turn, + and for DNS blocklist lookup results to arrive + (default: up to 2 seconds under stress, up to 6 seconds otherwise). postscreen_helo_required ($smtpd_helo_required) - Require that a remote SMTP client sends HELO or + Require that a remote SMTP client sends HELO or EHLO before commencing a MAIL transaction. postscreen_non_smtp_command_action (drop) - The action that postscreen(8) takes when an SMTP - client sends non-SMTP commands as specified with + The action that postscreen(8) takes when an SMTP + client sends non-SMTP commands as specified with the postscreen_forbidden_commands parameter. postscreen_non_smtp_command_enable (no) - Enable "non-SMTP command" tests in the + Enable "non-SMTP command" tests in the postscreen(8) server. postscreen_pipelining_action (enforce) - The action that postscreen(8) takes when an SMTP - client sends multiple commands instead of sending - one command and waiting for the server to respond. + The action that postscreen(8) takes when an SMTP + client sends multiple commands instead of sending + one command and waiting for the server to respond. postscreen_pipelining_enable (no) - Enable "pipelining" SMTP protocol tests in the + Enable "pipelining" SMTP protocol tests in the postscreen(8) server. postscreen_whitelist_networks ($mynetworks) Network addresses that are permanently whitelisted, - and that will not be subjected to postscreen(8) + and that will not be subjected to postscreen(8) checks. smtpd_service_name (smtpd) - The internal service that postscreen(8) forwards + The internal service that postscreen(8) forwards allowed connections to. CACHE CONTROLS postscreen_cache_cleanup_interval (12h) - The amount of time between postscreen(8) cache + The amount of time between postscreen(8) cache cleanup runs. postscreen_cache_map (btree:$data_directory/ps_cache) - Persistent storage for the postscreen(8) server + Persistent storage for the postscreen(8) server decisions. postscreen_cache_retention_time (7d) The amount of time that postscreen(8) will cache an - expired temporary whitelist entry before it is + expired temporary whitelist entry before it is removed. postscreen_bare_newline_ttl (30d) - The amount of time that postscreen(8) will cache - results from a successful "bare newline" SMTP pro- + The amount of time that postscreen(8) will cache + results from a successful "bare newline" SMTP pro- tocol test. postscreen_dnsbl_ttl (1h) - The amount of time that postscreen(8) will cache + The amount of time that postscreen(8) will cache results from a successful DNS blocklist test. postscreen_greet_ttl (1d) - The amount of time that postscreen(8) will cache + The amount of time that postscreen(8) will cache results from a successful PREGREET test. postscreen_non_smtp_command_ttl (30d) - The amount of time that postscreen(8) will cache - results from a successful "non_smtp_command" SMTP + The amount of time that postscreen(8) will cache + results from a successful "non_smtp_command" SMTP protocol test. postscreen_pipelining_ttl (30d) - The amount of time that postscreen(8) will cache - results from a successful "pipelining" SMTP proto- + The amount of time that postscreen(8) will cache + results from a successful "pipelining" SMTP proto- col test. RESOURCE CONTROLS line_length_limit (2048) - Upon input, long lines are chopped up into pieces - of at most this length; upon delivery, long lines + Upon input, long lines are chopped up into pieces + of at most this length; upon delivery, long lines are reconstructed. postscreen_client_connection_count_limit ($smtpd_client_connection_count_limit) - How many simultaneous connections any client is + How many simultaneous connections any client is allowed to have with the postscreen(8) daemon. postscreen_command_count_limit (20) - The limit on the total number of commands per SMTP - session for postscreen(8)'s built-in SMTP protocol + The limit on the total number of commands per SMTP + session for postscreen(8)'s built-in SMTP protocol engine. postscreen_command_time_limit (${stress?10}${stress:300}s) - The command "read" time limit for postscreen(8)'s + The command "read" time limit for postscreen(8)'s built-in SMTP protocol engine. postscreen_post_queue_limit ($default_process_limit) - The number of clients that can be waiting for ser- + The number of clients that can be waiting for ser- vice from a real SMTP server process. postscreen_pre_queue_limit ($default_process_limit) - The number of non-whitelisted clients that can be - waiting for a decision whether they will receive + The number of non-whitelisted clients that can be + waiting for a decision whether they will receive service from a real SMTP server process. postscreen_watchdog_timeout (10s) - How much time a postscreen(8) process may take to - respond to an SMTP client command or to perform a + How much time a postscreen(8) process may take to + respond to an SMTP client command or to perform a cache operation before it is terminated by a built- in watchdog timer. STARTTLS CONTROLS postscreen_tls_security_level ($smtpd_tls_security_level) - The SMTP TLS security level for the postscreen(8) - server; when a non-empty value is specified, this + The SMTP TLS security level for the postscreen(8) + server; when a non-empty value is specified, this overrides the obsolete parameters postscreen_use_tls and postscreen_enforce_tls. OBSOLETE STARTTLS SUPPORT CONTROLS - These parameters are supported for compatibility with + These parameters are supported for compatibility with smtpd(8) legacy parameters. postscreen_use_tls ($smtpd_use_tls) - Opportunistic TLS: announce STARTTLS support to - SMTP clients, but do not require that clients use + Opportunistic TLS: announce STARTTLS support to + SMTP clients, but do not require that clients use TLS encryption. postscreen_enforce_tls ($smtpd_enforce_tls) - Mandatory TLS: announce STARTTLS support to SMTP - clients, and require that clients use TLS encryp- + Mandatory TLS: announce STARTTLS support to SMTP + clients, and require that clients use TLS encryp- tion. MISCELLANEOUS CONTROLS 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. 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. command_directory (see 'postconf -d' output) - The location of all postfix administrative com- + The location of all postfix administrative com- mands. ipc_timeout (3600s) @@ -329,24 +332,24 @@ POSTSCREEN(8) POSTSCREEN(8) over an internal communication channel. 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. 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. 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". SEE ALSO @@ -359,12 +362,12 @@ POSTSCREEN(8) POSTSCREEN(8) POSTSCREEN_README, Postfix Postscreen Howto LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. HISTORY - Many ideas in postscreen(8) were explored in earlier work - by Michael Tokarev, in OpenBSD spamd, and in MailChannels + Many ideas in postscreen(8) were explored in earlier work + by Michael Tokarev, in OpenBSD spamd, and in MailChannels Traffic Control. AUTHOR(S) diff --git a/postfix/man/man8/postscreen.8 b/postfix/man/man8/postscreen.8 index f8acab135..67b09c982 100644 --- a/postfix/man/man8/postscreen.8 +++ b/postfix/man/man8/postscreen.8 @@ -63,7 +63,7 @@ RFC 2920 (SMTP Pipelining) RFC 3207 (STARTTLS command) RFC 3461 (SMTP DSN Extension) RFC 3463 (Enhanced Status Codes) -RFC 5321 (SMTP protocol, including multi-line 220 greetings) +RFC 5321 (SMTP protocol, including multi-line 220 banners) .SH DIAGNOSTICS .ad .fi @@ -71,6 +71,9 @@ Problems and transactions are logged to \fBsyslogd\fR(8). .SH BUGS .ad .fi +The \fBpostscreen\fR(8) server does not yet implement +the \fBsoft_bounce\fR feature. + The \fBpostscreen\fR(8) built-in SMTP protocol engine currently does not announce support for AUTH, XCLIENT or XFORWARD. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index c1e99f217..c7ae8e44e 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 "20110102" +#define MAIL_RELEASE_DATE "20110103" #define MAIL_VERSION_NUMBER "2.8" #ifdef SNAPSHOT diff --git a/postfix/src/postscreen/Makefile.in b/postfix/src/postscreen/Makefile.in index b856fc5ff..5e41241a9 100644 --- a/postfix/src/postscreen/Makefile.in +++ b/postfix/src/postscreen/Makefile.in @@ -180,6 +180,7 @@ postscreen_send.o: ../../include/dict_cache.h postscreen_send.o: ../../include/events.h postscreen_send.o: ../../include/htable.h postscreen_send.o: ../../include/iostuff.h +postscreen_send.o: ../../include/mail_params.h postscreen_send.o: ../../include/match_list.h postscreen_send.o: ../../include/match_ops.h postscreen_send.o: ../../include/msg.h diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c index f40f25e01..580955461 100644 --- a/postfix/src/postscreen/postscreen.c +++ b/postfix/src/postscreen/postscreen.c @@ -53,10 +53,13 @@ /* RFC 3207 (STARTTLS command) /* RFC 3461 (SMTP DSN Extension) /* RFC 3463 (Enhanced Status Codes) -/* RFC 5321 (SMTP protocol, including multi-line 220 greetings) +/* RFC 5321 (SMTP protocol, including multi-line 220 banners) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* BUGS +/* The \fBpostscreen\fR(8) server does not yet implement +/* the \fBsoft_bounce\fR feature. +/* /* The \fBpostscreen\fR(8) built-in SMTP protocol engine /* currently does not announce support for AUTH, XCLIENT or /* XFORWARD. @@ -542,9 +545,10 @@ static void psc_service(VSTREAM *smtp_client_stream, if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *) & addr_storage, &addr_storage_len) < 0) { msg_warn("getpeername: %m -- dropping this connection"); - psc_send_reply(vstream_fileno(smtp_client_stream), - "unknown_address", "unknown_port", - "421 4.3.2 No system resources\r\n"); + /* Best effort - if this non-blocking write(2) fails, so be it. */ + (void) write(vstream_fileno(smtp_client_stream), + "421 4.3.2 No system resources\r\n", + sizeof("421 4.3.2 No system resources\r\n") - 1); PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream); } @@ -558,9 +562,10 @@ static void psc_service(VSTREAM *smtp_client_stream, msg_warn("cannot convert client address/port to string: %s" " -- dropping this connection", MAI_STRERROR(aierr)); - psc_send_reply(vstream_fileno(smtp_client_stream), - "unknown_address", "unknown_port", - "421 4.3.2 No system resources\r\n"); + /* Best effort - if this non-blocking write(2) fails, so be it. */ + (void) write(vstream_fileno(smtp_client_stream), + "421 4.3.2 No system resources\r\n", + sizeof("421 4.3.2 No system resources\r\n") - 1); PSC_SERVICE_DISCONNECT_AND_RETURN(smtp_client_stream); } if (strncasecmp("::ffff:", smtp_client_addr.buf, 7) == 0) diff --git a/postfix/src/postscreen/postscreen.h b/postfix/src/postscreen/postscreen.h index c0885be85..f5b894e3d 100644 --- a/postfix/src/postscreen/postscreen.h +++ b/postfix/src/postscreen/postscreen.h @@ -44,6 +44,7 @@ typedef struct { char *smtp_client_port; /* client port */ int client_concurrency; /* per-client */ const char *final_reply; /* cause for hanging up */ + VSTRING *send_buf; /* pending output */ /* Test context. */ struct timeval start_time; /* start of current test */ const char *test_name; /* name of current test */ @@ -438,12 +439,8 @@ extern void psc_hangup_event(PSC_STATE *); /* * postscreen_send.c */ -#define PSC_SEND_REPLY(state, text) \ - psc_send_reply(vstream_fileno((state)->smtp_client_stream), \ - (state)->smtp_client_addr, \ - (state)->smtp_client_port, \ - (text)) -extern int psc_send_reply(int, const char *, const char *, const char *); +#define PSC_SEND_REPLY psc_send_reply /* legacy macro */ +extern int psc_send_reply(PSC_STATE *, const char *); extern void psc_send_socket(PSC_STATE *); /* diff --git a/postfix/src/postscreen/postscreen_send.c b/postfix/src/postscreen/postscreen_send.c index 7b7edc350..d74e60049 100644 --- a/postfix/src/postscreen/postscreen_send.c +++ b/postfix/src/postscreen/postscreen_send.c @@ -6,13 +6,12 @@ /* SYNOPSIS /* #include /* -/* int psc_send_reply(client_fd, client_addr, client_port, text) -/* int client_fd; -/* const char *client_addr; -/* const char *client_port; +/* int psc_send_reply(state, text) +/* PSC_STATE *state; /* const char *text; /* /* int PSC_SEND_REPLY(state, text) +/* PSC_STATE *state; /* const char *text; /* /* void psc_send_socket(state) @@ -23,9 +22,8 @@ /* a warning (except EPIPE) with the client address and port, /* and returns a non-zero result (all errors including EPIPE). /* -/* PSC_SEND_REPLY() is a convenience wrapper for psc_send_reply(). -/* It is an unsafe macro that evaluates its arguments multiple -/* times. +/* PSC_SEND_REPLY() is a legacy wrapper for psc_send_reply(). +/* It will eventually be replaced by its expansion. /* /* psc_send_socket() sends the specified socket to the real /* Postfix SMTP server. The socket is delivered in the background. @@ -57,6 +55,10 @@ #include #include +/* Global library. */ + +#include + /* Application-specific. */ #include @@ -67,28 +69,53 @@ */ #define PSC_SEND_SOCK_CONNECT_TIMEOUT 1 #define PSC_SEND_SOCK_NOTIFY_TIMEOUT 100 -#define PSC_SEND_TEXT_TIMEOUT 1 /* psc_send_reply - send reply to remote SMTP client */ -int psc_send_reply(int smtp_client_fd, const char *smtp_client_addr, - const char *smtp_client_port, const char *text) +int psc_send_reply(PSC_STATE *state, const char *text) { + int start; int ret; if (msg_verbose) - msg_info("> [%s]:%s: %.*s", smtp_client_addr, smtp_client_port, - (int) strlen(text) - 2, text); + msg_info("> [%s]:%s: %.*s", state->smtp_client_addr, + state->smtp_client_port, (int) strlen(text) - 2, text); /* - * XXX Need to make sure that the TCP send buffer is large enough for any - * response, so that a nasty client can't cause this process to block. + * Append the new text to earlier text that could not be sent because the + * output was throttled. */ - ret = (write_buf(smtp_client_fd, text, strlen(text), - PSC_SEND_TEXT_TIMEOUT) < 0); - if (ret != 0 && errno != EPIPE) - msg_warn("write [%s]:%s: %m", smtp_client_addr, smtp_client_port); - return (ret); + start = VSTRING_LEN(state->send_buf); + vstring_strcat(state->send_buf, text); + + /* + * XXX For soft_bounce support, it is not sufficient to fix replies here. + * We also need to fix the REJECT messages that are logged by the dummy + * SMTP engine. Those messages are set with the PSC_DROP_SESSION_STATE + * and PSC_ENFORCE_SESSION_STATE macros, and we should not mess up all + * the code that invokes those macros. + */ +#if 0 + if (var_soft_bounce) { + if (text[0] == '5') + STR(state->send_buf)[start + 0] = '4'; + if (text[4] == '5') + STR(state->send_buf)[start + 4] = '4'; + } +#endif + + /* + * Do a best effort sending text, but don't block when the output is + * throttled by a hostile peer. + */ + ret = write(vstream_fileno(state->smtp_client_stream), + STR(state->send_buf), LEN(state->send_buf)); + if (ret > 0) + vstring_truncate(state->send_buf, ret - LEN(state->send_buf)); + if (ret < 0 && errno != EAGAIN && errno != EPIPE) + msg_warn("write [%s]:%s: %m", state->smtp_client_addr, + state->smtp_client_port); + return (ret < 0 && errno != EAGAIN); } /* psc_send_socket_close_event - file descriptor has arrived or timeout */ diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c index 8b529bc77..07ebc8ca8 100644 --- a/postfix/src/postscreen/postscreen_smtpd.c +++ b/postfix/src/postscreen/postscreen_smtpd.c @@ -260,7 +260,8 @@ static int psc_helo_cmd(PSC_STATE *state, char *args) /* psc_smtpd_format_ehlo_reply - format EHLO response */ -static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask) +static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask + /*, const char *sasl_mechanism_list */) { const char *myname = "psc_smtpd_format_ehlo_reply"; int saved_len = 0; @@ -1063,6 +1064,9 @@ void psc_smtpd_init(void) case TLS_LEV_SECURE: case TLS_LEV_VERIFY: case TLS_LEV_FPRINT: + msg_warn("%s: unsupported TLS level \"%s\", using \"encrypt\"", + VAR_PSC_TLS_LEVEL, var_psc_tls_level); + /* FALLTHROUGH */ case TLS_LEV_ENCRYPT: var_psc_enforce_tls = var_psc_use_tls = 1; break; diff --git a/postfix/src/postscreen/postscreen_state.c b/postfix/src/postscreen/postscreen_state.c index 42e2f0aed..97ffae132 100644 --- a/postfix/src/postscreen/postscreen_state.c +++ b/postfix/src/postscreen/postscreen_state.c @@ -153,6 +153,7 @@ PSC_STATE *psc_new_session_state(VSTREAM *stream, state->smtp_server_fd = (-1); state->smtp_client_addr = mystrdup(addr); state->smtp_client_port = mystrdup(port); + state->send_buf = vstring_alloc(100); state->test_name = "TEST NAME HERE"; state->dnsbl_reply = 0; state->final_reply = "421 4.3.2 Service currently unavailable\r\n"; @@ -212,6 +213,8 @@ void psc_free_session_state(PSC_STATE *state) close(state->smtp_server_fd); psc_post_queue_length--; } + if (state->send_buf != 0) + state->send_buf = vstring_free(state->send_buf); myfree(state->smtp_client_addr); myfree(state->smtp_client_port); if (state->dnsbl_reply) diff --git a/postfix/src/tlsproxy/tlsproxy.c b/postfix/src/tlsproxy/tlsproxy.c index 4e0b350eb..a7351e6a3 100644 --- a/postfix/src/tlsproxy/tlsproxy.c +++ b/postfix/src/tlsproxy/tlsproxy.c @@ -293,6 +293,7 @@ int var_tlsp_watchdog; static TLS_APPL_STATE *tlsp_server_ctx; static int ask_client_cert; static int enforce_tls; +static int tlsp_tls_enforce_tls; /* * SLMs. @@ -625,9 +626,13 @@ static void tlsp_ciphertext_event(int event, char *context) if (event == EVENT_READ || event == EVENT_WRITE) { tlsp_strategy(state); } else { - msg_warn("read/write %s for %s", - event == EVENT_TIME ? "timeout" : "error", - state->remote_endpt); + if (event == EVENT_TIME && state->ssl_last_err == SSL_ERROR_NONE) + msg_warn("deadlock on plaintext stream for %s", + state->remote_endpt); + else + msg_warn("read/write %s for %s", + event == EVENT_TIME ? "timeout" : "error", + state->remote_endpt); tlsp_state_free(state); } } @@ -645,8 +650,6 @@ static void tlsp_start_tls(TLSP_STATE *state) * going to sanitize this because doing so surely will break things in * unexpected ways. */ - state->tls_use_tls = var_tlsp_use_tls | var_tlsp_enforce_tls; - state->tls_enforce_tls = var_tlsp_enforce_tls; /* * Perform the before-handshake portion of the per-session initalization. @@ -680,7 +683,7 @@ static void tlsp_start_tls(TLSP_STATE *state) log_level = var_tlsp_tls_loglevel, timeout = 0, /* unused */ requirecert = (var_tlsp_tls_req_ccert - && state->tls_enforce_tls), + && tlsp_tls_enforce_tls), serverid = state->service, namaddr = state->remote_endpt, cipher_grade = cipher_grade, @@ -894,7 +897,39 @@ static void pre_jail_init(char *unused_name, char **unused_argv) * The code in this routine is pasted literally from smtpd(8). I am not * going to sanitize this because doing so surely will break things in * unexpected ways. - * + */ + if (*var_tlsp_tls_level) { + switch (tls_level_lookup(var_tlsp_tls_level)) { + default: + msg_fatal("Invalid TLS level \"%s\"", var_tlsp_tls_level); + /* NOTREACHED */ + break; + case TLS_LEV_SECURE: + case TLS_LEV_VERIFY: + case TLS_LEV_FPRINT: + msg_warn("%s: unsupported TLS level \"%s\", using \"encrypt\"", + VAR_TLSP_TLS_LEVEL, var_tlsp_tls_level); + /* FALLTHROUGH */ + case TLS_LEV_ENCRYPT: + var_tlsp_enforce_tls = var_tlsp_use_tls = 1; + break; + case TLS_LEV_MAY: + var_tlsp_enforce_tls = 0; + var_tlsp_use_tls = 1; + break; + case TLS_LEV_NONE: + var_tlsp_enforce_tls = var_tlsp_use_tls = 0; + break; + } + } + tlsp_tls_enforce_tls = var_tlsp_enforce_tls; + if (!(var_tlsp_use_tls || var_tlsp_enforce_tls)) { + msg_warn("TLS service is requested, but disabled with %s or %s", + VAR_TLSP_TLS_LEVEL, VAR_TLSP_USE_TLS); + return; + } + + /* * Load TLS keys before dropping privileges. * * Can't use anonymous ciphers if we want client certificates. Must use diff --git a/postfix/src/tlsproxy/tlsproxy.h b/postfix/src/tlsproxy/tlsproxy.h index e18e38a75..0c4d129c7 100644 --- a/postfix/src/tlsproxy/tlsproxy.h +++ b/postfix/src/tlsproxy/tlsproxy.h @@ -33,8 +33,6 @@ typedef struct { char *remote_endpt; /* printable remote endpoint */ TLS_SESS_STATE *tls_context; /* llibtls state */ int ssl_last_err; /* TLS I/O state */ - int tls_use_tls; /* legacy libtls API */ - int tls_enforce_tls; /* legacy libtls API */ } TLSP_STATE; #define TLSP_FLAG_DO_HANDSHAKE (1<<0) diff --git a/postfix/src/util/vstring.c b/postfix/src/util/vstring.c index 783730d92..f7794ae74 100644 --- a/postfix/src/util/vstring.c +++ b/postfix/src/util/vstring.c @@ -173,7 +173,8 @@ /* arguments more than once. The result is NOT null-terminated. /* /* vstring_truncate() truncates the named string to the specified -/* length. The operation has no effect when the string is shorter. +/* length. If length is negative, the trailing portion is kept. +/* The operation has no effect when the string is shorter. /* The string is not null-terminated. /* /* VSTRING_RESET() is a macro that resets the write position of its @@ -393,8 +394,13 @@ void vstring_ctl(VSTRING *vp,...) VSTRING *vstring_truncate(VSTRING *vp, ssize_t len) { - if (len < 0) - msg_panic("vstring_truncate: bad length %ld", (long) len); + ssize_t move; + + if (len < 0) { + len = (-len); + if ((move = VSTRING_LEN(vp) - len) > 0) + memmove(vstring_str(vp), vstring_str(vp) + move, len); + } if (len < VSTRING_LEN(vp)) VSTRING_AT_OFFSET(vp, len); return (vp);