2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-28 12:48:01 +00:00

postfix-2.7-20091229

This commit is contained in:
Wietse Venema 2009-12-29 00:00:00 -05:00 committed by Viktor Dukhovni
parent 51826fc8f2
commit 2ccf57f4ac
37 changed files with 1692 additions and 408 deletions

1
postfix/.indent.pro vendored
View File

@ -57,6 +57,7 @@
-TDELIVER_REQUEST -TDELIVER_REQUEST
-TDELTA_TIME -TDELTA_TIME
-TDICT -TDICT
-TDICT_CACHE
-TDICT_CDBM -TDICT_CDBM
-TDICT_CDBQ -TDICT_CDBQ
-TDICT_CIDR -TDICT_CIDR

View File

@ -15453,7 +15453,7 @@ Apologies for any names omitted.
20091023 20091023
Feature: specify "smtp_command_filter = pcre:/file/name" Feature: specify "smtpd_command_filter = pcre:/file/name"
to replace remote SMTP client commands before they are to replace remote SMTP client commands before they are
executed by the Postfix SMTP server. This a last-resort executed by the Postfix SMTP server. This a last-resort
tool to fix inter-operability problems. See examples in tool to fix inter-operability problems. See examples in
@ -15563,3 +15563,42 @@ Apologies for any names omitted.
Cleanup: the postscreen daemon now applies the permanent Cleanup: the postscreen daemon now applies the permanent
whitelist first. It is a safety feature that prevents mail whitelist first. It is a safety feature that prevents mail
from being blocked. File: postscreeb/postscreen.c. from being blocked. File: postscreeb/postscreen.c.
20091224
Bugfix (introduced 20041215): dict_dbm_sequence() did not
release the shared lock when the end of the sequence was
reached. File: util/dict_dbm.c.
20091227
Cleanup: postscreen and verify periodic cache cleanup
(default: 12 hours after the previous cache cleanup run).
This is based on a new dict_cache(3) module that implements
a generalized version of the tlsmgr(8) cache maintenance
code. Once the new dict_cache(3) code is burned in, the
tlsmgr(8) will be migrated to it. See the RELEASE_NOTES for
user interface details. Files: util/htable.[hc], util/dict_ht.c,
util/dict_cache.[hc], postscreen/postscreen.c, verify/verify.c.
Bugfix: the event handler starved I/O events when a timer
call-back routine scheduled a zero-delay timer request.
This bug was exposed when adding the new dict_cache(3)
module for cache expiration. File: util/events.c.
20091228
Cleanup: postscreen and verify periodic cache cleanup is
now optional (specify a null time interval between cache
cleanup runs).
20091229
Cleanup: the address_verify_poll_count default parameter
value is now stress-dependent, so that the Postfix SMTP
server will not wait (up to 6 seconds) for the address
verification result. File: global/mail_params.h.
Final slution for the I/O event starvation problem when a
timer call-back schedules a zero-delay timer request. File:
util/events.c.

View File

@ -36,23 +36,28 @@ This document describes the following topics:
PPrriinncciipplleess ooff ooppeerraattiioonn PPrriinncciipplleess ooff ooppeerraattiioonn
The before-filter Postfix SMTP server accepts connections from the Internet and As shown in the diagram above, the before-queue filter sits between two Postfix
does the usual relay access control, SASL authentication, TLS negotiation, RBL SMTP server processes.
lookups, rejecting non-existent sender or recipient addresses, etc. The before-
queue filter receives unfiltered mail content from Postfix and does one of the
following:
1. Re-inject the mail back into Postfix via SMTP, perhaps after changing its * The before-filter Postfix SMTP server accepts connections from the Internet
content and/or destination. and does the usual relay access control, SASL authentication, TLS
negotiation, RBL lookups, rejecting non-existent sender or recipient
addresses, etc.
2. Discard or quarantine the mail. * The before-queue filter receives unfiltered mail content from Postfix and
does one of the following:
3. Reject the mail by sending a suitable SMTP status code back to Postfix. 1. Re-inject the mail back into Postfix via SMTP, perhaps after changing
Postfix passes the status back to the remote SMTP client. This way, Postfix its content and/or destination.
does not have to send a bounce message.
The after-filter Postfix SMTP server receives mail from the content filter. 2. Discard or quarantine the mail.
From then on Postfix processes the mail as usual.
3. Reject the mail by sending a suitable SMTP status code back to Postfix.
Postfix passes the status back to the remote SMTP client. This way,
Postfix does not have to send a bounce message.
* The after-filter Postfix SMTP server receives mail from the content filter.
From then on Postfix processes the mail as usual.
The before-queue content filter described here works just like the after-queue The before-queue content filter described here works just like the after-queue
content filter described in the FILTER_README document. In many cases you can content filter described in the FILTER_README document. In many cases you can

View File

@ -14,6 +14,33 @@ specifies the release date of a stable release or snapshot release.
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6 If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
before proceeding. before proceeding.
Incompatibility with snapshot 20091229
======================================
The verify(8) service now uses a persistent cache by default
(address_verify_map = btree:$data_directory/verify_cache). To
disable, specify "address_verify_map =" in main.cf.
When periodic cache cleanup is enabled (the default), the postscreen(8)
and verify(8) servers now require that their cache databases support
the "delete" and "sequence" operations. To disable periodic cache
cleanup specify a zero xxx_cache_cleanup_interval.
Major changes with snapshot 20091229
====================================
Periodic cache cleanup for the postscreen(8) and verify(8) cache
databases. The time between cache cleanup runs is controlled with
the address_verify_cache_cleanup_interval (default: 12h) and
postscreen_cache_cleanup_interval (default: 12h) parameters. Cache
cleanup increases the database access latency, so this should not
be run more often than necessary.
In addition, the postscreen_cache_retention_time (default: 1d)
parameter specifies how long to keep an expired entry in the cache.
This prevents a client from being logged as "NEW" after its record
expired only a little while ago.
Incompatibility with snapshot 20091209 Incompatibility with snapshot 20091209
====================================== ======================================
@ -112,11 +139,12 @@ without blocking mail:
1 - Comment out the "smtp inet ... smtpd" service in master.cf, 1 - Comment out the "smtp inet ... smtpd" service in master.cf,
including any "-o parameter=value" entries that follow. including any "-o parameter=value" entries that follow.
2 - Uncomment the new "smtpd pass ... smtpd" service in master.cf. 2 - Uncomment the new "smtpd pass ... smtpd" service in master.cf,
and duplicate any "-o parameter=value" entries from the smtpd
service that was commented out in step 1.
3 - Uncomment the the new "smtp inet ... postscreen" service in 3 - Uncomment the the new "smtp inet ... postscreen" service in
master.cf, and duplicate any "-o parameter=value" entries from master.cf.
the smtpd service that was commented out in step 1.
4 - Uncomment the new "dnsblog unix ... dnsblog" service in 4 - Uncomment the new "dnsblog unix ... dnsblog" service in
master.cf. This service does DNSBL lookups for postscreen(8) master.cf. This service does DNSBL lookups for postscreen(8)

View File

@ -2,11 +2,25 @@ Wish list:
Remove this file from the stable release. Remove this file from the stable release.
It would be nice if the generic dict_cache(3) cache manager
could postpone process suicide until cache cleanup is
completed (but that is not possible when postscreen forks
into the background to finish already-accepted connections).
When postscreen drops a connection, a 521 "greeting" should
be of the form "521 servername..." and not have an enhanced
status code. The "521 5.7.1" form can be used after EHLO.
Of course no spammer is going to complain about Postfix
SMTP compliance.
Find a place to document all the mail routing mechanisms Find a place to document all the mail routing mechanisms
in one place so people can figure out how Postfix works. in one place so people can figure out how Postfix works.
owner-listname does not work for shell commands. owner-listname does not work for shell commands.
Investigate viability of Sendmail socket maps (the moral
equivalent of tcp_table(5)), and dns maps.
The BCC action is marked "not stable", perhaps because The BCC action is marked "not stable", perhaps because
people would also expect BCC actions in header/body_checks. people would also expect BCC actions in header/body_checks.
How much would it take to make the queue file editing code How much would it take to make the queue file editing code

View File

@ -108,11 +108,18 @@ filter</a>
<h2><a name="principles">Principles of operation</a></h2> <h2><a name="principles">Principles of operation</a></h2>
<p> The before-filter Postfix SMTP server accepts connections from the <p> As shown in the diagram above, the before-queue filter sits
between two Postfix SMTP server processes. </p>
<ul>
<li> <p> The before-filter Postfix SMTP server accepts connections from the
Internet and does the usual relay access control, SASL authentication, Internet and does the usual relay access control, SASL authentication,
TLS negotiation, TLS negotiation,
RBL lookups, rejecting non-existent sender or recipient addresses, RBL lookups, rejecting non-existent sender or recipient addresses,
etc. The before-queue filter receives unfiltered mail content from etc. </p>
<li> <p> The before-queue filter receives unfiltered mail content from
Postfix and does one of the following: </p> Postfix and does one of the following: </p>
<ol> <ol>
@ -129,9 +136,11 @@ Postfix and does one of the following: </p>
</ol> </ol>
<p>The after-filter Postfix SMTP server receives mail from the <li> <p>The after-filter Postfix SMTP server receives mail from the
content filter. From then on Postfix processes the mail as usual. </p> content filter. From then on Postfix processes the mail as usual. </p>
</ul>
<p> The before-queue content filter described here works just like <p> The before-queue content filter described here works just like
the after-queue content filter described in the <a href="FILTER_README.html">FILTER_README</a> the after-queue content filter described in the <a href="FILTER_README.html">FILTER_README</a>
document. In many cases you can use the same software, within the document. In many cases you can use the same software, within the

View File

@ -58,8 +58,10 @@ CLEANUP(8) CLEANUP(8)
<a href="http://tools.ietf.org/html/rfc822">RFC 822</a> (ARPA Internet Text Messages) <a href="http://tools.ietf.org/html/rfc822">RFC 822</a> (ARPA Internet Text Messages)
<a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a> (MIME: Format of Internet Message Bodies) <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a> (MIME: Format of Internet Message Bodies)
<a href="http://tools.ietf.org/html/rfc2046">RFC 2046</a> (MIME: Media Types) <a href="http://tools.ietf.org/html/rfc2046">RFC 2046</a> (MIME: Media Types)
<a href="http://tools.ietf.org/html/rfc2822">RFC 2822</a> (Internet Message Format)
<a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced Status Codes) <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced Status Codes)
<a href="http://tools.ietf.org/html/rfc3464">RFC 3464</a> (Delivery status notifications) <a href="http://tools.ietf.org/html/rfc3464">RFC 3464</a> (Delivery status notifications)
<a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> (Internet Message Format)
<b>DIAGNOSTICS</b> <b>DIAGNOSTICS</b>
Problems and transactions are logged to <b>syslogd</b>(8). Problems and transactions are logged to <b>syslogd</b>(8).

View File

@ -119,6 +119,23 @@ Do not change this unless you have a complete understanding of <a href="http://t
</p> </p>
</DD>
<DT><b><a name="address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a>
(default: 12h)</b></DT><DD>
<p> The amount of time between <a href="verify.8.html">verify(8)</a> cache cleanup runs. Cache
cleanup increases the load on the cache database and should therefore
not be run frequently. This feature requires that the cache database
supports the "delete" and "sequence" operators. Specify a zero
interval to disable cache cleanup. </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p>
<p> This feature is available in Postfix 2.7. </p>
</DD> </DD>
<DT><b><a name="address_verify_default_transport">address_verify_default_transport</a> <DT><b><a name="address_verify_default_transport">address_verify_default_transport</a>
@ -249,7 +266,7 @@ This feature is available in Postfix 2.1 and later.
</DD> </DD>
<DT><b><a name="address_verify_poll_count">address_verify_poll_count</a> <DT><b><a name="address_verify_poll_count">address_verify_poll_count</a>
(default: 3)</b></DT><DD> (default: see "postconf -d" output)</b></DT><DD>
<p> <p>
How many times to query the <a href="verify.8.html">verify(8)</a> service for the completion How many times to query the <a href="verify.8.html">verify(8)</a> service for the completion
@ -257,12 +274,16 @@ of an address verification request in progress.
</p> </p>
<p> <p>
The default poll count is 3. With Postfix version 2.7 and later, the SMTP server polls the
<a href="verify.8.html">verify(8)</a> service up to three times under non-overload conditions,
and only once when under overload. With earlier Postfix versions,
the SMTP server always polls the <a href="verify.8.html">verify(8)</a> service up to three
times.
</p> </p>
<p> <p>
Specify 1 to implement a crude form of greylisting, that is, always Specify 1 to implement a crude form of greylisting, that is, always
defer the first delivery request for a never seen before address. defer the first delivery request for a new address.
</p> </p>
<p> <p>
@ -6561,6 +6582,23 @@ never uses the remote SMTP client hostname. </p>
<p> This feature is available in Postfix 2.7. </p> <p> This feature is available in Postfix 2.7. </p>
</DD>
<DT><b><a name="postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
(default: 12h)</b></DT><DD>
<p> The amount of time between <a href="postscreen.8.html">postscreen(8)</a> cache cleanup runs.
Cache cleanup increases the load on the cache database and should
therefore not be run frequently. This feature requires that the
cache database supports the "delete" and "sequence" operators.
Specify a zero interval to disable cache cleanup. </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p>
<p> This feature is available in Postfix 2.7. </p>
</DD> </DD>
<DT><b><a name="postscreen_cache_map">postscreen_cache_map</a> <DT><b><a name="postscreen_cache_map">postscreen_cache_map</a>
@ -6571,6 +6609,22 @@ never uses the remote SMTP client hostname. </p>
<p> This feature is available in Postfix 2.7. </p> <p> This feature is available in Postfix 2.7. </p>
</DD>
<DT><b><a name="postscreen_cache_retention_time">postscreen_cache_retention_time</a>
(default: 1d)</b></DT><DD>
<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will cache an expired
temporary whitelist entry before it is removed. This prevents clients
from being logged as "NEW" just because their cache entry expired
an hour ago. </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p>
<p> This feature is available in Postfix 2.7. </p>
</DD> </DD>
<DT><b><a name="postscreen_cache_ttl">postscreen_cache_ttl</a> <DT><b><a name="postscreen_cache_ttl">postscreen_cache_ttl</a>
@ -6579,9 +6633,9 @@ never uses the remote SMTP client hostname. </p>
<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will cache a decision for <p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will cache a decision for
a specific SMTP client IP address. During this time, the client IP a specific SMTP client IP address. During this time, the client IP
address is excluded from tests. If possible, expired decisions are address is excluded from tests. If possible, expired decisions are
renewed silently. Specify a non-zero time value (an integral value renewed automatically. Specify a non-zero time value (an integral
plus an optional one-letter suffix that specifies the time unit). value plus an optional one-letter suffix that specifies the time
</p> unit). </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w <p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p> (weeks). </p>
@ -6661,7 +6715,8 @@ IP address. </p>
<DT><b><a name="postscreen_greet_banner">postscreen_greet_banner</a> <DT><b><a name="postscreen_greet_banner">postscreen_greet_banner</a>
(default: $<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>)</b></DT><DD> (default: $<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>)</b></DT><DD>
<p> The text in the optional "220-text..." server response that <p> The <i>text</i> in the optional "220-<i>text</i>..." server
response that
<a href="postscreen.8.html">postscreen(8)</a> sends ahead of the real Postfix SMTP server's "220 <a href="postscreen.8.html">postscreen(8)</a> sends ahead of the real Postfix SMTP server's "220
text..." response, in an attempt to confuse bad SMTP clients so text..." response, in an attempt to confuse bad SMTP clients so
that they speak before their turn (pre-greet). Specify an empty that they speak before their turn (pre-greet). Specify an empty
@ -8905,7 +8960,7 @@ invalid responses. </p>
<ul> <ul>
<li> <p> In the case of a multi-line reply, the Postfix SMTP client <li> <p> In the case of a multi-line reply, the Postfix SMTP client
uses the last reply line's numerical SMTP reply code and enhanced uses the final reply line's numerical SMTP reply code and enhanced
status code. </p> status code. </p>
<li> <p> The numerical SMTP reply code (XYZ) takes precedence over <li> <p> The numerical SMTP reply code (XYZ) takes precedence over
@ -8924,16 +8979,16 @@ server, except that the trailing &lt;CR&gt;&lt;LF&gt; are removed. </p>
<pre> <pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>: /etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/command_filter <a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/reply_filter
</pre> </pre>
<pre> <pre>
/etc/postfix/reply_filter: /etc/postfix/reply_filter:
# Transform garbage into part of a multi-line reply. Note # Transform garbage into "250-filler..." so that it looks like
# that the Postfix SMTP client uses only the last numerical # one line from a multi-line reply. It does not matter what we
# SMTP reply code and enhanced status code from a multi-line # substitute here as long it has the right syntax. The Postfix
# reply, so it does not matter what we substitute here as # SMTP client will use the final line's numerical SMTP reply
# long as it has the right syntax. # code and enhanced status code.
!/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage !/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage
</pre> </pre>
@ -11226,6 +11281,20 @@ except that initial whitespace and the trailing &lt;CR&gt;&lt;LF&gt;
are removed. The result value is executed by the Postfix SMTP are removed. The result value is executed by the Postfix SMTP
server. </p> server. </p>
<p> Postfix already implements a number of workarounds for malformed
client commands. </p>
<ul>
<li> <p> Use "<a href="postconf.5.html#resolve_numeric_domain">resolve_numeric_domain</a> = yes" to accept "<i>user@ipaddress</i>"
Postfix already accepts the correct form "<i>user@[ipaddress]</i>".
</p>
<li> <p> Use "<a href="postconf.5.html#strict_rfc821_envelopes">strict_rfc821_envelopes</a> = no" to accept "<i>User Name
&lt;user@example.com&gt;</i>". </p>
</ul>
<p> Examples: </p> <p> Examples: </p>
<pre> <pre>
@ -11557,8 +11626,9 @@ it changes under overload to just 1 with Postfix 2.6 and later.
(default: no)</b></DT><DD> (default: no)</b></DT><DD>
<p> <p>
Require that a remote SMTP client introduces itself at the beginning Require that a remote SMTP client introduces itself with the HELO
of an SMTP session with the HELO or EHLO command. or EHLO command before sending the MAIL command or other commands
that require EHLO negotiation.
</p> </p>
<p> <p>
@ -12800,12 +12870,12 @@ inside the chroot jail. </p>
<p> By default (see <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>), client certificates are <p> By default (see <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>), client certificates are
not requested, and <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> should remain empty. In contrast not requested, and <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> should remain empty. In contrast
to <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>, DNs of certificate authorities installed to <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>, DNs of certificate authorities installed
in $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> are not included in the client certificate in $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> are not included in the client certificate
request message. MUAs with multiple client certificates may use the request message. MUAs with multiple client certificates may use the
list of preferred certificate authorities to select the correct list of preferred certificate authorities to select the correct
client certificate. You may want to put your "preferred" CA or client certificate. You may want to put your "preferred" CA or
CAs in $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>, and install the remaining trusted CAs in CAs in $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>, and install the remaining trusted CAs in
$<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>. </p> $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>. </p>
<p> Example: </p> <p> Example: </p>

View File

