Bugfix: smtpd_relay_restrictions compatibility shim did not
detect "empty" value. Sahil Tandon. The same problem existed
with the inet_protocols shim. File: conf/post-install.
+
+20121105
+
+ Cleanup: the postscreen(8) "deep protocol" tests now log
+ the SMTP command that precedes a protocol violation. Files:
+ postscreen/postscreen_smtpd.c, proto/POSTSCREEN_README.html.
+
+ Bugfix (introduced: Postfix 1.1): wrong string termination
+ when handling a MBOX From_ line at the start of a message.
+ File: qmqpd/qmqpd.c.
+
+20121110
+
+ Cleanup: specify $(WARN) on the MacOS X compiler command
+ line to suppress "nested comment" and possibly other unwanted
+ warnings. Problem reported by Jim Reid. File: makedefs,
+ Makefile.in.
+
+20121119
+
+ Documentation: added a note that key_format is required
+ when postscreen(8) and verify(8) share the same memcache
+ (with different persistent backup databases, or course)
+ otherwise automatic cache cleanup breaks due to a name
+ collision for the "last cache cleanup" database record.
+ File: proto/memcache.
+
+20121122
+
+ Cleanup: the safety-check for smtpd_recipient_restrictions
+ and smtpd_relay_restrictions now detects permit before
+ reject. File: smtpd/smtpd_check.c.
+
+ Cleanup: the safety-check for smtpd_recipient_restrictions
+ and smtpd_relay_restrictions is no longer case-sensitive.
+ File: smtpd/smtpd_check.c.
+
+20121123
+
+ Cleanup: consistent escaping of commands in postscreen deep
+ protocol test logging. File: postscreen/postscreen_smtpd.c.
SHELL = /bin/sh
-WARN = -Wmissing-prototypes -Wformat
+WARN = -Wmissing-prototypes -Wformat -Wno-comment
OPTS = 'CC=$(CC)'
DIRS = src/util src/global src/dns src/tls src/xsasl src/milter src/master \
src/postfix src/fsstone src/smtpstone \
impact on legitimate email traffic.
postscreen(8) should not be used on SMTP ports that receive mail from end-user
-clients (MUAs). In a typical deployment, postscreen(8) is used on the "port 25"
-service, while MUA clients submit mail via the submission service (port 587)
-which normally requires client authentication, or via a "port 25" server that
-provides no MX service (i.e. a dedicated server that provides submission
-service on port 25).
+clients (MUAs). In a typical deployment, postscreen(8) handles the MX service
+on TCP port 25, while MUA clients submit mail via the submission service on TCP
+port 587 which requires client authentication. Alternatively, a site could set
+up a dedicated, non-postscreen, "port 25" server that provides submission
+service and client authentication, but no MX service.
postscreen(8) is part of a multi-layer defense.
* As the first layer, postscreen(8) blocks connections from zombies and other
spambots that are responsible for about 90% of all spam. It is implemented
- as a single process to make this defense as cheap as possible.
+ as a single process to make this defense as inexpensive as possible.
* The second layer implements more complex SMTP-level access checks with
Postfix SMTP servers, policy daemons, and Milter applications.
When a client sends non-SMTP commands, postscreen(8) logs this as:
- N\bNO\bON\bN-\b-S\bSM\bMT\bTP\bP C\bCO\bOM\bMM\bMA\bAN\bND\bD f\bfr\bro\bom\bm [address]:port command
+ N\bNO\bON\bN-\b-S\bSM\bMT\bTP\bP C\bCO\bOM\bMM\bMA\bAN\bND\bD f\bfr\bro\bom\bm [address]:port a\baf\bft\bte\ber\br command: text
Translation: the SMTP client at [address]:port sent a command that matches the
postscreen_forbidden_commands parameter, or that has the syntax of a message
-header label.
+header label (text followed by optional space and ":"). The "a\baf\bft\bte\ber\br command"
+portion is logged with Postfix 2.10 and later.
The postscreen_non_smtp_command_action parameter specifies the action that is
taken next. See "When tests fail after the 220 SMTP server greeting" below.
When a client sends bare newline characters, postscreen(8) logs this as:
- B\bBA\bAR\bRE\bE N\bNE\bEW\bWL\bLI\bIN\bNE\bE f\bfr\bro\bom\bm [address]:port
+ B\bBA\bAR\bRE\bE N\bNE\bEW\bWL\bLI\bIN\bNE\bE f\bfr\bro\bom\bm [address]:port a\baf\bft\bte\ber\br command
Translation: the SMTP client at [address]:port sent a bare newline character,
-that is newline not preceded by carriage return.
+that is newline not preceded by carriage return. The "a\baf\bft\bte\ber\br command" portion is
+logged with Postfix 2.10 and later.
The postscreen_bare_newline_action parameter specifies the action that is taken
next. See "When tests fail after the 220 SMTP server greeting" below.
never accepts mail, therefore it has per-session limits on the number of
commands and on the session length.
- C\bCO\bOM\bMM\bMA\bAN\bND\bD T\bTI\bIM\bME\bE L\bLI\bIM\bMI\bIT\bT f\bfr\bro\bom\bm [address]:port
+ C\bCO\bOM\bMM\bMA\bAN\bND\bD T\bTI\bIM\bME\bE L\bLI\bIM\bMI\bIT\bT f\bfr\bro\bom\bm [address]:port a\baf\bft\bte\ber\br command
Translation: the SMTP client at [address]:port reached the per-command time
limit as specified with the postscreen_command_time_limit parameter. The
-session is terminated immediately.
+session is terminated immediately. The "a\baf\bft\bte\ber\br command" portion is logged with
+Postfix 2.10 and later.
- C\bCO\bOM\bMM\bMA\bAN\bND\bD C\bCO\bOU\bUN\bNT\bT L\bLI\bIM\bMI\bIT\bT f\bfr\bro\bom\bm [address]:port
+ C\bCO\bOM\bMM\bMA\bAN\bND\bD C\bCO\bOU\bUN\bNT\bT L\bLI\bIM\bMI\bIT\bT f\bfr\bro\bom\bm [address]:port a\baf\bft\bte\ber\br command
Translation: the SMTP client at [address]:port reached the per-session command
count limit as specified with the postscreen_command_count_limit parameter. The
-session is terminated immediately.
+session is terminated immediately. The "a\baf\bft\bte\ber\br command" portion is logged with
+Postfix 2.10 and later.
- C\bCO\bOM\bMM\bMA\bAN\bND\bD L\bLE\bEN\bNG\bGT\bTH\bH L\bLI\bIM\bMI\bIT\bT f\bfr\bro\bom\bm [address]:port
+ C\bCO\bOM\bMM\bMA\bAN\bND\bD L\bLE\bEN\bNG\bGT\bTH\bH L\bLI\bIM\bMI\bIT\bT f\bfr\bro\bom\bm [address]:port a\baf\bft\bte\ber\br command
Translation: the SMTP client at [address]:port reached the per-command length
limit, as specified with the line_length_limit parameter. The session is
-terminated immediately.
+terminated immediately. The "a\baf\bft\bte\ber\br command" portion is logged with Postfix 2.10
+and later.
When an SMTP client makes too many connections at the same time, or when all
postscreen(8) ports are busy, postscreen(8) rejects the connection with a 421
addresses the client may use.
Successful authentication in the Postfix SMTP server requires a functional SASL
-framework. Configuring SASL should therefore always be the first step.
+framework. Configuring SASL should therefore always be the first step, before
+configuring Postfix.
You can read more about the following topics:
smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
smtpd_tls_dkey_file = $smtpd_tls_dcert_file
-Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 0.9.9):
+Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 1.0.0):
/etc/postfix/main.cf:
# Most clients will not be ECDSA capable, so you will likely also need
% o\bop\bpe\ben\bns\bss\bsl\bl g\bge\ben\bnd\bdh\bh -\b-o\bou\but\bt /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/d\bdh\bh_\b_1\b10\b02\b24\b4.\b.p\bpe\bem\bm -\b-2\b2 1\b10\b02\b24\b4
Support for elliptic curve cryptography is available with Postfix 2.6 and
-OpenSSL 0.9.9 or later. To enable ephemeral elliptic curve Diffie-Hellman
+OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve Diffie-Hellman
(EECDH) key-exchange, set "smtpd_tls_eecdh_grade = strong" or
"smtpd_tls_eecdh_grade = ultra". The "ultra" setting is substantially more CPU
intensive, and "strong" is sufficiently secure for most situations.
smtp_tls_dcert_file = /etc/postfix/client-dsa.pem
smtp_tls_dkey_file = $smtp_tls_dcert_file
-Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 0.9.9):
+Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 1.0.0):
/etc/postfix/main.cf:
smtp_tls_eccert_file = /etc/postfix/client-ecdsa.pem
If you upgrade from Postfix 2.8 or earlier, read RELEASE_NOTES-2.9
before proceeding.
+Incompatible changes with snapshot 20121123
+===========================================
+
+The postscreen deep protocol tests now log the last command before
+a protocol error ("UNIMPLEMENTED" when the last command is not
+implemented, "CONNECT" when there was no prior command). The
+changed logfile messages are:
+
+NON-SMTP COMMAND from [address]:port after command: text
+BARE NEWLINE from [address]:port after command
+COMMAND TIME LIMIT from [address]:port after command
+COMMAND COUNT LIMIT from [address]:port after command
+COMMAND LENGTH LIMIT from [address]:port after command
+
Incompatible changes with snapshot 20121007
===========================================
Don't forget Apple's code donation for fetching mail from
IMAP server.
+ smtpd_muble_restrictions rule names are case-insensitive.
+ restriction_classes values are case-sensitive but should
+ be case-insensitive for consistency with smtpd_muble_restrictions.
+
Make "rename" the default when postmapping a DB file
(later: use copy+rename for postmap -i, postmap -d).
<p> <a href="postscreen.8.html">postscreen(8)</a> should not be used on SMTP ports that receive
mail from end-user clients (MUAs). In a typical deployment,
-<a href="postscreen.8.html">postscreen(8)</a> is used on the "port 25" service, while MUA clients
-submit mail via the submission service (port 587) which normally
-requires client authentication, or via a "port 25" server that
-provides no MX service (i.e. a dedicated server that provides
-submission service on port 25). </p>
+<a href="postscreen.8.html">postscreen(8)</a> handles the MX service on TCP port 25, while MUA
+clients submit mail via the submission service on TCP port 587 which
+requires client authentication. Alternatively, a site could set up
+a dedicated, non-postscreen, "port 25" server that provides submission
+service and client authentication, but no MX service. </p>
<p> <a href="postscreen.8.html">postscreen(8)</a> is part of a multi-layer defense. <p>
<li> <p> As the first layer, <a href="postscreen.8.html">postscreen(8)</a> blocks connections from
zombies and other spambots that are responsible for about 90% of
all spam. It is implemented as a single process to make this defense
-as cheap as possible. </p>
+as inexpensive as possible. </p>
<li> <p> The second layer implements more complex SMTP-level access
-checks with Postfix SMTP servers, policy daemons, and Milter
-applications. </p>
+checks with <a href="SMTPD_ACCESS_README.html">Postfix SMTP servers</a>,
+<a href="SMTPD_POLICY_README.html">policy daemons</a>, and
+<a href="MILTER_README.html">Milter applications</a>. </p>
<li> <p> The third layer performs light-weight content inspection
with the Postfix built-in <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>. This can
worms or viruses with easy-to-recognize signatures. </p>
<li> <p> The fourth layer provides heavy-weight content inspection
-with external content filters. Typical examples are Amavisd-new,
-SpamAssassin, and Milter applications. </p>
+with external content filters. Typical examples are <a
+href="http://www.ijs.si/software/amavisd/">Amavisd-new</a>, <a
+href="http://spamassassin.apache.org/">SpamAssassin</a>, and <a
+href="MILTER_README.html">Milter applications</a>. </p>
</ul>
as: </p>
<pre>
- <b>NON-SMTP COMMAND from</b> <i>[address]:port command</i>
+ <b>NON-SMTP COMMAND from</b> <i>[address]:port</i> <b>after</b> <i>command: text</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> sent a
-<i>command</i> that matches the <a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a>
-parameter, or that has the syntax of a message header label. </p>
+command that matches the <a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a>
+parameter, or that has the syntax of a message header label (text
+followed by optional space and ":").
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<p> The <a href="postconf.5.html#postscreen_non_smtp_command_action">postscreen_non_smtp_command_action</a> parameter specifies
the action that is taken next. See "<a href="#fail_after_220">When
</p>
<pre>
- <b>BARE NEWLINE from</b> <i>[address]:port</i>
+ <b>BARE NEWLINE from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> sent a bare
newline character, that is newline not preceded by carriage
-return. </p>
+return.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<p> The <a href="postconf.5.html#postscreen_bare_newline_action">postscreen_bare_newline_action</a> parameter specifies the
action that is taken next. See "<a href="#fail_after_220">When
on the number of commands and on the session length. </p>
<pre>
- <b>COMMAND TIME LIMIT</b> <b>from</b> <i>[address]:port</i>
+ <b>COMMAND TIME LIMIT</b> <b>from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
per-command time limit as specified with the <a href="postconf.5.html#postscreen_command_time_limit">postscreen_command_time_limit</a>
-parameter. The session is terminated immediately. </p>
+parameter. The session is terminated immediately.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<pre>
- <b>COMMAND COUNT LIMIT from</b> <i>[address]:port</i>
+ <b>COMMAND COUNT LIMIT from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
per-session command count limit as specified with the
<a href="postconf.5.html#postscreen_command_count_limit">postscreen_command_count_limit</a> parameter. The session is terminated
-immediately. </p>
+immediately.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<pre>
- <b>COMMAND LENGTH LIMIT from</b> <i>[address]:port</i>
+ <b>COMMAND LENGTH LIMIT from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
per-command length limit, as specified with the <a href="postconf.5.html#line_length_limit">line_length_limit</a>
-parameter. The session is terminated immediately. </p>
+parameter. The session is terminated immediately.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<p> When an SMTP client makes too many connections at the same time,
or when all <a href="postscreen.8.html">postscreen(8)</a> ports are busy, <a href="postscreen.8.html">postscreen(8)</a> rejects the
<p> Successful authentication in the Postfix SMTP server requires
a functional SASL framework. Configuring SASL should therefore
-always be the first step. </p>
+always be the first step, before configuring Postfix. </p>
<p> You can read more about the following topics: </p>
</pre>
</blockquote>
-<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 0.9.9): </p>
+<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 1.0.0): </p>
<blockquote>
<pre>
</blockquote>
<p> Support for elliptic curve cryptography is available with Postfix
-2.6 and OpenSSL 0.9.9 or later. To enable ephemeral elliptic curve
+2.6 and OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve
Diffie-Hellman (EECDH) key-exchange, set "<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> =
strong" or "<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = ultra". The "ultra" setting is
substantially more CPU intensive, and "strong" is sufficiently
</pre>
</blockquote>
-<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 0.9.9): </p>
+<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 1.0.0): </p>
<blockquote>
<pre>
Access to remote proxymap servers is under develop-
ment.
- NOTE 1: When using memcache with persistent backup
- as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache, disable auto-
- matic cache cleanup (*_cache_cleanup_interval = 0)
- in all Postfix instances except for one instance
- that will be responsible for cache cleanup.
-
- NOTE 2: In the case of a proxied backup database,
- the full backup database name (including the
- "<a href="proxymap.8.html">proxy</a>:" prefix) must be specified in the proxymap
- server's <a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a> or <a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> set-
- ting (depending on whether the access is read-only
- or read-write).
+ NOTE 1: When sharing a persistent <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or
+ <a href="verify.8.html"><b>verify</b>(8)</a> cache, disable automatic cache cleanup
+ (set *_cache_cleanup_interval = 0) except with one
+ Postfix instance that will be responsible for cache
+ cleanup.
+
+ NOTE 2: When different tables share the same mem-
+ cache database, each table should use the <b>key_for-</b>
+ <b>mat</b> feature (see below) to prepend its own unique
+ string to the lookup key. Otherwise, automatic
+ <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache cleanup may not
+ work.
+
+ NOTE 3: When the backup database is accessed with
+ "<a href="proxymap.8.html">proxy</a>:" lookups, the full backup database name
+ (including the "<a href="proxymap.8.html">proxy</a>:" prefix) must be specified
+ in the proxymap server's <a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a> or
+ <a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> setting (depending on whether the
+ access is read-only or read-write).
<b>flags (default: 0)</b>
- Optional flags that should be stored along with a
+ Optional flags that should be stored along with a
memcache update. The flags are ignored when looking
up information.
<b>ttl (default: 3600)</b>
The expiration time in seconds of memcache updates.
- NOTE 1: When using a memcache table as
+ NOTE 1: When using a memcache table as
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache without persistent
backup, specify a zero *_cache_cleanup_interval
- value with all Postfix instances that use the mem-
- cache, and specify the largest <a href="postscreen.8.html"><b>postscreen</b>(8)</a> *_ttl
- value or <a href="verify.8.html"><b>verify</b>(8)</a> *_expire_time value as the mem-
+ value with all Postfix instances that use the mem-
+ cache, and specify the largest <a href="postscreen.8.html"><b>postscreen</b>(8)</a> *_ttl
+ value or <a href="verify.8.html"><b>verify</b>(8)</a> *_expire_time value as the mem-
cache table's <b>ttl</b> value.
- NOTE 2: According to memcache protocol documenta-
- tion, a value greater than 30 days (2592000 sec-
- onds) specifies absolute UNIX time. Smaller values
+ NOTE 2: According to memcache protocol documenta-
+ tion, a value greater than 30 days (2592000 sec-
+ onds) specifies absolute UNIX time. Smaller values
are relative to the time of the update.
<b>MEMCACHE KEY PARAMETERS</b>
<b>key_format (default: %s)</b>
- Format of the lookup and update keys in memcache
- requests. By default, these are the same as the
- lookup and update keys that are given to the Post-
+ Format of the lookup and update keys in memcache
+ requests. By default, these are the same as the
+ lookup and update keys that are given to the Post-
fix memcache client.
- NOTE: The <b>key_format</b> feature is not used for <b>backup</b>
- database requests.
+ NOTE 1: The <b>key_format</b> feature is not used for
+ <b>backup</b> database requests.
- When the same memcache database is used to cache
- information from multiple tables, you can use the
- <b>key_format</b> feature to avoid name collisions by
- prepending a fixed string. Examples:
+ NOTE 2: When different tables share the same mem-
+ cache database, each table should prepend its own
+ unique string to the lookup key. Otherwise, auto-
+ matic <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache cleanup may
+ not work.
+
+ Examples:
key_format = aliases:%s
- key_format = access:%s
+ key_format = verify:%s
+ key_format = postscreen:%s
The <b>key_format</b> parameter supports the following '%'
expansions:
Darwin.*) SYSTYPE=MACOSX
# Use the native compiler by default
: ${CC=cc}
+ CCARGS="$CCARGS \$(WARN)"
# Darwin > 1.3 uses awk and flat_namespace
case $RELEASE in
1.[0-3]) AWK=gawk;;
Access to remote proxymap servers is under development.
-NOTE 1: When using memcache with persistent backup as
-\fBpostscreen\fR(8) or \fBverify\fR(8) cache, disable
-automatic cache cleanup (*_cache_cleanup_interval = 0) in
-all Postfix instances except for one instance that will be
-responsible for cache cleanup.
-
-NOTE 2: In the case of a proxied backup database, the full
-backup database
-name (including the "proxy:" prefix) must be specified in
-the proxymap server's proxy_read_maps or proxy_write_maps
-setting (depending on whether the access is read-only or
-read-write).
+NOTE 1: When sharing a persistent \fBpostscreen\fR(8) or
+\fBverify\fR(8) cache, disable automatic cache cleanup (set
+*_cache_cleanup_interval = 0) except with one Postfix
+instance that will be responsible for cache cleanup.
+
+NOTE 2: When different tables share the same memcache
+database, each table should use the \fBkey_format\fR feature
+(see below) to prepend its own unique string to the lookup
+key. Otherwise, automatic \fBpostscreen\fR(8) or \fBverify\fR(8)
+cache cleanup may not work.
+
+NOTE 3: When the backup database is accessed with "proxy:"
+lookups, the full backup database name (including the
+"proxy:" prefix) must be specified in the proxymap server's
+proxy_read_maps or proxy_write_maps setting (depending on
+whether the access is read-only or read-write).
.IP "\fBflags (default: 0)\fR"
Optional flags that should be stored along with a memcache
update. The flags are ignored when looking up information.
By default, these are the same as the lookup and update
keys that are given to the Postfix memcache client.
-NOTE: The \fBkey_format\fR feature is not used for \fBbackup\fR
+NOTE 1: The \fBkey_format\fR feature is not used for \fBbackup\fR
database requests.
-When the same memcache database is used to cache information
-from multiple tables, you can use the \fBkey_format\fR
-feature to avoid name collisions by prepending a fixed
-string. Examples:
+NOTE 2: When different tables share the same memcache
+database, each table should prepend its own unique string
+to the lookup key. Otherwise, automatic \fBpostscreen\fR(8)
+or \fBverify\fR(8) cache cleanup may not work.
+
+Examples:
.nf
key_format = aliases:%s
- key_format = access:%s
+ key_format = verify:%s
+ key_format = postscreen:%s
.fi
The \fBkey_format\fR parameter supports the following '%'
<p> postscreen(8) should not be used on SMTP ports that receive
mail from end-user clients (MUAs). In a typical deployment,
-postscreen(8) is used on the "port 25" service, while MUA clients
-submit mail via the submission service (port 587) which normally
-requires client authentication, or via a "port 25" server that
-provides no MX service (i.e. a dedicated server that provides
-submission service on port 25). </p>
+postscreen(8) handles the MX service on TCP port 25, while MUA
+clients submit mail via the submission service on TCP port 587 which
+requires client authentication. Alternatively, a site could set up
+a dedicated, non-postscreen, "port 25" server that provides submission
+service and client authentication, but no MX service. </p>
<p> postscreen(8) is part of a multi-layer defense. <p>
<li> <p> As the first layer, postscreen(8) blocks connections from
zombies and other spambots that are responsible for about 90% of
all spam. It is implemented as a single process to make this defense
-as cheap as possible. </p>
+as inexpensive as possible. </p>
<li> <p> The second layer implements more complex SMTP-level access
-checks with Postfix SMTP servers, policy daemons, and Milter
-applications. </p>
+checks with <a href="SMTPD_ACCESS_README.html">Postfix SMTP servers</a>,
+<a href="SMTPD_POLICY_README.html">policy daemons</a>, and
+<a href="MILTER_README.html">Milter applications</a>. </p>
<li> <p> The third layer performs light-weight content inspection
with the Postfix built-in header_checks and body_checks. This can
worms or viruses with easy-to-recognize signatures. </p>
<li> <p> The fourth layer provides heavy-weight content inspection
-with external content filters. Typical examples are Amavisd-new,
-SpamAssassin, and Milter applications. </p>
+with external content filters. Typical examples are <a
+href="http://www.ijs.si/software/amavisd/">Amavisd-new</a>, <a
+href="http://spamassassin.apache.org/">SpamAssassin</a>, and <a
+href="MILTER_README.html">Milter applications</a>. </p>
</ul>
as: </p>
<pre>
- <b>NON-SMTP COMMAND from</b> <i>[address]:port command</i>
+ <b>NON-SMTP COMMAND from</b> <i>[address]:port</i> <b>after</b> <i>command: text</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> sent a
-<i>command</i> that matches the postscreen_forbidden_commands
-parameter, or that has the syntax of a message header label. </p>
+command that matches the postscreen_forbidden_commands
+parameter, or that has the syntax of a message header label (text
+followed by optional space and ":").
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<p> The postscreen_non_smtp_command_action parameter specifies
the action that is taken next. See "<a href="#fail_after_220">When
</p>
<pre>
- <b>BARE NEWLINE from</b> <i>[address]:port</i>
+ <b>BARE NEWLINE from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> sent a bare
newline character, that is newline not preceded by carriage
-return. </p>
+return.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<p> The postscreen_bare_newline_action parameter specifies the
action that is taken next. See "<a href="#fail_after_220">When
on the number of commands and on the session length. </p>
<pre>
- <b>COMMAND TIME LIMIT</b> <b>from</b> <i>[address]:port</i>
+ <b>COMMAND TIME LIMIT</b> <b>from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
per-command time limit as specified with the postscreen_command_time_limit
-parameter. The session is terminated immediately. </p>
+parameter. The session is terminated immediately.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<pre>
- <b>COMMAND COUNT LIMIT from</b> <i>[address]:port</i>
+ <b>COMMAND COUNT LIMIT from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
per-session command count limit as specified with the
postscreen_command_count_limit parameter. The session is terminated
-immediately. </p>
+immediately.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<pre>
- <b>COMMAND LENGTH LIMIT from</b> <i>[address]:port</i>
+ <b>COMMAND LENGTH LIMIT from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
</pre>
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
per-command length limit, as specified with the line_length_limit
-parameter. The session is terminated immediately. </p>
+parameter. The session is terminated immediately.
+The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
+Postfix 2.10 and later. </p>
<p> When an SMTP client makes too many connections at the same time,
or when all postscreen(8) ports are busy, postscreen(8) rejects the
<p> Successful authentication in the Postfix SMTP server requires
a functional SASL framework. Configuring SASL should therefore
-always be the first step. </p>
+always be the first step, before configuring Postfix. </p>
<p> You can read more about the following topics: </p>
</pre>
</blockquote>
-<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 0.9.9): </p>
+<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 1.0.0): </p>
<blockquote>
<pre>
</blockquote>
<p> Support for elliptic curve cryptography is available with Postfix
-2.6 and OpenSSL 0.9.9 or later. To enable ephemeral elliptic curve
+2.6 and OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve
Diffie-Hellman (EECDH) key-exchange, set "smtpd_tls_eecdh_grade =
strong" or "smtpd_tls_eecdh_grade = ultra". The "ultra" setting is
substantially more CPU intensive, and "strong" is sufficiently
</pre>
</blockquote>
-<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 0.9.9): </p>
+<p> Their ECDSA counterparts (Postfix ≥ 2.6 + OpenSSL ≥ 1.0.0): </p>
<blockquote>
<pre>
#
# Access to remote proxymap servers is under development.
#
-# NOTE 1: When using memcache with persistent backup as
-# \fBpostscreen\fR(8) or \fBverify\fR(8) cache, disable
-# automatic cache cleanup (*_cache_cleanup_interval = 0) in
-# all Postfix instances except for one instance that will be
-# responsible for cache cleanup.
-#
-# NOTE 2: In the case of a proxied backup database, the full
-# backup database
-# name (including the "proxy:" prefix) must be specified in
-# the proxymap server's proxy_read_maps or proxy_write_maps
-# setting (depending on whether the access is read-only or
-# read-write).
+# NOTE 1: When sharing a persistent \fBpostscreen\fR(8) or
+# \fBverify\fR(8) cache, disable automatic cache cleanup (set
+# *_cache_cleanup_interval = 0) except with one Postfix
+# instance that will be responsible for cache cleanup.
+#
+# NOTE 2: When different tables share the same memcache
+# database, each table should use the \fBkey_format\fR feature
+# (see below) to prepend its own unique string to the lookup
+# key. Otherwise, automatic \fBpostscreen\fR(8) or \fBverify\fR(8)
+# cache cleanup may not work.
+#
+# NOTE 3: When the backup database is accessed with "proxy:"
+# lookups, the full backup database name (including the
+# "proxy:" prefix) must be specified in the proxymap server's
+# proxy_read_maps or proxy_write_maps setting (depending on
+# whether the access is read-only or read-write).
# .IP "\fBflags (default: 0)\fR"
# Optional flags that should be stored along with a memcache
# update. The flags are ignored when looking up information.
# By default, these are the same as the lookup and update
# keys that are given to the Postfix memcache client.
#
-# NOTE: The \fBkey_format\fR feature is not used for \fBbackup\fR
+# NOTE 1: The \fBkey_format\fR feature is not used for \fBbackup\fR
# database requests.
#
-# When the same memcache database is used to cache information
-# from multiple tables, you can use the \fBkey_format\fR
-# feature to avoid name collisions by prepending a fixed
-# string. Examples:
+# NOTE 2: When different tables share the same memcache
+# database, each table should prepend its own unique string
+# to the lookup key. Otherwise, automatic \fBpostscreen\fR(8)
+# or \fBverify\fR(8) cache cleanup may not work.
+#
+# Examples:
#
# .nf
# key_format = aliases:%s
-# key_format = access:%s
+# key_format = verify:%s
+# key_format = postscreen:%s
# .fi
#
# The \fBkey_format\fR parameter supports the following '%'
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20121031"
+#define MAIL_RELEASE_DATE "20121123"
#define MAIL_VERSION_NUMBER "2.10"
#ifdef SNAPSHOT
/* smtpd(8) compatibility */
int ehlo_discard_mask; /* EHLO filter */
VSTRING *expand_buf; /* macro expansion */
+ const char *where; /* SMTP protocol state */
} PSC_STATE;
#define PSC_TIME_STAMP_NEW (0) /* test was never passed */
#define PSC_STATE_MASK_ANY_UPDATE \
(PSC_STATE_MASK_ANY_PASS | PSC_STATE_FLAG_PENAL_UPDATE)
+ /*
+ * Meta-commands for state->where that reflect the initial command processor
+ * state and commands that aren't implemented.
+ */
+#define PSC_SMTPD_CMD_CONNECT "CONNECT"
+#define PSC_SMTPD_CMD_UNIMPL "UNIMPLEMENTED"
+
/*
* See log_adhoc.c for discussion.
*/
PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
psc_smtpd_time_event, (char *) (state));
+ /*
+ * Make control characters and other non-text visible.
+ */
+#define PSC_SMTPD_ESCAPE_TEXT(dest, src, src_len, max_len) do { \
+ ssize_t _s_len = (src_len); \
+ ssize_t _m_len = (max_len); \
+ (void) escape((dest), (src), _s_len < _m_len ? _s_len : _m_len); \
+ } while (0)
+
/*
* Command parser support.
*/
state->smtp_client_addr, state->smtp_client_port,
psc_print_state_flags(state->flags, myname));
- msg_info("COMMAND TIME LIMIT from [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ msg_info("COMMAND TIME LIMIT from [%s]:%s after %s",
+ PSC_CLIENT_ADDR_PORT(state), state->where);
PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
psc_smtpd_timeout_reply);
}
int want;
int next_state;
};
+ const char *saved_where;
#define PSC_SMTPD_CMD_ST_ANY 0
#define PSC_SMTPD_CMD_ST_CR 1
*/
if (state->read_state == PSC_SMTPD_CMD_ST_ANY
&& VSTRING_LEN(state->cmd_buffer) >= var_line_limit) {
- msg_info("COMMAND LENGTH LIMIT from [%s]:%s",
- PSC_CLIENT_ADDR_PORT(state));
+ msg_info("COMMAND LENGTH LIMIT from [%s]:%s after %s",
+ PSC_CLIENT_ADDR_PORT(state), state->where);
PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
psc_smtpd_421_reply);
return;
if (ch == '\n') {
if ((state->flags & PSC_STATE_MASK_BARLF_TODO_SKIP)
== PSC_STATE_FLAG_BARLF_TODO) {
- msg_info("BARE NEWLINE from [%s]:%s",
- PSC_CLIENT_ADDR_PORT(state));
+ PSC_SMTPD_ESCAPE_TEXT(psc_temp, STR(state->cmd_buffer),
+ VSTRING_LEN(state->cmd_buffer) - 1, 100);
+ msg_info("BARE NEWLINE from [%s]:%s after %s",
+ PSC_CLIENT_ADDR_PORT(state), STR(psc_temp));
PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_FAIL);
PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_PASS);
state->barlf_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */
*
* Caution: cmdp->name and cmdp->action may be null on loop exit.
*/
- for (cmdp = command_table; cmdp->name != 0; cmdp++)
- if (strcasecmp(command, cmdp->name) == 0)
+ saved_where = state->where;
+ state->where = PSC_SMTPD_CMD_UNIMPL;
+ for (cmdp = command_table; cmdp->name != 0; cmdp++) {
+ if (strcasecmp(command, cmdp->name) == 0) {
+ state->where = cmdp->name;
break;
+ }
+ }
if ((state->flags & PSC_STATE_FLAG_SMTPD_X21)
&& cmdp->action != psc_quit_cmd) {
|| (*var_psc_forbid_cmds
&& string_list_match(psc_forbid_cmds, command)))) {
printable(command, '?');
- msg_info("NON-SMTP COMMAND from [%s]:%s %.100s %.100s",
- PSC_CLIENT_ADDR_PORT(state), command, cmd_buffer_ptr);
+ PSC_SMTPD_ESCAPE_TEXT(psc_temp, cmd_buffer_ptr,
+ strlen(cmd_buffer_ptr), 100);
+ msg_info("NON-SMTP COMMAND from [%s]:%s after %s: %.100s %s",
+ PSC_CLIENT_ADDR_PORT(state), saved_where,
+ command, STR(psc_temp));
PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_FAIL);
PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_PASS);
state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */
if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_SKIP)
== PSC_STATE_FLAG_PIPEL_TODO && !PSC_SMTPD_BUFFER_EMPTY(state)) {
printable(command, '?');
- escape(psc_temp, PSC_SMTPD_PEEK_DATA(state),
- PSC_SMTPD_PEEK_LEN(state) < 100 ?
- PSC_SMTPD_PEEK_LEN(state) : 100);
+ PSC_SMTPD_ESCAPE_TEXT(psc_temp, PSC_SMTPD_PEEK_DATA(state),
+ PSC_SMTPD_PEEK_LEN(state), 100);
msg_info("COMMAND PIPELINING from [%s]:%s after %.100s: %s",
PSC_CLIENT_ADDR_PORT(state), command, STR(psc_temp));
PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_FAIL);
/* Command COUNT limit test. */
if (++state->command_count > var_psc_cmd_count
&& cmdp->action != psc_quit_cmd) {
- msg_info("COMMAND COUNT LIMIT from [%s]:%s",
- PSC_CLIENT_ADDR_PORT(state));
+ msg_info("COMMAND COUNT LIMIT from [%s]:%s after %s",
+ PSC_CLIENT_ADDR_PORT(state), saved_where);
PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
psc_smtpd_421_reply);
return;
state->read_state = 0;
state->ehlo_discard_mask = 0; /* XXX Should be ~0 */
state->expand_buf = 0;
+ state->where = PSC_SMTPD_CMD_CONNECT;
/*
* Update the stress level.
if (first) {
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
rec_fprintf(state->cleanup, rec_type,
- "X-Mailbox-Line: %*s", len, start);
+ "X-Mailbox-Line: %.*s", len, start);
continue;
}
first = 0;
* Recursively check list membership.
*/
for (rest = restrictions->argv; *rest; rest++) {
- if (strcmp(*rest, WARN_IF_REJECT) == 0 && rest[1] != 0) {
+ if (strcasecmp(*rest, WARN_IF_REJECT) == 0 && rest[1] != 0) {
rest += 1;
continue;
}
+ if (strcasecmp(*rest, PERMIT_ALL) == 0) {
+ if (rest[1] != 0)
+ msg_warn("restriction `%s' after `%s' is ignored",
+ rest[1], rest[0]);
+ return (0);
+ }
for (reqd = required; *reqd; reqd++)
- if (strcmp(*rest, *reqd) == 0)
+ if (strcasecmp(*rest, *reqd) == 0)
return (1);
+ /* XXX This lookup operation should not be case-sensitive. */
if ((expansion = (ARGV *) htable_find(smtpd_rest_classes, *rest)) != 0)
if (has_required(expansion, required))
return (1);
while ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) != 0) {
if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0)
msg_fatal("restriction class `%s' needs a definition", name);
+ /* XXX This store operation should not be case-sensitive. */
htable_enter(smtpd_rest_classes, name,
(char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
value));