From: Wietse Venema
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.
-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:
+Example:
+ ++/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 ++ +
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: +
WHITELISTED [address]:port
-The action is not configurable: immediately hand off the +
The whitelist action is not configurable: immediately hand off the connection to a Postfix SMTP server process.
-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:
+When the SMTP client address matches a "reject" action, +postscreen(8) logs this with the client address and port number as: +
BLACKLISTED [address]:port
@@ -224,7 +239,7 @@ for the short postscreen_greet_w
Pregreet test
- DNS Blocklist test
+ DNS White/blacklist test
When tests fail before the 220 SMTP server greeting
@@ -247,13 +262,18 @@ SMTP clients that correctly implement the protocol.
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:
/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
@@ -281,12 +301,13 @@ and \n for newline).
is taken next. See "When tests fail
before the 220 SMTP server greeting" below.
- DNS Blocklist test
+ DNS White/blacklist test
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.
+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.
@@ -799,9 +820,9 @@ reply; these clients were not so good 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.
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 817fbe3da..d9d88afb3 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -6618,6 +6618,67 @@ and enabled instances are processed in reverse order.
This feature is available in Postfix 2.6 and later.
+
+
+postscreen_access_list
+(default: permit_mynetworks)
+
+ 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.
+
+
+
+- permit_mynetworks
- 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.
+
+
+- type:table
- 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.
+To discourage the use of hash, btree, etc. tables, there is no
+support for substring matching like smtpd(8). Use CIDR tables
+instead.
+
+- permit
- 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.
+
+- reject
- Blacklist the client and terminate
+the search. Subject the client to the action configured with the
+postscreen_blacklist_action configuration parameter.
+
+- dunno
- When used inside a lookup table,
+return from the lookup table and evaluate the next command.
+When used outside a lookup table, terminate the search, and subject
+the client to the configured before/after 220 greeting tests.
+
+
+
+ Example:
+
+
+/etc/postfix/main.cf:
+ postscreen_access_list = permit_mynetworks,
+ cidr:/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 dunno
+ 192.168.0.0/16 reject
+
+
+ This feature is available in Postfix 2.8.
+
+
postscreen_bare_newline_action
@@ -6718,20 +6779,6 @@ this test the next time the client connects.
This feature is available in Postfix 2.8.
-
-
-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.
-
- This feature is available in Postfix 2.8.
-
-
postscreen_cache_cleanup_interval
@@ -7381,19 +7428,6 @@ one-letter suffix that specifies the time unit). Time units: s
This feature is available in Postfix 2.8.
-
-
-postscreen_whitelist_networks
-(default: $mynetworks)
-
- 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.
-
- This feature is available in Postfix 2.8.
-
-
prepend_delivered_header
diff --git a/postfix/html/postscreen.8.html b/postfix/html/postscreen.8.html
index 89411a593..6775e8f4e 100644
--- a/postfix/html/postscreen.8.html
+++ b/postfix/html/postscreen.8.html
@@ -130,30 +130,22 @@ POSTSCREEN(8) POSTSCREEN(8)
server will not send in the EHLO response to a
remote SMTP client.
-TRIAGE PARAMETERS
- postscreen_bare_newline_action (ignore)
- The action that postscreen(8) takes when an SMTP
- client sends a bare newline character, that is, a
- newline not preceded by carriage return.
-
- postscreen_bare_newline_enable (no)
- Enable "bare newline" SMTP protocol tests in the
- postscreen(8) server.
+BEFORE-GREETING TRIAGE
+ postscreen_access_list (permit_mynetworks)
+ Permanent white/blacklist for remote SMTP client IP
+ addresses; postscreen(8) searches this list immedi-
+ ately after a remote SMTP client connects.
postscreen_blacklist_action (ignore)
- The action that postscreen(8) takes when an SMTP
- client is permanently blacklisted with the
+ The action that postscreen(8) takes when an SMTP
+ client is permanently blacklisted with the
postscreen_blacklist_networks parameter.
postscreen_blacklist_networks (empty)
Network addresses that are permanently blacklisted;
- see the postscreen_blacklist_action parameter for
+ see the postscreen_blacklist_action parameter for
possible actions.
- postscreen_disable_vrfy_command ($disable_vrfy_command)
- Disable the SMTP VRFY command in the postscreen(8)
- daemon.
-
postscreen_dnsbl_action (ignore)
The action that postscreen(8) takes when an SMTP
client's combined DNSBL score is equal to or
@@ -176,12 +168,8 @@ POSTSCREEN(8) POSTSCREEN(8)
client, based on its combined DNSBL score as
defined with the postscreen_dnsbl_sites parameter.
- postscreen_forbidden_commands ($smtpd_forbidden_commands)
- List of commands that the postscreen(8) server con-
- siders in violation of the SMTP protocol.
-
postscreen_greet_action (ignore)
- The action that postscreen(8) takes when an SMTP
+ The action that postscreen(8) takes when an SMTP
client speaks before its turn within the time spec-
ified with the postscreen_greet_wait parameter.
@@ -189,16 +177,34 @@ POSTSCREEN(8) POSTSCREEN(8)
The text in the optional "220-text..." server
response that postscreen(8) sends ahead of the real
Postfix SMTP server's "220 text..." response, in an
- attempt to confuse bad SMTP clients so that they
+ attempt to confuse bad SMTP clients so that they
speak before their turn (pre-greet).
postscreen_greet_wait (${stress?2}${stress:6}s)
The amount of time that postscreen(8) will wait for
- an SMTP client to send a command before its turn,
- and for DNS blocklist lookup results to arrive
- (default: up to 2 seconds under stress, up to 6
+ an SMTP client to send a command before its turn,
+ and for DNS blocklist lookup results to arrive
+ (default: up to 2 seconds under stress, up to 6
seconds otherwise).
+AFTER-GREETING TRIAGE
+ postscreen_bare_newline_action (ignore)
+ The action that postscreen(8) takes when an SMTP
+ client sends a bare newline character, that is, a
+ newline not preceded by carriage return.
+
+ postscreen_bare_newline_enable (no)
+ Enable "bare newline" SMTP protocol tests in the
+ postscreen(8) server.
+
+ postscreen_disable_vrfy_command ($disable_vrfy_command)
+ Disable the SMTP VRFY command in the postscreen(8)
+ daemon.
+
+ postscreen_forbidden_commands ($smtpd_forbidden_commands)
+ List of commands that the postscreen(8) server con-
+ siders in violation of the SMTP protocol.
+
postscreen_helo_required ($smtpd_helo_required)
Require that a remote SMTP client sends HELO or
EHLO before commencing a MAIL transaction.
@@ -221,11 +227,7 @@ POSTSCREEN(8) POSTSCREEN(8)
Enable "pipelining" SMTP protocol tests in the
postscreen(8) server.
- postscreen_whitelist_networks ($mynetworks)
- Network addresses that are permanently whitelisted,
- and that will not be subjected to postscreen(8)
- checks.
-
+AFTER-TRIAGE CONTROLS
smtpd_service_name (smtpd)
The internal service that postscreen(8) forwards
allowed connections to.
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 9fcc06c53..d82229a3c 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -3723,6 +3723,66 @@ as "stop" commands. For these commands, disabled instances are skipped,
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
@@ -3778,14 +3838,6 @@ Drop the connection immediately with a 521 SMTP reply. Repeat
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
@@ -4192,13 +4244,6 @@ one-letter suffix that specifies the time unit). Time units: s
(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
diff --git a/postfix/man/man8/postscreen.8 b/postfix/man/man8/postscreen.8
index fbb0b7f8e..8888237b6 100644
--- a/postfix/man/man8/postscreen.8
+++ b/postfix/man/man8/postscreen.8
@@ -135,18 +135,15 @@ to a remote SMTP client.
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
@@ -154,8 +151,6 @@ parameter.
.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
@@ -172,9 +167,6 @@ factors.
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
@@ -190,6 +182,23 @@ The amount of time that \fBpostscreen\fR(8) will wait for an SMTP
client to send a command before its turn, and for DNS blocklist
lookup results to arrive (default: up to 2 seconds under stress,
up to 6 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.
@@ -206,9 +215,11 @@ the server to respond.
.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.
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index 96269579a..10f2376b9 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -945,6 +945,7 @@ while (<>) {
s;\bpostscreen_pipelining_action\b;$&;g;
s;\bpostscreen_pipelining_ttl\b;$&;g;
s;\bpostscreen_watchdog_timeout\b;$&;g;
+ s;\bpostscreen_access_list\b;$&;g;
s;\bpostscreen_whitelist_networks\b;$&;g;
s;\bpostscreen_black[-]*\n*[ ]*list_networks\b;$&;g;
s;\bpostscreen_black[- ]*\n*[ ]*list_action\b;$&;g;
diff --git a/postfix/proto/POSTSCREEN_README.html b/postfix/proto/POSTSCREEN_README.html
index 503aec71a..9231bef79 100644
--- a/postfix/proto/POSTSCREEN_README.html
+++ b/postfix/proto/POSTSCREEN_README.html
@@ -146,35 +146,50 @@ handling of known clients.
-- Permanent whitelist test
-
-
- Permanent blacklist test
+
- Permanent white/blacklist test
- Temporary whitelist test
- Permanent whitelist test
+ Permanent white/blacklist test
+
+ 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.
- 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:
+ Example:
+
+
+/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
+
+
+ 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:
+
WHITELISTED [address]:port
- The action is not configurable: immediately hand off the
+
The whitelist action is not configurable: immediately hand off the
connection to a Postfix SMTP server process.
- Permanent blacklist test
-
- 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:
+ When the SMTP client address matches a "reject" action,
+postscreen(8) logs this with the client address and port number as:
+
BLACKLISTED [address]:port
@@ -224,7 +239,7 @@ for the short postscreen_greet_wait delay).
Pregreet test
- DNS Blocklist test
+ DNS White/blacklist test
When tests fail before the 220 SMTP server greeting
@@ -247,13 +262,18 @@ SMTP clients that correctly implement the protocol.
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:
/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
@@ -281,12 +301,13 @@ and \n for newline).
is taken next. See "When tests fail
before the 220 SMTP server greeting" below.
- DNS Blocklist test
+ DNS White/blacklist test
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.
+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.
@@ -799,9 +820,9 @@ reply; these clients were not so good 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.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 2885e9807..c48412f07 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -12810,23 +12810,80 @@ IP address.
This feature is available in Postfix 2.8.
-%PARAM postscreen_whitelist_networks $mynetworks
+#%PARAM postscreen_whitelist_networks $mynetworks
+#
+# 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.
+#
+# This feature is available in Postfix 2.8.
+#
+#%PARAM postscreen_blacklist_networks
+#
+# 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.
+#
+# This feature is available in Postfix 2.8.
- 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.
+%PARAM postscreen_access_list permit_mynetworks
- This feature is available in Postfix 2.8.
+ 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.
+
+
+
+- permit_mynetworks
- 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.
+
+
+- type:table
- 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.
+To discourage the use of hash, btree, etc. tables, there is no
+support for substring matching like smtpd(8). Use CIDR tables
+instead.
+
+- permit
- 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.
-%PARAM postscreen_blacklist_networks
+- reject
- Blacklist the client and terminate
+the search. Subject the client to the action configured with the
+postscreen_blacklist_action configuration parameter.
- 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.
+- dunno
- When used inside a lookup table,
+return from the lookup table and evaluate the next command.
+When used outside a lookup table, terminate the search, and subject
+the client to the configured before/after 220 greeting tests.
+
+
+ Example:
+
+
+/etc/postfix/main.cf:
+ postscreen_access_list = permit_mynetworks,
+ cidr:/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 dunno
+ 192.168.0.0/16 reject
+
+
This feature is available in Postfix 2.8.
%PARAM postscreen_greet_banner $smtpd_banner
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index b430a0916..1a3511412 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -283,6 +283,9 @@ header_body_checks: header_body_checks.c $(LIB) $(LIBS)
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
diff --git a/postfix/src/global/addr_match_list.c b/postfix/src/global/addr_match_list.c
index a066c1072..7ba1166bb 100644
--- a/postfix/src/global/addr_match_list.c
+++ b/postfix/src/global/addr_match_list.c
@@ -78,7 +78,9 @@
#include
#include
#include
+#include
#include
+#include
#include
static void usage(char *progname)
@@ -89,7 +91,6 @@ static void usage(char *progname)
int main(int argc, char **argv)
{
ADDR_MATCH_LIST *list;
- char *host;
char *addr;
int ch;
@@ -108,9 +109,19 @@ int main(int argc, char **argv)
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);
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index fa01c5293..d7dda0048 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -3435,6 +3435,16 @@ extern char *var_psc_exp_filter;
#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;
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 989e78697..ac90cf17f 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20110109"
+#define MAIL_RELEASE_DATE "20110112"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
diff --git a/postfix/src/postscreen/Makefile.in b/postfix/src/postscreen/Makefile.in
index 013f0f7b4..2afc1da0c 100644
--- a/postfix/src/postscreen/Makefile.in
+++ b/postfix/src/postscreen/Makefile.in
@@ -2,16 +2,16 @@ SHELL = /bin/sh
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 \
@@ -38,6 +38,11 @@ update: ../../libexec/$(PROG)
../../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
@@ -93,6 +98,27 @@ postscreen.o: ../../include/vstream.h
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
diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c
index 2ba285c0e..3d4f30f48 100644
--- a/postfix/src/postscreen/postscreen.c
+++ b/postfix/src/postscreen/postscreen.c
@@ -117,16 +117,13 @@
/* 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
@@ -134,8 +131,6 @@
/* .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
@@ -152,9 +147,6 @@
/* 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
@@ -170,6 +162,21 @@
/* 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.
@@ -186,9 +193,9 @@
/* .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.
@@ -394,8 +401,14 @@ int var_psc_post_queue_limit;
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;
@@ -464,8 +477,12 @@ HTABLE *psc_client_concurrency; /* per-client concurrency */
/*
* 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 */
@@ -539,7 +556,6 @@ static void psc_service(VSTREAM *smtp_client_stream,
MAI_SERVPORT_STR smtp_client_port;
int aierr;
const char *stamp_str;
- int window_size;
int saved_flags;
/*
@@ -631,6 +647,58 @@ static void psc_service(VSTREAM *smtp_client_stream,
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).
@@ -669,6 +737,7 @@ static void psc_service(VSTREAM *smtp_client_stream,
myname, psc_blist_action);
}
}
+#endif
/*
* The temporary whitelist (i.e. the postscreen cache) has the lowest
@@ -712,18 +781,6 @@ static void psc_service(VSTREAM *smtp_client_stream,
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.
@@ -766,6 +823,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
* 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);
@@ -773,6 +831,16 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
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);
@@ -1002,8 +1070,11 @@ int main(int argc, char **argv)
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,
diff --git a/postfix/src/postscreen/postscreen.h b/postfix/src/postscreen/postscreen.h
index 74f35a30d..f141a0d36 100644
--- a/postfix/src/postscreen/postscreen.h
+++ b/postfix/src/postscreen/postscreen.h
@@ -459,6 +459,18 @@ extern VSTRING *psc_expand_filter;
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
diff --git a/postfix/src/postscreen/postscreen_access.c b/postfix/src/postscreen/postscreen_access.c
new file mode 100644
index 000000000..52a320872
--- /dev/null
+++ b/postfix/src/postscreen/postscreen_access.c
@@ -0,0 +1,252 @@
+/*++
+/* NAME
+/* postscreen_access 3
+/* SUMMARY
+/* postscreen access list support
+/* SYNOPSIS
+/* #include
+/*
+/* 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
+#include
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include
+#endif
+
+/* Utility library. */
+
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+#include
+
+/* Application-specific. */
+
+#include
+
+#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
+#include
+#include
+#include
+#include
+
+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
diff --git a/postfix/src/postscreen/postscreen_send.c b/postfix/src/postscreen/postscreen_send.c
index 355542707..9a99997fe 100644
--- a/postfix/src/postscreen/postscreen_send.c
+++ b/postfix/src/postscreen/postscreen_send.c
@@ -90,8 +90,8 @@ int psc_send_reply(PSC_STATE *state, const char *text)
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.
@@ -156,7 +156,6 @@ void psc_send_socket(PSC_STATE *state)
{
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",
@@ -164,17 +163,6 @@ void psc_send_socket(PSC_STATE *state)
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.
@@ -192,8 +180,8 @@ void psc_send_socket(PSC_STATE *state)
* 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);
diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c
index 377347eb8..e3cc92712 100644
--- a/postfix/src/postscreen/postscreen_smtpd.c
+++ b/postfix/src/postscreen/postscreen_smtpd.c
@@ -164,6 +164,10 @@
#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.
*/
@@ -357,6 +361,7 @@ static void psc_starttls_resume(int unused_event, char *context)
* 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
@@ -365,9 +370,12 @@ static void psc_starttls_resume(int unused_event, char *context)
}
/*
- * 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 */
@@ -620,11 +628,12 @@ typedef struct {
#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,
@@ -688,9 +697,6 @@ static void psc_smtpd_read_event(int event, char *context)
* 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,
@@ -983,6 +989,14 @@ static void psc_smtpd_read_event(int event, char *context)
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.
*/
diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in
index f72ddaec2..4455fbf20 100644
--- a/postfix/src/util/Makefile.in
+++ b/postfix/src/util/Makefile.in
@@ -1309,6 +1309,7 @@ mask_addr.o: msg.h
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
@@ -1323,6 +1324,8 @@ match_list.o: vstring_vstream.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
diff --git a/postfix/src/util/unix_pass_trigger.c b/postfix/src/util/unix_pass_trigger.c
index 5c0a9c8e3..612300924 100644
--- a/postfix/src/util/unix_pass_trigger.c
+++ b/postfix/src/util/unix_pass_trigger.c
@@ -118,6 +118,8 @@ int unix_pass_trigger(const char *service, const char *buf, ssize_t len, int
*/
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);