@ -14,26 +14,34 @@ POSTSCREEN(8) POSTSCREEN(8)
<b>DESCRIPTION</b> <b>DESCRIPTION</b>
The Postfix <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server performs triage on multi- The Postfix <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server performs triage on multi-
ple inbound SMTP connections in parallel. The program can ple inbound SMTP connections in parallel. By running
run in two basic modes. time-consuming tests in parallel in <a href="postscreen.8.html"><b>postscreen</b>(8)</a>, zombies
and other bogus clients can be kept away from Postfix SMTP
server processes. Thus, more Postfix SMTP server processes
remain available for legitimate clients.
The purpose of <b>observation mode</b> is to collect statistics This triage process involves a number of tests, documented
without actually blocking mail. <a href="postscreen.8.html"><b>postscreen</b>(8)</a> runs a num- below. The tests introduce a delay of a few seconds; once
ber of tests before it forwards a connection to a real a client passes the tests, its IP address is temporarily
SMTP server process. These tests introduce a delay of a whitelisted, typically for 24 hours.
few seconds; once a client passes the tests as "clean",
its IP address is temporarily whitelisted and subsequent
connections incur no delays until the temporary whitelist
entry expires.
The purpose of <b>enforcement mode</b> is to block mail without The program can run in two basic modes.
using up one Postfix SMTP server process for every connec-
tion. Here, <a href="postscreen.8.html"><b>postscreen</b>(8)</a> terminates connections from <b>Observation mode</b>
SMTP clients that fail the above tests, and forwards only <a href="postscreen.8.html"><b>postscreen</b>(8)</a> reports the results of the tests, and
the remaining connections to a real SMTP server process. forwards all connections to a real Postfix SMTP
By running time-consuming spam tests in parallel in server process.
<a href="postscreen.8.html"><b>postscreen</b>(8)</a>, more Postfix SMTP server processes remain
available for legitimate clients. <b>Enforcement mode</b>
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> reports the results of the tests, but
forwards only connections to a real SMTP server
process from clients that passed the tests.
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> disconnects clients that fail the
tests, after sending a 521 status message (a future
version may pass the connection to a dummy SMTP
protocol engine that logs sender and recipient
information).
Note: <a href="postscreen.8.html"><b>postscreen</b>(8)</a> is not an SMTP proxy; this is inten- Note: <a href="postscreen.8.html"><b>postscreen</b>(8)</a> is not an SMTP proxy; this is inten-
tional. The purpose is to prioritize legitimate clients tional. The purpose is to prioritize legitimate clients
@ -44,144 +52,145 @@ POSTSCREEN(8) POSTSCREEN(8)
<b>1. PERMANENT WHITELIST TEST</b> <b>1. PERMANENT WHITELIST TEST</b>
The <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> parameter (default: The <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> parameter (default:
$<a href="postconf.5.html#mynetworks">mynetworks</a>) specifies a permanent whitelist for SMTP $<a href="postconf.5.html#mynetworks">mynetworks</a>) specifies a permanent whitelist for SMTP
client IP addresses. This feature is not used for client IP addresses.
addresses that appear on the permanent blacklist.
When the SMTP client address matches the permanent When the SMTP client address matches the permanent
whitelist, this is logged as: whitelist, this is logged as:
<b>WHITELISTED</b> <i>address</i> <b>WHITELISTED</b> <i>address</i>
The action is not configurable: immediately forward the The action is not configurable: immediately forward the
connection to a real SMTP server process. connection to a real SMTP server process.
<b>2. PERMANENT BLACKLIST TEST</b> <b>2. PERMANENT BLACKLIST TEST</b>
The <a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter (default: The <a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter (default:
empty) specifies a permanent blacklist for SMTP client IP empty) specifies a permanent blacklist for SMTP client IP
addresses. The address syntax is as with <a href="postconf.5.html#mynetworks">mynetworks</a>. addresses. The address syntax is as with <a href="postconf.5.html#mynetworks">mynetworks</a>.
When the SMTP client address matches the permanent black- When the SMTP client address matches the permanent black-
list, this is logged as: list, this is logged as:
<b>BLACKLISTED</b> <i>address</i> <b>BLACKLISTED</b> <i>address</i>
The <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter specifies the The <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter specifies the
action that is taken next: action that is taken next:
<b>continue</b> (default, observation mode) <b>continue</b> (default, observation mode)
Continue with the SMTP GREETING PHASE TESTS below. Continue with the SMTP GREETING PHASE TESTS below.
<b>drop</b> (enforcement mode) <b>drop</b> (enforcement mode)
Drop the connection immediately with a 521 SMTP Drop the connection immediately with a 521 SMTP
reply. In a future implementation, the connection reply. In a future implementation, the connection
may instead be passed to a dummy SMTP protocol may instead be passed to a dummy SMTP protocol
engine that logs sender and recipient information. engine that logs sender and recipient information.
<b>3. TEMPORARY WHITELIST TEST</b> <b>3. TEMPORARY WHITELIST TEST</b>
The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon maintains a <i>temporary</i> whitelist The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon maintains a <i>temporary</i> whitelist
for SMTP client IP addresses that have passed all the for SMTP client IP addresses that have passed all the
tests described below. The <a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> parameter tests described below. The <a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> parameter
specifies the location of the temporary whitelist. The specifies the location of the temporary whitelist. The
temporary whitelist is not used for SMTP client addresses temporary whitelist is not used for SMTP client addresses
that appear on the <i>permanent</i> blacklist or whitelist. that appear on the <i>permanent</i> blacklist or whitelist.
When the SMTP client address appears on the temporary When the SMTP client address appears on the temporary
whitelist, this is logged as: whitelist, this is logged as:
<b>PASS OLD</b> <i>address</i> <b>PASS OLD</b> <i>address</i>
The action is not configurable: immediately forward the The action is not configurable: immediately forward the
connection to a real SMTP server process. The client is connection to a real SMTP server process. The client is
excluded from further tests until its temporary whitelist excluded from further tests until its temporary whitelist
entry expires, as controlled with the <a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> entry expires, as controlled with the <a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a>
parameter. Expired entries are silently renewed if possi- parameter. Expired entries are silently renewed if possi-
ble. ble.
<b>4. SMTP GREETING PHASE TESTS</b> <b>4. SMTP GREETING PHASE TESTS</b>
The <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter specifies a time The <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter specifies a time
interval during which <a href="postscreen.8.html"><b>postscreen</b>(8)</a> runs a number of tests interval during which <a href="postscreen.8.html"><b>postscreen</b>(8)</a> runs a number of tests
as described below. These tests run before the client may in parallel. These tests are described below, and are run
see the real SMTP server's "220 text..." server greeting. before the client may see the real SMTP server's "220
text..." server greeting.
When the SMTP client passes all the tests, this is logged When the SMTP client passes all greeting-phase tests, this
as: is logged as:
<b>PASS NEW</b> <i>address</i> <b>PASS NEW</b> <i>address</i>
The action is to forward the connection to a real SMTP The action is to forward the connection to a real SMTP
server process and to create a temporary whitelist entry server process and to create a temporary whitelist entry
that excludes the client IP address from further tests that excludes the client IP address from further tests
until the temporary whitelist entry expires, as controlled until the temporary whitelist entry expires, as controlled
with the <a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> parameter. with the <a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> parameter.
In a future implementation, the connection may first be In a future implementation, the connection may first be
passed to a dummy SMTP protocol engine that implements passed to a dummy SMTP protocol engine that implements
more protocol tests including greylisting, before the more protocol tests including greylisting, before the
client is allowed to talk to a real SMTP server process. client is allowed to talk to a real SMTP server process.
<b>4A. PREGREET TEST</b> <b>4A. PREGREET TEST</b>
The <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> parameter specifies the text The <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> parameter specifies the <i>text</i>
for a "220-text..." teaser banner (default: $<a href="postconf.5.html#smtpd_banner">smtpd_ban</a>- portion of a "220-<i>text</i>..." teaser banner (default:
<a href="postconf.5.html#smtpd_banner">ner</a>). The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon sends this before the $<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>). The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> daemon sends this
<a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer is started. The purpose of before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer is started. The
the teaser banner is to confuse SPAM clients so that they purpose of the teaser banner is to confuse SPAM clients so
speak before their turn. It has no effect on SMTP clients that they speak before their turn. It has no effect on
that correctly implement the protocol. SMTP clients that correctly implement the protocol.
To avoid problems with broken SMTP engines in network To avoid problems with broken SMTP engines in network
appliances, either exclude them from all tests with the appliances, either exclude them from all tests with the
<a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> feature or else specify an <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> feature or else specify an
empty <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> value to disable the empty <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> value to disable the
"220-text..." teaser banner. "220-text..." teaser banner.
When an SMTP client sends a command before the When an SMTP client sends a command before the
<a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, this is logged as: <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, this is logged as:
<b>PREGREET</b> <i>count</i> <b>after</b> <i>time</i> <b>from</b> <i>address text...</i> <b>PREGREET</b> <i>count</i> <b>after</b> <i>time</i> <b>from</b> <i>address text...</i>
Translation: the client at <i>address</i> sent <i>count</i> bytes before Translation: the client at <i>address</i> sent <i>count</i> bytes before
its turn to speak, and this happened <i>time</i> seconds after its turn to speak, and this happened <i>time</i> seconds after
the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer was started. The <i>text</i> is the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> timer was started. The <i>text</i> is
what the client sent (truncated to 100 bytes, and with what the client sent (truncated to 100 bytes, and with
non-printable characters replaced with "?"). non-printable characters replaced with "?").
The <a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> parameter specifies the action The <a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> parameter specifies the action
that is taken next: that is taken next:
<b>continue</b> (default, observation mode) <b>continue</b> (default, observation mode)
Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
elapsed, then report DNSBL lookup results if appli- elapsed, then report DNSBL lookup results if appli-
cable. Either perform DNSBL-related actions or for- cable. Either perform DNSBL-related actions or for-
ward the connection to a real SMTP server process. ward the connection to a real SMTP server process.
<b>drop</b> (enforcement mode) <b>drop</b> (enforcement mode)
Drop the connection immediately with a 521 SMTP Drop the connection immediately with a 521 SMTP
reply. In a future implementation, the connection reply. In a future implementation, the connection
may instead be passed to a dummy SMTP protocol may instead be passed to a dummy SMTP protocol
engine that logs sender and recipient information. engine that logs sender and recipient information.
<b>4B. HANGUP TEST</b> <b>4B. HANGUP TEST</b>
When the SMTP client hangs up without sending any data When the SMTP client hangs up without sending any data
before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, this is before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, this is
logged as: logged as:
<b>HANGUP after</b> <i>time</i> <b>from</b> <i>address</i> <b>HANGUP after</b> <i>time</i> <b>from</b> <i>address</i>
The <a href="postconf.5.html#postscreen_hangup_action">postscreen_hangup_action</a> specifies the action that is The <a href="postconf.5.html#postscreen_hangup_action">postscreen_hangup_action</a> specifies the action that is
taken next: taken next:
<b>continue</b> (default, observation mode) <b>continue</b> (default, observation mode)
Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has Wait until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
elapsed, then report DNSBL lookup results if appli- elapsed, then report DNSBL lookup results if appli-
cable. Do not forward the broken connection to a cable. Do not forward the broken connection to a
real SMTP server process. real SMTP server process.
<b>drop</b> (enforcement mode) <b>drop</b> (enforcement mode)
Drop the connection immediately. Drop the connection immediately.
<b>4C. DNS BLOCKLIST TEST</b> <b>4C. DNS BLOCKLIST TEST</b>
The <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter (default: empty) The <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter (default: empty)
specifies a list of DNS blocklist servers. specifies a list of DNS blocklist servers. These lookups
are made in parallel.
When the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, and the When the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, and the
SMTP client address is listed with at least one of these SMTP client address is listed with at least one of these
@ -237,14 +246,6 @@ POSTSCREEN(8) POSTSCREEN(8)
see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for
possible actions. possible actions.
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_whitelist)</b>
Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
decisions.
<b><a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> (1d)</b>
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache a
decision for a specific SMTP client IP address.
<b><a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> (continue)</b> <b><a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> (continue)</b>
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
client is listed at the DNS blocklist domains spec- client is listed at the DNS blocklist domains spec-
@ -259,7 +260,7 @@ POSTSCREEN(8) POSTSCREEN(8)
ified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter. ified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter.
<b><a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> ($<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>)</b> <b><a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> ($<a href="postconf.5.html#smtpd_banner">smtpd_banner</a>)</b>
The text in the optional "220-text..." server The <i>text</i> in the optional "220-<i>text</i>..." server
response that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> sends ahead of the real response that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> sends ahead of the real
Postfix SMTP server's "220 text..." response, in an 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
@ -294,22 +295,40 @@ POSTSCREEN(8) POSTSCREEN(8)
The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
allowed connections to. allowed connections to.
<b>CACHE CONTROLS</b>
<b><a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> (12h)</b>
The amount of time between <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
cleanup runs.
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_whitelist)</b>
Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
decisions.
<b><a href="postconf.5.html#postscreen_cache_retention_time">postscreen_cache_retention_time</a> (1d)</b>
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache an
expired temporary whitelist entry before it is
removed.
<b><a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> (1d)</b>
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache a
decision for a specific SMTP client IP address.
<b>MISCELLANEOUS CONTROLS</b> <b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files. <a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b> <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
How much time a Postfix daemon process may take to How much time a Postfix daemon process may take to
handle a request before it is terminated by a handle a request before it is terminated by a
built-in watchdog timer. built-in watchdog timer.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b> <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
The maximal number of digits after the decimal The maximal number of digits after the decimal
point when logging sub-second delay values. point when logging sub-second delay values.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
The location of all postfix administrative com- The location of all postfix administrative com-
mands. mands.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b> <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@ -317,24 +336,24 @@ POSTSCREEN(8) POSTSCREEN(8)
over an internal communication channel. over an internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b> <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
The maximum amount of time that an idle Postfix The maximum amount of time that an idle Postfix
daemon process waits for an incoming connection daemon process waits for an incoming connection
before terminating voluntarily. before terminating voluntarily.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b> <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The process ID of a Postfix command or daemon The process ID of a Postfix command or daemon
process. process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b> <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
The process name of a Postfix command or daemon The process name of a Postfix command or daemon
process. process.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b> <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging. The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
The mail system name that is prepended to the The mail system name that is prepended to the
process name in syslog records, so that "smtpd" process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd". becomes, for example, "postfix/smtpd".
<b>SEE ALSO</b> <b>SEE ALSO</b>
@ -343,7 +362,7 @@ POSTSCREEN(8) POSTSCREEN(8)
syslogd(8), system logging syslogd(8), system logging
<b>LICENSE</b> <b>LICENSE</b>
The Secure Mailer license must be distributed with this The Secure Mailer license must be distributed with this
software. software.
<b>AUTHOR(S)</b> <b>AUTHOR(S)</b>

View File

