was useless code. Files: util/stream_pass_connect.c,
util/unix_pass_listen.c, util/unix_pass_trigger.c.
- Cleanup: on Solaris the Postfix event engine was deaf for
- SIGHUP and SIGALRM (and probably more) signals after the
- switch to /dev/poll. Symptoms were delayed "postfix reload"
- response, and killed processes when the watchdog timeout
- was less than max_idle. The fix is to set up SIGHUP and
- SIGALRM handlers that write to a pipe, and to monitor that
- pipe for read events via the Postfix event engine. Files:
- master/master_sig.c, util/watchdog.c.
+ Bugfix (introduced Postfix 2.4): on Solaris the Postfix
+ event engine was deaf for SIGHUP and SIGALRM signals after
+ the switch to /dev/poll. Symptoms were delayed "postfix
+ reload" response, and killed processes when the watchdog
+ timeout was less than max_idle. The fix is to set up SIGHUP
+ and SIGALRM handlers that write to a pipe, and to monitor
+ that pipe for read events via the Postfix event engine.
+ Files: master/master_sig.c, util/watchdog.c, util/sys_defs.h.
+
+20110111
+
+ Cleanup: replaced the postscreen(8) separate blacklist and
+ whitelist lookup tables by one postscreen_access_list table.
+ See postconf(5) and POSTSCREEN_README for examples. Files:
+ postscreen/postscreen_access.c, postscreen/postscreen.c,
+ proto/postconf.proto, proto/POSTSCREEN_README.html.
+
+20110112
+
+ Cleanup: suspend/resume logic for postscreen(8) SMTP sessions
+ that temporarily switch control to an external program such
+ as tlsproxy, or perhaps a future policy plugin. Files:
+ postscreen/postscreen_smtpd, postscreen/postscreen_starttls.c.
Before engaging in SMTP-level tests. postscreen(8) queries a number of local
black and whitelists. These tests speed up the handling of known clients.
- * Permanent whitelist test
- * Permanent blacklist test
+ * Permanent white/blacklist test
* Temporary whitelist test
-P\bPe\ber\brm\bma\ban\bne\ben\bnt\bt w\bwh\bhi\bit\bte\bel\bli\bis\bst\bt t\bte\bes\bst\bt
+P\bPe\ber\brm\bma\ban\bne\ben\bnt\bt w\bwh\bhi\bit\bte\be/\b/b\bbl\bla\bac\bck\bkl\bli\bis\bst\bt t\bte\bes\bst\bt
-The postscreen_whitelist_networks parameter (default: $mynetworks) specifies a
-permanent whitelist for SMTP client IP addresses. When the SMTP client address
-matches the permanent whitelist, postscreen(8) logs this with the client
-address and port number as:
+The postscreen_access_list parameter (default: permit_mynetworks) specifies a
+permanent access list for SMTP client IP addresses. Typically one would specify
+something that whitelists local networks, followed by a CIDR table for
+selective white- and blacklisting.
- W\bWH\bHI\bIT\bTE\bEL\bLI\bIS\bST\bTE\bED\bD [address]:port
+Example:
-The action is not configurable: immediately hand off the connection to a
-Postfix SMTP server process.
+/etc/postfix/main.cf:
+ postscreen_access_list = permit_mynetworks,
+ /etc/postfix/postscreen_access.cidr
-P\bPe\ber\brm\bma\ban\bne\ben\bnt\bt b\bbl\bla\bac\bck\bkl\bli\bis\bst\bt t\bte\bes\bst\bt
+/etc/postfix/postscreen_access.cidr:
+ # Rules are evaluated in the order as specified.
+ # Blacklist 192.168.* except 192.168.0.1.
+ 192.168.0.1 permit
+ 192.168.0.0/16 reject
-The postscreen_blacklist_networks parameter (default: empty) specifies a
-permanent blacklist for SMTP client IP addresses. The address syntax is as with
-mynetworks. When the SMTP client address matches the permanent blacklist,
-postscreen(8) logs this with the client address and port number as:
+See the postscreen_access_list manpage documentation for more details.
+
+When the SMTP client address matches a "permit" action, postscreen(8) logs this
+with the client address and port number as:
+
+ W\bWH\bHI\bIT\bTE\bEL\bLI\bIS\bST\bTE\bED\bD [address]:port
+
+The whitelist action is not configurable: immediately hand off the connection
+to a Postfix SMTP server process.
+
+When the SMTP client address matches a "reject" action, postscreen(8) logs this
+with the client address and port number as:
B\bBL\bLA\bAC\bCK\bKL\bLI\bIS\bST\bTE\bED\bD [address]:port
postscreen_greet_wait delay).
* Pregreet test
- * DNS Blocklist test
+ * DNS White/blacklist test
* When tests fail before the 220 SMTP server greeting
P\bPr\bre\beg\bgr\bre\bee\bet\bt t\bte\bes\bst\bt
To avoid problems with poorly-implemented SMTP engines in network appliances or
network testing tools, either exclude them from all tests with the
-postscreen_whitelist_networks feature or else specify an empty teaser banner:
+postscreen_access_list feature or else specify an empty teaser banner:
/etc/postfix/main.cf:
- # Exclude broken clients by whitelisting. $mynetworks is default.
- postscreen_whitelist_networks = $mynetworks, 192.168.254.0/24
+ # Exclude broken clients by whitelisting. Clients in mynetworks
+ # should always be whitelisted.
+ postscreen_access_list = permit_mynetworks,
+ cidr:/etc/postfix/postscreen_access.cidr
+
+/etc/postfix/postscreen_access.cidr:
+ 192.168.254.0/24 permit
/etc/postfix/main.cf:
# Disable the teaser banner (try whitelisting first if you can).
The postscreen_greet_action parameter specifies the action that is taken next.
See "When tests fail before the 220 SMTP server greeting" below.
-D\bDN\bNS\bS B\bBl\blo\boc\bck\bkl\bli\bis\bst\bt t\bte\bes\bst\bt
+D\bDN\bNS\bS W\bWh\bhi\bit\bte\be/\b/b\bbl\bla\bac\bck\bkl\bli\bis\bst\bt t\bte\bes\bst\bt
The postscreen_dnsbl_sites parameter (default: empty) specifies a list of DNS
-blocklist servers with optional filters and weight factors. These servers will
-be queried in parallel with the reverse client IP address. This test is
-disabled by default.
+blocklist servers with optional filters and weight factors (positive weights
+for blacklisting, negative for whitelisting). These servers will be queried in
+parallel with the reverse client IP address. This test is disabled by default.
CAUTION: when postscreen rejects mail, its SMTP reply contains the DNSBL
domain name. Use the postscreen_dnsbl_reply_map feature to hide "password"
after all. Wietse enables "deep protocol tests" on his own internet-facing
mail server.
- * There is also support for permanent blacklists and whitelists; see the
- description of the postscreen_whitelist_networks and
- postscreen_blacklist_networks parameters for details.
+ * There is also support for permanent blacklisting and whitelisting; see the
+ description of the postscreen_access_list parameter for details.
T\bTu\bur\brn\bni\bin\bng\bg o\bof\bff\bf p\bpo\bos\bst\bts\bsc\bcr\bre\bee\ben\bn(\b(8\b8)\b)
default). Other postscreen parameters always evaluate as if the
stress value is equal to the empty string.
+Incompatibility with snapshot 20110111
+======================================
+
+For performance reasons the postscreen_access_list feature replaces
+the postscreen_whitelist_networks and postscreen_blacklist_networks
+features. CIDR-style access maps are some 100x faster than the code
+that implemented the postscreen_white/blacklist_networks support.
+It can match about 100 million CIDR patterns/second on a modern CPU,
+which is not blindingly fast but adequate for the near future.
+
Major changes with snapshot 20110105
====================================
Remove this file from the stable release.
- To speed up postscreen_whitelist/blacklist_networks lookups
- invent match_list support that does not recompile CIDR
- patterns on every call. Otherwise, large CIDR files will
- make postscreen unacceptably slow.
-
- Better, replace the postscreen_whitelist/blacklist_networks
- mechanisms with one single postscreen_client_restrictions
- mechanism that understands "permit_mynetworks" and (cidr)
- access maps with entries of "pattern permit", "pattern
- reject", or "pattern dunno". Tables that require locking
- should not be used for performance reasons. The new mechanism
- can reduce the number of table lookups when sites have both
- whitelists and blacklists. We then use "permit_mynetworks"
- to whitelist local networks by default. Unlike match_lists,
- PCRE maps in access tables are compiled once, and even
- Stan's very large tables resolve in a millisecond or so on
- modern hardware.
-
Things to do after the stable release:
+ inline table where the "whitespace replacement" character
+ is specified in-line. Ex: inline:XYname1Xvalue1Yname2Xvalue2
+ would instantiate a table with (name1, value1) and (name2,
+ value2). I'm afraid this is just too ugly.
+
tlsproxy(8) should receive TLS preferences from postscreen(8)
and smtpd(8), instead of reading them from main.cf. This
means that many tlsproxy_ parameters become postscreen_
<ul>
-<li> <a href="#perm_white"> Permanent whitelist test </a>
-
-<li> <a href="#perm_black"> Permanent blacklist test </a>
+<li> <a href="#perm_white_black"> Permanent white/blacklist test </a>
<li> <a href="#temp_white"> Temporary whitelist test </a>
</ul>
-<h3> <a name="perm_white"> Permanent whitelist test </a> </h3>
+<h3> <a name="perm_white_black"> Permanent white/blacklist test </a> </h3>
+
+<p> The <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> parameter (default: <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>)
+specifies a permanent access list for SMTP client IP addresses. Typically
+one would specify something that whitelists local networks, followed
+by a CIDR table for selective white- and blacklisting. </p>
-<p> 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 client IP addresses. When
-the SMTP client address matches the permanent whitelist, <a href="postscreen.8.html">postscreen(8)</a>
-logs this with the client address and port number as: </p>
+<p> Example: </p>
+
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
+ /etc/postfix/postscreen_access.cidr
+
+/etc/postfix/postscreen_access.<a href="cidr_table.5.html">cidr</a>:
+ # Rules are evaluated in the order as specified.
+ # Blacklist 192.168.* except 192.168.0.1.
+ 192.168.0.1 permit
+ 192.168.0.0/16 reject
+</pre>
+
+<p> See the <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> manpage documentation for more
+details. </p>
+
+<p> When the SMTP client address matches a "permit" action,
+<a href="postscreen.8.html">postscreen(8)</a> logs this with the client address and port number as:
+</p>
<pre>
<b>WHITELISTED</b> <i>[address]:port</i>
</pre>
-<p> The action is not configurable: immediately hand off the
+<p> The whitelist action is not configurable: immediately hand off the
connection to a Postfix SMTP server process. </p>
-<h3> <a name="perm_black"> Permanent blacklist test </a> </h3>
-
-<p> The <a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter (default: empty)
-specifies a permanent blacklist for SMTP client IP addresses. The
-address syntax is as with <a href="postconf.5.html#mynetworks">mynetworks</a>. When the SMTP client address
-matches the permanent blacklist, <a href="postscreen.8.html">postscreen(8)</a> logs this with the
-client address and port number as: </p>
+<p> When the SMTP client address matches a "reject" action,
+<a href="postscreen.8.html">postscreen(8)</a> logs this with the client address and port number as:
+</p>
<pre>
<b>BLACKLISTED</b> <i>[address]:port</i>
<li> <a href="#pregreet"> Pregreet test </a>
-<li> <a href="#dnsbl"> DNS Blocklist test </a>
+<li> <a href="#dnsbl"> DNS White/blacklist test </a>
<li> <a href="#fail_before_220">When tests fail before the 220 SMTP server greeting</a>
<p> To avoid problems with poorly-implemented SMTP engines in network
appliances or network testing tools, either exclude them from all
-tests with the <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> feature or else specify
+tests with the <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> feature or else specify
an empty teaser banner: </p>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- # Exclude broken clients by whitelisting. $<a href="postconf.5.html#mynetworks">mynetworks</a> is default.
- <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>, 192.168.254.0/24
+ # Exclude broken clients by whitelisting. Clients in <a href="postconf.5.html#mynetworks">mynetworks</a>
+ # should always be whitelisted.
+ <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
+ <a href="cidr_table.5.html">cidr</a>:/etc/postfix/postscreen_access.cidr
+
+/etc/postfix/postscreen_access.<a href="cidr_table.5.html">cidr</a>:
+ 192.168.254.0/24 permit
</pre>
<pre>
is taken next. See "<a href="#fail_before_220">When tests fail
before the 220 SMTP server greeting</a>" below. </p>
-<h3> <a name="dnsbl"> DNS Blocklist test </a> </h3>
+<h3> <a name="dnsbl"> DNS White/blacklist test </a> </h3>
<p> The <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter (default: empty) specifies
a list of DNS blocklist servers with optional filters and weight
-factors. These servers will be queried in parallel with the reverse
-client IP address. This test is disabled by default. </p>
+factors (positive weights for blacklisting, negative for whitelisting).
+These servers will be queried in parallel with the reverse client
+IP address. This test is disabled by default. </p>
<blockquote>
<p>
"<a href="#after_220">deep protocol tests</a>" on his own internet-facing
mail server. </p>
-<li> <p> There is also support for permanent blacklists and whitelists;
-see the description of the <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> and
-<a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameters for details. </p>
+<li> <p> There is also support for permanent blacklisting and
+whitelisting; see the description of the <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a>
+parameter for details. </p>
</ul>
<p> This feature is available in Postfix 2.6 and later. </p>
+</DD>
+
+<DT><b><a name="postscreen_access_list">postscreen_access_list</a>
+(default: <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>)</b></DT><DD>
+
+<p> Permanent white/blacklist for remote SMTP client IP addresses;
+<a href="postscreen.8.html">postscreen(8)</a> searches this list immediately after a remote SMTP
+client connects. Specify a comma- or whitespace-separated list of
+commands (in upper or lower case) or lookup tables. The search stops
+upon the first command that fires for the client IP address. </p>
+
+<dl>
+
+<dt> <b> <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a> </b> </dt> <dd> Whitelist the client and
+terminate the search if the client IP address matches $<a href="postconf.5.html#mynetworks">mynetworks</a>.
+Do not subject the client to any before/after 220 greeting tests.
+Pass the connection immediately to a Postfix SMTP server process.
+</dd>
+
+<dt> <b> <a href="DATABASE_README.html">type:table</a> </b> </dt> <dd> Query the specified lookup
+table. Each table lookup result is an access list, except that
+access lists inside a table cannot specify <a href="DATABASE_README.html">type:table</a> entries. <br>
+To discourage the use of hash, btree, etc. tables, there is no
+support for substring matching like <a href="smtpd.8.html">smtpd(8)</a>. Use CIDR tables
+instead. </dd>
+
+<dt> <b> permit </b> </dt> <dd> Whitelist the client and terminate
+the search. Do not subject the client to any before/after 220
+greeting tests. Pass the connection immediately to a Postfix SMTP
+server process. </dd>
+
+<dt> <b> reject </b> </dt> <dd> Blacklist the client and terminate
+the search. Subject the client to the action configured with the
+<a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> configuration parameter. </dd>
+
+<dt> <b> dunno </b> </dt> <dd> When used inside a lookup table,
+return from the lookup table and evaluate the next command. <br>
+When used outside a lookup table, terminate the search, and subject
+the client to the configured before/after 220 greeting tests. </dd>
+
+</dl>
+
+<p> Example: </p>
+
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
+ <a href="cidr_table.5.html">cidr</a>:/etc/postfix/postscreen_access.cidr
+</pre>
+
+<pre>
+/etc/postfix/postscreen_access.<a href="cidr_table.5.html">cidr</a>:
+ # Rules are evaluated in the order as specified.
+ # Blacklist 192.168.* except 192.168.0.1.
+ 192.168.0.1 dunno
+ 192.168.0.0/16 reject
+</pre>
+
+<p> This feature is available in Postfix 2.8. </p>
+
+
</DD>
<DT><b><a name="postscreen_bare_newline_action">postscreen_bare_newline_action</a>
<p> This feature is available in Postfix 2.8. </p>
-</DD>
-
-<DT><b><a name="postscreen_blacklist_networks">postscreen_blacklist_networks</a>
-(default: empty)</b></DT><DD>
-
-<p> Network addresses that are permanently blacklisted; see the
-<a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for possible actions. This
-parameter uses the same address syntax as the <a href="postconf.5.html#mynetworks">mynetworks</a> parameter.
-The blacklist has higher precedence than whitelists. This feature
-never uses the remote SMTP client hostname. </p>
-
-<p> This feature is available in Postfix 2.8. </p>
-
-
</DD>
<DT><b><a name="postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
<p> This feature is available in Postfix 2.8. </p>
-</DD>
-
-<DT><b><a name="postscreen_whitelist_networks">postscreen_whitelist_networks</a>
-(default: $<a href="postconf.5.html#mynetworks">mynetworks</a>)</b></DT><DD>
-
-<p> Network addresses that are permanently whitelisted, and that
-will not be subjected to <a href="postscreen.8.html">postscreen(8)</a> checks. This parameter uses
-the same address syntax as the <a href="postconf.5.html#mynetworks">mynetworks</a> parameter. This feature
-never uses the remote SMTP client hostname. </p>
-
-<p> This feature is available in Postfix 2.8. </p>
-
-
</DD>
<DT><b><a name="prepend_delivered_header">prepend_delivered_header</a>
server will not send in the EHLO response to a
remote SMTP client.
-<b>TRIAGE PARAMETERS</b>
- <b><a href="postconf.5.html#postscreen_bare_newline_action">postscreen_bare_newline_action</a> (ignore)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
- client sends a bare newline character, that is, a
- newline not preceded by carriage return.
-
- <b><a href="postconf.5.html#postscreen_bare_newline_enable">postscreen_bare_newline_enable</a> (no)</b>
- Enable "bare newline" SMTP protocol tests in the
- <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
+<b>BEFORE-GREETING TRIAGE</b>
+ <b><a href="postconf.5.html#postscreen_access_list">postscreen_access_list</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>)</b>
+ Permanent white/blacklist for remote SMTP client IP
+ addresses; <a href="postscreen.8.html"><b>postscreen</b>(8)</a> searches this list immedi-
+ ately after a remote SMTP client connects.
<b><a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> (ignore)</b>
- The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
- client is permanently blacklisted with the
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ client is permanently blacklisted with the
<a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter.
<b><a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> (empty)</b>
Network addresses that are permanently blacklisted;
- 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.
- <b><a href="postconf.5.html#postscreen_disable_vrfy_command">postscreen_disable_vrfy_command</a> ($<a href="postconf.5.html#disable_vrfy_command">disable_vrfy_command</a>)</b>
- Disable the SMTP VRFY command in the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
- daemon.
-
<b><a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> (ignore)</b>
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
client's combined DNSBL score is equal to or
client, based on its combined DNSBL score as
defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.
- <b><a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> ($<a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a>)</b>
- List of commands that the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server con-
- siders in violation of the SMTP protocol.
-
<b><a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> (ignore)</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 speaks before its turn within the time spec-
ified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter.
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
Postfix SMTP server's "220 text..." response, in an
- attempt to confuse bad SMTP clients so that they
+ attempt to confuse bad SMTP clients so that they
speak before their turn (pre-greet).
<b><a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> (${stress?2}${stress:6}s)</b>
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will wait for
- an SMTP client to send a command before its turn,
- and for DNS blocklist lookup results to arrive
- (default: up to 2 seconds under stress, up to 6
+ an SMTP client to send a command before its turn,
+ and for DNS blocklist lookup results to arrive
+ (default: up to 2 seconds under stress, up to 6
seconds otherwise).
+<b>AFTER-GREETING TRIAGE</b>
+ <b><a href="postconf.5.html#postscreen_bare_newline_action">postscreen_bare_newline_action</a> (ignore)</b>
+ The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
+ client sends a bare newline character, that is, a
+ newline not preceded by carriage return.
+
+ <b><a href="postconf.5.html#postscreen_bare_newline_enable">postscreen_bare_newline_enable</a> (no)</b>
+ Enable "bare newline" SMTP protocol tests in the
+ <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
+
+ <b><a href="postconf.5.html#postscreen_disable_vrfy_command">postscreen_disable_vrfy_command</a> ($<a href="postconf.5.html#disable_vrfy_command">disable_vrfy_command</a>)</b>
+ Disable the SMTP VRFY command in the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+ daemon.
+
+ <b><a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> ($<a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a>)</b>
+ List of commands that the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server con-
+ siders in violation of the SMTP protocol.
+
<b><a href="postconf.5.html#postscreen_helo_required">postscreen_helo_required</a> ($<a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a>)</b>
Require that a remote SMTP client sends HELO or
EHLO before commencing a MAIL transaction.
Enable "pipelining" SMTP protocol tests in the
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
- <b><a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- Network addresses that are permanently whitelisted,
- and that will not be subjected to <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
- checks.
-
+<b>AFTER-TRIAGE CONTROLS</b>
<b><a href="postconf.5.html#smtpd_service_name">smtpd_service_name</a> (smtpd)</b>
The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
allowed connections to.
and enabled instances are processed in reverse order.
.PP
This feature is available in Postfix 2.6 and later.
+.SH postscreen_access_list (default: permit_mynetworks)
+Permanent white/blacklist for remote SMTP client IP addresses;
+\fBpostscreen\fR(8) searches this list immediately after a remote SMTP
+client connects. Specify a comma- or whitespace-separated list of
+commands (in upper or lower case) or lookup tables. The search stops
+upon the first command that fires for the client IP address.
+.IP "\fB permit_mynetworks \fR"
+Whitelist the client and
+terminate the search if the client IP address matches $mynetworks.
+Do not subject the client to any before/after 220 greeting tests.
+Pass the connection immediately to a Postfix SMTP server process.
+.IP "\fB type:table \fR"
+Query the specified lookup
+table. Each table lookup result is an access list, except that
+access lists inside a table cannot specify type:table entries.
+.br
+To discourage the use of hash, btree, etc. tables, there is no
+support for substring matching like \fBsmtpd\fR(8). Use CIDR tables
+instead.
+.IP "\fB permit \fR"
+Whitelist the client and terminate
+the search. Do not subject the client to any before/after 220
+greeting tests. Pass the connection immediately to a Postfix SMTP
+server process.
+.IP "\fB reject \fR"
+Blacklist the client and terminate
+the search. Subject the client to the action configured with the
+postscreen_blacklist_action configuration parameter.
+.IP "\fB dunno \fR"
+When used inside a lookup table,
+return from the lookup table and evaluate the next command.
+.br
+When used outside a lookup table, terminate the search, and subject
+the client to the configured before/after 220 greeting tests.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ postscreen_access_list = permit_mynetworks,
+ cidr:/etc/postfix/postscreen_access.cidr
+.fi
+.ad
+.ft R
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/postscreen_access.cidr:
+ # Rules are evaluated in the order as specified.
+ # Blacklist 192.168.* except 192.168.0.1.
+ 192.168.0.1 dunno
+ 192.168.0.0/16 reject
+.fi
+.ad
+.ft R
+.PP
+This feature is available in Postfix 2.8.
.SH postscreen_bare_newline_action (default: ignore)
The action that \fBpostscreen\fR(8) takes when an SMTP client sends
a bare newline character, that is, a newline not preceded by carriage
this test the next time the client connects.
.PP
This feature is available in Postfix 2.8.
-.SH postscreen_blacklist_networks (default: empty)
-Network addresses that are permanently blacklisted; see the
-postscreen_blacklist_action parameter for possible actions. This
-parameter uses the same address syntax as the mynetworks parameter.
-The blacklist has higher precedence than whitelists. This feature
-never uses the remote SMTP client hostname.
-.PP
-This feature is available in Postfix 2.8.
.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
(seconds), m (minutes), h (hours), d (days), w (weeks).
.PP
This feature is available in Postfix 2.8.
-.SH postscreen_whitelist_networks (default: $mynetworks)
-Network addresses that are permanently whitelisted, and that
-will not be subjected to \fBpostscreen\fR(8) checks. This parameter uses
-the same address syntax as the mynetworks parameter. This feature
-never uses the remote SMTP client hostname.
-.PP
-This feature is available in Postfix 2.8.
.SH prepend_delivered_header (default: command, file, forward)
The message delivery contexts where the Postfix \fBlocal\fR(8) delivery
agent prepends a Delivered-To: message header with the address
A case insensitive list of EHLO keywords (pipelining, starttls,
auth, etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO
response to a remote SMTP client.
-.SH "TRIAGE PARAMETERS"
+.SH "BEFORE-GREETING TRIAGE"
.na
.nf
.ad
.fi
-.IP "\fBpostscreen_bare_newline_action (ignore)\fR"
-The action that \fBpostscreen\fR(8) takes when an SMTP client sends
-a bare newline character, that is, a newline not preceded by carriage
-return.
-.IP "\fBpostscreen_bare_newline_enable (no)\fR"
-Enable "bare newline" SMTP protocol tests in the \fBpostscreen\fR(8)
-server.
+.IP "\fBpostscreen_access_list (permit_mynetworks)\fR"
+Permanent white/blacklist for remote SMTP client IP addresses;
+\fBpostscreen\fR(8) searches this list immediately after a remote SMTP
+client connects.
.IP "\fBpostscreen_blacklist_action (ignore)\fR"
The action that \fBpostscreen\fR(8) takes when an SMTP client is
permanently blacklisted with the postscreen_blacklist_networks
.IP "\fBpostscreen_blacklist_networks (empty)\fR"
Network addresses that are permanently blacklisted; see the
postscreen_blacklist_action parameter for possible actions.
-.IP "\fBpostscreen_disable_vrfy_command ($disable_vrfy_command)\fR"
-Disable the SMTP VRFY command in the \fBpostscreen\fR(8) daemon.
.IP "\fBpostscreen_dnsbl_action (ignore)\fR"
The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
DNSBL score is equal to or greater than a threshold (as defined
The inclusive lower bound for blocking an SMTP client, based on
its combined DNSBL score as defined with the postscreen_dnsbl_sites
parameter.
-.IP "\fBpostscreen_forbidden_commands ($smtpd_forbidden_commands)\fR"
-List of commands that the \fBpostscreen\fR(8) server considers in
-violation of the SMTP protocol.
.IP "\fBpostscreen_greet_action (ignore)\fR"
The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
before its turn within the time specified with the postscreen_greet_wait
client to send a command before its turn, and for DNS blocklist
lookup results to arrive (default: up to 2 seconds under stress,
up to 6 seconds otherwise).
+.SH "AFTER-GREETING TRIAGE"
+.na
+.nf
+.ad
+.fi
+.IP "\fBpostscreen_bare_newline_action (ignore)\fR"
+The action that \fBpostscreen\fR(8) takes when an SMTP client sends
+a bare newline character, that is, a newline not preceded by carriage
+return.
+.IP "\fBpostscreen_bare_newline_enable (no)\fR"
+Enable "bare newline" SMTP protocol tests in the \fBpostscreen\fR(8)
+server.
+.IP "\fBpostscreen_disable_vrfy_command ($disable_vrfy_command)\fR"
+Disable the SMTP VRFY command in the \fBpostscreen\fR(8) daemon.
+.IP "\fBpostscreen_forbidden_commands ($smtpd_forbidden_commands)\fR"
+List of commands that the \fBpostscreen\fR(8) server considers in
+violation of the SMTP protocol.
.IP "\fBpostscreen_helo_required ($smtpd_helo_required)\fR"
Require that a remote SMTP client sends HELO or EHLO before
commencing a MAIL transaction.
.IP "\fBpostscreen_pipelining_enable (no)\fR"
Enable "pipelining" SMTP protocol tests in the \fBpostscreen\fR(8)
server.
-.IP "\fBpostscreen_whitelist_networks ($mynetworks)\fR"
-Network addresses that are permanently whitelisted, and that
-will not be subjected to \fBpostscreen\fR(8) checks.
+.SH "AFTER-TRIAGE CONTROLS"
+.na
+.nf
+.ad
+.fi
.IP "\fBsmtpd_service_name (smtpd)\fR"
The internal service that \fBpostscreen\fR(8) forwards allowed
connections to.
s;\bpostscreen_pipelining_action\b;<a href="postconf.5.html#postscreen_pipelining_action">$&</a>;g;
s;\bpostscreen_pipelining_ttl\b;<a href="postconf.5.html#postscreen_pipelining_ttl">$&</a>;g;
s;\bpostscreen_watchdog_timeout\b;<a href="postconf.5.html#postscreen_watchdog_timeout">$&</a>;g;
+ s;\bpostscreen_access_list\b;<a href="postconf.5.html#postscreen_access_list">$&</a>;g;
s;\bpostscreen_whitelist_networks\b;<a href="postconf.5.html#postscreen_whitelist_networks">$&</a>;g;
s;\bpostscreen_black[-</bB>]*\n*[ <bB>]*list_networks\b;<a href="postconf.5.html#postscreen_blacklist_networks">$&</a>;g;
s;\bpostscreen_black[-</bB>]*\n*[ <bB>]*list_action\b;<a href="postconf.5.html#postscreen_blacklist_action">$&</a>;g;
<ul>
-<li> <a href="#perm_white"> Permanent whitelist test </a>
-
-<li> <a href="#perm_black"> Permanent blacklist test </a>
+<li> <a href="#perm_white_black"> Permanent white/blacklist test </a>
<li> <a href="#temp_white"> Temporary whitelist test </a>
</ul>
-<h3> <a name="perm_white"> Permanent whitelist test </a> </h3>
+<h3> <a name="perm_white_black"> Permanent white/blacklist test </a> </h3>
+
+<p> The postscreen_access_list parameter (default: permit_mynetworks)
+specifies a permanent access list for SMTP client IP addresses. Typically
+one would specify something that whitelists local networks, followed
+by a CIDR table for selective white- and blacklisting. </p>
-<p> The postscreen_whitelist_networks parameter (default: $mynetworks)
-specifies a permanent whitelist for SMTP client IP addresses. When
-the SMTP client address matches the permanent whitelist, postscreen(8)
-logs this with the client address and port number as: </p>
+<p> Example: </p>
+
+<pre>
+/etc/postfix/main.cf:
+ postscreen_access_list = permit_mynetworks,
+ /etc/postfix/postscreen_access.cidr
+
+/etc/postfix/postscreen_access.cidr:
+ # Rules are evaluated in the order as specified.
+ # Blacklist 192.168.* except 192.168.0.1.
+ 192.168.0.1 permit
+ 192.168.0.0/16 reject
+</pre>
+
+<p> See the postscreen_access_list manpage documentation for more
+details. </p>
+
+<p> When the SMTP client address matches a "permit" action,
+postscreen(8) logs this with the client address and port number as:
+</p>
<pre>
<b>WHITELISTED</b> <i>[address]:port</i>
</pre>
-<p> The action is not configurable: immediately hand off the
+<p> The whitelist action is not configurable: immediately hand off the
connection to a Postfix SMTP server process. </p>
-<h3> <a name="perm_black"> Permanent blacklist test </a> </h3>
-
-<p> The postscreen_blacklist_networks parameter (default: empty)
-specifies a permanent blacklist for SMTP client IP addresses. The
-address syntax is as with mynetworks. When the SMTP client address
-matches the permanent blacklist, postscreen(8) logs this with the
-client address and port number as: </p>
+<p> When the SMTP client address matches a "reject" action,
+postscreen(8) logs this with the client address and port number as:
+</p>
<pre>
<b>BLACKLISTED</b> <i>[address]:port</i>
<li> <a href="#pregreet"> Pregreet test </a>
-<li> <a href="#dnsbl"> DNS Blocklist test </a>
+<li> <a href="#dnsbl"> DNS White/blacklist test </a>
<li> <a href="#fail_before_220">When tests fail before the 220 SMTP server greeting</a>
<p> To avoid problems with poorly-implemented SMTP engines in network
appliances or network testing tools, either exclude them from all
-tests with the postscreen_whitelist_networks feature or else specify
+tests with the postscreen_access_list feature or else specify
an empty teaser banner: </p>
<pre>
/etc/postfix/main.cf:
- # Exclude broken clients by whitelisting. $mynetworks is default.
- postscreen_whitelist_networks = $mynetworks, 192.168.254.0/24
+ # Exclude broken clients by whitelisting. Clients in mynetworks
+ # should always be whitelisted.
+ postscreen_access_list = permit_mynetworks,
+ cidr:/etc/postfix/postscreen_access.cidr
+
+/etc/postfix/postscreen_access.cidr:
+ 192.168.254.0/24 permit
</pre>
<pre>
is taken next. See "<a href="#fail_before_220">When tests fail
before the 220 SMTP server greeting</a>" below. </p>
-<h3> <a name="dnsbl"> DNS Blocklist test </a> </h3>
+<h3> <a name="dnsbl"> DNS White/blacklist test </a> </h3>
<p> The postscreen_dnsbl_sites parameter (default: empty) specifies
a list of DNS blocklist servers with optional filters and weight
-factors. These servers will be queried in parallel with the reverse
-client IP address. This test is disabled by default. </p>
+factors (positive weights for blacklisting, negative for whitelisting).
+These servers will be queried in parallel with the reverse client
+IP address. This test is disabled by default. </p>
<blockquote>
<p>
"<a href="#after_220">deep protocol tests</a>" on his own internet-facing
mail server. </p>
-<li> <p> There is also support for permanent blacklists and whitelists;
-see the description of the postscreen_whitelist_networks and
-postscreen_blacklist_networks parameters for details. </p>
+<li> <p> There is also support for permanent blacklisting and
+whitelisting; see the description of the postscreen_access_list
+parameter for details. </p>
</ul>
<p> This feature is available in Postfix 2.8. </p>
-%PARAM postscreen_whitelist_networks $mynetworks
+#%PARAM postscreen_whitelist_networks $mynetworks
+#
+#<p> Network addresses that are permanently whitelisted, and that
+#will not be subjected to postscreen(8) checks. This parameter uses
+#the same address syntax as the mynetworks parameter. This feature
+#never uses the remote SMTP client hostname. </p>
+#
+#<p> This feature is available in Postfix 2.8. </p>
+#
+#%PARAM postscreen_blacklist_networks
+#
+#<p> Network addresses that are permanently blacklisted; see the
+#postscreen_blacklist_action parameter for possible actions. This
+#parameter uses the same address syntax as the mynetworks parameter.
+#The blacklist has higher precedence than whitelists. This feature
+#never uses the remote SMTP client hostname. </p>
+#
+#<p> This feature is available in Postfix 2.8. </p>
-<p> Network addresses that are permanently whitelisted, and that
-will not be subjected to postscreen(8) checks. This parameter uses
-the same address syntax as the mynetworks parameter. This feature
-never uses the remote SMTP client hostname. </p>
+%PARAM postscreen_access_list permit_mynetworks
-<p> This feature is available in Postfix 2.8. </p>
+<p> Permanent white/blacklist for remote SMTP client IP addresses;
+postscreen(8) searches this list immediately after a remote SMTP
+client connects. Specify a comma- or whitespace-separated list of
+commands (in upper or lower case) or lookup tables. The search stops
+upon the first command that fires for the client IP address. </p>
+
+<dl>
+
+<dt> <b> permit_mynetworks </b> </dt> <dd> Whitelist the client and
+terminate the search if the client IP address matches $mynetworks.
+Do not subject the client to any before/after 220 greeting tests.
+Pass the connection immediately to a Postfix SMTP server process.
+</dd>
+
+<dt> <b> type:table </b> </dt> <dd> Query the specified lookup
+table. Each table lookup result is an access list, except that
+access lists inside a table cannot specify type:table entries. <br>
+To discourage the use of hash, btree, etc. tables, there is no
+support for substring matching like smtpd(8). Use CIDR tables
+instead. </dd>
+
+<dt> <b> permit </b> </dt> <dd> Whitelist the client and terminate
+the search. Do not subject the client to any before/after 220
+greeting tests. Pass the connection immediately to a Postfix SMTP
+server process. </dd>
-%PARAM postscreen_blacklist_networks
+<dt> <b> reject </b> </dt> <dd> Blacklist the client and terminate
+the search. Subject the client to the action configured with the
+postscreen_blacklist_action configuration parameter. </dd>
-<p> Network addresses that are permanently blacklisted; see the
-postscreen_blacklist_action parameter for possible actions. This
-parameter uses the same address syntax as the mynetworks parameter.
-The blacklist has higher precedence than whitelists. This feature
-never uses the remote SMTP client hostname. </p>
+<dt> <b> dunno </b> </dt> <dd> When used inside a lookup table,
+return from the lookup table and evaluate the next command. <br>
+When used outside a lookup table, terminate the search, and subject
+the client to the configured before/after 220 greeting tests. </dd>
+</dl>
+
+<p> Example: </p>
+
+<pre>
+/etc/postfix/main.cf:
+ postscreen_access_list = permit_mynetworks,
+ cidr:/etc/postfix/postscreen_access.cidr
+</pre>
+
+<pre>
+/etc/postfix/postscreen_access.cidr:
+ # Rules are evaluated in the order as specified.
+ # Blacklist 192.168.* except 192.168.0.1.
+ 192.168.0.1 dunno
+ 192.168.0.0/16 reject
+</pre>
+
<p> This feature is available in Postfix 2.8. </p>
%PARAM postscreen_greet_banner $smtpd_banner
data_redirect: data_redirect.c $(LIB) $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+addr_match_list: addr_match_list.c $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
tests: tok822_test mime_tests strip_addr_test tok822_limit_test \
xtext_test scache_multi_test ehlo_mask_test \
namadr_list_test mail_conf_time_test header_body_checks_tests
#include <msg.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
#include <vstream.h>
+#include <vstring_vstream.h>
#include <msg_vstream.h>
static void usage(char *progname)
int main(int argc, char **argv)
{
ADDR_MATCH_LIST *list;
- char *host;
char *addr;
int ch;
usage(argv[0]);
list = addr_match_list_init(MATCH_FLAG_PARENT, argv[optind]);
addr = argv[optind + 1];
- vstream_printf("%s: %s\n", addr,
- addr_match_list_match(list, addr) ?
- "YES" : "NO");
+ if (strcmp(addr, "-") == 0) {
+ VSTRING *buf = vstring_alloc(100);
+
+ while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF)
+ vstream_printf("%s: %s\n", vstring_str(buf),
+ addr_match_list_match(list, vstring_str(buf)) ?
+ "YES" : "NO");
+ vstring_free(buf);
+ } else {
+ vstream_printf("%s: %s\n", addr,
+ addr_match_list_match(list, addr) ?
+ "YES" : "NO");
+ }
vstream_fflush(VSTREAM_OUT);
addr_match_list_free(list);
return (0);
#define DEF_PSC_CMD_FILTER ""
extern char *var_psc_cmd_filter;
+#define PSC_ACL_NAME_WL_MYNETWORKS "permit_mynetworks"
+#define PSC_ACL_NAME_WHITELIST "permit"
+#define PSC_ACL_NAME_BLACKLIST "reject"
+#define PSC_ACL_NAME_DUNNO "dunno"
+#define PSC_ACL_NAME_ERROR "error"
+
+#define VAR_PSC_ACL "postscreen_access_list"
+#define DEF_PSC_ACL PSC_ACL_NAME_WL_MYNETWORKS
+extern char *var_psc_acl;
+
#define VAR_DNSBLOG_DELAY "dnsblog_reply_delay"
#define DEF_DNSBLOG_DELAY "0s"
extern int var_dnsblog_delay;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20110109"
+#define MAIL_RELEASE_DATE "20110112"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
SRCS = postscreen.c postscreen_dict.c postscreen_dnsbl.c \
postscreen_early.c postscreen_smtpd.c postscreen_misc.c \
postscreen_state.c postscreen_tests.c postscreen_send.c \
- postscreen_starttls.c postscreen_expand.c
+ postscreen_starttls.c postscreen_expand.c postscreen_access.c
OBJS = postscreen.o postscreen_dict.o postscreen_dnsbl.o \
postscreen_early.o postscreen_smtpd.o postscreen_misc.o \
postscreen_state.o postscreen_tests.o postscreen_send.o \
- postscreen_starttls.o postscreen_expand.o
+ postscreen_starttls.o postscreen_expand.o postscreen_access.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
-TESTPROG=
+TESTPROG= postscreen_access
PROG = postscreen
INC_DIR = ../../include
LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libglobal.a \
../../libexec/$(PROG): $(PROG)
cp $(PROG) ../../libexec
+postscreen_access: $(PROG) $(LIBS)
+ mv $@.o junk
+ $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
postscreen.o: ../../include/vstring.h
postscreen.o: postscreen.c
postscreen.o: postscreen.h
+postscreen_access.o: ../../include/addr_match_list.h
+postscreen_access.o: ../../include/argv.h
+postscreen_access.o: ../../include/dict.h
+postscreen_access.o: ../../include/dict_cache.h
+postscreen_access.o: ../../include/events.h
+postscreen_access.o: ../../include/htable.h
+postscreen_access.o: ../../include/mail_params.h
+postscreen_access.o: ../../include/maps.h
+postscreen_access.o: ../../include/match_list.h
+postscreen_access.o: ../../include/match_ops.h
+postscreen_access.o: ../../include/match_parent_style.h
+postscreen_access.o: ../../include/msg.h
+postscreen_access.o: ../../include/mymalloc.h
+postscreen_access.o: ../../include/string_list.h
+postscreen_access.o: ../../include/stringops.h
+postscreen_access.o: ../../include/sys_defs.h
+postscreen_access.o: ../../include/vbuf.h
+postscreen_access.o: ../../include/vstream.h
+postscreen_access.o: ../../include/vstring.h
+postscreen_access.o: postscreen.h
+postscreen_access.o: postscreen_access.c
postscreen_dict.o: ../../include/addr_match_list.h
postscreen_dict.o: ../../include/argv.h
postscreen_dict.o: ../../include/dict.h
/* A case insensitive list of EHLO keywords (pipelining, starttls,
/* auth, etc.) that the \fBpostscreen\fR(8) server will not send in the EHLO
/* response to a remote SMTP client.
-/* TRIAGE PARAMETERS
+/* BEFORE-GREETING TRIAGE
/* .ad
/* .fi
-/* .IP "\fBpostscreen_bare_newline_action (ignore)\fR"
-/* The action that \fBpostscreen\fR(8) takes when an SMTP client sends
-/* a bare newline character, that is, a newline not preceded by carriage
-/* return.
-/* .IP "\fBpostscreen_bare_newline_enable (no)\fR"
-/* Enable "bare newline" SMTP protocol tests in the \fBpostscreen\fR(8)
-/* server.
+/* .IP "\fBpostscreen_access_list (permit_mynetworks)\fR"
+/* Permanent white/blacklist for remote SMTP client IP addresses;
+/* \fBpostscreen\fR(8) searches this list immediately after a remote SMTP
+/* client connects.
/* .IP "\fBpostscreen_blacklist_action (ignore)\fR"
/* The action that \fBpostscreen\fR(8) takes when an SMTP client is
/* permanently blacklisted with the postscreen_blacklist_networks
/* .IP "\fBpostscreen_blacklist_networks (empty)\fR"
/* Network addresses that are permanently blacklisted; see the
/* postscreen_blacklist_action parameter for possible actions.
-/* .IP "\fBpostscreen_disable_vrfy_command ($disable_vrfy_command)\fR"
-/* Disable the SMTP VRFY command in the \fBpostscreen\fR(8) daemon.
/* .IP "\fBpostscreen_dnsbl_action (ignore)\fR"
/* The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
/* DNSBL score is equal to or greater than a threshold (as defined
/* The inclusive lower bound for blocking an SMTP client, based on
/* its combined DNSBL score as defined with the postscreen_dnsbl_sites
/* parameter.
-/* .IP "\fBpostscreen_forbidden_commands ($smtpd_forbidden_commands)\fR"
-/* List of commands that the \fBpostscreen\fR(8) server considers in
-/* violation of the SMTP protocol.
/* .IP "\fBpostscreen_greet_action (ignore)\fR"
/* The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
/* before its turn within the time specified with the postscreen_greet_wait
/* client to send a command before its turn, and for DNS blocklist
/* lookup results to arrive (default: up to 2 seconds under stress,
/* up to 6 seconds otherwise).
+/* AFTER-GREETING TRIAGE
+/* .ad
+/* .fi
+/* .IP "\fBpostscreen_bare_newline_action (ignore)\fR"
+/* The action that \fBpostscreen\fR(8) takes when an SMTP client sends
+/* a bare newline character, that is, a newline not preceded by carriage
+/* return.
+/* .IP "\fBpostscreen_bare_newline_enable (no)\fR"
+/* Enable "bare newline" SMTP protocol tests in the \fBpostscreen\fR(8)
+/* server.
+/* .IP "\fBpostscreen_disable_vrfy_command ($disable_vrfy_command)\fR"
+/* Disable the SMTP VRFY command in the \fBpostscreen\fR(8) daemon.
+/* .IP "\fBpostscreen_forbidden_commands ($smtpd_forbidden_commands)\fR"
+/* List of commands that the \fBpostscreen\fR(8) server considers in
+/* violation of the SMTP protocol.
/* .IP "\fBpostscreen_helo_required ($smtpd_helo_required)\fR"
/* Require that a remote SMTP client sends HELO or EHLO before
/* commencing a MAIL transaction.
/* .IP "\fBpostscreen_pipelining_enable (no)\fR"
/* Enable "pipelining" SMTP protocol tests in the \fBpostscreen\fR(8)
/* server.
-/* .IP "\fBpostscreen_whitelist_networks ($mynetworks)\fR"
-/* Network addresses that are permanently whitelisted, and that
-/* will not be subjected to \fBpostscreen\fR(8) checks.
+/* AFTER-TRIAGE CONTROLS
+/* .ad
+/* .fi
/* .IP "\fBsmtpd_service_name (smtpd)\fR"
/* The internal service that \fBpostscreen\fR(8) forwards allowed
/* connections to.
int var_psc_pre_queue_limit;
int var_psc_watchdog;
+#define MIGRATION_WARNING
+
+#ifdef MIGRATION_WARNING
char *var_psc_wlist_nets;
char *var_psc_blist_nets;
+
+#endif
+char *var_psc_acl;
char *var_psc_blist_action;
char *var_psc_greet_ttl;
/*
* Local variables.
*/
+#ifdef MIGRATION_WARNING
static ADDR_MATCH_LIST *psc_wlist_nets; /* permanently whitelisted networks */
static ADDR_MATCH_LIST *psc_blist_nets; /* permanently blacklisted networks */
+
+#endif
+static ARGV *psc_acl; /* permanent white/backlist */
static int psc_blist_action; /* PSC_ACT_DROP/ENFORCE/etc */
/* psc_dump - dump some statistics before exit */
MAI_SERVPORT_STR smtp_client_port;
int aierr;
const char *stamp_str;
- int window_size;
int saved_flags;
/*
return;
}
+ /*
+ * The permanent white/blacklist has highest precedence.
+ */
+ if (psc_acl != 0) {
+ switch (psc_acl_eval(state, psc_acl, VAR_PSC_ACL)) {
+
+ /*
+ * Permanently blacklisted.
+ */
+ case PSC_ACL_ACT_BLACKLIST:
+ msg_info("BLACKLISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
+ switch (psc_blist_action) {
+ case PSC_ACT_DROP:
+ PSC_DROP_SESSION_STATE(state,
+ "521 5.3.2 Service currently unavailable\r\n");
+ return;
+ case PSC_ACT_ENFORCE:
+ PSC_ENFORCE_SESSION_STATE(state,
+ "550 5.3.2 Service currently unavailable\r\n");
+ break;
+ case PSC_ACT_IGNORE:
+ PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
+
+ /*
+ * Not: PSC_PASS_SESSION_STATE. Repeat this test the next
+ * time.
+ */
+ break;
+ default:
+ msg_panic("%s: unknown blacklist action value %d",
+ myname, psc_blist_action);
+ }
+ break;
+
+ /*
+ * Permanently whitelisted.
+ */
+ case PSC_ACL_ACT_WHITELIST:
+ msg_info("WHITELISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
+ psc_conclude(state);
+ return;
+
+ /*
+ * Other: dunno (don't know) or error.
+ */
+ default:
+ break;
+ }
+ }
+#ifdef MIGRATION_WARNING
+
/*
* The permanent whitelist has highest precedence (never block mail from
* whitelisted sites, and never run tests against those sites).
myname, psc_blist_action);
}
}
+#endif
/*
* The temporary whitelist (i.e. the postscreen cache) has the lowest
return;
}
- /*
- * Before commencing the tests we could set the TCP window to the
- * smallest possible value to save some network bandwidth, at least with
- * spamware that waits until the server starts speaking.
- */
-#if 0
- window_size = 1;
- if (setsockopt(vstream_fileno(smtp_client_stream), SOL_SOCKET, SO_RCVBUF,
- (char *) &window_size, sizeof(window_size)) < 0)
- msg_warn("setsockopt SO_RCVBUF %d: %m", window_size);
-#endif
-
/*
* If the client has no up-to-date results for some tests, do those tests
* first. Otherwise, skip the tests and hand off the connection.
* Open read-only maps before dropping privilege, for consistency with
* other Postfix daemons.
*/
+#ifdef MIGRATION_WARNING
if (*var_psc_wlist_nets)
psc_wlist_nets =
addr_match_list_init(MATCH_FLAG_NONE, var_psc_wlist_nets);
if (*var_psc_blist_nets)
psc_blist_nets = addr_match_list_init(MATCH_FLAG_NONE,
var_psc_blist_nets);
+ if (psc_blist_nets || psc_wlist_nets) {
+ msg_warn("The %s and %s features will be removed soon. Use %s instead",
+ VAR_PSC_WLIST_NETS, VAR_PSC_BLIST_NETS, VAR_PSC_ACL);
+ msg_warn("To stop this warning, specify empty values for %s and %s",
+ VAR_PSC_WLIST_NETS, VAR_PSC_BLIST_NETS);
+ }
+#endif
+ psc_acl_pre_jail_init();
+ if (*var_psc_acl)
+ psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
if (*var_psc_forbid_cmds)
psc_forbid_cmds = string_list_init(MATCH_FLAG_NONE,
var_psc_forbid_cmds);
VAR_PSC_PIPEL_ACTION, DEF_PSC_PIPEL_ACTION, &var_psc_pipel_action, 1, 0,
VAR_PSC_NSMTP_ACTION, DEF_PSC_NSMTP_ACTION, &var_psc_nsmtp_action, 1, 0,
VAR_PSC_BARLF_ACTION, DEF_PSC_BARLF_ACTION, &var_psc_barlf_action, 1, 0,
+#ifdef MIGRATION_WARNING
VAR_PSC_WLIST_NETS, DEF_PSC_WLIST_NETS, &var_psc_wlist_nets, 0, 0,
VAR_PSC_BLIST_NETS, DEF_PSC_BLIST_NETS, &var_psc_blist_nets, 0, 0,
+#endif
+ VAR_PSC_ACL, DEF_PSC_ACL, &var_psc_acl, 0, 0,
VAR_PSC_BLIST_ACTION, DEF_PSC_BLIST_ACTION, &var_psc_blist_action, 1, 0,
VAR_PSC_FORBID_CMDS, DEF_PSC_FORBID_CMDS, &var_psc_forbid_cmds, 0, 0,
VAR_PSC_EHLO_DIS_WORDS, DEF_PSC_EHLO_DIS_WORDS, &var_psc_ehlo_dis_words, 0, 0,
extern void psc_expand_init(void);
extern const char *psc_expand_lookup(const char *, int, char *);
+ /*
+ * postscreen_access.c
+ */
+#define PSC_ACL_ACT_WHITELIST 1
+#define PSC_ACL_ACT_DUNNO 0
+#define PSC_ACL_ACT_BLACKLIST (-1)
+#define PSC_ACL_ACT_ERROR (-2)
+
+extern void psc_acl_pre_jail_init(void);
+extern ARGV *psc_acl_parse(const char *, const char *);
+extern int psc_acl_eval(PSC_STATE *,ARGV *, const char *);
+
/* LICENSE
/* .ad
/* .fi
--- /dev/null
+/*++
+/* NAME
+/* postscreen_access 3
+/* SUMMARY
+/* postscreen access list support
+/* SYNOPSIS
+/* #include <postscreen.h>
+/*
+/* void psc_acl_pre_jail_init()
+/*
+/* ARGV *psc_acl_parse(raw_acl, origin)
+/* const char *raw_acl;
+/* const char *origin;
+/*
+/* int psc_acl_eval(state, cooked_acl, origin)
+/* PSC_STATE *state;
+/* ARGV *cooked_acl;
+/* const char *origin;
+/* DESCRIPTION
+/* This module implements the permanent black/whitelist that
+/* is evaluated immediately after a client connects to postscreen.
+/*
+/* psc_acl_pre_jail_init() does before-chroot initialization.
+/*
+/* psc_acl_parse() converts an access list from raw string
+/* form to binary form.
+/*
+/* psc_acl_eval() evaluates an access list for the specified
+/* SMTP session.
+/*
+/* Arguments:
+/* .IP raw_acl
+/* String with space/comma separated commands.
+/* .IP cooked_acl
+/* The parsed access list.
+/* .IP origin
+/* This should be "postscreen_access_list" for an access list
+/* from main.cf, and the type:name of a lookup table otherwise.
+/* The information is used for error reporting (nested table,
+/* unknown keyword).
+/* .IP state
+/* Connection state.
+/* 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
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <addr_match_list.h>
+#include <match_parent_style.h>
+
+/* Application-specific. */
+
+#include <postscreen.h>
+
+#define PSC_ACL_SEPARATORS " \t\r"
+
+static ADDR_MATCH_LIST *psc_mynetworks;
+
+/* psc_acl_pre_jail_init - initialize */
+
+void psc_acl_pre_jail_init(void)
+{
+ if (psc_mynetworks)
+ addr_match_list_free(psc_mynetworks);
+ psc_mynetworks = addr_match_list_init(match_parent_style(VAR_MYNETWORKS),
+ var_mynetworks);
+}
+
+/* psc_acl_parse - parse access list */
+
+ARGV *psc_acl_parse(const char *acl, const char *origin)
+{
+ char *saved_checks = mystrdup(acl);
+ ARGV *argv = argv_alloc(1);
+ char *bp = saved_checks;
+ char *name;
+
+#define STREQ(x,y) ((*x) == (*y) && strcasecmp((x), (y)) == 0)
+#define STRNE(x,y) ((*x) != (*y) || strcasecmp((x), (y)) != 0)
+
+ /*
+ * Nested tables are not allowed. Tables are opened before entering the
+ * chroot jail, while access lists are evaluated after entering the
+ * chroot jail.
+ */
+ while ((name = mystrtok(&bp, PSC_ACL_SEPARATORS)) != 0) {
+ if (strchr(name, ':') != 0) {
+ if (STRNE(origin, VAR_PSC_ACL)) {
+ msg_warn("table %s: lookup result \"%s\" is not allowed"
+ " -- ignoring remainder of access list",
+ origin, name);
+ argv_add(argv, PSC_ACL_NAME_DUNNO, (char *) 0);
+ break;
+ } else {
+ if (dict_handle(name) == 0)
+ dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK
+ | DICT_FLAG_FOLD_FIX));
+ }
+ }
+ argv_add(argv, name, (char *) 0);
+ }
+ argv_terminate(argv);
+
+ /*
+ * Cleanup.
+ */
+ myfree(saved_checks);
+ return (argv);
+}
+
+/* psc_acl_eval - evaluate access list */
+
+int psc_acl_eval(PSC_STATE *state, ARGV *acl, const char *origin)
+{
+ const char *myname = "psc_acl_eval";
+ char **cpp;
+ DICT *dict;
+ ARGV *argv;
+ const char *name;
+ const char *dict_val;
+ int ret;
+
+ for (cpp = acl->argv; (name = *cpp) != 0; cpp++) {
+ if (msg_verbose)
+ msg_info("source=%s address=%s acl=%s",
+ origin, state->smtp_client_addr, name);
+ if (STREQ(name, PSC_ACL_NAME_BLACKLIST)) {
+ return (PSC_ACL_ACT_BLACKLIST);
+ } else if (STREQ(name, PSC_ACL_NAME_WHITELIST)) {
+ return (PSC_ACL_ACT_WHITELIST);
+ } else if (STREQ(name, PSC_ACL_NAME_WL_MYNETWORKS)) {
+ if (addr_match_list_match(psc_mynetworks, state->smtp_client_addr))
+ return (PSC_ACL_ACT_WHITELIST);
+ } else if (strchr(name, ':') != 0) {
+ if ((dict = dict_handle(name)) == 0)
+ msg_panic("%s: unexpected dictionary: %s", myname, name);
+ if ((dict_val = dict_get(dict, state->smtp_client_addr)) != 0) {
+ argv = psc_acl_parse(dict_val, name);
+ ret = psc_acl_eval(state, argv, name);
+ argv_free(argv);
+ if (ret != PSC_ACL_ACT_DUNNO)
+ return (ret);
+ } else if (dict_errno != 0) {
+ msg_warn("%s: table lookup error -- ignoring the remainder "
+ "of this access list", name);
+ return (PSC_ACL_ACT_ERROR);
+ }
+ } else {
+ msg_warn("%s: unknown command: %s -- ignoring the remainder "
+ "of this access list", origin, name);
+ return (PSC_ACL_ACT_ERROR);
+ }
+ }
+ if (msg_verbose)
+ msg_info("source=%s address=%s - no match",
+ origin, state->smtp_client_addr);
+ return (PSC_ACL_ACT_DUNNO);
+}
+
+ /*
+ * Access lists need testing. Not only with good inputs; error cases must
+ * also be handled appropriately.
+ */
+#ifdef TEST
+#include <unistd.h>
+#include <stdlib.h>
+#include <vstring_vstream.h>
+#include <name_code.h>
+#include <split_at.h>
+
+char *var_par_dom_match = DEF_PAR_DOM_MATCH;
+char *var_mynetworks = "";
+char *var_psc_acl = "";
+
+#define UPDATE_VAR(s,v) do { if (*(s)) myfree(s); (s) = mystrdup(v); } while (0)
+
+int main(void)
+{
+ VSTRING *buf = vstring_alloc(100);
+ PSC_STATE state;
+ ARGV *argv;
+ int ret;
+ int have_tty = isatty(0);
+ char *bufp;
+ char *cmd;
+ char *value;
+ const NAME_CODE acl_map[] = {
+ PSC_ACL_NAME_ERROR, PSC_ACL_ACT_ERROR,
+ PSC_ACL_NAME_WHITELIST, PSC_ACL_ACT_WHITELIST,
+ PSC_ACL_NAME_BLACKLIST, PSC_ACL_ACT_BLACKLIST,
+ PSC_ACL_NAME_DUNNO, PSC_ACL_ACT_DUNNO,
+ 0,
+ };
+
+ while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
+ bufp = STR(buf);
+ if (have_tty == 0) {
+ vstream_printf("> %s\n", bufp);
+ vstream_fflush(VSTREAM_OUT);
+ }
+ if (*bufp == '#')
+ continue;
+ if ((cmd = mystrtok(&bufp, " =")) == 0 || STREQ(cmd, "?")) {
+ vstream_printf("usage: %s=value|%s=value|address=value\n",
+ VAR_MYNETWORKS, VAR_PSC_ACL);
+ } else if ((value = mystrtok(&bufp, " =")) == 0) {
+ vstream_printf("missing value\n");
+ } else if (STREQ(cmd, VAR_MYNETWORKS)) {
+ UPDATE_VAR(var_mynetworks, value);
+ } else if (STREQ(cmd, VAR_PSC_ACL)) {
+ UPDATE_VAR(var_psc_acl, value);
+ } else if (STREQ(cmd, "address")) {
+ psc_acl_pre_jail_init();
+ argv = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
+ state.smtp_client_addr = value;
+ ret = psc_acl_eval(&state, argv, VAR_PSC_ACL);
+ argv_free(argv);
+ vstream_printf("%s: %s\n", value, str_name_code(acl_map, ret));
+ } else {
+ vstream_printf("unknown command: \"%s\"\n", cmd);
+ }
+ vstream_fflush(VSTREAM_OUT);
+ }
+ vstring_free(buf);
+ exit(0);
+}
+
+#endif
vstring_strcat(state->send_buf, text);
if (*var_psc_rej_footer && (*text == '4' || *text == '5'))
smtp_reply_footer(state->send_buf, start, var_psc_rej_footer,
- STR(psc_expand_filter), psc_expand_lookup,
- (char *) state);
+ STR(psc_expand_filter), psc_expand_lookup,
+ (char *) state);
/*
* XXX For soft_bounce support, it is not sufficient to fix replies here.
{
const char *myname = "psc_send_socket";
int server_fd;
- int window_size;
if (msg_verbose > 1)
msg_info("%s: sq=%d cq=%d send socket %d from [%s]:%s",
vstream_fileno(state->smtp_client_stream),
state->smtp_client_addr, state->smtp_client_port);
- /*
- * This is where we would adjust the window size to a value that is
- * appropriate for this client class.
- */
-#if 0
- window_size = 65535;
- if (setsockopt(vstream_fileno(state->smtp_client_stream), SOL_SOCKET, SO_RCVBUF,
- (char *) &window_size, sizeof(window_size)) < 0)
- msg_warn("setsockopt SO_RCVBUF %d: %m", window_size);
-#endif
-
/*
* Connect to the real SMTP service over a local IPC channel, send the
* file descriptor, and close the file descriptor to save resources.
* Postfix-specific.
*/
if ((server_fd =
- PASS_CONNECT(psc_smtpd_service_name, NON_BLOCKING,
- PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) {
+ PASS_CONNECT(psc_smtpd_service_name, NON_BLOCKING,
+ PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) {
msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name);
PSC_SEND_REPLY(state, "421 4.3.2 All server ports are busy\r\n");
psc_free_session_state(state);
#define PSC_SMTPD_NEXT_CHAR(state) \
VSTREAM_GETC((state)->smtp_client_stream)
+#define PSC_SMTPD_BUFFER_EMPTY(state) \
+ (!PSC_SMTPD_HAVE_PUSH_BACK(state) \
+ && vstream_peek(state->smtp_client_stream) <= 0)
+
/*
* Dynamic reply strings. To minimize overhead we format these once.
*/
* Reset SMTP server state if STARTTLS was successful.
*/
if (state->flags & PSC_STATE_FLAG_USING_TLS) {
+ /* Purge the push-back buffer, when implemented. */
PSC_STRING_RESET(state->helo_name);
PSC_STRING_RESET(state->sender);
#ifdef TODO_SASL_AUTH
}
/*
- * Wait for the client to respond.
+ * Resume read/timeout events. If we still have unread input, resume the
+ * command processor immediately.
*/
PSC_RESUME_SMTP_CMD_EVENTS(state);
+ if (!PSC_SMTPD_BUFFER_EMPTY(state))
+ psc_smtpd_read_event(EVENT_READ, (char *) state);
}
/* psc_starttls_cmd - activate the tlsproxy server */
#define PSC_SMTPD_CMD_FLAG_ENABLE (1<<0) /* command is enabled */
#define PSC_SMTPD_CMD_FLAG_DESTROY (1<<1) /* dangling pointer alert */
#define PSC_SMTPD_CMD_FLAG_PRE_TLS (1<<2) /* allowed with mandatory TLS */
+#define PSC_SMTPD_CMD_FLAG_SUSPEND (1<<3) /* suspend command engine */
static const PSC_SMTPD_COMMAND command_table[] = {
"HELO", psc_helo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
"EHLO", psc_ehlo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
- "STARTTLS", psc_starttls_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
+ "STARTTLS", psc_starttls_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS | PSC_SMTPD_CMD_FLAG_SUSPEND,
"XCLIENT", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
"XFORWARD", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
"AUTH", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
* was called. Also, yielding the pseudo thread will improve fairness for
* other pseudo threads.
*/
-#define PSC_SMTPD_BUFFER_EMPTY(state) \
- (!PSC_SMTPD_HAVE_PUSH_BACK(state) \
- && vstream_peek(state->smtp_client_stream) <= 0)
/*
* Note: on entry into this function the VSTREAM buffer is still empty,
return;
}
+ /*
+ * We're suspended, waiting for some external event to happen.
+ * Hopefully, someone will call us back to process the remainder of
+ * the pending input, otherwise we could hang.
+ */
+ if (cmdp->flags & PSC_SMTPD_CMD_FLAG_SUSPEND)
+ return;
+
/*
* Reset the command read timeout before reading the next command.
*/
mask_addr.o: sys_defs.h
match_list.o: argv.h
match_list.o: dict.h
+match_list.o: htable.h
match_list.o: match_list.c
match_list.o: match_list.h
match_list.o: match_ops.h
match_ops.o: argv.h
match_ops.o: cidr_match.h
match_ops.o: dict.h
+match_ops.o: htable.h
+match_ops.o: match_list.h
match_ops.o: match_ops.c
match_ops.o: match_ops.h
match_ops.o: msg.h
*/
if (pipe(pair) < 0)
msg_fatal("%s: pipe: %m", myname);
+ close_on_exec(pair[0], CLOSE_ON_EXEC);
+ close_on_exec(pair[1], CLOSE_ON_EXEC);
if (unix_send_fd(fd, pair[0]) < 0)
msg_fatal("%s: send file descriptor: %m", myname);