due to expensive crypto operations. Files: global/anvil_clnt.c,
anvil/anvil.c, smtpd/smtpd.c.
- Cleanup: eliminated code duplicatiom in the anvil server
- that resulted from adding similar features one at a time.
- File: anvil/anvil.c.
+ Cleanup: eliminated massive code duplicatiom in the anvil
+ server that resulted from adding similar features one at a
+ time. File: anvil/anvil.c.
+
+20051011
+
+ Bugfix: raise the "policy violation" flag when a client
+ request exceeds a concurrency or rate limit. File:
+ smtpd/smtpd.c.
+
+ Bugfix (cut-and-paste error): don't reply with 421 (too
+ many MAIL FROM or RCPT TO commands) when we aren't closing
+ the connection. File: smtpd/smtpd.c.
Open problems:
It's much easier to develop a new feature in few lines of Perl, than trying to
do the same in C code. The difference in performance will be unnoticeable
except in the most demanding environments. On active systems a policy daemon
-process is used multiple times, for up to 100 incoming SMTP connections.
+process is used multiple times, for up to $max_use incoming SMTP connections.
This document covers the following topics:
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
-Incompatibility with snapshot 20050923
+Incompatibility with snapshot 20051011
======================================
The Postfix local(8) delivery agent no longer updates its idea of
reduce the number of queue files and cleanup process instances. To
get the earlier behavior, specify "frozen_delivered_to = no".
-The frozen_delivered_to feature also fixes an old problem with
-duplicate deliveries to recipients that are listed in multiple
-nested aliases.
+The frozen_delivered_to feature also fixes a long-standing problem
+with multiple deliveries to recipients that are listed in multiple
+nested aliases, but does so only when only the top-level alias has
+an owner- alias, and none of the subordinate aliases.
+
+Major changes with snapshot 20051011
+====================================
+
+Optional protection against SMTP clients that hammer the server
+with too many new (i.e. uncached) SMTP-over-TLS sessions. Cached
+sessions are much less expensive in terms of CPU cycles. Use the
+smtpd_client_new_tls_session_rate_limit parameter to specify a limit
+that is at least the inbound client concurrency limit, or else you
+may deny legitimate service requests.
+
+Optional suppression of remote SMTP client hostname lookup and
+hostname verification. Specify "smtpd_peername_lookup = no" to
+eliminate DNS lookup latencies, but do so only under extreme
+conditions, as it makes Postfix logging less informative.
Incompatibility with snapshot 20050828
======================================
# Delivered-To: address while expanding aliases or
# .forward files.
#
-# sticky_owner_alias
-# When expanding a local(8) alias that has an owner
-# alias (see owner-name discussion above), use the
-# owner information even when the expansion invokes a
-# subordinate alias that has no owner alias.
-#
# STANDARDS
# RFC 822 (ARPA Internet Text Messages)
#
# postconf(5), configuration parameters
#
# README FILES
-# Use "postconf readme_directory" or "postconf html_direc-
+# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
#
# LICENSE
-# The Secure Mailer license must be distributed with this
+# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
of Perl, than trying to do the same in C code. The difference in
performance will be unnoticeable except in the most demanding
environments. On active systems a policy daemon process is used
-multiple times, for up to 100 incoming SMTP connections. </p>
+multiple times, for up to $<a href="postconf.5.html#max_use">max_use</a> incoming SMTP connections. </p>
<p> This document covers the following topics: </p>
Delivered-To: address while expanding aliases or
.forward files.
- <b><a href="postconf.5.html#sticky_owner_alias">sticky_owner_alias</a></b>
- When expanding a <a href="local.8.html">local(8)</a> alias that has an owner
- alias (see owner-<i>name</i> discussion above), use the
- owner information even when the expansion invokes a
- subordinate alias that has no owner alias.
-
<b>STANDARDS</b>
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<b>rate=</b><i>number</i>
To retrieve new TLS session request rate information with-
- out updating the counter information, use:
+ out updating the counter information, send:
<b>request=newtls_report</b>
<b>ident=</b><i>string</i>
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of new TLS
session requests per unit time for the (service, client)
- combination specified with <b>ident</b>.
+ combination specified with <b>ident</b>:
<b>status=0</b>
<b>rate=</b><i>number</i>
<b><a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a> (0)</b>
The maximal number of new (i.e., uncached) TLS ses-
- sions that any client is allowed to negotiate with
- this service per time unit.
+ sions that a remote SMTP client is allowed to nego-
+ tiate with this service per time unit.
<b>TARPIT CONTROLS</b>
When a remote SMTP client makes errors, the Postfix SMTP
(see prepend_delivered_header) only once, at the start of
a delivery; do not update the Delivered-To: address while
expanding aliases or .forward files.
-.IP \fBsticky_owner_alias\fR
-When expanding a local(8) alias that has an owner alias
-(see owner-\fIname\fR discussion above), use the owner
-information even when the expansion invokes a subordinate
-alias that has no owner alias.
.SH "STANDARDS"
.na
.nf
.in
.PP
To retrieve new TLS session request rate information without
-updating the counter information, use:
+updating the counter information, send:
.PP
.in +4
\fBrequest=newtls_report\fR
.PP
The \fBanvil\fR(8) server answers with the number of new
TLS session requests per unit time for the (service, client)
-combination specified with \fBident\fR.
+combination specified with \fBident\fR:
.PP
.in +4
\fBstatus=0\fR
.PP
Available in Postfix version 2.3 and later:
.IP "\fBsmtpd_client_new_tls_session_rate_limit (0)\fR"
-The maximal number of new (i.e., uncached) TLS sessions that any
-client is allowed to negotiate with this service per time unit.
+The maximal number of new (i.e., uncached) TLS sessions that a
+remote SMTP client is allowed to negotiate with this service per
+time unit.
.SH "TARPIT CONTROLS"
.na
.nf
of Perl, than trying to do the same in C code. The difference in
performance will be unnoticeable except in the most demanding
environments. On active systems a policy daemon process is used
-multiple times, for up to 100 incoming SMTP connections. </p>
+multiple times, for up to $max_use incoming SMTP connections. </p>
<p> This document covers the following topics: </p>
# (see prepend_delivered_header) only once, at the start of
# a delivery; do not update the Delivered-To: address while
# expanding aliases or .forward files.
-# .IP \fBsticky_owner_alias\fR
-# When expanding a local(8) alias that has an owner alias
-# (see owner-\fIname\fR discussion above), use the owner
-# information even when the expansion invokes a subordinate
-# alias that has no owner alias.
# STANDARDS
# RFC 822 (ARPA Internet Text Messages)
# SEE ALSO
/* .in
/* .PP
/* To retrieve new TLS session request rate information without
-/* updating the counter information, use:
+/* updating the counter information, send:
/* .PP
/* .in +4
/* \fBrequest=newtls_report\fR
/* .PP
/* The \fBanvil\fR(8) server answers with the number of new
/* TLS session requests per unit time for the (service, client)
-/* combination specified with \fBident\fR.
+/* combination specified with \fBident\fR:
/* .PP
/* .in +4
/* \fBstatus=0\fR
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20051010"
+#define MAIL_RELEASE_DATE "20051011"
#define MAIL_VERSION_NUMBER "2.3"
#ifdef SNAPSHOT
/* .IP SMTP_ERR_TIME
/* The time limit specified to smtp_timeout_setup() was exceeded.
/* .IP SMTP_ERR_PROTO
+/* A protocol error happened.
+/* This error is never generated by the smtp_stream(3) module, but
+/* is defined for application-specific use.
+/* .IP SMTP_ERR_QUIET
+/* Perform silent cleanup; the error was already reported by
+/* the application.
/* This error is never generated by the smtp_stream(3) module, but
/* is defined for application-specific use.
/* BUGS
#define SMTP_ERR_EOF 1 /* unexpected client disconnect */
#define SMTP_ERR_TIME 2 /* time out */
#define SMTP_ERR_PROTO 3 /* protocol (application) */
+#define SMTP_ERR_QUIET 4 /* silent cleanup (application) */
extern void smtp_timeout_setup(VSTREAM *, int);
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
case SMTP_ERR_PROTO:
lmtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
"4.5.0", "403 remote protocol error",
- "protocol error in reply from %s while %s",
+ "remote protocol error in reply from %s while %s",
session->namaddr, description);
break;
}
&& (owner_rhs = maps_find(alias_maps, owner, DICT_FLAG_NONE)) != 0) {
canon_owner = canon_addr_internal(vstring_alloc(10),
var_exp_own_alias ? owner_rhs : owner);
+ /* Set envelope sender and owner attribute. */
SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
} else {
canon_owner = 0;
+ /* Note: this does not reset the envelope sender. */
RESET_OWNER_ATTR(state.msg_attr, state.level);
}
case SMTP_ERR_PROTO:
smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
"4.5.0", "403 remote protocol error",
- "protocol error in reply from %s while %s",
+ "remote protocol error in reply from %s while %s",
session->namaddr, description);
break;
}
/* .PP
/* Available in Postfix version 2.3 and later:
/* .IP "\fBsmtpd_client_new_tls_session_rate_limit (0)\fR"
-/* The maximal number of new (i.e., uncached) TLS sessions that any
-/* client is allowed to negotiate with this service per time unit.
+/* The maximal number of new (i.e., uncached) TLS sessions that a
+/* remote SMTP client is allowed to negotiate with this service per
+/* time unit.
/* TARPIT CONTROLS
/* .ad
/* .fi
&& anvil_clnt_mail(anvil_clnt, state->service, state->addr,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_cmail_limit) {
- smtpd_chat_reply(state, "421 4.7.0 %s Error: too much mail from %s",
- var_myhostname, state->addr);
+ state->error_mask |= MAIL_ERROR_POLICY;
+ smtpd_chat_reply(state, "450 4.7.1 Error: too much mail from %s",
+ state->addr);
msg_warn("Message delivery request rate limit exceeded: %d from %s for service %s",
rate, state->namaddr, state->service);
return (-1);
&& anvil_clnt_rcpt(anvil_clnt, state->service, state->addr,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_crcpt_limit) {
- smtpd_chat_reply(state,
- "421 4.7.0 %s Error: too many recipients from %s",
- var_myhostname, state->addr);
+ state->error_mask |= MAIL_ERROR_POLICY;
+ smtpd_chat_reply(state, "450 4.7.1 Error: too many recipients from %s",
+ state->addr);
msg_warn("Recipient address rate limit exceeded: %d from %s for service %s",
rate, state->namaddr, state->service);
return (-1);
{
int rate;
- /*
- * XXX The client event count/rate control must be consistent in its use
- * of client address information in connect and disconnect events. For
- * now we exclude xclient authorized hosts from event count/rate control.
- */
- if (SMTPD_STAND_ALONE(state) == 0
- && !xclient_allowed
- && anvil_clnt
- && var_smtpd_cntls_limit > 0
- && !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_newtls_stat(anvil_clnt, state->service, state->addr,
- &rate) == ANVIL_STAT_OK
- && rate > var_smtpd_cntls_limit) {
- msg_warn("Refusing STARTTLS request from %s for service %s",
- state->namaddr, state->service);
- vstream_longjmp(state->client, SMTP_ERR_EOF);
- }
-
/*
* Wrapper mode uses a dedicated port and always requires TLS.
*
* of client address information in connect and disconnect events. For
* now we exclude xclient authorized hosts from event count/rate control.
*/
- if (state->tls_context
+ if (var_smtpd_cntls_limit > 0
+ && state->tls_context
&& state->tls_context->session_reused == 0
&& SMTPD_STAND_ALONE(state) == 0
&& !xclient_allowed
&& anvil_clnt
- && var_smtpd_cntls_limit > 0
&& !namadr_list_match(hogger_list, state->name, state->addr)
&& anvil_clnt_newtls(anvil_clnt, state->service, state->addr,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_cntls_limit) {
- msg_warn("Too many uncached TLS sessions: "
- "%d from %s for service %s",
+ state->error_mask |= MAIL_ERROR_POLICY;
+ smtpd_chat_reply(state,
+ "421 4.7.0 %s Error: too many new TLS sessions from %s",
+ var_myhostname, state->namaddr);
+ msg_warn("Too many new TLS sessions: %d from %s for service %s",
rate, state->namaddr, state->service);
- tls_reset(state);
+ /* XXX Use regular return to signal end of session. */
+ vstream_longjmp(state->client, SMTP_ERR_QUIET);
}
/*
static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
{
+ int rate;
+
if (argc != 1) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 5.5.4 Syntax: STARTTLS");
smtpd_chat_reply(state, "454 4.3.0 TLS not available due to local problem");
return (-1);
}
+
+ /*
+ * XXX The client event count/rate control must be consistent in its use
+ * of client address information in connect and disconnect events. For
+ * now we exclude xclient authorized hosts from event count/rate control.
+ */
+ if (var_smtpd_cntls_limit > 0
+ && SMTPD_STAND_ALONE(state) == 0
+ && !xclient_allowed
+ && anvil_clnt
+ && !namadr_list_match(hogger_list, state->name, state->addr)
+ && anvil_clnt_newtls_stat(anvil_clnt, state->service, state->addr,
+ &rate) == ANVIL_STAT_OK
+ && rate > var_smtpd_cntls_limit) {
+ state->error_mask |= MAIL_ERROR_POLICY;
+ smtpd_chat_reply(state,
+ "454 4.7.0 Error: too many new TLS sessions from %s",
+ state->namaddr);
+ msg_warn("Refusing STARTTLS request from %s for service %s",
+ state->namaddr, state->service);
+ return (-1);
+ }
smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
+ /* Flush before we switch the stream's read/write routines. */
smtp_flush(state->client);
/*
state->reason = REASON_LOST_CONNECTION;
break;
+ case SMTP_ERR_QUIET:
+ break;
+
case 0:
/*
* the STARTTLS command. This code does not return when the handshake
* fails.
*
- * XXX We must start TLS before we can apply the connection and rate
- * limits, because otherwise there is no way to report transgressions
- * to the client. This is unfortunate.
+ * XXX We start TLS before we apply access control, concurrency or
+ * connection rate limits, so that we can inform the client why
+ * service is denied. This means we spend a lot of CPU just to tell
+ * the client that we don't provide service. TLS wrapper mode is
+ * obsolete, so we don't have to provide perfect support.
*/
#ifdef USE_TLS
- if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode)
+ if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode) {
+ if (var_smtpd_cntls_limit > 0
+ && !xclient_allowed
+ && anvil_clnt
+ && !namadr_list_match(hogger_list, state->name, state->addr)
+ && anvil_clnt_newtls_stat(anvil_clnt, state->service,
+ state->addr, &crate) == ANVIL_STAT_OK
+ && crate > var_smtpd_cntls_limit) {
+ state->error_mask |= MAIL_ERROR_POLICY;
+ msg_warn("Refusing TLS service request from %s for service %s",
+ state->namaddr, state->service);
+ break;
+ }
smtpd_start_tls(state);
+ }
#endif
/*
&& anvil_clnt_connect(anvil_clnt, service, state->addr,
&count, &crate) == ANVIL_STAT_OK) {
if (var_smtpd_cconn_limit > 0 && count > var_smtpd_cconn_limit) {
+ state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "421 4.7.0 %s Error: too many connections from %s",
var_myhostname, state->addr);
msg_warn("Connection concurrency limit exceeded: %d from %s for service %s",