@ -906,123 +906,124 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b> <b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b>
Require that a remote SMTP client introduces itself Require that a remote SMTP client introduces itself
at the beginning of an SMTP session with the HELO with the HELO or EHLO command before sending the
or EHLO command. MAIL command or other commands that require EHLO
negotiation.
<b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b> <b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
Optional restrictions that the Postfix SMTP server Optional restrictions that the Postfix SMTP server
applies in the context of the SMTP HELO command. applies in the context of the SMTP HELO command.
<b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b> <b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
Optional restrictions that the Postfix SMTP server Optional restrictions that the Postfix SMTP server
applies in the context of the MAIL FROM command. applies in the context of the MAIL FROM command.
<b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b> <b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b>
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b> <b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b>
The access restrictions that the Postfix SMTP The access restrictions that the Postfix SMTP
server applies in the context of the RCPT TO com- server applies in the context of the RCPT TO com-
mand. mand.
<b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b> <b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
Optional SMTP server access restrictions in the Optional SMTP server access restrictions in the
context of a client ETRN request. context of a client ETRN request.
<b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b> <b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b>
Forward mail with sender-specified routing Forward mail with sender-specified routing
(user[@%!]remote[@%!]site) from untrusted clients (user[@%!]remote[@%!]site) from untrusted clients
to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>. to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b> <b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b>
User-defined aliases for groups of access restric- User-defined aliases for groups of access restric-
tions. tions.
<b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b>&lt;&gt;<b>)</b> <b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b>&lt;&gt;<b>)</b>
The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
instead of the null sender address. instead of the null sender address.
<b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b> <b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b>
Restrict the use of the <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a> SMTP Restrict the use of the <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a> SMTP
access feature to only domains whose primary MX access feature to only domains whose primary MX
hosts match the listed networks. hosts match the listed networks.
Available in Postfix version 2.0 and later: Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b> <b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b>
Optional access restrictions that the Postfix SMTP Optional access restrictions that the Postfix SMTP
server applies in the context of the SMTP DATA com- server applies in the context of the SMTP DATA com-
mand. mand.
<b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b>
What characters are allowed in $name expansions of What characters are allowed in $name expansions of
RBL reply templates. RBL reply templates.
Available in Postfix version 2.1 and later: Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b> <b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
Request that the Postfix SMTP server rejects mail Request that the Postfix SMTP server rejects mail
from unknown sender addresses, even when no from unknown sender addresses, even when no
explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
is specified. is specified.
<b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b> <b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b>
Request that the Postfix SMTP server rejects mail Request that the Postfix SMTP server rejects mail
for unknown recipient addresses, even when no for unknown recipient addresses, even when no
explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric- explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
tion is specified. tion is specified.
Available in Postfix version 2.2 and later: Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b> <b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b>
Optional access restrictions that the Postfix SMTP Optional access restrictions that the Postfix SMTP
server applies in the context of the SMTP END-OF- server applies in the context of the SMTP END-OF-
DATA command. DATA command.
<b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b> <b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
Postfix version 2.1 introduces sender and recipient Postfix version 2.1 introduces sender and recipient
address verification. This feature is implemented by address verification. This feature is implemented by
sending probe email messages that are not actually deliv- sending probe email messages that are not actually deliv-
ered. This feature is requested via the reject_unveri- ered. This feature is requested via the reject_unveri-
fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
restrictions. The status of verification probes is main- restrictions. The status of verification probes is main-
tained by the <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VER</a>- tained by the <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VER</a>-
<a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
and operate the Postfix sender/recipient address verifica- and operate the Postfix sender/recipient address verifica-
tion service. tion service.
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (3)</b> <b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (see 'postconf -d' output)</b>
How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
the completion of an address verification request the completion of an address verification request
in progress. in progress.
<b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b> <b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b>
The delay between queries for the completion of an The delay between queries for the completion of an
address verification request in progress. address verification request in progress.
<b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> ($<a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a>)</b> <b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> ($<a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a>)</b>
The sender address to use in address verification The sender address to use in address verification
probes; prior to Postfix 2.5 the default was "post- probes; prior to Postfix 2.5 the default was "post-
master". master".
<b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b> <b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a recipient address is rejected by the when a recipient address is rejected by the
<a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction. <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction.
<b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b> <b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b>
The numerical Postfix SMTP server response when a The numerical Postfix SMTP server response when a
recipient address is rejected by the reject_unveri- recipient address is rejected by the reject_unveri-
fied_recipient restriction. fied_recipient restriction.
Available in Postfix version 2.6 and later: Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#unverified_sender_defer_code">unverified_sender_defer_code</a> (450)</b> <b><a href="postconf.5.html#unverified_sender_defer_code">unverified_sender_defer_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a sender address probe fails due to a tempo- when a sender address probe fails due to a tempo-
rary error condition. rary error condition.
<b><a href="postconf.5.html#unverified_recipient_defer_code">unverified_recipient_defer_code</a> (450)</b> <b><a href="postconf.5.html#unverified_recipient_defer_code">unverified_recipient_defer_code</a> (450)</b>
The numerical Postfix SMTP server response when a The numerical Postfix SMTP server response when a
recipient address probe fails due to a temporary recipient address probe fails due to a temporary
error condition. error condition.
<b><a href="postconf.5.html#unverified_sender_reject_reason">unverified_sender_reject_reason</a> (empty)</b> <b><a href="postconf.5.html#unverified_sender_reject_reason">unverified_sender_reject_reason</a> (empty)</b>
@ -1036,7 +1037,7 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b> <b><a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b> <b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unver</a>- The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unver</a>-
<a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi- <a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
tion. tion.
<b><a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b> <b><a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
@ -1046,7 +1047,7 @@ SMTPD(8) SMTPD(8)
dition. dition.
<b>ACCESS CONTROL RESPONSES</b> <b>ACCESS CONTROL RESPONSES</b>
The following parameters control numerical SMTP reply The following parameters control numerical SMTP reply
codes and/or text responses. codes and/or text responses.
<b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b> <b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b>
@ -1054,18 +1055,18 @@ SMTPD(8) SMTPD(8)
an <a href="access.5.html"><b>access</b>(5)</a> map "reject" action. an <a href="access.5.html"><b>access</b>(5)</a> map "reject" action.
<b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b> <b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a remote SMTP client request is rejected by when a remote SMTP client request is rejected by
the "defer" restriction. the "defer" restriction.
<b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b> <b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when the client HELO or EHLO command parameter is when the client HELO or EHLO command parameter is
rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a> rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
restriction. restriction.
<b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b> <b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>, <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>, <a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>, <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>,
<a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a> or <a href="postconf.5.html#reject_rhsbl_recipient">reject_rhsbl_recipient</a> <a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a> or <a href="postconf.5.html#reject_rhsbl_recipient">reject_rhsbl_recipient</a>
@ -1073,53 +1074,53 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b> <b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
The numerical Postfix SMTP server reply code when a The numerical Postfix SMTP server reply code when a
client request is rejected by the client request is rejected by the
<a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>, <a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
<a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a> <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
restriction. restriction.
<b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b> <b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a request is rejected by the <b>reject_plain-</b> when a request is rejected by the <b>reject_plain-</b>
<b>text_session</b> restriction. <b>text_session</b> restriction.
<b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b> <b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a remote SMTP client request is rejected by when a remote SMTP client request is rejected by
the "reject" restriction. the "reject" restriction.
<b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b> <b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a client request is rejected by the when a client request is rejected by the
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction. <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
<b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b> <b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a sender or recipient address is rejected by when a sender or recipient address is rejected by
the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction. <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
<b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b> <b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a client without valid address &lt;=&gt; name map- when a client without valid address &lt;=&gt; name map-
ping is rejected by the reject_unknown_client_host- ping is rejected by the reject_unknown_client_host-
name restriction. name restriction.
<b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b> <b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when the hostname specified with the HELO or EHLO when the hostname specified with the HELO or EHLO
command is rejected by the command is rejected by the
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction. <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
Available in Postfix version 2.0 and later: Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
The default SMTP server response template for a The default SMTP server response template for a
request that is rejected by an RBL-based restric- request that is rejected by an RBL-based restric-
tion. tion.
<b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b> <b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
The numerical Postfix SMTP server response code The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction. <a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
@ -1130,38 +1131,38 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> (450)</b> <b><a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> (450)</b>
The numerical Postfix SMTP server response code for The numerical Postfix SMTP server response code for
an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
"<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" or "<a href="postconf.5.html#defer_if_reject">defer_if_reject</a>". "<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" or "<a href="postconf.5.html#defer_if_reject">defer_if_reject</a>".
<b><a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a> (<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>)</b> <b><a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a> (<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>)</b>
The Postfix SMTP server's action when a reject-type The Postfix SMTP server's action when a reject-type
restriction fails due to a temporary error condi- restriction fails due to a temporary error condi-
tion. tion.
<b><a href="postconf.5.html#unknown_helo_hostname_tempfail_action">unknown_helo_hostname_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b> <b><a href="postconf.5.html#unknown_helo_hostname_tempfail_action">unknown_helo_hostname_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b> <b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
The Postfix SMTP server's action when The Postfix SMTP server's action when
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> fails due to an tempo- <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> fails due to an tempo-
rary error condition. rary error condition.
<b><a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b> <b><a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b>
The Postfix SMTP server's action when The Postfix SMTP server's action when
<a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem- <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
porary error condition. porary error condition.
<b>MISCELLANEOUS CONTROLS</b> <b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files. <a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b> <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
How much time a Postfix daemon process may take to How much time a Postfix daemon process may take to
handle a request before it is terminated by a handle a request before it is terminated by a
built-in watchdog timer. built-in watchdog timer.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
The location of all postfix administrative com- The location of all postfix administrative com-
mands. mands.
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b> <b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
@ -1182,37 +1183,37 @@ SMTPD(8) SMTPD(8)
and most Postfix daemon processes. and most Postfix daemon processes.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b> <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
The maximum amount of time that an idle Postfix The maximum amount of time that an idle Postfix
daemon process waits for an incoming connection daemon process waits for an incoming connection
before terminating voluntarily. before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b> <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
The maximal number of incoming connections that a The maximal number of incoming connections that a
Postfix daemon process will service before termi- Postfix daemon process will service before termi-
nating voluntarily. nating voluntarily.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
The internet hostname of this mail system. The internet hostname of this mail system.
<b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
The list of "trusted" SMTP clients that have more The list of "trusted" SMTP clients that have more
privileges than "strangers". privileges than "strangers".
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b> <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to The domain name that locally-posted mail appears to
come from, and that locally posted mail is deliv- come from, and that locally posted mail is deliv-
ered to. ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b> <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The process ID of a Postfix command or daemon The process ID of a Postfix command or daemon
process. process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b> <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
The process name of a Postfix command or daemon The process name of a Postfix command or daemon
process. process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc- The location of the Postfix top-level queue direc-
tory. tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b> <b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
@ -1220,28 +1221,28 @@ SMTPD(8) SMTPD(8)
sions (user+foo). sions (user+foo).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b> <b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
The text that follows the 220 status code in the The text that follows the 220 status code in the
SMTP greeting banner. SMTP greeting banner.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b> <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging. The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
The mail system name that is prepended to the The mail system name that is prepended to the
process name in syslog records, so that "smtpd" process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd". becomes, for example, "postfix/smtpd".
Available in Postfix version 2.2 and later: Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b> <b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
List of commands that causes the Postfix SMTP List of commands that causes the Postfix SMTP
server to immediately terminate the session with a server to immediately terminate the session with a
221 code. 221 code.
Available in Postfix version 2.5 and later: Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> (no)</b> <b><a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> (no)</b>
Enable logging of the remote SMTP client port in Enable logging of the remote SMTP client port in
addition to the hostname and IP address. addition to the hostname and IP address.
<b>SEE ALSO</b> <b>SEE ALSO</b>
@ -1271,7 +1272,7 @@ SMTPD(8) SMTPD(8)
<a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension <a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
<b>LICENSE</b> <b>LICENSE</b>
The Secure Mailer license must be distributed with this The Secure Mailer license must be distributed with this
software. software.
<b>AUTHOR(S)</b> <b>AUTHOR(S)</b>

View File

@ -115,17 +115,23 @@ VERIFY(8) VERIFY(8)
The time after which a failed address verification The time after which a failed address verification
probe needs to be refreshed. probe needs to be refreshed.
Available with Postfix 2.7 and later:
<b><a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> (12h)</b>
The amount of time between <a href="verify.8.html"><b>verify</b>(8)</a> cache cleanup
runs.
<b>PROBE MESSAGE ROUTING CONTROLS</b> <b>PROBE MESSAGE ROUTING CONTROLS</b>
By default, probe messages are delivered via the same By default, probe messages are delivered via the same
route as regular messages. The following parameters can route as regular messages. The following parameters can
be used to override specific message routing mechanisms. be used to override specific message routing mechanisms.
<b><a href="postconf.5.html#address_verify_relayhost">address_verify_relayhost</a> ($<a href="postconf.5.html#relayhost">relayhost</a>)</b> <b><a href="postconf.5.html#address_verify_relayhost">address_verify_relayhost</a> ($<a href="postconf.5.html#relayhost">relayhost</a>)</b>
Overrides the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting for Overrides the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting for
address verification probes. address verification probes.
<b><a href="postconf.5.html#address_verify_transport_maps">address_verify_transport_maps</a> ($<a href="postconf.5.html#transport_maps">transport_maps</a>)</b> <b><a href="postconf.5.html#address_verify_transport_maps">address_verify_transport_maps</a> ($<a href="postconf.5.html#transport_maps">transport_maps</a>)</b>
Overrides the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter setting for Overrides the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter setting for
address verification probes. address verification probes.
<b><a href="postconf.5.html#address_verify_local_transport">address_verify_local_transport</a> ($<a href="postconf.5.html#local_transport">local_transport</a>)</b> <b><a href="postconf.5.html#address_verify_local_transport">address_verify_local_transport</a> ($<a href="postconf.5.html#local_transport">local_transport</a>)</b>
@ -133,7 +139,7 @@ VERIFY(8) VERIFY(8)
address verification probes. address verification probes.
<b><a href="postconf.5.html#address_verify_virtual_transport">address_verify_virtual_transport</a> ($<a href="postconf.5.html#virtual_transport">virtual_transport</a>)</b> <b><a href="postconf.5.html#address_verify_virtual_transport">address_verify_virtual_transport</a> ($<a href="postconf.5.html#virtual_transport">virtual_transport</a>)</b>
Overrides the <a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter setting Overrides the <a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter setting
for address verification probes. for address verification probes.
<b><a href="postconf.5.html#address_verify_relay_transport">address_verify_relay_transport</a> ($<a href="postconf.5.html#relay_transport">relay_transport</a>)</b> <b><a href="postconf.5.html#address_verify_relay_transport">address_verify_relay_transport</a> ($<a href="postconf.5.html#relay_transport">relay_transport</a>)</b>
@ -141,17 +147,32 @@ VERIFY(8) VERIFY(8)
address verification probes. address verification probes.
<b><a href="postconf.5.html#address_verify_default_transport">address_verify_default_transport</a> ($<a href="postconf.5.html#default_transport">default_transport</a>)</b> <b><a href="postconf.5.html#address_verify_default_transport">address_verify_default_transport</a> ($<a href="postconf.5.html#default_transport">default_transport</a>)</b>
Overrides the <a href="postconf.5.html#default_transport">default_transport</a> parameter setting Overrides the <a href="postconf.5.html#default_transport">default_transport</a> parameter setting
for address verification probes. for address verification probes.
Available in Postfix 2.3 and later:
<b><a href="postconf.5.html#address_verify_sender_dependent_relayhost_maps">address_verify_sender_dependent_relayhost_maps</a></b>
<b>($<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>)</b>
Overrides the <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>
parameter setting for address verification probes.
Available in Postfix 2.7 and later:
<b><a href="postconf.5.html#address_verify_sender_dependent_default_transport_maps">address_verify_sender_dependent_default_transport_maps</a></b>
<b>($<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>)</b>
Overrides the <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_trans</a>-
<a href="postconf.5.html#sender_dependent_default_transport_maps">port_maps</a> parameter setting for address verifica-
tion probes.
<b>MISCELLANEOUS CONTROLS</b> <b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files. <a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b> <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
How much time a Postfix daemon process may take to How much time a Postfix daemon process may take to
handle a request before it is terminated by a handle a request before it is terminated by a
built-in watchdog timer. built-in watchdog timer.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b> <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@ -159,23 +180,23 @@ VERIFY(8) VERIFY(8)
over an internal communication channel. over an internal communication channel.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b> <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The process ID of a Postfix command or daemon The process ID of a Postfix command or daemon
process. process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b> <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
The process name of a Postfix command or daemon The process name of a Postfix command or daemon
process. process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc- The location of the Postfix top-level queue direc-
tory. tory.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b> <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging. The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b> <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
The mail system name that is prepended to the The mail system name that is prepended to the
process name in syslog records, so that "smtpd" process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd". becomes, for example, "postfix/smtpd".
<b>SEE ALSO</b> <b>SEE ALSO</b>
@ -188,7 +209,7 @@ VERIFY(8) VERIFY(8)
<a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VERIFICATION_README</a>, address verification howto <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VERIFICATION_README</a>, address verification howto
<b>LICENSE</b> <b>LICENSE</b>
The Secure Mailer license must be distributed with this The Secure Mailer license must be distributed with this
software. software.
<b>HISTORY</b> <b>HISTORY</b>

View File

