From: Wietse Venema Date: Wed, 12 Jan 2011 05:00:00 +0000 (-0500) Subject: postfix-2.8-20110112 X-Git-Tag: v2.8.0-RC1~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da8c6ed0790c8991efe88d317edb9413f508ff67;p=thirdparty%2Fpostfix.git postfix-2.8-20110112 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index cad0567ef..43f0b42b7 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -16418,11 +16418,26 @@ Apologies for any names omitted. 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. diff --git a/postfix/README_FILES/POSTSCREEN_README b/postfix/README_FILES/POSTSCREEN_README index 428d5d6a0..6badf305a 100644 --- a/postfix/README_FILES/POSTSCREEN_README +++ b/postfix/README_FILES/POSTSCREEN_README @@ -106,28 +106,40 @@ QQuuiicckk tteessttss bbeeffoorree eevveerryytthhiinng 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 -PPeerrmmaanneenntt wwhhiitteelliisstt tteesstt +PPeerrmmaanneenntt wwhhiittee//bbllaacckklliisstt tteesstt -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. - WWHHIITTEELLIISSTTEEDD [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 -PPeerrmmaanneenntt bbllaacckklliisstt tteesstt +/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: + + WWHHIITTEELLIISSTTEEDD [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: BBLLAACCKKLLIISSTTEEDD [address]:port @@ -165,7 +177,7 @@ continue as if postscreen(8) never even existed (except of course 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 PPrreeggrreeeett tteesstt @@ -183,11 +195,16 @@ effect on 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 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). @@ -207,12 +224,12 @@ return and \n for newline). The postscreen_greet_action parameter specifies the action that is taken next. See "When tests fail before the 220 SMTP server greeting" below. -DDNNSS BBlloocckklliisstt tteesstt +DDNNSS WWhhiittee//bbllaacckklliisstt tteesstt 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" @@ -574,9 +591,8 @@ more of: 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. TTuurrnniinngg ooffff ppoossttssccrreeeenn((88)) diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 79f4421c6..5ea4c491f 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -34,6 +34,16 @@ is the $name of an smtpd_xxx parameter with a stress-dependent 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 ==================================== diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 39f17a30e..b6ef68996 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -4,26 +4,13 @@ Wish list: 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_ diff --git a/postfix/html/POSTSCREEN_README.html b/postfix/html/POSTSCREEN_README.html index d16b5afbd..784d12b56 100644 --- a/postfix/html/POSTSCREEN_README.html +++ b/postfix/html/POSTSCREEN_README.html @@ -146,35 +146,50 @@ handling of known clients.

-

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_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 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);