@ -77,6 +77,17 @@ The numerical Postfix SMTP server response code for
an \fBaccess\fR(5) map "reject" action. an \fBaccess\fR(5) map "reject" action.
.PP .PP
Do not change this unless you have a complete understanding of RFC 2821. Do not change this unless you have a complete understanding of RFC 2821.
.SH address_verify_cache_cleanup_interval (default: 12h)
The amount of time between \fBverify\fR(8) cache cleanup runs. Cache
cleanup increases the load on the cache database and should therefore
not be run frequently. This feature requires that the cache database
supports the "delete" and "sequence" operators. Specify a zero
interval to disable cache cleanup.
.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks).
.PP
This feature is available in Postfix 2.7.
.SH address_verify_default_transport (default: $default_transport) .SH address_verify_default_transport (default: $default_transport)
Overrides the default_transport parameter setting for address Overrides the default_transport parameter setting for address
verification probes. verification probes.
@ -138,14 +149,18 @@ be refreshed.
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
.PP .PP
This feature is available in Postfix 2.1 and later. This feature is available in Postfix 2.1 and later.
.SH address_verify_poll_count (default: 3) .SH address_verify_poll_count (default: see "postconf -d" output)
How many times to query the \fBverify\fR(8) service for the completion How many times to query the \fBverify\fR(8) service for the completion
of an address verification request in progress. of an address verification request in progress.
.PP .PP
The default poll count is 3. With Postfix version 2.7 and later, the SMTP server polls the
\fBverify\fR(8) service up to three times under non-overload conditions,
and only once when under overload. With earlier Postfix versions,
the SMTP server always polls the \fBverify\fR(8) service up to three
times.
.PP .PP
Specify 1 to implement a crude form of greylisting, that is, always Specify 1 to implement a crude form of greylisting, that is, always
defer the first delivery request for a never seen before address. defer the first delivery request for a new address.
.PP .PP
Example: Example:
.PP .PP
@ -3673,16 +3688,38 @@ The blacklist has higher precedence than whitelists. This feature
never uses the remote SMTP client hostname. never uses the remote SMTP client hostname.
.PP .PP
This feature is available in Postfix 2.7. This feature is available in Postfix 2.7.
.SH postscreen_cache_cleanup_interval (default: 12h)
The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
Cache cleanup increases the load on the cache database and should
therefore not be run frequently. This feature requires that the
cache database supports the "delete" and "sequence" operators.
Specify a zero interval to disable cache cleanup.
.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks).
.PP
This feature is available in Postfix 2.7.
.SH postscreen_cache_map (default: btree:$data_directory/ps_whitelist) .SH postscreen_cache_map (default: btree:$data_directory/ps_whitelist)
Persistent storage for the \fBpostscreen\fR(8) server decisions. Persistent storage for the \fBpostscreen\fR(8) server decisions.
.PP .PP
This feature is available in Postfix 2.7. This feature is available in Postfix 2.7.
.SH postscreen_cache_retention_time (default: 1d)
The amount of time that \fBpostscreen\fR(8) will cache an expired
temporary whitelist entry before it is removed. This prevents clients
from being logged as "NEW" just because their cache entry expired
an hour ago.
.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks).
.PP
This feature is available in Postfix 2.7.
.SH postscreen_cache_ttl (default: 1d) .SH postscreen_cache_ttl (default: 1d)
The amount of time that \fBpostscreen\fR(8) will cache a decision for The amount of time that \fBpostscreen\fR(8) will cache a decision for
a specific SMTP client IP address. During this time, the client IP a specific SMTP client IP address. During this time, the client IP
address is excluded from tests. If possible, expired decisions are address is excluded from tests. If possible, expired decisions are
renewed silently. Specify a non-zero time value (an integral value renewed automatically. Specify a non-zero time value (an integral
plus an optional one-letter suffix that specifies the time unit). value plus an optional one-letter suffix that specifies the time
unit).
.PP .PP
Time units: s (seconds), m (minutes), h (hours), d (days), w Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). (weeks).
@ -3722,7 +3759,8 @@ IP address.
.PP .PP
This feature is available in Postfix 2.7. This feature is available in Postfix 2.7.
.SH postscreen_greet_banner (default: $smtpd_banner) .SH postscreen_greet_banner (default: $smtpd_banner)
The text in the optional "220-text..." server response that The \fItext\fR in the optional "220-\fItext\fR..." server
response that
\fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220 \fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
text..." response, in an attempt to confuse bad SMTP clients so text..." response, in an attempt to confuse bad SMTP clients so
that they speak before their turn (pre-greet). Specify an empty that they speak before their turn (pre-greet). Specify an empty
@ -5028,7 +5066,7 @@ invalid responses.
Notes: Notes:
.IP \(bu .IP \(bu
In the case of a multi-line reply, the Postfix SMTP client In the case of a multi-line reply, the Postfix SMTP client
uses the last reply line's numerical SMTP reply code and enhanced uses the final reply line's numerical SMTP reply code and enhanced
status code. status code.
.IP \(bu .IP \(bu
The numerical SMTP reply code (XYZ) takes precedence over The numerical SMTP reply code (XYZ) takes precedence over
@ -5047,7 +5085,7 @@ Examples:
.na .na
.ft C .ft C
/etc/postfix/main.cf: /etc/postfix/main.cf:
smtp_reply_filter = pcre:/etc/postfix/command_filter smtp_reply_filter = pcre:/etc/postfix/reply_filter
.fi .fi
.ad .ad
.ft R .ft R
@ -5056,11 +5094,11 @@ Examples:
.na .na
.ft C .ft C
/etc/postfix/reply_filter: /etc/postfix/reply_filter:
# Transform garbage into part of a multi-line reply. Note # Transform garbage into "250-filler..." so that it looks like
# that the Postfix SMTP client uses only the last numerical # one line from a multi-line reply. It does not matter what we
# SMTP reply code and enhanced status code from a multi-line # substitute here as long it has the right syntax. The Postfix
# reply, so it does not matter what we substitute here as # SMTP client will use the final line's numerical SMTP reply
# long as it has the right syntax. # code and enhanced status code.
!/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage !/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage
.fi .fi
.ad .ad
@ -6890,6 +6928,15 @@ except that initial whitespace and the trailing <CR><LF>
are removed. The result value is executed by the Postfix SMTP are removed. The result value is executed by the Postfix SMTP
server. server.
.PP .PP
Postfix already implements a number of workarounds for malformed
client commands.
.IP \(bu
Use "resolve_numeric_domain = yes" to accept "\fIuser@ipaddress\fR"
Postfix already accepts the correct form "\fIuser@[ipaddress]\fR".
.IP \(bu
Use "strict_rfc821_envelopes = no" to accept "\fIUser Name
<user@example.com>\fR".
.PP
Examples: Examples:
.PP .PP
.nf .nf
@ -7104,8 +7151,9 @@ make without delivering mail. The Postfix SMTP server disconnects
when the limit is exceeded. Normally the default limit is 20, but when the limit is exceeded. Normally the default limit is 20, but
it changes under overload to just 1 with Postfix 2.6 and later. it changes under overload to just 1 with Postfix 2.6 and later.
.SH smtpd_helo_required (default: no) .SH smtpd_helo_required (default: no)
Require that a remote SMTP client introduces itself at the beginning Require that a remote SMTP client introduces itself with the HELO
of an SMTP session with the HELO or EHLO command. or EHLO command before sending the MAIL command or other commands
that require EHLO negotiation.
.PP .PP
Example: Example:
.PP .PP
@ -7927,12 +7975,12 @@ inside the chroot jail.
.PP .PP
By default (see smtpd_tls_ask_ccert), client certificates are By default (see smtpd_tls_ask_ccert), client certificates are
not requested, and smtpd_tls_CApath should remain empty. In contrast not requested, and smtpd_tls_CApath should remain empty. In contrast
to smtp_tls_CAfile, DNs of certificate authorities installed to smtpd_tls_CAfile, DNs of certificate authorities installed
in $smtpd_tls_CApath are not included in the client certificate in $smtpd_tls_CApath are not included in the client certificate
request message. MUAs with multiple client certificates may use the request message. MUAs with multiple client certificates may use the
list of preferred certificate authorities to select the correct list of preferred certificate authorities to select the correct
client certificate. You may want to put your "preferred" CA or client certificate. You may want to put your "preferred" CA or
CAs in $smtp_tls_CAfile, and install the remaining trusted CAs in CAs in $smtpd_tls_CAfile, and install the remaining trusted CAs in
$smtpd_tls_CApath. $smtpd_tls_CApath.
.PP .PP
Example: Example:

View File

@ -54,8 +54,10 @@ in case of trouble.
RFC 822 (ARPA Internet Text Messages) RFC 822 (ARPA Internet Text Messages)
RFC 2045 (MIME: Format of Internet Message Bodies) RFC 2045 (MIME: Format of Internet Message Bodies)
RFC 2046 (MIME: Media Types) RFC 2046 (MIME: Media Types)
RFC 2822 (Internet Message Format)
RFC 3463 (Enhanced Status Codes) RFC 3463 (Enhanced Status Codes)
RFC 3464 (Delivery status notifications) RFC 3464 (Delivery status notifications)
RFC 5322 (Internet Message Format)
.SH DIAGNOSTICS .SH DIAGNOSTICS
.ad .ad
.fi .fi

View File

@ -13,26 +13,31 @@ Postfix SMTP triage server
.ad .ad
.fi .fi
The Postfix \fBpostscreen\fR(8) server performs triage on The Postfix \fBpostscreen\fR(8) server performs triage on
multiple inbound SMTP connections in parallel. The program multiple inbound SMTP connections in parallel. By running
can run in two basic modes. time-consuming tests in parallel in \fBpostscreen\fR(8),
zombies and other bogus clients can be kept away from Postfix
SMTP server processes. Thus, more Postfix SMTP server
processes remain available for legitimate clients.
The purpose of \fBobservation mode\fR is to collect statistics This triage process involves a number of tests, documented
without actually blocking mail. \fBpostscreen\fR(8) runs a below. The tests introduce a delay of a few seconds; once
number of tests before it forwards a connection to a real a client passes the tests, its IP address is temporarily
SMTP server process. These tests introduce a delay of a whitelisted, typically for 24 hours.
few seconds; once a client passes the tests as "clean", its
IP address is temporarily whitelisted and subsequent
connections incur no delays until the temporary whitelist
entry expires.
The purpose of \fBenforcement mode\fR is to block mail The program can run in two basic modes.
without using up one Postfix SMTP server process for every .IP "\fBObservation mode\fR"
connection. Here, \fBpostscreen\fR(8) terminates connections \fBpostscreen\fR(8) reports the results of the tests, and
from SMTP clients that fail the above tests, and forwards forwards all connections to a real Postfix SMTP server
only the remaining connections to a real SMTP server process. process.
By running time-consuming spam tests in parallel in .IP "\fBEnforcement mode\fR"
\fBpostscreen\fR(8), more Postfix SMTP server processes \fBpostscreen\fR(8) reports the results of the tests, but
remain available for legitimate clients. forwards only connections to a real SMTP server process
from clients that passed the tests.
.sp
\fBpostscreen\fR(8) disconnects clients that fail the tests,
after sending a 521 status message (a future version may
pass the connection to a dummy SMTP protocol engine that
logs sender and recipient information).
.PP .PP
Note: \fBpostscreen\fR(8) is not an SMTP proxy; this is Note: \fBpostscreen\fR(8) is not an SMTP proxy; this is
intentional. The purpose is to prioritize legitimate clients intentional. The purpose is to prioritize legitimate clients
@ -44,8 +49,7 @@ with as little overhead as possible.
.fi .fi
The postscreen_whitelist_networks parameter (default: The postscreen_whitelist_networks parameter (default:
$mynetworks) specifies a permanent whitelist for SMTP client $mynetworks) specifies a permanent whitelist for SMTP client
IP addresses. This feature is not used for addresses that IP addresses.
appear on the permanent blacklist.
When the SMTP client address matches the permanent whitelist, When the SMTP client address matches the permanent whitelist,
this is logged as: this is logged as:
@ -105,12 +109,13 @@ parameter. Expired entries are silently renewed if possible.
.ad .ad
.fi .fi
The postscreen_greet_wait parameter specifies a time interval The postscreen_greet_wait parameter specifies a time interval
during which \fBpostscreen\fR(8) runs a number of tests as during which \fBpostscreen\fR(8) runs a number of tests in
described below. These tests run before the client may parallel. These tests are described below, and are run
see the real SMTP server's "220 text..." server greeting. before the client may see the real SMTP server's "220
text..." server greeting.
When the SMTP client passes all the tests, this is logged When the SMTP client passes all greeting-phase tests, this
as: is logged as:
.sp .sp
.nf .nf
\fBPASS NEW \fIaddress\fR \fBPASS NEW \fIaddress\fR
@ -129,8 +134,9 @@ to talk to a real SMTP server process.
.SH 4A. PREGREET TEST .SH 4A. PREGREET TEST
.ad .ad
.fi .fi
The postscreen_greet_banner parameter specifies the text The postscreen_greet_banner parameter specifies the \fItext\fR
for a "220-text..." teaser banner (default: $smtpd_banner). portion of a "220-\fItext\fR..." teaser banner (default:
$smtpd_banner).
The \fBpostscreen\fR(8) daemon sends this before the The \fBpostscreen\fR(8) daemon sends this before the
postscreen_greet_wait timer is started. The purpose of the postscreen_greet_wait timer is started. The purpose of the
teaser banner is to confuse SPAM clients so that they speak teaser banner is to confuse SPAM clients so that they speak
@ -191,7 +197,8 @@ Drop the connection immediately.
.ad .ad
.fi .fi
The postscreen_dnsbl_sites parameter (default: empty) The postscreen_dnsbl_sites parameter (default: empty)
specifies a list of DNS blocklist servers. specifies a list of DNS blocklist servers. These lookups
are made in parallel.
When the postscreen_greet_wait time has elapsed, and the When the postscreen_greet_wait time has elapsed, and the
SMTP client address is listed with at least one of these SMTP client address is listed with at least one of these
@ -256,11 +263,6 @@ parameter.
.IP "\fBpostscreen_blacklist_networks (empty)\fR" .IP "\fBpostscreen_blacklist_networks (empty)\fR"
Network addresses that are permanently blacklisted; see the Network addresses that are permanently blacklisted; see the
postscreen_blacklist_action parameter for possible actions. postscreen_blacklist_action parameter for possible actions.
.IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
Persistent storage for the \fBpostscreen\fR(8) server decisions.
.IP "\fBpostscreen_cache_ttl (1d)\fR"
The amount of time that \fBpostscreen\fR(8) will cache a decision for
a specific SMTP client IP address.
.IP "\fBpostscreen_dnsbl_action (continue)\fR" .IP "\fBpostscreen_dnsbl_action (continue)\fR"
The action that \fBpostscreen\fR(8) takes when an SMTP client is listed The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
at the DNS blocklist domains specified with the postscreen_dnsbl_sites at the DNS blocklist domains specified with the postscreen_dnsbl_sites
@ -272,7 +274,8 @@ The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
before its turn within the time specified with the postscreen_greet_wait before its turn within the time specified with the postscreen_greet_wait
parameter. parameter.
.IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR" .IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR"
The text in the optional "220-text..." server response that The \fItext\fR in the optional "220-\fItext\fR..." server
response that
\fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220 \fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
text..." response, in an attempt to confuse bad SMTP clients so text..." response, in an attempt to confuse bad SMTP clients so
that they speak before their turn (pre-greet). that they speak before their turn (pre-greet).
@ -297,6 +300,21 @@ will not be subjected to \fBpostscreen\fR(8) checks.
.IP "\fBsmtpd_service (smtpd)\fR" .IP "\fBsmtpd_service (smtpd)\fR"
The internal service that \fBpostscreen\fR(8) forwards allowed The internal service that \fBpostscreen\fR(8) forwards allowed
connections to. connections to.
.SH "CACHE CONTROLS"
.na
.nf
.ad
.fi
.IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
.IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
Persistent storage for the \fBpostscreen\fR(8) server decisions.
.IP "\fBpostscreen_cache_retention_time (1d)\fR"
The amount of time that \fBpostscreen\fR(8) will cache an expired
temporary whitelist entry before it is removed.
.IP "\fBpostscreen_cache_ttl (1d)\fR"
The amount of time that \fBpostscreen\fR(8) will cache a decision for
a specific SMTP client IP address.
.SH "MISCELLANEOUS CONTROLS" .SH "MISCELLANEOUS CONTROLS"
.na .na
.nf .nf

View File

@ -729,8 +729,9 @@ instead of requiring an explicit ".domain.tld" pattern.
Optional SMTP server access restrictions in the context of a client Optional SMTP server access restrictions in the context of a client
SMTP connection request. SMTP connection request.
.IP "\fBsmtpd_helo_required (no)\fR" .IP "\fBsmtpd_helo_required (no)\fR"
Require that a remote SMTP client introduces itself at the beginning Require that a remote SMTP client introduces itself with the HELO
of an SMTP session with the HELO or EHLO command. or EHLO command before sending the MAIL command or other commands
that require EHLO negotiation.
.IP "\fBsmtpd_helo_restrictions (empty)\fR" .IP "\fBsmtpd_helo_restrictions (empty)\fR"
Optional restrictions that the Postfix SMTP server applies in the Optional restrictions that the Postfix SMTP server applies in the
context of the SMTP HELO command. context of the SMTP HELO command.
@ -791,7 +792,7 @@ verification probes is maintained by the \fBverify\fR(8) server.
See the file ADDRESS_VERIFICATION_README for information See the file ADDRESS_VERIFICATION_README for information
about how to configure and operate the Postfix sender/recipient about how to configure and operate the Postfix sender/recipient
address verification service. address verification service.
.IP "\fBaddress_verify_poll_count (3)\fR" .IP "\fBaddress_verify_poll_count (see 'postconf -d' output)\fR"
How many times to query the \fBverify\fR(8) service for the completion How many times to query the \fBverify\fR(8) service for the completion
of an address verification request in progress. of an address verification request in progress.
.IP "\fBaddress_verify_poll_delay (3s)\fR" .IP "\fBaddress_verify_poll_delay (3s)\fR"

View File

@ -113,6 +113,10 @@ verification cache.
.IP "\fBaddress_verify_negative_refresh_time (3h)\fR" .IP "\fBaddress_verify_negative_refresh_time (3h)\fR"
The time after which a failed address verification probe needs to The time after which a failed address verification probe needs to
be refreshed. be refreshed.
.PP
Available with Postfix 2.7 and later:
.IP "\fBaddress_verify_cache_cleanup_interval (12h)\fR"
The amount of time between \fBverify\fR(8) cache cleanup runs.
.SH "PROBE MESSAGE ROUTING CONTROLS" .SH "PROBE MESSAGE ROUTING CONTROLS"
.na .na
.nf .nf
@ -139,6 +143,16 @@ verification probes.
.IP "\fBaddress_verify_default_transport ($default_transport)\fR" .IP "\fBaddress_verify_default_transport ($default_transport)\fR"
Overrides the default_transport parameter setting for address Overrides the default_transport parameter setting for address
verification probes. verification probes.
.PP
Available in Postfix 2.3 and later:
.IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR"
Overrides the sender_dependent_relayhost_maps parameter setting for address
verification probes.
.PP
Available in Postfix 2.7 and later:
.IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR"
Overrides the sender_dependent_default_transport_maps parameter
setting for address verification probes.
.SH "MISCELLANEOUS CONTROLS" .SH "MISCELLANEOUS CONTROLS"
.na .na
.nf .nf

View File

@ -76,6 +76,7 @@ while (<>) {
s;\baddress_verify_negative_cache\b;<a href="postconf.5.html#address_verify_negative_cache">$&</a>;g; s;\baddress_verify_negative_cache\b;<a href="postconf.5.html#address_verify_negative_cache">$&</a>;g;
s;\baddress_verify_negative_expire_time\b;<a href="postconf.5.html#address_verify_negative_expire_time">$&</a>;g; s;\baddress_verify_negative_expire_time\b;<a href="postconf.5.html#address_verify_negative_expire_time">$&</a>;g;
s;\baddress_verify_negative_refresh_time\b;<a href="postconf.5.html#address_verify_negative_refresh_time">$&</a>;g; s;\baddress_verify_negative_refresh_time\b;<a href="postconf.5.html#address_verify_negative_refresh_time">$&</a>;g;
s;\baddress_verify_cache_cleanup_interval\b;<a href="postconf.5.html#address_verify_cache_cleanup_interval">$&</a>;g;
s;\baddress_verify_poll_count\b;<a href="postconf.5.html#address_verify_poll_count">$&</a>;g; s;\baddress_verify_poll_count\b;<a href="postconf.5.html#address_verify_poll_count">$&</a>;g;
s;\baddress_verify_poll_delay\b;<a href="postconf.5.html#address_verify_poll_delay">$&</a>;g; s;\baddress_verify_poll_delay\b;<a href="postconf.5.html#address_verify_poll_delay">$&</a>;g;
s;\baddress_verify_positive_expire_time\b;<a href="postconf.5.html#address_verify_positive_expire_time">$&</a>;g; s;\baddress_verify_positive_expire_time\b;<a href="postconf.5.html#address_verify_positive_expire_time">$&</a>;g;
@ -899,6 +900,8 @@ while (<>) {
# postscreen # postscreen
s;\bpostscreen_cache_map\b;<a href="postconf.5.html#postscreen_cache_map">$&</a>;g; s;\bpostscreen_cache_map\b;<a href="postconf.5.html#postscreen_cache_map">$&</a>;g;
s;\bpostscreen_cache_ttl\b;<a href="postconf.5.html#postscreen_cache_ttl">$&</a>;g; s;\bpostscreen_cache_ttl\b;<a href="postconf.5.html#postscreen_cache_ttl">$&</a>;g;
s;\bpostscreen_cache_cleanup_interval\b;<a href="postconf.5.html#postscreen_cache_cleanup_interval">$&</a>;g;
s;\bpostscreen_cache_retention_time\b;<a href="postconf.5.html#postscreen_cache_retention_time">$&</a>;g;
s;\bsmtpd_service\b;<a href="postconf.5.html#smtpd_service">$&</a>;g; s;\bsmtpd_service\b;<a href="postconf.5.html#smtpd_service">$&</a>;g;
s;\bpostscreen_post_queue_limit\b;<a href="postconf.5.html#postscreen_post_queue_limit">$&</a>;g; s;\bpostscreen_post_queue_limit\b;<a href="postconf.5.html#postscreen_post_queue_limit">$&</a>;g;
s;\bpostscreen_pre_queue_limit\b;<a href="postconf.5.html#postscreen_pre_queue_limit">$&</a>;g; s;\bpostscreen_pre_queue_limit\b;<a href="postconf.5.html#postscreen_pre_queue_limit">$&</a>;g;

View File

@ -108,11 +108,18 @@ filter</a>
<h2><a name="principles">Principles of operation</a></h2> <h2><a name="principles">Principles of operation</a></h2>
<p> The before-filter Postfix SMTP server accepts connections from the <p> As shown in the diagram above, the before-queue filter sits
between two Postfix SMTP server processes. </p>
<ul>
<li> <p> The before-filter Postfix SMTP server accepts connections from the
Internet and does the usual relay access control, SASL authentication, Internet and does the usual relay access control, SASL authentication,
TLS negotiation, TLS negotiation,
RBL lookups, rejecting non-existent sender or recipient addresses, RBL lookups, rejecting non-existent sender or recipient addresses,
etc. The before-queue filter receives unfiltered mail content from etc. </p>
<li> <p> The before-queue filter receives unfiltered mail content from
Postfix and does one of the following: </p> Postfix and does one of the following: </p>
<ol> <ol>
@ -129,9 +136,11 @@ Postfix and does one of the following: </p>
</ol> </ol>
<p>The after-filter Postfix SMTP server receives mail from the <li> <p>The after-filter Postfix SMTP server receives mail from the
content filter. From then on Postfix processes the mail as usual. </p> content filter. From then on Postfix processes the mail as usual. </p>
</ul>
<p> The before-queue content filter described here works just like <p> The before-queue content filter described here works just like
the after-queue content filter described in the FILTER_README the after-queue content filter described in the FILTER_README
document. In many cases you can use the same software, within the document. In many cases you can use the same software, within the

View File

@ -199,7 +199,7 @@ verification probes.
This feature is available in Postfix 2.1 and later. This feature is available in Postfix 2.1 and later.
</p> </p>
%PARAM address_verify_map %PARAM address_verify_map
<p> <p>
Optional lookup table for persistent address verification status Optional lookup table for persistent address verification status
@ -280,7 +280,20 @@ Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
This feature is available in Postfix 2.1 and later. This feature is available in Postfix 2.1 and later.
</p> </p>
%PARAM address_verify_poll_count 3 %PARAM address_verify_cache_cleanup_interval 12h
<p> The amount of time between verify(8) cache cleanup runs. Cache
cleanup increases the load on the cache database and should therefore
not be run frequently. This feature requires that the cache database
supports the "delete" and "sequence" operators. Specify a zero
interval to disable cache cleanup. </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p>
<p> This feature is available in Postfix 2.7. </p>
%PARAM address_verify_poll_count see "postconf -d" output
<p> <p>
How many times to query the verify(8) service for the completion How many times to query the verify(8) service for the completion
@ -288,12 +301,16 @@ of an address verification request in progress.
</p> </p>
<p> <p>
The default poll count is 3. With Postfix version 2.7 and later, the SMTP server polls the
verify(8) service up to three times under non-overload conditions,
and only once when under overload. With earlier Postfix versions,
the SMTP server always polls the verify(8) service up to three
times.
</p> </p>
<p> <p>
Specify 1 to implement a crude form of greylisting, that is, always Specify 1 to implement a crude form of greylisting, that is, always
defer the first delivery request for a never seen before address. defer the first delivery request for a new address.
</p> </p>
<p> <p>
@ -5215,8 +5232,9 @@ This feature is available in Postfix 2.2 and later.
%PARAM smtpd_helo_required no %PARAM smtpd_helo_required no
<p> <p>
Require that a remote SMTP client introduces itself at the beginning Require that a remote SMTP client introduces itself with the HELO
of an SMTP session with the HELO or EHLO command. or EHLO command before sending the MAIL command or other commands
that require EHLO negotiation.
</p> </p>
<p> <p>
@ -8631,12 +8649,12 @@ inside the chroot jail. </p>
<p> By default (see smtpd_tls_ask_ccert), client certificates are <p> By default (see smtpd_tls_ask_ccert), client certificates are
not requested, and smtpd_tls_CApath should remain empty. In contrast not requested, and smtpd_tls_CApath should remain empty. In contrast
to smtp_tls_CAfile, DNs of certificate authorities installed to smtpd_tls_CAfile, DNs of certificate authorities installed
in $smtpd_tls_CApath are not included in the client certificate in $smtpd_tls_CApath are not included in the client certificate
request message. MUAs with multiple client certificates may use the request message. MUAs with multiple client certificates may use the
list of preferred certificate authorities to select the correct list of preferred certificate authorities to select the correct
client certificate. You may want to put your "preferred" CA or client certificate. You may want to put your "preferred" CA or
CAs in $smtp_tls_CAfile, and install the remaining trusted CAs in CAs in $smtpd_tls_CAfile, and install the remaining trusted CAs in
$smtpd_tls_CApath. </p> $smtpd_tls_CApath. </p>
<p> Example: </p> <p> Example: </p>
@ -12436,9 +12454,34 @@ receive a 421 reponse. </p>
<p> The amount of time that postscreen(8) will cache a decision for <p> The amount of time that postscreen(8) will cache a decision for
a specific SMTP client IP address. During this time, the client IP a specific SMTP client IP address. During this time, the client IP
address is excluded from tests. If possible, expired decisions are address is excluded from tests. If possible, expired decisions are
renewed silently. Specify a non-zero time value (an integral value renewed automatically. Specify a non-zero time value (an integral
plus an optional one-letter suffix that specifies the time unit). value plus an optional one-letter suffix that specifies the time
</p> unit). </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p>
<p> This feature is available in Postfix 2.7. </p>
%PARAM postscreen_cache_retention_time 1d
<p> The amount of time that postscreen(8) will cache an expired
temporary whitelist entry before it is removed. This prevents clients
from being logged as "NEW" just because their cache entry expired
an hour ago. </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p>
<p> This feature is available in Postfix 2.7. </p>
%PARAM postscreen_cache_cleanup_interval 12h
<p> The amount of time between postscreen(8) cache cleanup runs.
Cache cleanup increases the load on the cache database and should
therefore not be run frequently. This feature requires that the
cache database supports the "delete" and "sequence" operators.
Specify a zero interval to disable cache cleanup. </p>
<p> Time units: s (seconds), m (minutes), h (hours), d (days), w <p> Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). </p> (weeks). </p>
@ -12560,7 +12603,8 @@ never uses the remote SMTP client hostname. </p>
%PARAM postscreen_greet_banner $smtpd_banner %PARAM postscreen_greet_banner $smtpd_banner
<p> The text in the optional "220-text..." server response that <p> The <i>text</i> in the optional "220-<i>text</i>..." server
response that
postscreen(8) sends ahead of the real Postfix SMTP server's "220 postscreen(8) sends ahead of the real Postfix SMTP server's "220
text..." response, in an attempt to confuse bad SMTP clients so text..." response, in an attempt to confuse bad SMTP clients so
that they speak before their turn (pre-greet). Specify an empty that they speak before their turn (pre-greet). Specify an empty
@ -12608,6 +12652,20 @@ except that initial whitespace and the trailing &lt;CR&gt;&lt;LF&gt;
are removed. The result value is executed by the Postfix SMTP are removed. The result value is executed by the Postfix SMTP
server. </p> server. </p>
<p> Postfix already implements a number of workarounds for malformed
client commands. </p>
<ul>
<li> <p> Use "resolve_numeric_domain = yes" to accept "<i>user@ipaddress</i>"
Postfix already accepts the correct form "<i>user@[ipaddress]</i>".
</p>
<li> <p> Use "strict_rfc821_envelopes = no" to accept "<i>User Name
&lt;user@example.com&gt;</i>". </p>
</ul>
<p> Examples: </p> <p> Examples: </p>
<pre> <pre>
@ -12647,7 +12705,7 @@ invalid responses. </p>
<ul> <ul>
<li> <p> In the case of a multi-line reply, the Postfix SMTP client <li> <p> In the case of a multi-line reply, the Postfix SMTP client
uses the last reply line's numerical SMTP reply code and enhanced uses the final reply line's numerical SMTP reply code and enhanced
status code. </p> status code. </p>
<li> <p> The numerical SMTP reply code (XYZ) takes precedence over <li> <p> The numerical SMTP reply code (XYZ) takes precedence over
@ -12666,16 +12724,16 @@ server, except that the trailing &lt;CR&gt;&lt;LF&gt; are removed. </p>
<pre> <pre>
/etc/postfix/main.cf: /etc/postfix/main.cf:
smtp_reply_filter = pcre:/etc/postfix/command_filter smtp_reply_filter = pcre:/etc/postfix/reply_filter
</pre> </pre>
<pre> <pre>
/etc/postfix/reply_filter: /etc/postfix/reply_filter:
# Transform garbage into part of a multi-line reply. Note # Transform garbage into "250-filler..." so that it looks like
# that the Postfix SMTP client uses only the last numerical # one line from a multi-line reply. It does not matter what we
# SMTP reply code and enhanced status code from a multi-line # substitute here as long it has the right syntax. The Postfix
# reply, so it does not matter what we substitute here as # SMTP client will use the final line's numerical SMTP reply
# long as it has the right syntax. # code and enhanced status code.
!/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage !/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage
</pre> </pre>

View File

@ -46,8 +46,10 @@
/* RFC 822 (ARPA Internet Text Messages) /* RFC 822 (ARPA Internet Text Messages)
/* RFC 2045 (MIME: Format of Internet Message Bodies) /* RFC 2045 (MIME: Format of Internet Message Bodies)
/* RFC 2046 (MIME: Media Types) /* RFC 2046 (MIME: Media Types)
/* RFC 2822 (Internet Message Format)
/* RFC 3463 (Enhanced Status Codes) /* RFC 3463 (Enhanced Status Codes)
/* RFC 3464 (Delivery status notifications) /* RFC 3464 (Delivery status notifications)
/* RFC 5322 (Internet Message Format)
/* DIAGNOSTICS /* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8). /* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS /* BUGS

View File

@ -2552,7 +2552,7 @@ extern int var_scache_stat_time;
extern char *var_verify_service; extern char *var_verify_service;
#define VAR_VERIFY_MAP "address_verify_map" #define VAR_VERIFY_MAP "address_verify_map"
#define DEF_VERIFY_MAP "" #define DEF_VERIFY_MAP "btree:$data_directory/verify_cache"
extern char *var_verify_map; extern char *var_verify_map;
#define VAR_VERIFY_POS_EXP "address_verify_positive_expire_time" #define VAR_VERIFY_POS_EXP "address_verify_positive_expire_time"
@ -2575,12 +2575,16 @@ extern int var_verify_neg_try;
#define DEF_VERIFY_NEG_CACHE 1 #define DEF_VERIFY_NEG_CACHE 1
extern bool var_verify_neg_cache; extern bool var_verify_neg_cache;
#define VAR_VERIFY_SCAN_CACHE "address_verify_cache_cleanup_interval"
#define DEF_VERIFY_SCAN_CACHE "12h"
extern int var_verify_scan_cache;
#define VAR_VERIFY_SENDER "address_verify_sender" #define VAR_VERIFY_SENDER "address_verify_sender"
#define DEF_VERIFY_SENDER "$" VAR_DOUBLE_BOUNCE #define DEF_VERIFY_SENDER "$" VAR_DOUBLE_BOUNCE
extern char *var_verify_sender; extern char *var_verify_sender;
#define VAR_VERIFY_POLL_COUNT "address_verify_poll_count" #define VAR_VERIFY_POLL_COUNT "address_verify_poll_count"
#define DEF_VERIFY_POLL_COUNT 3 #define DEF_VERIFY_POLL_COUNT "${stress?1}${stress:3}"
extern int var_verify_poll_count; extern int var_verify_poll_count;
#define VAR_VERIFY_POLL_DELAY "address_verify_poll_delay" #define VAR_VERIFY_POLL_DELAY "address_verify_poll_delay"
@ -3186,6 +3190,14 @@ extern int var_ps_pre_queue_limit;
#define DEF_PS_CACHE_TTL "1d" #define DEF_PS_CACHE_TTL "1d"
extern int var_ps_cache_ttl; extern int var_ps_cache_ttl;
#define VAR_PS_CACHE_RET "postscreen_cache_retention_time"
#define DEF_PS_CACHE_RET "1d"
extern int var_ps_cache_ret;
#define VAR_PS_CACHE_SCAN "postscreen_cache_cleanup_interval"
#define DEF_PS_CACHE_SCAN "12h"
extern int var_ps_cache_scan;
#define VAR_PS_GREET_WAIT "postscreen_greet_wait" #define VAR_PS_GREET_WAIT "postscreen_greet_wait"
#define DEF_PS_GREET_WAIT "4s" #define DEF_PS_GREET_WAIT "4s"
extern int var_ps_greet_wait; extern int var_ps_greet_wait;

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20091209" #define MAIL_RELEASE_DATE "20091229"
#define MAIL_VERSION_NUMBER "2.7" #define MAIL_VERSION_NUMBER "2.7"
#ifdef SNAPSHOT #ifdef SNAPSHOT

View File

@ -61,7 +61,9 @@ postscreen.o: ../../include/addr_match_list.h
postscreen.o: ../../include/argv.h postscreen.o: ../../include/argv.h
postscreen.o: ../../include/attr.h postscreen.o: ../../include/attr.h
postscreen.o: ../../include/connect.h postscreen.o: ../../include/connect.h
postscreen.o: ../../include/data_redirect.h
postscreen.o: ../../include/dict.h postscreen.o: ../../include/dict.h
postscreen.o: ../../include/dict_cache.h
postscreen.o: ../../include/events.h postscreen.o: ../../include/events.h
postscreen.o: ../../include/format_tv.h postscreen.o: ../../include/format_tv.h
postscreen.o: ../../include/htable.h postscreen.o: ../../include/htable.h

View File

@ -7,26 +7,31 @@
/* \fBpostscreen\fR [generic Postfix daemon options] /* \fBpostscreen\fR [generic Postfix daemon options]
/* DESCRIPTION /* DESCRIPTION
/* The Postfix \fBpostscreen\fR(8) server performs triage on /* The Postfix \fBpostscreen\fR(8) server performs triage on
/* multiple inbound SMTP connections in parallel. The program /* multiple inbound SMTP connections in parallel. By running
/* can run in two basic modes. /* time-consuming tests in parallel in \fBpostscreen\fR(8),
/* zombies and other bogus clients can be kept away from Postfix
/* SMTP server processes. Thus, more Postfix SMTP server
/* processes remain available for legitimate clients.
/* /*
/* The purpose of \fBobservation mode\fR is to collect statistics /* This triage process involves a number of tests, documented
/* without actually blocking mail. \fBpostscreen\fR(8) runs a /* below. The tests introduce a delay of a few seconds; once
/* number of tests before it forwards a connection to a real /* a client passes the tests, its IP address is temporarily
/* SMTP server process. These tests introduce a delay of a /* whitelisted, typically for 24 hours.
/* few seconds; once a client passes the tests as "clean", its
/* IP address is temporarily whitelisted and subsequent
/* connections incur no delays until the temporary whitelist
/* entry expires.
/* /*
/* The purpose of \fBenforcement mode\fR is to block mail /* The program can run in two basic modes.
/* without using up one Postfix SMTP server process for every /* .IP "\fBObservation mode\fR"
/* connection. Here, \fBpostscreen\fR(8) terminates connections /* \fBpostscreen\fR(8) reports the results of the tests, and
/* from SMTP clients that fail the above tests, and forwards /* forwards all connections to a real Postfix SMTP server
/* only the remaining connections to a real SMTP server process. /* process.
/* By running time-consuming spam tests in parallel in /* .IP "\fBEnforcement mode\fR"
/* \fBpostscreen\fR(8), more Postfix SMTP server processes /* \fBpostscreen\fR(8) reports the results of the tests, but
/* remain available for legitimate clients. /* forwards only connections to a real SMTP server process
/* from clients that passed the tests.
/* .sp
/* \fBpostscreen\fR(8) disconnects clients that fail the tests,
/* after sending a 521 status message (a future version may
/* pass the connection to a dummy SMTP protocol engine that
/* logs sender and recipient information).
/* .PP /* .PP
/* Note: \fBpostscreen\fR(8) is not an SMTP proxy; this is /* Note: \fBpostscreen\fR(8) is not an SMTP proxy; this is
/* intentional. The purpose is to prioritize legitimate clients /* intentional. The purpose is to prioritize legitimate clients
@ -38,8 +43,7 @@
/* .fi /* .fi
/* The postscreen_whitelist_networks parameter (default: /* The postscreen_whitelist_networks parameter (default:
/* $mynetworks) specifies a permanent whitelist for SMTP client /* $mynetworks) specifies a permanent whitelist for SMTP client
/* IP addresses. This feature is not used for addresses that /* IP addresses.
/* appear on the permanent blacklist.
/* /*
/* When the SMTP client address matches the permanent whitelist, /* When the SMTP client address matches the permanent whitelist,
/* this is logged as: /* this is logged as:
@ -99,12 +103,13 @@
/* .ad /* .ad
/* .fi /* .fi
/* The postscreen_greet_wait parameter specifies a time interval /* The postscreen_greet_wait parameter specifies a time interval
/* during which \fBpostscreen\fR(8) runs a number of tests as /* during which \fBpostscreen\fR(8) runs a number of tests in
/* described below. These tests run before the client may /* parallel. These tests are described below, and are run
/* see the real SMTP server's "220 text..." server greeting. /* before the client may see the real SMTP server's "220
/* text..." server greeting.
/* /*
/* When the SMTP client passes all the tests, this is logged /* When the SMTP client passes all greeting-phase tests, this
/* as: /* is logged as:
/* .sp /* .sp
/* .nf /* .nf
/* \fBPASS NEW \fIaddress\fR /* \fBPASS NEW \fIaddress\fR
@ -123,8 +128,9 @@
/* .SH 4A. PREGREET TEST /* .SH 4A. PREGREET TEST
/* .ad /* .ad
/* .fi /* .fi
/* The postscreen_greet_banner parameter specifies the text /* The postscreen_greet_banner parameter specifies the \fItext\fR
/* for a "220-text..." teaser banner (default: $smtpd_banner). /* portion of a "220-\fItext\fR..." teaser banner (default:
/* $smtpd_banner).
/* The \fBpostscreen\fR(8) daemon sends this before the /* The \fBpostscreen\fR(8) daemon sends this before the
/* postscreen_greet_wait timer is started. The purpose of the /* postscreen_greet_wait timer is started. The purpose of the
/* teaser banner is to confuse SPAM clients so that they speak /* teaser banner is to confuse SPAM clients so that they speak
@ -185,7 +191,8 @@
/* .ad /* .ad
/* .fi /* .fi
/* The postscreen_dnsbl_sites parameter (default: empty) /* The postscreen_dnsbl_sites parameter (default: empty)
/* specifies a list of DNS blocklist servers. /* specifies a list of DNS blocklist servers. These lookups
/* are made in parallel.
/* /*
/* When the postscreen_greet_wait time has elapsed, and the /* When the postscreen_greet_wait time has elapsed, and the
/* SMTP client address is listed with at least one of these /* SMTP client address is listed with at least one of these
@ -240,11 +247,6 @@
/* .IP "\fBpostscreen_blacklist_networks (empty)\fR" /* .IP "\fBpostscreen_blacklist_networks (empty)\fR"
/* Network addresses that are permanently blacklisted; see the /* Network addresses that are permanently blacklisted; see the
/* postscreen_blacklist_action parameter for possible actions. /* postscreen_blacklist_action parameter for possible actions.
/* .IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
/* Persistent storage for the \fBpostscreen\fR(8) server decisions.
/* .IP "\fBpostscreen_cache_ttl (1d)\fR"
/* The amount of time that \fBpostscreen\fR(8) will cache a decision for
/* a specific SMTP client IP address.
/* .IP "\fBpostscreen_dnsbl_action (continue)\fR" /* .IP "\fBpostscreen_dnsbl_action (continue)\fR"
/* The action that \fBpostscreen\fR(8) takes when an SMTP client is listed /* The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
/* at the DNS blocklist domains specified with the postscreen_dnsbl_sites /* at the DNS blocklist domains specified with the postscreen_dnsbl_sites
@ -256,7 +258,8 @@
/* before its turn within the time specified with the postscreen_greet_wait /* before its turn within the time specified with the postscreen_greet_wait
/* parameter. /* parameter.
/* .IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR" /* .IP "\fBpostscreen_greet_banner ($smtpd_banner)\fR"
/* The text in the optional "220-text..." server response that /* The \fItext\fR in the optional "220-\fItext\fR..." server
/* response that
/* \fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220 /* \fBpostscreen\fR(8) sends ahead of the real Postfix SMTP server's "220
/* text..." response, in an attempt to confuse bad SMTP clients so /* text..." response, in an attempt to confuse bad SMTP clients so
/* that they speak before their turn (pre-greet). /* that they speak before their turn (pre-greet).
@ -281,6 +284,19 @@
/* .IP "\fBsmtpd_service (smtpd)\fR" /* .IP "\fBsmtpd_service (smtpd)\fR"
/* The internal service that \fBpostscreen\fR(8) forwards allowed /* The internal service that \fBpostscreen\fR(8) forwards allowed
/* connections to. /* connections to.
/* CACHE CONTROLS
/* .ad
/* .fi
/* .IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
/* The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
/* .IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
/* Persistent storage for the \fBpostscreen\fR(8) server decisions.
/* .IP "\fBpostscreen_cache_retention_time (1d)\fR"
/* The amount of time that \fBpostscreen\fR(8) will cache an expired
/* temporary whitelist entry before it is removed.
/* .IP "\fBpostscreen_cache_ttl (1d)\fR"
/* The amount of time that \fBpostscreen\fR(8) will cache a decision for
/* a specific SMTP client IP address.
/* MISCELLANEOUS CONTROLS /* MISCELLANEOUS CONTROLS
/* .ad /* .ad
/* .fi /* .fi
@ -347,7 +363,7 @@
#include <events.h> #include <events.h>
#include <mymalloc.h> #include <mymalloc.h>
#include <myaddrinfo.h> #include <myaddrinfo.h>
#include <dict.h> #include <dict_cache.h>
#include <sane_accept.h> #include <sane_accept.h>
#include <stringops.h> #include <stringops.h>
#include <set_eugid.h> #include <set_eugid.h>
@ -363,6 +379,7 @@
#include <mail_version.h> #include <mail_version.h>
#include <mail_proto.h> #include <mail_proto.h>
#include <addr_match_list.h> #include <addr_match_list.h>
#include <data_redirect.h>
/* Master server protocols. */ /* Master server protocols. */
@ -378,6 +395,8 @@ int var_ps_post_queue_limit;
int var_ps_pre_queue_limit; int var_ps_pre_queue_limit;
int var_proc_limit; int var_proc_limit;
int var_ps_cache_ttl; int var_ps_cache_ttl;
int var_ps_cache_ret;
int var_ps_cache_scan;
int var_ps_greet_wait; int var_ps_greet_wait;
char *var_ps_dnsbl_sites; char *var_ps_dnsbl_sites;
char *var_ps_dnsbl_action; char *var_ps_dnsbl_action;
@ -425,7 +444,7 @@ typedef struct {
static int check_queue_length; /* connections being checked */ static int check_queue_length; /* connections being checked */
static int post_queue_length; /* being sent to real SMTPD */ static int post_queue_length; /* being sent to real SMTPD */
static DICT *cache_map; /* cache table handle */ static DICT_CACHE *cache_map; /* cache table handle */
static VSTRING *temp; /* scratchpad */ static VSTRING *temp; /* scratchpad */
static char *smtp_service_name; /* path to real SMTPD */ static char *smtp_service_name; /* path to real SMTPD */
static char *teaser_greeting; /* spamware teaser banner */ static char *teaser_greeting; /* spamware teaser banner */
@ -520,26 +539,26 @@ static int ps_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
/* ps_dict_get - time-critical table lookup */ /* ps_dict_get - time-critical table lookup */
static const char *ps_dict_get(DICT *dict, const char *key) static const char *ps_dict_get(DICT_CACHE *cache, const char *key)
{ {
const char *myname = "ps_dict_get"; const char *myname = "ps_dict_get";
const char *result; const char *result;
PS_GET_TIME_BEFORE_LOOKUP; PS_GET_TIME_BEFORE_LOOKUP;
result = dict_get(dict, key); result = dict_cache_lookup(cache, key);
PS_CHECK_TIME_AFTER_LOOKUP(dict->name, "lookup"); PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup");
return (result); return (result);
} }
/* ps_dict_put - table dictionary update */ /* ps_dict_put - table dictionary update */
static void ps_dict_put(DICT *dict, const char *key, const char *value) static void ps_dict_put(DICT_CACHE *cache, const char *key, const char *value)
{ {
const char *myname = "ps_dict_put"; const char *myname = "ps_dict_put";
PS_GET_TIME_BEFORE_LOOKUP; PS_GET_TIME_BEFORE_LOOKUP;
dict_put(dict, key, value); dict_cache_update(cache, key, value);
PS_CHECK_TIME_AFTER_LOOKUP(dict->name, "update"); PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
} }
/* /*
@ -965,6 +984,23 @@ static void smtp_read_event(int event, char *context)
} }
} }
/* postscreen_dump - dump some statistics before exit */
static void postscreen_dump(void)
{
/*
* Dump preliminary cache cleanup statistics when the process commits
* suicide while a cache cleanup run is in progress. We can't currently
* distinguish between "postfix reload" (we should restart) or "maximal
* idle time reached" (we could finish the cache cleanup first).
*/
if (cache_map) {
dict_cache_close(cache_map);
cache_map = 0;
}
}
/* postscreen_drain - delayed exit after "postfix reload" */ /* postscreen_drain - delayed exit after "postfix reload" */
static void postscreen_drain(char *unused_service, char **unused_argv) static void postscreen_drain(char *unused_service, char **unused_argv)
@ -989,7 +1025,7 @@ static void postscreen_drain(char *unused_service, char **unused_argv)
* version is an improvement over its predecessor. * version is an improvement over its predecessor.
*/ */
if (cache_map != 0) { if (cache_map != 0) {
dict_close(cache_map); dict_cache_close(cache_map);
cache_map = 0; cache_map = 0;
} }
for (count = 0; /* see below */ ; count++) { for (count = 0; /* see below */ ; count++) {
@ -1181,10 +1217,31 @@ static void postscreen_service(VSTREAM *smtp_client_stream,
postscreen_dnsbl_query(smtp_client_addr.buf); postscreen_dnsbl_query(smtp_client_addr.buf);
} }
/* postscreen_cache_validator - validate one cache entry */
static int postscreen_cache_validator(const char *client_addr,
const char *stamp_str,
char *unused_context)
{
time_t stamp_time;
/*
* This function is called by the cache cleanup pseudo thread.
*
* XX Eliminate code duplication and abstract the parser into a separate
* routine.
*
* Don't report a client as "NEW" just because their cache entry expired.
*/
stamp_time = strtoul(stamp_str, 0, 10);
return (event_time() < stamp_time + var_ps_cache_ttl + var_ps_cache_ret);
}
/* pre_jail_init - pre-jail initialization */ /* pre_jail_init - pre-jail initialization */
static void pre_jail_init(char *unused_name, char **unused_argv) static void pre_jail_init(char *unused_name, char **unused_argv)
{ {
VSTRING *redirect;
/* /*
* Open read-only maps as before dropping privilege, for consistency with * Open read-only maps as before dropping privilege, for consistency with
@ -1192,7 +1249,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
*/ */
if (*var_ps_wlist_nets) if (*var_ps_wlist_nets)
wlist_nets = wlist_nets =
addr_match_list_init(MATCH_FLAG_NONE, var_ps_wlist_nets); addr_match_list_init(MATCH_FLAG_NONE, var_ps_wlist_nets);
if (*var_ps_blist_nets) if (*var_ps_blist_nets)
blist_nets = blist_nets =
@ -1213,22 +1270,26 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
* to jail, temporarily drop root privileges. * to jail, temporarily drop root privileges.
*/ */
SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid); SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
redirect = vstring_alloc(100);
/* /*
* Keep state in persistent external map. As a safety measure we sync the * Keep state in persistent external map. As a safety measure we sync the
* database on each update. This hurts on LINUX systems that sync all * database on each update. This hurts on LINUX systems that sync all
* their dirty disk blocks whenever any application invokes fsync(). * their dirty disk blocks whenever any application invokes fsync().
*
* Start the cache maintenance pseudo thread after dropping privileges.
*/ */
#define PS_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE) #define PS_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
if (*var_ps_cache_map) if (*var_ps_cache_map)
cache_map = dict_open(var_ps_cache_map, cache_map =
O_CREAT | O_RDWR, dict_cache_open(data_redirect_map(redirect, var_ps_cache_map),
PS_DICT_OPEN_FLAGS); O_CREAT | O_RDWR, PS_DICT_OPEN_FLAGS);
/* /*
* Clean up and restore privilege. * Clean up and restore privilege.
*/ */
vstring_free(redirect);
RESTORE_SAVED_EUGID(); RESTORE_SAVED_EUGID();
} }
@ -1241,6 +1302,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
"continue", PS_ACT_CONT, "continue", PS_ACT_CONT,
0, -1, 0, -1,
}; };
int expire_flags;
/* /*
* This routine runs after the skeleton code has entered the chroot jail. * This routine runs after the skeleton code has entered the chroot jail.
@ -1275,6 +1337,18 @@ static void post_jail_init(char *unused_name, char **unused_argv)
if ((hangup_action = name_code(actions, NAME_CODE_FLAG_NONE, if ((hangup_action = name_code(actions, NAME_CODE_FLAG_NONE,
var_ps_hangup_action)) < 0) var_ps_hangup_action)) < 0)
msg_fatal("bad %s value: %s", VAR_PS_HUP_ACTION, var_ps_hangup_action); msg_fatal("bad %s value: %s", VAR_PS_HUP_ACTION, var_ps_hangup_action);
/*
* Start the cache maintenance pseudo thread last. Early cleanup makes
* verbose logging more informative (we get positive confirmation that
* the cleanup thread runs).
*/
expire_flags = DICT_CACHE_FLAG_EXP_SUMMARY;
if (msg_verbose)
expire_flags |= DICT_CACHE_FLAG_EXP_VERBOSE;
if (cache_map != 0 && var_ps_cache_scan > 0)
dict_cache_expire(cache_map, expire_flags, var_ps_cache_scan,
postscreen_cache_validator, (char *) 0);
} }
MAIL_VERSION_STAMP_DECLARE; MAIL_VERSION_STAMP_DECLARE;
@ -1309,6 +1383,8 @@ int main(int argc, char **argv)
static const CONFIG_TIME_TABLE time_table[] = { static const CONFIG_TIME_TABLE time_table[] = {
VAR_PS_CACHE_TTL, DEF_PS_CACHE_TTL, &var_ps_cache_ttl, 1, 0, VAR_PS_CACHE_TTL, DEF_PS_CACHE_TTL, &var_ps_cache_ttl, 1, 0,
VAR_PS_GREET_WAIT, DEF_PS_GREET_WAIT, &var_ps_greet_wait, 1, 0, VAR_PS_GREET_WAIT, DEF_PS_GREET_WAIT, &var_ps_greet_wait, 1, 0,
VAR_PS_CACHE_RET, DEF_PS_CACHE_RET, &var_ps_cache_ret, 0, 0,
VAR_PS_CACHE_SCAN, DEF_PS_CACHE_SCAN, &var_ps_cache_scan, 0, 0,
0, 0,
}; };
@ -1326,5 +1402,6 @@ int main(int argc, char **argv)
MAIL_SERVER_POST_INIT, post_jail_init, MAIL_SERVER_POST_INIT, post_jail_init,
MAIL_SERVER_SOLITARY, MAIL_SERVER_SOLITARY,
MAIL_SERVER_SLOW_EXIT, postscreen_drain, MAIL_SERVER_SLOW_EXIT, postscreen_drain,
MAIL_SERVER_EXIT, postscreen_dump,
0); 0);
} }

View File

@ -681,8 +681,9 @@
/* Optional SMTP server access restrictions in the context of a client /* Optional SMTP server access restrictions in the context of a client
/* SMTP connection request. /* SMTP connection request.
/* .IP "\fBsmtpd_helo_required (no)\fR" /* .IP "\fBsmtpd_helo_required (no)\fR"
/* Require that a remote SMTP client introduces itself at the beginning /* Require that a remote SMTP client introduces itself with the HELO
/* of an SMTP session with the HELO or EHLO command. /* or EHLO command before sending the MAIL command or other commands
/* that require EHLO negotiation.
/* .IP "\fBsmtpd_helo_restrictions (empty)\fR" /* .IP "\fBsmtpd_helo_restrictions (empty)\fR"
/* Optional restrictions that the Postfix SMTP server applies in the /* Optional restrictions that the Postfix SMTP server applies in the
/* context of the SMTP HELO command. /* context of the SMTP HELO command.
@ -741,7 +742,7 @@
/* See the file ADDRESS_VERIFICATION_README for information /* See the file ADDRESS_VERIFICATION_README for information
/* about how to configure and operate the Postfix sender/recipient /* about how to configure and operate the Postfix sender/recipient
/* address verification service. /* address verification service.
/* .IP "\fBaddress_verify_poll_count (3)\fR" /* .IP "\fBaddress_verify_poll_count (see 'postconf -d' output)\fR"
/* How many times to query the \fBverify\fR(8) service for the completion /* How many times to query the \fBverify\fR(8) service for the completion
/* of an address verification request in progress. /* of an address verification request in progress.
/* .IP "\fBaddress_verify_poll_delay (3s)\fR" /* .IP "\fBaddress_verify_poll_delay (3s)\fR"
@ -4942,6 +4943,7 @@ int main(int argc, char **argv)
VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0, VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0,
VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0, VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0,
VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0, VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0,
0, 0,
}; };
static const CONFIG_INT_TABLE int_table[] = { static const CONFIG_INT_TABLE int_table[] = {
@ -4970,7 +4972,6 @@ int main(int argc, char **argv)
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0, VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0, VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0,
VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0, VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0,
VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0,
VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0, VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0,
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0, VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0, VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,

View File

@ -32,7 +32,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \ write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \ allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \
upass_listen.c upass_trigger.c edit_file.c inet_windowsize.c \ upass_listen.c upass_trigger.c edit_file.c inet_windowsize.c \
unix_pass_fd_fix.c unix_pass_fd_fix.c dict_cache.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@ -66,7 +66,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \ write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \ allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \
upass_listen.o upass_trigger.o edit_file.o inet_windowsize.o \ upass_listen.o upass_trigger.o edit_file.o inet_windowsize.o \
unix_pass_fd_fix.o unix_pass_fd_fix.o dict_cache.o
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \ chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \ dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
@ -86,7 +86,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \ stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \
username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \ username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \ vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
edit_file.h edit_file.h dict_cache.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c test_send_fd test_recv_fd stream_test.c dup2_pass_on_exec.c test_send_fd test_recv_fd
DEFS = -I. -D$(SYSTYPE) DEFS = -I. -D$(SYSTYPE)
@ -740,6 +740,17 @@ dict_alloc.o: sys_defs.h
dict_alloc.o: vbuf.h dict_alloc.o: vbuf.h
dict_alloc.o: vstream.h dict_alloc.o: vstream.h
dict_alloc.o: vstring.h dict_alloc.o: vstring.h
dict_cache.o: argv.h
dict_cache.o: dict.h
dict_cache.o: dict_cache.c
dict_cache.o: dict_cache.h
dict_cache.o: events.h
dict_cache.o: msg.h
dict_cache.o: mymalloc.h
dict_cache.o: sys_defs.h
dict_cache.o: vbuf.h
dict_cache.o: vstream.h
dict_cache.o: vstring.h
dict_cdb.o: argv.h dict_cdb.o: argv.h
dict_cdb.o: dict.h dict_cdb.o: dict.h
dict_cdb.o: dict_cdb.c dict_cdb.o: dict_cdb.c
@ -1505,7 +1516,6 @@ stream_trigger.o: mymalloc.h
stream_trigger.o: stream_trigger.c stream_trigger.o: stream_trigger.c
stream_trigger.o: sys_defs.h stream_trigger.o: sys_defs.h
stream_trigger.o: trigger.h stream_trigger.o: trigger.h
sys_compat.o: iostuff.h
sys_compat.o: sys_compat.c sys_compat.o: sys_compat.c
sys_compat.o: sys_defs.h sys_compat.o: sys_defs.h
timed_connect.o: iostuff.h timed_connect.o: iostuff.h

View File

@ -107,15 +107,16 @@
/* modified, or if the result is to survive multiple dict_lookup() calls. /* modified, or if the result is to survive multiple dict_lookup() calls.
/* /*
/* dict_delete() removes the named member from the named dictionary. /* dict_delete() removes the named member from the named dictionary.
/* The result is non-zero when the member does not exist. /* The result value is zero when the member was found.
/* /*
/* dict_sequence() steps throuh the named dictionary and returns /* dict_sequence() steps through the named dictionary and returns
/* keys and values in some implementation-defined order. The func /* keys and values in some implementation-defined order. The func
/* argument is DICT_SEQ_FUN_FIRST to set the cursor to the first /* argument is DICT_SEQ_FUN_FIRST to set the cursor to the first
/* entry or DICT_SEQ_FUN_NEXT to select the next entry. The result /* entry or DICT_SEQ_FUN_NEXT to select the next entry. The result
/* is owned by the underlying dictionary method. Make a copy if the /* is owned by the underlying dictionary method. Make a copy if the
/* result is to be modified, or if the result is to survive multiple /* result is to be modified, or if the result is to survive multiple
/* dict_sequence() calls. /* dict_sequence() calls. The result value is zero when a member
/* was found.
/* /*
/* dict_eval() expands macro references in the specified string. /* dict_eval() expands macro references in the specified string.
/* The result is owned by the dictionary manager. Make a copy if the /* The result is owned by the dictionary manager. Make a copy if the

View File

@ -0,0 +1,577 @@
/*++
/* NAME
/* dict_cache 3
/* SUMMARY
/* External cache manager
/* SYNOPSIS
/* #include <dict_cache.h>
/*
/* DICT_CACHE *dict_cache_open(dbname, open_flags, dict_flags)
/* const char *dbname;
/* int open_flags;
/* int dict_flags;
/*
/* void dict_cache_close(cache)
/* DICT_CACHE *cache;
/*
/* const char *dict_cache_lookup(cache, cache_key)
/* DICT_CACHE *cache;
/* const char *cache_key;
/*
/* int dict_cache_update(cache, cache_key, cache_val)
/* DICT_CACHE *cache;
/* const char *cache_key;
/* const char *cache_val;
/*
/* int dict_cache_delete(cache, cache_key)
/* DICT_CACHE *cache;
/* const char *cache_key;
/*
/* int dict_cache_sequence(cache, first_next, cache_key, cache_val)
/* DICT_CACHE *cache;
/* int first_next;
/* const char **cache_key;
/* const char **cache_val;
/*
/* void dict_cache_expire(cache, flags, interval, validator, context)
/* DICT_CACHE *cache;
/* int flags;
/* int interval;
/* int (*validator)(const char *cache_key, const char *cache_val,
/* char *context);
/* char *context;
/* AUXILIARY FUNCTIONS
/* const char *dict_cache_name(cache)
/* DICT_CACHE *cache;
/*
/* DICT_CACHE *dict_cache_import(table)
/* DICT *table;
/* DESCRIPTION
/* This module maintains external cache files with support
/* for expiration. The underlying table must implement the
/* "lookup", "update", "delete" and "sequence" operations.
/*
/* Although this API is similar to the one documented in
/* dict_open(3), there are subtle differences in the interaction
/* between the iterators that access all cache elements, and
/* other operations that access individual cache elements.
/*
/* In particular, when a "sequence" or "expire" operation is
/* in progress the cache intercepts requests to delete the
/* "current" entry, as this would cause some databases to
/* mis-behave. Instead, the cache implements a "delete behind"
/* strategy, and deletes such an entry after the "sequence"
/* or "expire" operation moves on to the next cache element.
/* The "delete behind" strategy also affects the cache lookup
/* and update operations as detailed below.
/*
/* dict_cache_open() opens the specified cache and returns a
/* handle that must be used for subsequent access. This function
/* does not return in case of error.
/*
/* dict_cache_close() closes the specified cache and releases
/* memory that was allocated by dict_cache_open(), and terminates
/* any thread that was started with dict_cache_expire().
/*
/* dict_cache_lookup() looks up the specified cache entry.
/* The result value is a null pointer when the cache entry was
/* not found, or when the entry is scheduled for "delete
/* behind".
/*
/* dict_cache_update() updates the specified cache entry. If
/* the entry is scheduled for "delete behind", the delete
/* operation is canceled (meaning that the cache must be opened
/* with DICT_FLAG_DUP_REPLACE). This function does not return
/* in case of error.
/*
/* dict_cache_delete() removes the specified cache entry. If
/* this is the "current" entry of a "sequence" operation, the
/* entry is scheduled for "delete behind". The result value
/* is zero when the entry was found.
/*
/* dict_cache_sequence() iterates over the specified cache and
/* returns each entry in an implementation-defined order. The
/* result value is zero when a cache entry was found. Programs
/* must not use both dict_cache_sequence() and dict_cache_expire().
/*
/* dict_cache_expire() schedules a thread that expires cache
/* entries periodically. Specify a null validator argument to
/* cancel the thread. It is an error to schedule a cache
/* cleanup thread when one already exists. Programs must not
/* use both dict_cache_sequence() and dict_cache_expire().
/*
/* dict_cache_name() returns the name of the specified cache.
/*
/* dict_cache_import() encapsulates a pre-opened database
/* handle and adds the above features.
/*
/* Arguments:
/* .IP "dbname, open_flags, dict_flags"
/* These are passed unchanged to dict_open().
/* .IP cache
/* Cache handle created with dict_cache_open()or dict_cache_import().
/* .IP cache_key
/* Cache lookup key.
/* .IP cache_val
/* Information that is stored under a cache lookup key.
/* .IP first_next
/* One of DICT_SEQ_FUN_FIRST (first cache element) or
/* DICT_SEQ_FUN_NEXT (next cache element).
/* .sp
/* Note: there is no "stop" request. To ensure that the "delete
/* behind" strategy does not interfere with database access,
/* allow dict_cache_sequence() to run to completion.
/* .IP flags
/* Bit-wise OR of zero or more of the following:
/* .RS
/* .IP DICT_CACHE_FLAG_EXP_VERBOSE
/* Log each cache entry's status during a cache cleanup run.
/* .IP DICT_CACHE_FLAG_EXP_SUMMARY
/* Log the number of cache entries retained and dropped after
/* a cache cleaning run.
/* .RE
/* .IP interval
/* The non-zero time between scans for expired cache entries.
/* The interval timer starts after a scan completes.
/* .IP validator
/* Application call-back routine that returns non-zero when a
/* cache entry should be kept. The validator must not modify
/* or close the cache.
/* .IP context
/* Application-specific context.
/* .IP table
/* A bare dictonary handle.
/* DIAGNOSTICS
/* These routines terminate with a fatal run-time error
/* for unrecoverable database errors. This allows the
/* program to restart and reset the database to an
/* empty initial state.
/* BUGS
/* There should be a way to suspend automatic program suicide
/* until a cache cleanup run is completed. Some entries may
/* never be removed when the process max_idle time is less
/* than the time needed to make a full pass over the cache.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* HISTORY
/* .ad
/* .fi
/* A predecessor of this code was written first for the Postfix
/* tlsmgr(8) daemon.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
#include <stdlib.h>
/* Utility library. */
#include <msg.h>
#include <dict.h>
#include <mymalloc.h>
#include <events.h>
#include <dict_cache.h>
/* Application-specific. */
/*
* XXX Deleting entries while enumerating a map can he tricky. Some map
* types have a concept of cursor and support a "delete the current element"
* operation. Some map types without cursors don't behave well when the
* current first/next entry is deleted (example: with Berkeley DB < 2, the
* "next" operation produces garbage). To avoid trouble, we delete an entry
* after advancing the current first/next position beyond it; we use the
* same strategy with application requests to delete the current entry.
*/
/*
* Opaque data structure. Use dict_cache_name() to access the name of the
* underlying database.
*/
struct DICT_CACHE {
int flags; /* see below */
DICT *db; /* database handle */
/* Iterator support. */
char *saved_curr_key; /* "current" cache lookup key */
char *saved_curr_val; /* "current" cache lookup result */
/* Cleanup support. */
int exp_flags; /* logging */
int exp_interval; /* time between cleanup runs */
DICT_CACHE_VALIDATOR_FN exp_validator; /* expiration call-back */
char *exp_context; /* call-back context */
int retained; /* entries retained in cleanup run */
int dropped; /* entries removed in cleanup run */
};
#define DC_FLAG_DEL_SAVED_CURRENT_KEY (1<<0) /* delete-behind is scheduled */
/*
* Macros to make obscure code more readable.
*/
#define DC_SCHEDULE_FOR_DELETE_BEHIND(cp) \
((cp)->flags |= DC_FLAG_DEL_SAVED_CURRENT_KEY)
#define DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key) \
((cp)->saved_curr_key && strcmp((cp)->saved_curr_key, (cache_key)) == 0)
#define DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) \
(/* NOT: (cp)->saved_curr_key && */ \
((cp)->flags & DC_FLAG_DEL_SAVED_CURRENT_KEY) != 0)
#define DC_CANCEL_DELETE_BEHIND(cp) \
((cp)->flags &= ~DC_FLAG_DEL_SAVED_CURRENT_KEY)
/*
* Special key to store the time of last cache cleanup run completion.
*/
#define DC_LAST_CACHE_CLEANUP_COMPLETED "_LAST_CACHE_CLEANUP_COMPLETED_"
/* dict_cache_lookup - load entry from cache */
const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key)
{
/*
* Search for the cache entry. Don't return an entry that was scheduled
* for deletion.
*/
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
return (0);
} else {
return (dict_get(cp->db, cache_key));
}
}
/* dict_cache_update - save entry to cache */
void dict_cache_update(DICT_CACHE *cp, const char *cache_key,
const char *cache_val)
{
/*
* Store the cache entry and cancel a scheduled delete-behind operation.
*/
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)
&& DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key))
DC_CANCEL_DELETE_BEHIND(cp);
dict_put(cp->db, cache_key, cache_val);
}
/* dict_cache_delete - delete entry from cache */
int dict_cache_delete(DICT_CACHE *cp, const char *cache_key)
{
int zero_means_found;
/*
* Delete the entry, unless we would delete the current first/next entry.
* Instead, schedule the "current" entry for delete-behind to avoid
* mis-behavior by some databases.
*/
if (DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) {
DC_SCHEDULE_FOR_DELETE_BEHIND(cp);
zero_means_found = 0;
} else {
zero_means_found = dict_del(cp->db, cache_key);
}
return (zero_means_found);
}
/* dict_cache_sequence - look up the first/next cache entry */
int dict_cache_sequence(DICT_CACHE *cp, int first_next,
const char **cache_key,
const char **cache_val)
{
int zero_means_found;
const char *raw_cache_key;
const char *raw_cache_val;
char *previous_curr_key;
char *previous_curr_val;
/*
* Find the first or next database entry. Hide the record with the cache
* cleanup completion time stamp.
*/
zero_means_found =
dict_seq(cp->db, first_next, &raw_cache_key, &raw_cache_val);
if (zero_means_found == 0
&& strcmp(raw_cache_key, DC_LAST_CACHE_CLEANUP_COMPLETED) == 0)
zero_means_found =
dict_seq(cp->db, DICT_SEQ_FUN_NEXT, &raw_cache_key, &raw_cache_val);
/*
* Save the current cache_key and cache_val before they are clobbered by
* our own delete operation below. This also prevents surprises when the
* application accesses the database after this function returns.
*
* We also use the saved cache_key to protect the current entry against
* application delete requests.
*/
previous_curr_key = cp->saved_curr_key;
previous_curr_val = cp->saved_curr_val;
if (zero_means_found == 0) {
cp->saved_curr_key = mystrdup(raw_cache_key);
cp->saved_curr_val = mystrdup(raw_cache_val);
} else {
cp->saved_curr_key = 0;
cp->saved_curr_val = 0;
}
/*
* Delete behind.
*/
if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)) {
DC_CANCEL_DELETE_BEHIND(cp);
if (dict_del(cp->db, previous_curr_key) != 0)
msg_warn("database %s: could not delete entry for %s",
cp->db->name, previous_curr_key);
}
/*
* Clean up previous iteration key and value.
*/
if (previous_curr_key)
myfree(previous_curr_key);
if (previous_curr_val)
myfree(previous_curr_val);
/*
* Return the result.
*/
*cache_key = (cp)->saved_curr_key;
*cache_val = (cp)->saved_curr_val;
return (zero_means_found);
}
/* dict_cache_delete_behind_reset - reset "delete behind" state */
static void dict_cache_delete_behind_reset(DICT_CACHE *cp)
{
#define FREE_AND_WIPE(s) do { if (s) { myfree(s); (s) = 0; } } while (0)
DC_CANCEL_DELETE_BEHIND(cp);
FREE_AND_WIPE(cp->saved_curr_key);
FREE_AND_WIPE(cp->saved_curr_val);
}
/* dict_cache_clean_stat_log_reset - log and reset cache cleanup statistics */
static void dict_cache_clean_stat_log_reset(DICT_CACHE *cp,
const char *full_partial)
{
if (cp->flags & DICT_CACHE_FLAG_EXP_SUMMARY)
msg_info("cache %s %s cleanup: retained=%d dropped=%d entries",
cp->db->name, full_partial, cp->retained, cp->dropped);
cp->retained = cp->dropped = 0;
}
/* dict_cache_expire_event - examine one cache entry */
static void dict_cache_expire_event(int unused_event, char *cache_context)
{
DICT_CACHE *cp = (DICT_CACHE *) cache_context;
const char *cache_key;
const char *cache_val;
int next_interval;
VSTRING *stamp_buf;
int first_next;
/*
* We interleave cache cleanup with other processing, so that the
* application's service remains available, with perhaps increased
* latency.
*/
/*
* Start a new cache cleanup run.
*/
if (cp->saved_curr_key == 0) {
cp->retained = cp->dropped = 0;
first_next = DICT_SEQ_FUN_FIRST;
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
msg_info("start %s cache cleanup", cp->db->name);
}
/*
* Continue a cache cleanup run in progress.
*/
else {
first_next = DICT_SEQ_FUN_NEXT;
}
/*
* Examine one cache entry.
*/
if (dict_cache_sequence(cp, first_next, &cache_key, &cache_val) == 0) {
if (cp->exp_validator(cache_key, cache_val, cp->exp_context) == 0) {
DC_SCHEDULE_FOR_DELETE_BEHIND(cp);
cp->dropped++;
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
msg_info("drop %s cache entry for %s", cp->db->name, cache_key);
} else {
cp->retained++;
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
msg_info("keep %s cache entry for %s", cp->db->name, cache_key);
}
next_interval = 0;
}
/*
* Cache cleanup completed. Report vital statistics.
*/
else {
if (cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE)
msg_info("done %s cache cleanup scan", cp->db->name);
dict_cache_clean_stat_log_reset(cp, "full");
stamp_buf = vstring_alloc(100);
vstring_sprintf(stamp_buf, "%ld", (long) event_time());
dict_put(cp->db, DC_LAST_CACHE_CLEANUP_COMPLETED,
vstring_str(stamp_buf));
vstring_free(stamp_buf);
next_interval = cp->exp_interval;
}
event_request_timer(dict_cache_expire_event, cache_context, next_interval);
}
/* dict_cache_expire - schedule or stop the cache cleanup thread */
void dict_cache_expire(DICT_CACHE *cp, int flags, int interval,
DICT_CACHE_VALIDATOR_FN validator,
char *context)
{
const char *myname = "dict_cache_expire";
const char *last_done;
time_t next_interval;
/*
* Schedule the cache cleanup thread.
*/
if (validator != 0) {
/*
* Sanity checks.
*/
if (cp->exp_validator != 0)
msg_panic("%s: %s cache cleanup is already scheduled",
myname, cp->db->name);
if (interval <= 0)
msg_panic("%s: bad %s cache cleanup interval %d",
myname, cp->db->name, interval);
cp->exp_flags = flags;
cp->exp_interval = interval;
cp->exp_validator = validator;
cp->exp_context = context;
/*
* The next start time depends on the last completion time.
*/
#define NEXT_START(last, delta) ((delta) + (unsigned long) atol(last))
#define NOW (time((time_t *) 0)) /* NOT: event_time() */
if ((last_done = dict_get(cp->db, DC_LAST_CACHE_CLEANUP_COMPLETED)) == 0
|| (next_interval = (NEXT_START(last_done, interval) - NOW)) < 0)
next_interval = 0;
if (next_interval > interval)
next_interval = interval;
if ((cp->exp_flags & DICT_CACHE_FLAG_EXP_VERBOSE) && next_interval > 0)
msg_info("%s cache cleanup will start after %ds",
cp->db->name, (int) next_interval);
event_request_timer(dict_cache_expire_event, (char *) cp,
(int) next_interval);
}
/*
* Cancel the cache cleanup thread.
*/
else if (cp->exp_validator) {
if (cp->retained || cp->dropped)
dict_cache_clean_stat_log_reset(cp, "partial");
dict_cache_delete_behind_reset(cp);
cp->exp_interval = 0;
cp->exp_validator = 0;
cp->exp_context = 0;
event_cancel_timer(dict_cache_expire_event, (char *) cp);
}
}
/* dict_cache_open - open cache file */
DICT_CACHE *dict_cache_open(const char *dbname, int open_flags, int dict_flags)
{
DICT *dict;
/*
* Open the database as requested. Don't attempt to second-guess the
* application.
*/
dict = dict_open(dbname, open_flags, dict_flags);
return (dict_cache_import(dict));
}
/* dict_cache_import - encapsulate pre-opened database */
DICT_CACHE *dict_cache_import(DICT *dict)
{
DICT_CACHE *cp;
/*
* Create the DICT_CACHE object.
*/
cp = (DICT_CACHE *) mymalloc(sizeof(*cp));
cp->flags = 0;
cp->db = dict;
cp->saved_curr_key = 0;
cp->saved_curr_val = 0;
cp->exp_interval = 0;
cp->exp_validator = 0;
cp->exp_context = 0;
cp->retained = 0;
cp->dropped = 0;
return (cp);
}
/* dict_cache_close - close cache file */
void dict_cache_close(DICT_CACHE *cp)
{
/*
* Destroy the DICT_CACHE object.
*/
if (cp->exp_validator)
dict_cache_expire(cp, 0, 0, (DICT_CACHE_VALIDATOR_FN) 0, (char *) 0);
dict_close(cp->db);
if (cp->saved_curr_key)
myfree(cp->saved_curr_key);
if (cp->saved_curr_val)
myfree(cp->saved_curr_val);
myfree((char *) cp);
}
/* dict_cache_name - get the cache name */
const char *dict_cache_name(DICT_CACHE *cp)
{
/*
* This is used for verbose logging or warning messages, so the cost of
* call is only made where needed (well sort off - code that does not
* execute still presents overhead for the processor pipeline, processor
* cache, etc).
*/
return (cp->db->name);
}

View File

@ -0,0 +1,49 @@
#ifndef _DICT_CACHE_H_INCLUDED_
#define _DICT_CACHE_H_INCLUDED_
/*++
/* NAME
/* dict_cache 3h
/* SUMMARY
/* External cache manager
/* SYNOPSIS
/* #include <dict_cache.h>
/* DESCRIPTION
/* .nf
/*
* Utility library.
*/
#include <dict.h>
/*
* External interface.
*/
typedef struct DICT_CACHE DICT_CACHE;
typedef int (*DICT_CACHE_VALIDATOR_FN) (const char *, const char *, char *);
extern DICT_CACHE *dict_cache_open(const char *, int, int);
extern void dict_cache_close(DICT_CACHE *);
extern const char *dict_cache_lookup(DICT_CACHE *, const char *);
extern void dict_cache_update(DICT_CACHE *, const char *, const char *);
extern int dict_cache_delete(DICT_CACHE *, const char *);
extern int dict_cache_sequence(DICT_CACHE *, int, const char **, const char **);
extern void dict_cache_expire(DICT_CACHE *, int, int, DICT_CACHE_VALIDATOR_FN, char *);
extern const char *dict_cache_name(DICT_CACHE *);
extern DICT_CACHE *dict_cache_import(DICT *);
#define DICT_CACHE_FLAG_EXP_VERBOSE (1<<0)
#define DICT_CACHE_FLAG_EXP_SUMMARY (1<<1)
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
#endif

View File

@ -310,6 +310,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
DICT_DBM *dict_dbm = (DICT_DBM *) dict; DICT_DBM *dict_dbm = (DICT_DBM *) dict;
datum dbm_key; datum dbm_key;
datum dbm_value; datum dbm_value;
int status;
/* /*
* Acquire a shared lock. * Acquire a shared lock.
@ -350,6 +351,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
* Copy the value so that it is guaranteed null terminated. * Copy the value so that it is guaranteed null terminated.
*/ */
*value = SCOPY(dict_dbm->val_buf, dbm_value.dptr, dbm_value.dsize); *value = SCOPY(dict_dbm->val_buf, dbm_value.dptr, dbm_value.dsize);
status = 0;
} else { } else {
/* /*
@ -358,7 +360,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
*/ */
if (dbm_error(dict_dbm->dbm)) if (dbm_error(dict_dbm->dbm))
msg_fatal("error seeking %s: %m", dict_dbm->dict.name); msg_fatal("error seeking %s: %m", dict_dbm->dict.name);
return (1); /* no error: eof/not found status = 1; /* no error: eof/not found
* (should not happen!) */ * (should not happen!) */
} }
} else { } else {
@ -368,7 +370,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
*/ */
if (dbm_error(dict_dbm->dbm)) if (dbm_error(dict_dbm->dbm))
msg_fatal("error seeking %s: %m", dict_dbm->dict.name); msg_fatal("error seeking %s: %m", dict_dbm->dict.name);
return (1); /* no error: eof/not found */ status = 1; /* no error: eof/not found */
} }
/* /*
@ -378,7 +380,7 @@ static int dict_dbm_sequence(DICT *dict, int function,
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name); msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
return (0); return (status);
} }
/* dict_dbm_close - disassociate from data base */ /* dict_dbm_close - disassociate from data base */

View File

@ -75,6 +75,29 @@ static void dict_ht_update(DICT *dict, const char *name, const char *value)
ht->value = mystrdup(value); ht->value = mystrdup(value);
} }
/* dict_ht_sequence - first/next iterator */
static int dict_ht_sequence(DICT *dict, int how, const char **name,
const char **value)
{
DICT_HT *dict_ht = (DICT_HT *) dict;
HTABLE_INFO *ht;
ht = htable_sequence(dict_ht->table,
how == DICT_SEQ_FUN_FIRST ? HTABLE_SEQ_FIRST :
how == DICT_SEQ_FUN_NEXT ? HTABLE_SEQ_NEXT :
HTABLE_SEQ_STOP);
if (ht != 0) {
*name = ht->key;
*value = ht->value;
return (0);
} else {
*name = 0;
*value = 0;
return (1);
}
}
/* dict_ht_close - disassociate from hash table */ /* dict_ht_close - disassociate from hash table */
static void dict_ht_close(DICT *dict) static void dict_ht_close(DICT *dict)
@ -95,6 +118,7 @@ DICT *dict_ht_open(const char *name, HTABLE *table, void (*remove) (char *))
dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht)); dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht));
dict_ht->dict.lookup = dict_ht_lookup; dict_ht->dict.lookup = dict_ht_lookup;
dict_ht->dict.update = dict_ht_update; dict_ht->dict.update = dict_ht_update;
dict_ht->dict.sequence = dict_ht_sequence;
dict_ht->dict.close = dict_ht_close; dict_ht->dict.close = dict_ht_close;
dict_ht->table = table; dict_ht->table = table;
dict_ht->remove = remove; dict_ht->remove = remove;

View File

@ -144,13 +144,13 @@
/* dict_put() stores the specified key and value into the named /* dict_put() stores the specified key and value into the named
/* dictionary. /* dictionary.
/* /*
/* dict_del() removes a dictionary entry, and returns non-zero /* dict_del() removes a dictionary entry, and returns zero
/* in case of success. /* in case of success.
/* /*
/* dict_seq() iterates over all members in the named dictionary. /* dict_seq() iterates over all members in the named dictionary.
/* func is define DICT_SEQ_FUN_FIRST (select first member) or /* func is define DICT_SEQ_FUN_FIRST (select first member) or
/* DICT_SEQ_FUN_NEXT (select next member). A null result means /* DICT_SEQ_FUN_NEXT (select next member). A zero result means
/* there is more. /* that an entry was found.
/* /*
/* dict_close() closes the specified dictionary and cleans up the /* dict_close() closes the specified dictionary and cleans up the
/* associated data structures. /* associated data structures.

View File

@ -496,6 +496,11 @@ typedef struct epoll_event EVENT_BUFFER;
/* /*
* Timer events. Timer requests are kept sorted, in a circular list. We use * Timer events. Timer requests are kept sorted, in a circular list. We use
* the RING abstraction, so we get to use a couple ugly macros. * the RING abstraction, so we get to use a couple ugly macros.
*
* When a call-back function adds a timer request, we label the request with
* the event_loop() call instance that invoked the call-back. We use this to
* prevent zero-delay timer requests from running in a tight loop and
* starving I/O events.
*/ */
typedef struct EVENT_TIMER EVENT_TIMER; typedef struct EVENT_TIMER EVENT_TIMER;
@ -503,10 +508,12 @@ struct EVENT_TIMER {
time_t when; /* when event is wanted */ time_t when; /* when event is wanted */
EVENT_NOTIFY_TIME callback; /* callback function */ EVENT_NOTIFY_TIME callback; /* callback function */
char *context; /* callback context */ char *context; /* callback context */
long loop_instance; /* event_loop() call instance */
RING ring; /* linkage */ RING ring; /* linkage */
}; };
static RING event_timer_head; /* timer queue head */ static RING event_timer_head; /* timer queue head */
static long event_loop_instance; /* event_loop() call instance */
#define RING_TO_TIMER(r) \ #define RING_TO_TIMER(r) \
((EVENT_TIMER *) ((char *) (r) - offsetof(EVENT_TIMER, ring))) ((EVENT_TIMER *) ((char *) (r) - offsetof(EVENT_TIMER, ring)))
@ -921,18 +928,24 @@ time_t event_request_timer(EVENT_NOTIFY_TIME callback, char *context, int delay
timer->when = event_present + delay; timer->when = event_present + delay;
timer->callback = callback; timer->callback = callback;
timer->context = context; timer->context = context;
timer->loop_instance = event_loop_instance;
if (msg_verbose > 2) if (msg_verbose > 2)
msg_info("%s: set 0x%lx 0x%lx %d", myname, msg_info("%s: set 0x%lx 0x%lx %d", myname,
(long) callback, (long) context, delay); (long) callback, (long) context, delay);
} }
/* /*
* Insert the request at the right place. Timer requests are kept sorted * Timer requests are kept sorted to reduce lookup overhead in the event
* to reduce lookup overhead in the event loop. * loop.
*
* XXX Append the new request after existing requests for the same time
* slot. The event_loop() routine depends on this to avoid starving I/O
* events when a call-back function schedules a zero-delay timer request.
*/ */
FOREACH_QUEUE_ENTRY(ring, &event_timer_head) FOREACH_QUEUE_ENTRY(ring, &event_timer_head) {
if (timer->when < RING_TO_TIMER(ring)->when) if (timer->when < RING_TO_TIMER(ring)->when)
break; break;
}
ring_prepend(ring, &timer->ring); ring_prepend(ring, &timer->ring);
return (timer->when); return (timer->when);
@ -1079,17 +1092,35 @@ void event_loop(int delay)
msg_panic("event_loop: recursive call"); msg_panic("event_loop: recursive call");
/* /*
* Deliver timer events. Requests are sorted: we can stop when we reach * Deliver timer events. Allow the application to add/delete timer queue
* the future or the list end. Allow the application to update the timer * requests while it is being called back. Requests are sorted: we keep
* queue while it is being called back. To this end, we repeatedly pop * running over the timer request queue from the start, and stop when we
* the first request off the timer queue before delivering the event to * reach the future or the list end. We also stop when we reach a timer
* the application. * request that was added by a call-back that was invoked from this
* event_loop() call instance, for reasons that are explained below.
*
* To avoid dangling pointer problems 1) we must remove a request from the
* timer queue before delivering its event to the application and 2) we
* must look up the next timer request *after* calling the application.
* The latter complicates the handling of zero-delay timer requests that
* are added by event_loop() call-back functions.
*
* XXX When a timer event call-back function adds a new timer request,
* event_request_timer() labels the request with the event_loop() call
* instance that invoked the timer event call-back. We use this instance
* label here to prevent zero-delay timer requests from running in a
* tight loop and starving I/O events. To make this solution work,
* event_request_timer() appends a new request after existing requests
* for the same time slot.
*/ */
event_present = time((time_t *) 0); event_present = time((time_t *) 0);
event_loop_instance += 1;
while ((timer = FIRST_TIMER(&event_timer_head)) != 0) { while ((timer = FIRST_TIMER(&event_timer_head)) != 0) {
if (timer->when > event_present) if (timer->when > event_present)
break; break;
if (timer->loop_instance == event_loop_instance)
break;
ring_detach(&timer->ring); /* first this */ ring_detach(&timer->ring); /* first this */
if (msg_verbose > 2) if (msg_verbose > 2)
msg_info("%s: timer 0x%lx 0x%lx", myname, msg_info("%s: timer 0x%lx 0x%lx", myname,
@ -1192,10 +1223,10 @@ static void echo(int unused_event, char *unused_context)
printf("Result: %s", buf); printf("Result: %s", buf);
} }
int main(int argc, char **argv) /* request - request a bunch of timer events */
static void request(int unused_event, char *unused_context)
{ {
if (argv[1])
msg_verbose = atoi(argv[1]);
event_request_timer(timer_event, "3 first", 3); event_request_timer(timer_event, "3 first", 3);
event_request_timer(timer_event, "3 second", 3); event_request_timer(timer_event, "3 second", 3);
event_request_timer(timer_event, "4 first", 4); event_request_timer(timer_event, "4 first", 4);
@ -1206,6 +1237,13 @@ int main(int argc, char **argv)
event_request_timer(timer_event, "1 second", 1); event_request_timer(timer_event, "1 second", 1);
event_request_timer(timer_event, "0 first", 0); event_request_timer(timer_event, "0 first", 0);
event_request_timer(timer_event, "0 second", 0); event_request_timer(timer_event, "0 second", 0);
}
int main(int argc, char **argv)
{
if (argv[1])
msg_verbose = atoi(argv[1]);
event_request_timer(request, (char *) 0, 0);
event_enable_read(fileno(stdin), echo, (char *) 0); event_enable_read(fileno(stdin), echo, (char *) 0);
event_drain(10); event_drain(10);
exit(0); exit(0);

View File

@ -46,6 +46,10 @@
/* /*
/* HTABLE_INFO **htable_list(table) /* HTABLE_INFO **htable_list(table)
/* HTABLE *table; /* HTABLE *table;
/*
/* HTABLE_INFO *htable_sequence(table, how)
/* HTABLE *table;
/* int how;
/* DESCRIPTION /* DESCRIPTION
/* This module maintains one or more hash tables. Each table entry /* This module maintains one or more hash tables. Each table entry
/* consists of a unique string-valued lookup key and a generic /* consists of a unique string-valued lookup key and a generic
@ -85,6 +89,12 @@
/* htable_list() returns a null-terminated list of pointers to /* htable_list() returns a null-terminated list of pointers to
/* all elements in the named table. The list should be passed to /* all elements in the named table. The list should be passed to
/* myfree(). /* myfree().
/*
/* htable_sequence() returns the first or next element depending
/* on the value of the "how" argument. Specify HTABLE_SEQ_FIRST
/* to start a new sequence, HTABLE_SEQ_NEXT to continue, and
/* HTABLE_SEQ_STOP to terminate a sequence early. The caller
/* must not delete the current element.
/* RESTRICTIONS /* RESTRICTIONS
/* A callback function should not modify the hash table that is /* A callback function should not modify the hash table that is
/* specified to its caller. /* specified to its caller.
@ -172,6 +182,7 @@ HTABLE *htable_create(int size)
table = (HTABLE *) mymalloc(sizeof(HTABLE)); table = (HTABLE *) mymalloc(sizeof(HTABLE));
htable_size(table, size < 13 ? 13 : size); htable_size(table, size < 13 ? 13 : size);
table->seq_element = 0;
return (table); return (table);
} }
@ -202,7 +213,7 @@ HTABLE_INFO *htable_enter(HTABLE *table, const char *key, char *value)
{ {
HTABLE_INFO *ht; HTABLE_INFO *ht;
if (table->used >= table->size) if (table->used >= table->size && table->seq_element == 0)
htable_grow(table); htable_grow(table);
ht = (HTABLE_INFO *) mymalloc(sizeof(HTABLE_INFO)); ht = (HTABLE_INFO *) mymalloc(sizeof(HTABLE_INFO));
ht->key = mystrdup(key); ht->key = mystrdup(key);
@ -332,6 +343,34 @@ HTABLE_INFO **htable_list(HTABLE *table)
return (list); return (list);
} }
/* htable_sequence - dict_cache(3) compatibility iterator */
HTABLE_INFO *htable_sequence(HTABLE *table, int how)
{
if (table == 0)
return (0);
switch (how) {
case HTABLE_SEQ_FIRST: /* start new sequence */
table->seq_bucket = table->data;
table->seq_element = table->seq_bucket[0];
break;
case HTABLE_SEQ_NEXT: /* next element */
if (table->seq_element) {
table->seq_element = table->seq_element->next;
break;
}
/* FALLTHROUGH */
default: /* terminate sequence */
return (table->seq_element = 0);
}
while (table->seq_element == 0
&& ++(table->seq_bucket) < table->data + table->size)
table->seq_element = table->seq_bucket[0];
return (table->seq_element);
}
#ifdef TEST #ifdef TEST
#include <vstring_vstream.h> #include <vstring_vstream.h>
#include <myrand.h> #include <myrand.h>
@ -346,6 +385,7 @@ int main(int unused_argc, char **unused_argv)
HTABLE_INFO *info; HTABLE_INFO *info;
int i; int i;
int r; int r;
int op;
/* /*
* Load a large number of strings and delete them in a random order. * Load a large number of strings and delete them in a random order.
@ -353,6 +393,11 @@ int main(int unused_argc, char **unused_argv)
hash = htable_create(10); hash = htable_create(10);
while (vstring_get(buf, VSTREAM_IN) != VSTREAM_EOF) while (vstring_get(buf, VSTREAM_IN) != VSTREAM_EOF)
htable_enter(hash, vstring_str(buf), CAST_INT_TO_CHAR_PTR(count++)); htable_enter(hash, vstring_str(buf), CAST_INT_TO_CHAR_PTR(count++));
for (i = 0, op = HTABLE_SEQ_FIRST; htable_sequence(hash, op) != 0;
i++, op = HTABLE_SEQ_NEXT)
/* void */ ;
if (i != hash->used)
msg_panic("%d entries found, but %d entries exist", i, hash->used);
ht_info = htable_list(hash); ht_info = htable_list(hash);
for (i = 0; i < hash->used; i++) { for (i = 0; i < hash->used; i++) {
r = myrand() % hash->used; r = myrand() % hash->used;

View File

@ -26,6 +26,8 @@ typedef struct HTABLE {
int size; /* length of entries array */ int size; /* length of entries array */
int used; /* number of entries in table */ int used; /* number of entries in table */
HTABLE_INFO **data; /* entries array, auto-resized */ HTABLE_INFO **data; /* entries array, auto-resized */
HTABLE_INFO **seq_bucket; /* current sequence bucket */
HTABLE_INFO *seq_element; /* current sequence element */
} HTABLE; } HTABLE;
extern HTABLE *htable_create(int); extern HTABLE *htable_create(int);
@ -36,6 +38,11 @@ extern void htable_delete(HTABLE *, const char *, void (*) (char *));
extern void htable_free(HTABLE *, void (*) (char *)); extern void htable_free(HTABLE *, void (*) (char *));
extern void htable_walk(HTABLE *, void (*) (HTABLE_INFO *, char *), char *); extern void htable_walk(HTABLE *, void (*) (HTABLE_INFO *, char *), char *);
extern HTABLE_INFO **htable_list(HTABLE *); extern HTABLE_INFO **htable_list(HTABLE *);
extern HTABLE_INFO *htable_sequence(HTABLE *, int);
#define HTABLE_SEQ_FIRST 0
#define HTABLE_SEQ_NEXT 1
#define HTABLE_SEQ_STOP (-1)
/* LICENSE /* LICENSE
/* .ad /* .ad

View File

@ -63,8 +63,10 @@ verify.o: ../../include/cleanup_user.h
verify.o: ../../include/data_redirect.h verify.o: ../../include/data_redirect.h
verify.o: ../../include/deliver_request.h verify.o: ../../include/deliver_request.h
verify.o: ../../include/dict.h verify.o: ../../include/dict.h
verify.o: ../../include/dict_cache.h
verify.o: ../../include/dict_ht.h verify.o: ../../include/dict_ht.h
verify.o: ../../include/dsn.h verify.o: ../../include/dsn.h
verify.o: ../../include/events.h
verify.o: ../../include/htable.h verify.o: ../../include/htable.h
verify.o: ../../include/int_filt.h verify.o: ../../include/int_filt.h
verify.o: ../../include/iostuff.h verify.o: ../../include/iostuff.h

View File

@ -97,6 +97,10 @@
/* .IP "\fBaddress_verify_negative_refresh_time (3h)\fR" /* .IP "\fBaddress_verify_negative_refresh_time (3h)\fR"
/* The time after which a failed address verification probe needs to /* The time after which a failed address verification probe needs to
/* be refreshed. /* be refreshed.
/* .PP
/* Available with Postfix 2.7 and later:
/* .IP "\fBaddress_verify_cache_cleanup_interval (12h)\fR"
/* The amount of time between \fBverify\fR(8) cache cleanup runs.
/* PROBE MESSAGE ROUTING CONTROLS /* PROBE MESSAGE ROUTING CONTROLS
/* .ad /* .ad
/* .fi /* .fi
@ -121,6 +125,16 @@
/* .IP "\fBaddress_verify_default_transport ($default_transport)\fR" /* .IP "\fBaddress_verify_default_transport ($default_transport)\fR"
/* Overrides the default_transport parameter setting for address /* Overrides the default_transport parameter setting for address
/* verification probes. /* verification probes.
/* .PP
/* Available in Postfix 2.3 and later:
/* .IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR"
/* Overrides the sender_dependent_relayhost_maps parameter setting for address
/* verification probes.
/* .PP
/* Available in Postfix 2.7 and later:
/* .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR"
/* Overrides the sender_dependent_default_transport_maps parameter
/* setting for address verification probes.
/* MISCELLANEOUS CONTROLS /* MISCELLANEOUS CONTROLS
/* .ad /* .ad
/* .fi /* .fi
@ -187,10 +201,11 @@
#include <mymalloc.h> #include <mymalloc.h>
#include <htable.h> #include <htable.h>
#include <dict_ht.h> #include <dict_ht.h>
#include <dict.h> #include <dict_cache.h>
#include <split_at.h> #include <split_at.h>
#include <stringops.h> #include <stringops.h>
#include <set_eugid.h> #include <set_eugid.h>
#include <events.h>
/* Global library. */ /* Global library. */
@ -216,12 +231,13 @@ int var_verify_pos_exp;
int var_verify_pos_try; int var_verify_pos_try;
int var_verify_neg_exp; int var_verify_neg_exp;
int var_verify_neg_try; int var_verify_neg_try;
int var_verify_scan_cache;
char *var_verify_sender; char *var_verify_sender;
/* /*
* State. * State.
*/ */
static DICT *verify_map; static DICT_CACHE *verify_map;
/* /*
* Silly little macros. * Silly little macros.
@ -344,7 +360,7 @@ static void verify_update_service(VSTREAM *client_stream)
* some probes succeed the address will remain cached as OK. * some probes succeed the address will remain cached as OK.
*/ */
if (addr_status == DEL_RCPT_STAT_OK if (addr_status == DEL_RCPT_STAT_OK
|| (raw_data = dict_get(verify_map, STR(addr))) == 0 || (raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0
|| STATUS_FROM_RAW_ENTRY(raw_data) != DEL_RCPT_STAT_OK) { || STATUS_FROM_RAW_ENTRY(raw_data) != DEL_RCPT_STAT_OK) {
probed = 0; probed = 0;
updated = (long) time((time_t *) 0); updated = (long) time((time_t *) 0);
@ -352,7 +368,7 @@ static void verify_update_service(VSTREAM *client_stream)
if (msg_verbose) if (msg_verbose)
msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s", msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s",
STR(addr), addr_status, probed, updated, STR(text)); STR(addr), addr_status, probed, updated, STR(text));
dict_put(verify_map, STR(addr), STR(buf)); dict_cache_update(verify_map, STR(addr), STR(buf));
} }
attr_print(client_stream, ATTR_FLAG_NONE, attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK, ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK,
@ -419,7 +435,7 @@ static void verify_query_service(VSTREAM *client_stream)
/* FIX 200501 IPv6 patch did not neuter ":" in address literals. */ /* FIX 200501 IPv6 patch did not neuter ":" in address literals. */
translit(STR(addr), ":", "_"); translit(STR(addr), ":", "_");
if ((raw_data = dict_get(verify_map, STR(addr))) == 0 /* not found */ if ((raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0 /* not found */
|| ((get_buf = vstring_alloc(10)), || ((get_buf = vstring_alloc(10)),
vstring_strcpy(get_buf, raw_data), /* malformed */ vstring_strcpy(get_buf, raw_data), /* malformed */
verify_parse_entry(STR(get_buf), &addr_status, &probed, verify_parse_entry(STR(get_buf), &addr_status, &probed,
@ -432,7 +448,7 @@ static void verify_query_service(VSTREAM *client_stream)
updated = 0; updated = 0;
text = "Address verification in progress"; text = "Address verification in progress";
if (raw_data != 0 && var_verify_neg_cache == 0) if (raw_data != 0 && var_verify_neg_cache == 0)
dict_del(verify_map, STR(addr)); dict_cache_delete(verify_map, STR(addr));
} }
if (msg_verbose) if (msg_verbose)
msg_info("GOT %s status=%d probed=%ld updated=%ld text=%s", msg_info("GOT %s status=%d probed=%ld updated=%ld text=%s",
@ -482,7 +498,7 @@ static void verify_query_service(VSTREAM *client_stream)
if (msg_verbose) if (msg_verbose)
msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s", msg_info("PUT %s status=%d probed=%ld updated=%ld text=%s",
STR(addr), addr_status, now, updated, text); STR(addr), addr_status, now, updated, text);
dict_put(verify_map, STR(addr), STR(put_buf)); dict_cache_update(verify_map, STR(addr), STR(put_buf));
} }
} }
} }
@ -493,6 +509,29 @@ static void verify_query_service(VSTREAM *client_stream)
vstring_free(put_buf); vstring_free(put_buf);
} }
/* verify_cache_validator - cache cleanup validator */
static int verify_cache_validator(const char *addr, const char *raw_data,
char *context)
{
VSTRING *get_buf = (VSTRING *) context;
int addr_status;
long probed;
long updated;
char *text;
long now = (long) event_time();
#define POS_OR_NEG_ENTRY_EXPIRED(stat, stamp) \
(POSITIVE_ENTRY_EXPIRED((stat), (stamp)) \
|| NEGATIVE_ENTRY_EXPIRED((stat), (stamp)))
vstring_strcpy(get_buf, raw_data);
return (verify_parse_entry(STR(get_buf), &addr_status, /* syntax OK */
&probed, &updated, &text) == 0
&& (now - probed < PROBE_TTL /* probe in progress */
|| !POS_OR_NEG_ENTRY_EXPIRED(addr_status, updated)));
}
/* verify_service - perform service for client */ /* verify_service - perform service for client */
static void verify_service(VSTREAM *client_stream, char *unused_service, static void verify_service(VSTREAM *client_stream, char *unused_service,
@ -530,6 +569,21 @@ static void verify_service(VSTREAM *client_stream, char *unused_service,
vstring_free(request); vstring_free(request);
} }
/* verify_dump - dump some statistics */
static void verify_dump(void)
{
/*
* Dump preliminary cache cleanup statistics when the process commits
* suicide while a cache cleanup run is in progress. We can't currently
* distinguish between "postfix reload" (we should restart) or "maximal
* idle time reached" (we could finish the cache cleanup first).
*/
dict_cache_close(verify_map);
verify_map = 0;
}
/* post_jail_init - post-jail initialization */ /* post_jail_init - post-jail initialization */
static void post_jail_init(char *unused_name, char **unused_argv) static void post_jail_init(char *unused_name, char **unused_argv)
@ -544,6 +598,20 @@ static void post_jail_init(char *unused_name, char **unused_argv)
var_use_limit = 0; var_use_limit = 0;
var_idle_limit = 0; var_idle_limit = 0;
} }
/*
* Start the cache cleanup thread.
*/
if (var_verify_scan_cache > 0) {
int expire_flags;
expire_flags = DICT_CACHE_FLAG_EXP_SUMMARY;
if (msg_verbose)
expire_flags |= DICT_CACHE_FLAG_EXP_VERBOSE;
dict_cache_expire(verify_map, expire_flags, var_verify_scan_cache,
verify_cache_validator,
(char *) vstring_alloc(100));
}
} }
/* pre_jail_init - pre-jail initialization */ /* pre_jail_init - pre-jail initialization */
@ -585,17 +653,20 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
/* /*
* Keep state in persistent (external) or volatile (internal) map. * Keep state in persistent (external) or volatile (internal) map.
*
* Start the cache cleanup thread after permanently dropping privileges.
*/ */
#define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE) #define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
if (*var_verify_map) { if (*var_verify_map) {
saved_mask = umask(022); saved_mask = umask(022);
verify_map = dict_open(data_redirect_map(redirect, var_verify_map), verify_map =
O_CREAT | O_RDWR, dict_cache_open(data_redirect_map(redirect, var_verify_map),
VERIFY_DICT_OPEN_FLAGS); O_CREAT | O_RDWR, VERIFY_DICT_OPEN_FLAGS);
(void) umask(saved_mask); (void) umask(saved_mask);
} else { } else {
verify_map = dict_ht_open("verify", htable_create(0), myfree); verify_map =
dict_cache_import(dict_ht_open("verify", htable_create(0), myfree));
} }
/* /*
@ -621,6 +692,7 @@ int main(int argc, char **argv)
VAR_VERIFY_POS_TRY, DEF_VERIFY_POS_TRY, &var_verify_pos_try, 1, 0, VAR_VERIFY_POS_TRY, DEF_VERIFY_POS_TRY, &var_verify_pos_try, 1, 0,
VAR_VERIFY_NEG_EXP, DEF_VERIFY_NEG_EXP, &var_verify_neg_exp, 1, 0, VAR_VERIFY_NEG_EXP, DEF_VERIFY_NEG_EXP, &var_verify_neg_exp, 1, 0,
VAR_VERIFY_NEG_TRY, DEF_VERIFY_NEG_TRY, &var_verify_neg_try, 1, 0, VAR_VERIFY_NEG_TRY, DEF_VERIFY_NEG_TRY, &var_verify_neg_try, 1, 0,
VAR_VERIFY_SCAN_CACHE, DEF_VERIFY_SCAN_CACHE, &var_verify_scan_cache, 0, 0,
0, 0,
}; };
@ -635,5 +707,6 @@ int main(int argc, char **argv)
MAIL_SERVER_PRE_INIT, pre_jail_init, MAIL_SERVER_PRE_INIT, pre_jail_init,
MAIL_SERVER_POST_INIT, post_jail_init, MAIL_SERVER_POST_INIT, post_jail_init,
MAIL_SERVER_SOLITARY, MAIL_SERVER_SOLITARY,
MAIL_SERVER_EXIT, verify_dump,
0); 0);
} }