]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.11-20130512
authorWietse Venema <wietse@porcupine.org>
Sun, 12 May 2013 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 13 May 2013 00:52:49 +0000 (20:52 -0400)
16 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/postconf.5.html
postfix/html/postscreen.8.html
postfix/man/man5/postconf.5
postfix/man/man8/postscreen.8
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/postscreen/Makefile.in
postfix/src/postscreen/postscreen.c
postfix/src/postscreen/postscreen.h
postfix/src/postscreen/postscreen_early.c
postfix/src/postscreen/postscreen_state.c
postfix/src/postscreen/postscreen_tests.c

index e885287b7fe14378cd2e8041200c4c5c71242dd7..bc63c9114ee5d354239dd9918d4e9056d5fb6131 100644 (file)
@@ -18431,3 +18431,13 @@ Apologies for any names omitted.
        src/qmgr/qmgr_message.c, src/smtpd/smtpd.c,
        src/smtpd/smtpd_check.c, src/trivial-rewrite/transport.c,
        src/trivial-rewrite/trivial-rewrite.c.
+
+20130512
+
+       Feature: allow an SMTP client to skip postscreen(8) tests
+       before or after the 220 greeting, based on its DNSBL score.
+       Suggested by Rob McGee (/dev/rob0). Files: mantools/postlink,
+       proto/postconf.proto, global/mail_params.h,
+       postscreen/postscreen.c, postscreen/postscreen.h,
+       postscreen/postscreen_early.c, postscreen/postscreen_state.c,
+       postscreen/postscreen_tests.c.
index 593f1d7c3c6086da0cba65170096e7c69e4228a3..4ca9e12dcae81b9edad847a7be4c4a18bca9acac 100644 (file)
@@ -14,6 +14,17 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 2.9 or earlier, read RELEASE_NOTES-2.10
 before proceeding.
 
+Major changes with snapshot 20130512
+====================================
+
+Allow an SMTP client to skip postscreen(8) tests based on its
+postscreen_dnsbl_sites score. 
+
+Specify a negative "postscreen_dnsbl_whitelist_threshold" to enable
+this feature.  When a client passes the threshold value without
+having failed other tests, all pending or disabled tests are flagged
+as completed.
+
 Major changes with snapshot 20130405
 ====================================
 
index 09d0cf166c507108b69f8ebd4f8e3c9ab224b59f..426601d76414f6b4c94b6cdf5fcee45e5aa41c39 100644 (file)
@@ -7405,6 +7405,25 @@ one-letter suffix that specifies the time unit).  Time units: s
 <p> This feature is available in Postfix 2.8.  </p>
 
 
+</DD>
+
+<DT><b><a name="postscreen_dnsbl_whitelist_threshold">postscreen_dnsbl_whitelist_threshold</a>
+(default: 0)</b></DT><DD>
+
+<p> Allow a remote SMTP client to skip "before" and "after 220
+greeting" protocol tests, based on its combined DNSBL score as
+defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.  </p>
+
+<p> Specify a negative value to enable this feature. When a client
+passes the <a href="postconf.5.html#postscreen_dnsbl_whitelist_threshold">postscreen_dnsbl_whitelist_threshold</a> without having
+failed other tests, all pending or disabled tests are flagged as
+completed with a time-to-live value equal to <a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>.
+When a test was already completed, its time-to-live value is updated
+if it was less than <a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>. </p>
+
+<p> This feature is available in Postfix 2.11.  </p>
+
+
 </DD>
 
 <DT><b><a name="postscreen_enforce_tls">postscreen_enforce_tls</a>
index 12f9b02f11ed98ec2b65555c608cceb20cab6217..f746a465098ff9482f35c116268f656a9708f886 100644 (file)
@@ -245,25 +245,33 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
               The  internal  service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> hands off
               allowed connections to.
 
+       Available in Postfix version 2.11 and later:
+
+       <b><a href="postconf.5.html#postscreen_dnsbl_whitelist_threshold">postscreen_dnsbl_whitelist_threshold</a> (0)</b>
+              Allow a remote SMTP client  to  skip  "before"  and
+              "after  220  greeting" protocol tests, based on its
+              combined  DNSBL   score   as   defined   with   the
+              <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.
+
 <b>AFTER-GREETING TESTS</b>
-       These tests are executed  after  the  remote  SMTP  client
+       These  tests  are  executed  after  the remote SMTP client
        receives the "220 servername" greeting. If a client passes
-       all tests  during  this  phase,  it  will  receive  a  4XX
-       response  to  RCPT  TO commands until the client hangs up.
+       all  tests  during  this  phase,  it  will  receive  a 4XX
+       response to RCPT TO commands until the  client  hangs  up.
        After this, the client will be allowed to talk directly to
        a Postfix SMTP server process.
 
        <b><a href="postconf.5.html#postscreen_bare_newline_action">postscreen_bare_newline_action</a> (ignore)</b>
-              The  action  that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when a remote
-              SMTP client sends a bare  newline  character,  that
+              The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when  a  remote
+              SMTP  client  sends  a bare newline character, that
               is, a newline not preceded by carriage return.
 
        <b><a href="postconf.5.html#postscreen_bare_newline_enable">postscreen_bare_newline_enable</a> (no)</b>
-              Enable  "bare  newline"  SMTP protocol tests in the
+              Enable "bare newline" SMTP protocol  tests  in  the
               <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
 
        <b><a href="postconf.5.html#postscreen_disable_vrfy_command">postscreen_disable_vrfy_command</a> ($<a href="postconf.5.html#disable_vrfy_command">disable_vrfy_command</a>)</b>
-              Disable the SMTP VRFY command in the  <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+              Disable  the SMTP VRFY command in the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
               daemon.
 
        <b><a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> ($<a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a>)</b>
@@ -271,159 +279,159 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
               siders in violation of the SMTP protocol.
 
        <b><a href="postconf.5.html#postscreen_helo_required">postscreen_helo_required</a> ($<a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a>)</b>
-              Require that a remote SMTP  client  sends  HELO  or
+              Require  that  a  remote  SMTP client sends HELO or
               EHLO before commencing a MAIL transaction.
 
        <b><a href="postconf.5.html#postscreen_non_smtp_command_action">postscreen_non_smtp_command_action</a> (drop)</b>
-              The  action  that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when a remote
-              SMTP client sends non-SMTP  commands  as  specified
+              The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when  a  remote
+              SMTP  client  sends  non-SMTP commands as specified
               with the <a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> parameter.
 
        <b><a href="postconf.5.html#postscreen_non_smtp_command_enable">postscreen_non_smtp_command_enable</a> (no)</b>
-              Enable    "non-SMTP    command"    tests   in   the
+              Enable   "non-SMTP   command"    tests    in    the
               <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
 
        <b><a href="postconf.5.html#postscreen_pipelining_action">postscreen_pipelining_action</a> (enforce)</b>
-              The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when  a  remote
-              SMTP  client  sends  multiple  commands  instead of
-              sending one command and waiting for the  server  to
+              The  action  that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when a remote
+              SMTP client  sends  multiple  commands  instead  of
+              sending  one  command and waiting for the server to
               respond.
 
        <b><a href="postconf.5.html#postscreen_pipelining_enable">postscreen_pipelining_enable</a> (no)</b>
-              Enable  "pipelining"  SMTP  protocol  tests  in the
+              Enable "pipelining"  SMTP  protocol  tests  in  the
               <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server.
 
 <b>CACHE CONTROLS</b>
        <b><a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> (12h)</b>
-              The amount  of  time  between  <a href="postscreen.8.html"><b>postscreen</b>(8)</a>  cache
+              The  amount  of  time  between  <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
               cleanup runs.
 
        <b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a>                   (btree:$data_direc-</b>
        <b>tory/postscreen_cache)</b>
-              Persistent  storage  for  the  <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
+              Persistent storage  for  the  <a href="postscreen.8.html"><b>postscreen</b>(8)</a>  server
               decisions.
 
        <b><a href="postconf.5.html#postscreen_cache_retention_time">postscreen_cache_retention_time</a> (7d)</b>
               The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache an
-              expired  temporary  whitelist  entry  before  it is
+              expired temporary  whitelist  entry  before  it  is
               removed.
 
        <b><a href="postconf.5.html#postscreen_bare_newline_ttl">postscreen_bare_newline_ttl</a> (30d)</b>
-              The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use  the
+              The  amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
               result from a successful "bare newline" SMTP proto-
               col test.
 
        <b><a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a> (1h)</b>
-              The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use  the
+              The  amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
               result from a successful DNS blocklist test.
 
        <b><a href="postconf.5.html#postscreen_greet_ttl">postscreen_greet_ttl</a> (1d)</b>
-              The  amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
+              The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use  the
               result from a successful PREGREET test.
 
        <b><a href="postconf.5.html#postscreen_non_smtp_command_ttl">postscreen_non_smtp_command_ttl</a> (30d)</b>
-              The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use  the
-              result  from  a  successful "non_smtp_command" SMTP
+              The  amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
+              result from a  successful  "non_smtp_command"  SMTP
               protocol test.
 
        <b><a href="postconf.5.html#postscreen_pipelining_ttl">postscreen_pipelining_ttl</a> (30d)</b>
-              The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use  the
+              The  amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
               result from a successful "pipelining" SMTP protocol
               test.
 
 <b>RESOURCE CONTROLS</b>
        <b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
-              Upon input, long lines are chopped up  into  pieces
-              of  at  most this length; upon delivery, long lines
+              Upon  input,  long lines are chopped up into pieces
+              of at most this length; upon delivery,  long  lines
               are reconstructed.
 
        <b><a href="postconf.5.html#postscreen_client_connection_count_limit">postscreen_client_connection_count_limit</a></b>
        <b>($<a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a>)</b>
-              How many simultaneous connections any  remote  SMTP
-              client  is  allowed  to have with the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+              How  many  simultaneous connections any remote SMTP
+              client is allowed to have  with  the  <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
               daemon.
 
        <b><a href="postconf.5.html#postscreen_command_count_limit">postscreen_command_count_limit</a> (20)</b>
-              The limit on the total number of commands per  SMTP
-              session  for <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol
+              The  limit on the total number of commands per SMTP
+              session for <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP  protocol
               engine.
 
        <b><a href="postconf.5.html#postscreen_command_time_limit">postscreen_command_time_limit</a> (${stress?10}${stress:300}s)</b>
-              The time limit to read an entire command line  with
+              The  time limit to read an entire command line with
               <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol engine.
 
        <b><a href="postconf.5.html#postscreen_post_queue_limit">postscreen_post_queue_limit</a> ($<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
-              The  number of clients that can be waiting for ser-
+              The number of clients that can be waiting for  ser-
               vice from a real Postfix SMTP server process.
 
        <b><a href="postconf.5.html#postscreen_pre_queue_limit">postscreen_pre_queue_limit</a> ($<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
-              The number of non-whitelisted clients that  can  be
-              waiting  for  a  decision whether they will receive
+              The  number  of non-whitelisted clients that can be
+              waiting for a decision whether  they  will  receive
               service from a real Postfix SMTP server process.
 
        <b><a href="postconf.5.html#postscreen_watchdog_timeout">postscreen_watchdog_timeout</a> (10s)</b>
-              How much time a <a href="postscreen.8.html"><b>postscreen</b>(8)</a> process may  take  to
-              respond  to a remote SMTP client command or to per-
+              How  much  time a <a href="postscreen.8.html"><b>postscreen</b>(8)</a> process may take to
+              respond to a remote SMTP client command or to  per-
               form a cache operation before it is terminated by a
               built-in watchdog timer.
 
 <b>STARTTLS CONTROLS</b>
        <b><a href="postconf.5.html#postscreen_tls_security_level">postscreen_tls_security_level</a> ($<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b>
-              The  SMTP  TLS security level for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
-              server; when a non-empty value is  specified,  this
+              The SMTP TLS security level for  the  <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
+              server;  when  a non-empty value is specified, this
               overrides       the       obsolete       parameters
               <a href="postconf.5.html#postscreen_use_tls">postscreen_use_tls</a> and <a href="postconf.5.html#postscreen_enforce_tls">postscreen_enforce_tls</a>.
 
        <b><a href="postconf.5.html#tlsproxy_service_name">tlsproxy_service_name</a> (tlsproxy)</b>
-              The name of the <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> service entry  in  mas-
+              The  name  of the <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> service entry in mas-
               ter.cf.
 
 <b>OBSOLETE STARTTLS SUPPORT CONTROLS</b>
-       These  parameters  are  supported  for  compatibility with
+       These parameters  are  supported  for  compatibility  with
        <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy parameters.
 
        <b><a href="postconf.5.html#postscreen_use_tls">postscreen_use_tls</a> ($<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b>
-              Opportunistic TLS:  announce  STARTTLS  support  to
+              Opportunistic  TLS:  announce  STARTTLS  support to
               remote  SMTP  clients,  but  do  not  require  that
               clients use TLS encryption.
 
        <b><a href="postconf.5.html#postscreen_enforce_tls">postscreen_enforce_tls</a> ($<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b>
-              Mandatory TLS: announce STARTTLS support to  remote
-              SMTP  clients,  and  require  that  clients use TLS
+              Mandatory  TLS: announce STARTTLS support to remote
+              SMTP clients, and  require  that  clients  use  TLS
               encryption.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
               <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
-              The  maximal  number  of  digits  after the decimal
+              The maximal number  of  digits  after  the  decimal
               point when logging sub-second delay values.
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
-              The location of  all  postfix  administrative  com-
+              The  location  of  all  postfix administrative com-
               mands.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The  maximum  amount  of  time that an idle Postfix
-              daemon process waits  for  an  incoming  connection
+              The maximum amount of time  that  an  idle  Postfix
+              daemon  process  waits  for  an incoming connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The  process  ID  of  a  Postfix  command or daemon
+              The process ID  of  a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The process name of a  Postfix  command  or  daemon
+              The  process  name  of  a Postfix command or daemon
               process.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
-              The  mail  system  name  that  is  prepended to the
-              process name in syslog  records,  so  that  "smtpd"
+              The mail system  name  that  is  prepended  to  the
+              process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
 
 <b>SEE ALSO</b>
@@ -436,14 +444,14 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
        <a href="POSTSCREEN_README.html">POSTSCREEN_README</a>, Postfix Postscreen Howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>HISTORY</b>
        This service was introduced with Postfix version 2.8.
 
-       Many  ideas in <a href="postscreen.8.html"><b>postscreen</b>(8)</a> were explored in earlier work
-       by Michael Tokarev, in OpenBSD spamd, and in  MailChannels
+       Many ideas in <a href="postscreen.8.html"><b>postscreen</b>(8)</a> were explored in earlier  work
+       by  Michael Tokarev, in OpenBSD spamd, and in MailChannels
        Traffic Control.
 
 <b>AUTHOR(S)</b>
index 8d22aa22d83cadae8af045a70ae248ffdb91ed83..54d1263117d52edc641b19e718d351b720a10704 100644 (file)
@@ -4459,6 +4459,19 @@ 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_dnsbl_whitelist_threshold (default: 0)
+Allow a remote SMTP client to skip "before" and "after 220
+greeting" protocol tests, based on its combined DNSBL score as
+defined with the postscreen_dnsbl_sites parameter.
+.PP
+Specify a negative value to enable this feature. When a client
+passes the postscreen_dnsbl_whitelist_threshold without having
+failed other tests, all pending or disabled tests are flagged as
+completed with a time-to-live value equal to postscreen_dnsbl_ttl.
+When a test was already completed, its time-to-live value is updated
+if it was less than postscreen_dnsbl_ttl.
+.PP
+This feature is available in Postfix 2.11.
 .SH postscreen_enforce_tls (default: $smtpd_enforce_tls)
 Mandatory TLS: announce STARTTLS support to remote SMTP clients, and
 require that clients use TLS encryption.  See smtpd_postscreen_enforce_tls
index 821748de83bdb3afea920e8a819c5eac21a76754..2aa1aacb295e40a7d198386dbb32f02b3a4c149e 100644 (file)
@@ -242,6 +242,12 @@ up to 6 seconds otherwise).
 .IP "\fBsmtpd_service_name (smtpd)\fR"
 The internal service that \fBpostscreen\fR(8) hands off allowed
 connections to.
+.PP
+Available in Postfix version 2.11 and later:
+.IP "\fBpostscreen_dnsbl_whitelist_threshold (0)\fR"
+Allow a remote SMTP client to skip "before" and "after 220
+greeting" protocol tests, based on its combined DNSBL score as
+defined with the postscreen_dnsbl_sites parameter.
 .SH "AFTER-GREETING TESTS"
 .na
 .nf
index 4c12073ae579d7a6bd680eb5bd1975195721f72d..4ae0b9964bc0226380a9ee6f966455a6a9178d26 100755 (executable)
@@ -964,6 +964,7 @@ while (<>) {
     s;\bpostscreen_dnsbl_reply_map\b;<a href="postconf.5.html#postscreen_dnsbl_reply_map">$&</a>;g;
     s;\bpostscreen_dnsbl_sites\b;<a href="postconf.5.html#postscreen_dnsbl_sites">$&</a>;g;
     s;\bpostscreen_dnsbl_thresh[-</bB>]*\n* *[<bB>]*old\b;<a href="postconf.5.html#postscreen_dnsbl_threshold">$&</a>;g;
+    s;\bpostscreen_dnsbl_whitelist_thresh[-</bB>]*\n* *[<bB>]*old\b;<a href="postconf.5.html#postscreen_dnsbl_whitelist_threshold">$&</a>;g;
     s;\bpostscreen_dnsbl_action\b;<a href="postconf.5.html#postscreen_dnsbl_action">$&</a>;g;
     s;\bpostscreen_dnsbl_ttl\b;<a href="postconf.5.html#postscreen_dnsbl_ttl">$&</a>;g;
     s;\bpostscreen_for[-</bB>]*\n*[ <bB>]*bidden_commands\b;<a href="postconf.5.html#postscreen_forbidden_commands">$&</a>;g;
index 9c8d9fd8c32b8a569544007ae8fbd2bcf0176332..35ca415555958463e8eb5907722d5efb7ac7c150 100644 (file)
@@ -13770,6 +13770,21 @@ parameter. </p>
 
 <p> This feature is available in Postfix 2.8.  </p>
 
+%PARAM postscreen_dnsbl_whitelist_threshold 0
+
+<p> Allow a remote SMTP client to skip "before" and "after 220
+greeting" protocol tests, based on its combined DNSBL score as
+defined with the postscreen_dnsbl_sites parameter.  </p>
+
+<p> Specify a negative value to enable this feature. When a client
+passes the postscreen_dnsbl_whitelist_threshold without having
+failed other tests, all pending or disabled tests are flagged as
+completed with a time-to-live value equal to postscreen_dnsbl_ttl.
+When a test was already completed, its time-to-live value is updated
+if it was less than postscreen_dnsbl_ttl. </p>
+
+<p> This feature is available in Postfix 2.11.  </p>
+
 %PARAM postscreen_command_count_limit 20
 
 <p> The limit on the total number of commands per SMTP session for
index 1e368f8a50a817e96169f97215b6b63396fad43f..274f654b8fba4623acf128056b8ec017943d78ac 100644 (file)
@@ -3353,6 +3353,10 @@ extern char *var_psc_dnsbl_sites;
 #define DEF_PSC_DNSBL_THRESH   1
 extern int var_psc_dnsbl_thresh;
 
+#define VAR_PSC_DNSBL_WTHRESH  "postscreen_dnsbl_whitelist_threshold"
+#define DEF_PSC_DNSBL_WTHRESH  0
+extern int var_psc_dnsbl_wthresh;
+
 #define VAR_PSC_DNSBL_ENABLE   "postscreen_dnsbl_enable"
 #define DEF_PSC_DNSBL_ENABLE   0
 extern char *var_psc_dnsbl_enable;
index 434e516e84da5d54c7459865ddd017bdfffbb9e5..5245a0958563d4810753e6d9dab6bd5451bb103f 100644 (file)
@@ -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      "20130405"
+#define MAIL_RELEASE_DATE      "20130512"
 #define MAIL_VERSION_NUMBER    "2.11"
 
 #ifdef SNAPSHOT
index 4d2f8265ace170dc97bbcc7bbd1f6aac84ddc9ce..9c29a3d5544c94f5cb465c5f9f4bb668d148c7e5 100644 (file)
@@ -385,6 +385,7 @@ postscreen_tests.o: ../../include/match_list.h
 postscreen_tests.o: ../../include/msg.h
 postscreen_tests.o: ../../include/myaddrinfo.h
 postscreen_tests.o: ../../include/myflock.h
+postscreen_tests.o: ../../include/name_code.h
 postscreen_tests.o: ../../include/server_acl.h
 postscreen_tests.o: ../../include/string_list.h
 postscreen_tests.o: ../../include/sys_defs.h
index 0149b59ad78dc302fe40d6048c15885a0189daee..deff9abfabd6160a36ab9e462448bf4fa6c329c9 100644 (file)
 /* .IP "\fBsmtpd_service_name (smtpd)\fR"
 /*     The internal service that \fBpostscreen\fR(8) hands off allowed
 /*     connections to.
+/* .PP
+/*     Available in Postfix version 2.11 and later:
+/* .IP "\fBpostscreen_dnsbl_whitelist_threshold (0)\fR"
+/*     Allow a remote SMTP client to skip "before" and "after 220
+/*     greeting" protocol tests, based on its combined DNSBL score as
+/*     defined with the postscreen_dnsbl_sites parameter.
 /* AFTER-GREETING TESTS
 /* .ad
 /* .fi
@@ -465,6 +471,7 @@ int     var_psc_pregr_ttl;
 char   *var_psc_dnsbl_sites;
 char   *var_psc_dnsbl_reply;
 int     var_psc_dnsbl_thresh;
+int     var_psc_dnsbl_wthresh;
 char   *var_psc_dnsbl_action;
 int     var_psc_dnsbl_ttl;
 
@@ -1095,6 +1102,7 @@ int     main(int argc, char **argv)
     static const CONFIG_INT_TABLE int_table[] = {
        VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
        VAR_PSC_DNSBL_THRESH, DEF_PSC_DNSBL_THRESH, &var_psc_dnsbl_thresh, 0, 0,
+       VAR_PSC_DNSBL_WTHRESH, DEF_PSC_DNSBL_WTHRESH, &var_psc_dnsbl_wthresh, 0, 0,
        VAR_PSC_CMD_COUNT, DEF_PSC_CMD_COUNT, &var_psc_cmd_count, 1, 0,
        VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
        0,
index 3fe0a9b6bf53c23ed38b4edcfb94562da6977735..beb725fbbdddd68aed9e73d3e30892b2fcaf1aba 100644 (file)
   */
 #define PSC_READ_BUF_SIZE      1024
 
+ /*
+  * Numeric indices and symbolic names for tests whose time stamps and status
+  * flags can be accessed by numeric index.
+  */
+#define PSC_TINDX_PREGR        0               /* pregreet */
+#define PSC_TINDX_DNSBL        1               /* dnsbl */
+#define PSC_TINDX_PIPEL        2               /* pipelining */
+#define PSC_TINDX_NSMTP        3               /* non-smtp command */
+#define PSC_TINDX_BARLF        4               /* bare newline */
+#define PSC_TINDX_COUNT        5               /* number of tests */
+
+#define PSC_TNAME_PREGR        "pregreet"
+#define PSC_TNAME_DNSBL        "dnsbl"
+#define PSC_TNAME_PIPEL        "pipelining"
+#define PSC_TNAME_NSMTP        "non-smtp command"
+#define PSC_TNAME_BARLF        "bare newline"
+
+#define PSC_TINDX_BYTNAME(tname) (PSC_TINDX_ ## tname)
+
  /*
   * Per-session state.
   */
@@ -53,16 +72,11 @@ typedef struct {
     /* Test context. */
     struct timeval start_time;         /* start of current test */
     const char *test_name;             /* name of current test */
-    /* Before-handshake tests. */
-    time_t  pregr_stamp;               /* pregreet expiration time */
-    time_t  dnsbl_stamp;               /* dnsbl expiration time */
+    time_t  expire_time[PSC_TINDX_COUNT];      /* per-test expiration */
     VSTRING *dnsbl_reply;              /* dnsbl reject text */
+    int     dnsbl_score;               /* saved DNSBL score */
+    const char *dnsbl_name;            /* DNSBL name with largest weight */
     int     dnsbl_index;               /* dnsbl request index */
-    time_t  penal_stamp;               /* penalty expiration time */
-    /* Built-in SMTP protocol engine. */
-    time_t  pipel_stamp;               /* pipelining expiration time */
-    time_t  nsmtp_stamp;               /* non-smtp command expiration time */
-    time_t  barlf_stamp;               /* bare newline expiration time */
     const char *rcpt_reply;            /* how to reject recipients */
     int     command_count;             /* error + junk command count */
     const char *protocol;              /* SMTP or ESMTP */
@@ -76,10 +90,26 @@ typedef struct {
     const char *where;                 /* SMTP protocol state */
 } PSC_STATE;
 
+ /*
+  * Emulate legacy ad-hoc variables on top of indexable time stamps. This
+  * avoids massive scar tissue during initial feature development.
+  */
+#define pregr_stamp    expire_time[PSC_TINDX_PREGR]
+#define dnsbl_stamp    expire_time[PSC_TINDX_DNSBL]
+#define pipel_stamp    expire_time[PSC_TINDX_PIPEL]
+#define nsmtp_stamp    expire_time[PSC_TINDX_NSMTP]
+#define barlf_stamp    expire_time[PSC_TINDX_BARLF]
+
+ /*
+  * Special expiration time values.
+  */
 #define PSC_TIME_STAMP_NEW             (0)     /* test was never passed */
 #define PSC_TIME_STAMP_DISABLED                (1)     /* never passed but disabled */
 #define PSC_TIME_STAMP_INVALID         (-1)    /* must not be cached */
 
+ /*
+  * Status flags.
+  */
 #define PSC_STATE_FLAG_NOFORWARD       (1<<0)  /* don't forward this session */
 #define PSC_STATE_FLAG_USING_TLS       (1<<1)  /* using the TLS proxy */
 #define PSC_STATE_FLAG_UNUSED2         (1<<2)  /* use me! */
@@ -88,8 +118,11 @@ typedef struct {
 #define PSC_STATE_FLAG_HANGUP          (1<<5)  /* NOT a test failure */
 #define PSC_STATE_FLAG_SMTPD_X21       (1<<6)  /* hang up after command */
 #define PSC_STATE_FLAG_WLIST_FAIL      (1<<7)  /* do not whitelist */
+#define PSC_STATE_FLAG_TEST_BASE       (8)     /* start of indexable flags */
 
  /*
+  * Tests whose flags and expiration time can be accessed by numerical index.
+  * 
   * Important: every MUMBLE_TODO flag must have a MUMBLE_PASS flag, such that
   * MUMBLE_PASS == PSC_STATE_FLAGS_TODO_TO_PASS(MUMBLE_TODO).
   * 
@@ -107,39 +140,74 @@ typedef struct {
   * the result was ignored. MUMBLE_FAIL, on the other hand, is always final.
   * We use MUMBLE_SKIP to indicate that a decision was either "fail" or
   * forced "pass".
+  * 
+  * The difference between DONE and SKIP is in the beholder's eye. These flags
+  * share the same bit.
   */
 #define PSC_STATE_FLAGS_TODO_TO_PASS(todo_flags) ((todo_flags) >> 1)
 #define PSC_STATE_FLAGS_TODO_TO_DONE(todo_flags) ((todo_flags) << 1)
 
-#define PSC_STATE_FLAG_PENAL_UPDATE    (1<<6)  /* save new penalty */
-#define PSC_STATE_FLAG_PENAL_FAIL      (1<<7)  /* penalty is active */
-
-#define PSC_STATE_FLAG_PREGR_FAIL      (1<<8)  /* failed pregreet test */
-#define PSC_STATE_FLAG_PREGR_PASS      (1<<9)  /* passed pregreet test */
-#define PSC_STATE_FLAG_PREGR_TODO      (1<<10) /* pregreet test expired */
-#define PSC_STATE_FLAG_PREGR_DONE      (1<<11) /* decision is final */
-
-#define PSC_STATE_FLAG_DNSBL_FAIL      (1<<12) /* failed DNSBL test */
-#define PSC_STATE_FLAG_DNSBL_PASS      (1<<13) /* passed DNSBL test */
-#define PSC_STATE_FLAG_DNSBL_TODO      (1<<14) /* DNSBL test expired */
-#define PSC_STATE_FLAG_DNSBL_DONE      (1<<15) /* decision is final */
+#define PSC_STATE_FLAG_SHIFT_FAIL      (0)     /* failed test */
+#define PSC_STATE_FLAG_SHIFT_PASS      (1)     /* passed test */
+#define PSC_STATE_FLAG_SHIFT_TODO      (2)     /* expired test */
+#define PSC_STATE_FLAG_SHIFT_DONE      (3)     /* decision is final */
+#define PSC_STATE_FLAG_SHIFT_SKIP      (3)     /* action is already logged */
+#define PSC_STATE_FLAG_SHIFT_STRIDE    (4)     /* nr of flags per test */
 
- /* Room here for one more after-handshake test. */
+#define PSC_STATE_FLAG_SHIFT_BYFNAME(fname) (PSC_STATE_FLAG_SHIFT_ ## fname)
 
-#define PSC_STATE_FLAG_PIPEL_FAIL      (1<<20) /* failed pipelining test */
-#define PSC_STATE_FLAG_PIPEL_PASS      (1<<21) /* passed pipelining test */
-#define PSC_STATE_FLAG_PIPEL_TODO      (1<<22) /* pipelining test expired */
-#define PSC_STATE_FLAG_PIPEL_SKIP      (1<<23) /* action is already logged */
-
-#define PSC_STATE_FLAG_NSMTP_FAIL      (1<<24) /* failed non-SMTP test */
-#define PSC_STATE_FLAG_NSMTP_PASS      (1<<25) /* passed non-SMTP test */
-#define PSC_STATE_FLAG_NSMTP_TODO      (1<<26) /* non-SMTP test expired */
-#define PSC_STATE_FLAG_NSMTP_SKIP      (1<<27) /* action is already logged */
+ /*
+  * Indexable per-test flags. These are used for DNS whitelisting multiple
+  * tests, without needing per-test ad-hoc code.
+  */
+#define PSC_STATE_FLAG_BYTINDX_FNAME(tindx, fname) \
+       (1U << (PSC_STATE_FLAG_TEST_BASE \
+           + PSC_STATE_FLAG_SHIFT_STRIDE * (tindx) \
+           + PSC_STATE_FLAG_SHIFT_BYFNAME(fname)))
+
+#define PSC_STATE_FLAG_BYTINDX_FAIL(tindx) \
+       PSC_STATE_FLAG_BYTINDX_FNAME((tindx), FAIL)
+#define PSC_STATE_FLAG_BYTINDX_PASS(tindx) \
+       PSC_STATE_FLAG_BYTINDX_FNAME((tindx), PASS)
+#define PSC_STATE_FLAG_BYTINDX_TODO(tindx) \
+       PSC_STATE_FLAG_BYTINDX_FNAME((tindx), TODO)
+#define PSC_STATE_FLAG_BYTINDX_DONE(tindx) \
+       PSC_STATE_FLAG_BYTINDX_FNAME((tindx), DONE)
+#define PSC_STATE_FLAG_BYTINDX_SKIP(tindx) \
+       PSC_STATE_FLAG_BYTINDX_FNAME((tindx), SKIP)
 
-#define PSC_STATE_FLAG_BARLF_FAIL      (1<<28) /* failed bare newline test */
-#define PSC_STATE_FLAG_BARLF_PASS      (1<<29) /* passed bare newline test */
-#define PSC_STATE_FLAG_BARLF_TODO      (1<<30) /* bare newline test expired */
-#define PSC_STATE_FLAG_BARLF_SKIP      (1<<31) /* action is already logged */
+ /*
+  * Flags with distinct names. These are used in the per-test ad-hoc code.
+  */
+#define PSC_STATE_FLAG_BYTNAME_FNAME(tname, fname) \
+       (1U << (PSC_STATE_FLAG_TEST_BASE \
+           + PSC_STATE_FLAG_SHIFT_STRIDE * PSC_TINDX_BYTNAME(tname) \
+           + PSC_STATE_FLAG_SHIFT_BYFNAME(fname)))
+
+#define PSC_STATE_FLAG_PREGR_FAIL PSC_STATE_FLAG_BYTNAME_FNAME(PREGR, FAIL)
+#define PSC_STATE_FLAG_PREGR_PASS PSC_STATE_FLAG_BYTNAME_FNAME(PREGR, PASS)
+#define PSC_STATE_FLAG_PREGR_TODO PSC_STATE_FLAG_BYTNAME_FNAME(PREGR, TODO)
+#define PSC_STATE_FLAG_PREGR_DONE PSC_STATE_FLAG_BYTNAME_FNAME(PREGR, DONE)
+
+#define PSC_STATE_FLAG_DNSBL_FAIL PSC_STATE_FLAG_BYTNAME_FNAME(DNSBL, FAIL)
+#define PSC_STATE_FLAG_DNSBL_PASS PSC_STATE_FLAG_BYTNAME_FNAME(DNSBL, PASS)
+#define PSC_STATE_FLAG_DNSBL_TODO PSC_STATE_FLAG_BYTNAME_FNAME(DNSBL, TODO)
+#define PSC_STATE_FLAG_DNSBL_DONE PSC_STATE_FLAG_BYTNAME_FNAME(DNSBL, DONE)
+
+#define PSC_STATE_FLAG_PIPEL_FAIL PSC_STATE_FLAG_BYTNAME_FNAME(PIPEL, FAIL)
+#define PSC_STATE_FLAG_PIPEL_PASS PSC_STATE_FLAG_BYTNAME_FNAME(PIPEL, PASS)
+#define PSC_STATE_FLAG_PIPEL_TODO PSC_STATE_FLAG_BYTNAME_FNAME(PIPEL, TODO)
+#define PSC_STATE_FLAG_PIPEL_SKIP PSC_STATE_FLAG_BYTNAME_FNAME(PIPEL, SKIP)
+
+#define PSC_STATE_FLAG_NSMTP_FAIL PSC_STATE_FLAG_BYTNAME_FNAME(NSMTP, FAIL)
+#define PSC_STATE_FLAG_NSMTP_PASS PSC_STATE_FLAG_BYTNAME_FNAME(NSMTP, PASS)
+#define PSC_STATE_FLAG_NSMTP_TODO PSC_STATE_FLAG_BYTNAME_FNAME(NSMTP, TODO)
+#define PSC_STATE_FLAG_NSMTP_SKIP PSC_STATE_FLAG_BYTNAME_FNAME(NSMTP, SKIP)
+
+#define PSC_STATE_FLAG_BARLF_FAIL PSC_STATE_FLAG_BYTNAME_FNAME(BARLF, FAIL)
+#define PSC_STATE_FLAG_BARLF_PASS PSC_STATE_FLAG_BYTNAME_FNAME(BARLF, PASS)
+#define PSC_STATE_FLAG_BARLF_TODO PSC_STATE_FLAG_BYTNAME_FNAME(BARLF, TODO)
+#define PSC_STATE_FLAG_BARLF_SKIP PSC_STATE_FLAG_BYTNAME_FNAME(BARLF, SKIP)
 
  /*
   * Aggregates for individual tests.
@@ -155,6 +223,8 @@ typedef struct {
 #define PSC_STATE_MASK_BARLF_TODO_FAIL \
        (PSC_STATE_FLAG_BARLF_TODO | PSC_STATE_FLAG_BARLF_FAIL)
 
+#define PSC_STATE_MASK_PREGR_TODO_DONE \
+       (PSC_STATE_FLAG_PREGR_TODO | PSC_STATE_FLAG_PREGR_DONE)
 #define PSC_STATE_MASK_PIPEL_TODO_SKIP \
        (PSC_STATE_FLAG_PIPEL_TODO | PSC_STATE_FLAG_PIPEL_SKIP)
 #define PSC_STATE_MASK_NSMTP_TODO_SKIP \
@@ -195,7 +265,7 @@ typedef struct {
   * Super-aggregates for all tests combined.
   */
 #define PSC_STATE_MASK_ANY_FAIL \
-       (PSC_STATE_FLAG_BLIST_FAIL | PSC_STATE_FLAG_PENAL_FAIL | \
+       (PSC_STATE_FLAG_BLIST_FAIL | \
        PSC_STATE_MASK_EARLY_FAIL | PSC_STATE_MASK_SMTPD_FAIL | \
        PSC_STATE_FLAG_WLIST_FAIL)
 
@@ -209,7 +279,7 @@ typedef struct {
        (PSC_STATE_MASK_ANY_TODO | PSC_STATE_MASK_ANY_FAIL)
 
 #define PSC_STATE_MASK_ANY_UPDATE \
-       (PSC_STATE_MASK_ANY_PASS | PSC_STATE_FLAG_PENAL_UPDATE)
+       (PSC_STATE_MASK_ANY_PASS)
 
  /*
   * Meta-commands for state->where that reflect the initial command processor
@@ -414,12 +484,12 @@ extern int psc_dnsbl_request(const char *, void (*) (int, char *), char *);
   * postscreen_tests.c
   */
 #define PSC_INIT_TESTS(dst) do { \
+       time_t *_it_stamp_p; \
        (dst)->flags = 0; \
-       (dst)->pregr_stamp = PSC_TIME_STAMP_INVALID; \
-       (dst)->dnsbl_stamp = PSC_TIME_STAMP_INVALID; \
-       (dst)->pipel_stamp = PSC_TIME_STAMP_INVALID; \
-       (dst)->barlf_stamp = PSC_TIME_STAMP_INVALID; \
-       (dst)->penal_stamp = PSC_TIME_STAMP_INVALID; \
+       for (_it_stamp_p = (dst)->expire_time; \
+           _it_stamp_p < (dst)->expire_time + PSC_TINDX_COUNT; \
+           _it_stamp_p++) \
+           *_it_stamp_p = PSC_TIME_STAMP_INVALID; \
     } while (0)
 #define PSC_BEGIN_TESTS(state, name) do { \
        (state)->test_name = (name); \
@@ -430,6 +500,7 @@ extern void psc_parse_tests(PSC_STATE *, const char *, time_t);
 extern char *psc_print_tests(VSTRING *, PSC_STATE *);
 extern char *psc_print_grey_key(VSTRING *, const char *, const char *,
                                        const char *, const char *);
+extern const char *psc_test_name(int);
 
 #define PSC_MIN(x, y) ((x) < (y) ? (x) : (y))
 #define PSC_MAX(x, y) ((x) > (y) ? (x) : (y))
index cd77f5afd23081463024ac028efa9271fb79543e..54f0a5789903c4ad4ffe69808f43a49825609fea 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <sys_defs.h>
 #include <sys/socket.h>
+#include <limits.h>
 
 /* Utility library. */
 
@@ -58,9 +59,7 @@ static void psc_early_event(int event, char *context)
     PSC_STATE *state = (PSC_STATE *) context;
     char    read_buf[PSC_READ_BUF_SIZE];
     int     read_count;
-    int     dnsbl_score;
     DELTA_TIME elapsed;
-    const char *dnsbl_name;
 
     if (msg_verbose > 1)
        msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
@@ -91,7 +90,7 @@ static void psc_early_event(int event, char *context)
         * Check if the SMTP client spoke before its turn.
         */
        if ((state->flags & PSC_STATE_MASK_PREGR_TODO_FAIL)
-           == PSC_STATE_FLAG_PREGR_TODO) {
+           == (state->flags & PSC_STATE_MASK_PREGR_TODO_DONE)) {
            state->pregr_stamp = event_time() + var_psc_pregr_ttl;
            PSC_PASS_SESSION_STATE(state, "pregreet test",
                                   PSC_STATE_FLAG_PREGR_PASS);
@@ -108,30 +107,35 @@ static void psc_early_event(int event, char *context)
         */
 #define PSC_DNSBL_FORMAT \
        "%s 5.7.1 Service unavailable; client [%s] blocked using %s\r\n"
+#define NO_DNSBL_SCORE INT_MAX
 
        if (state->flags & PSC_STATE_FLAG_DNSBL_TODO) {
-           dnsbl_score =
-               psc_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
-                                  state->dnsbl_index);
-           if (dnsbl_score < var_psc_dnsbl_thresh) {
+           if (state->dnsbl_score == NO_DNSBL_SCORE)
+               state->dnsbl_score =
+                   psc_dnsbl_retrieve(state->smtp_client_addr,
+                                      &state->dnsbl_name,
+                                      state->dnsbl_index);
+           if (state->dnsbl_score < var_psc_dnsbl_thresh) {
                state->dnsbl_stamp = event_time() + var_psc_dnsbl_ttl;
                PSC_PASS_SESSION_STATE(state, "dnsbl test",
                                       PSC_STATE_FLAG_DNSBL_PASS);
            } else {
                msg_info("DNSBL rank %d for [%s]:%s",
-                        dnsbl_score, PSC_CLIENT_ADDR_PORT(state));
+                        state->dnsbl_score, PSC_CLIENT_ADDR_PORT(state));
                PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_DNSBL_FAIL);
                switch (psc_dnsbl_action) {
                case PSC_ACT_DROP:
                    state->dnsbl_reply = vstring_sprintf(vstring_alloc(100),
                                                    PSC_DNSBL_FORMAT, "521",
-                                      state->smtp_client_addr, dnsbl_name);
+                                                   state->smtp_client_addr,
+                                                        state->dnsbl_name);
                    PSC_DROP_SESSION_STATE(state, STR(state->dnsbl_reply));
                    return;
                case PSC_ACT_ENFORCE:
                    state->dnsbl_reply = vstring_sprintf(vstring_alloc(100),
                                                    PSC_DNSBL_FORMAT, "550",
-                                      state->smtp_client_addr, dnsbl_name);
+                                                   state->smtp_client_addr,
+                                                        state->dnsbl_name);
                    PSC_ENFORCE_SESSION_STATE(state, STR(state->dnsbl_reply));
                    break;
                case PSC_ACT_IGNORE:
@@ -150,7 +154,9 @@ static void psc_early_event(int event, char *context)
         * Pass the connection to a real SMTP server, or enter the dummy
         * engine for deep tests.
         */
-       if (state->flags & (PSC_STATE_FLAG_NOFORWARD | PSC_STATE_MASK_SMTPD_TODO))
+       if ((state->flags & PSC_STATE_FLAG_NOFORWARD) != 0
+           || ((state->flags & PSC_STATE_MASK_SMTPD_PASS)
+               != PSC_STATE_FLAGS_TODO_TO_PASS(state->flags & PSC_STATE_MASK_SMTPD_TODO)))
            psc_smtpd_tests(state);
        else
            psc_conclude(state);
@@ -166,7 +172,8 @@ static void psc_early_event(int event, char *context)
                          read_buf, sizeof(read_buf) - 1, MSG_PEEK)) <= 0) {
            /* Avoid memory leak. */
            if (state->flags & PSC_STATE_FLAG_DNSBL_TODO)
-               (void) psc_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
+               (void) psc_dnsbl_retrieve(state->smtp_client_addr,
+                                         &state->dnsbl_name,
                                          state->dnsbl_index);
            /* XXX Wait for DNS replies to come in. */
            psc_hangup_event(state);
@@ -182,7 +189,8 @@ static void psc_early_event(int event, char *context)
        case PSC_ACT_DROP:
            /* Avoid memory leak. */
            if (state->flags & PSC_STATE_FLAG_DNSBL_TODO)
-               (void) psc_dnsbl_retrieve(state->smtp_client_addr, &dnsbl_name,
+               (void) psc_dnsbl_retrieve(state->smtp_client_addr,
+                                         &state->dnsbl_name,
                                          state->dnsbl_index);
            PSC_DROP_SESSION_STATE(state, "521 5.5.1 Protocol error\r\n");
            return;
@@ -226,10 +234,45 @@ static void psc_early_dnsbl_event(int unused_event, char *context)
 {
     const char *myname = "psc_early_dnsbl_event";
     PSC_STATE *state = (PSC_STATE *) context;
+    time_t  now;
+    int     tindx;
 
     if (msg_verbose)
        msg_info("%s: notify [%s]:%s", myname, PSC_CLIENT_ADDR_PORT(state));
 
+    /*
+     * Collect the DNSBL score. If no tests failed (we can't undo those), and
+     * if the whitelist threshold is met, flag all other pending or disabled
+     * tests as successfully completed, and set their expiration times equal
+     * to the DNSBL expiration time, except for tests that would expire
+     * later.
+     */
+    state->dnsbl_score =
+       psc_dnsbl_retrieve(state->smtp_client_addr, &state->dnsbl_name,
+                          state->dnsbl_index);
+    if (var_psc_dnsbl_wthresh < 0
+       && (state->flags & PSC_STATE_MASK_ANY_FAIL) == 0
+       && state->dnsbl_score <= var_psc_dnsbl_wthresh) {
+       now = event_time();
+       for (tindx = 0; tindx < PSC_TINDX_COUNT; tindx++) {
+           if (tindx == PSC_TINDX_DNSBL)
+               continue;
+           if ((state->flags & PSC_STATE_FLAG_BYTINDX_TODO(tindx))
+               && !(state->flags & PSC_STATE_FLAG_BYTINDX_PASS(tindx))) {
+               if (msg_verbose)
+                   msg_info("skip %s test for [%s]:%s",
+                        psc_test_name(tindx), PSC_CLIENT_ADDR_PORT(state));
+               /* Wrong for deep protocol tests, but we disable those. */
+               state->flags |= PSC_STATE_FLAG_BYTINDX_DONE(tindx);
+               /* This also disables pending deep protocol tests. */
+               state->flags |= PSC_STATE_FLAG_BYTINDX_PASS(tindx);
+           }
+           /* Update expiration even if the test was completed or disabled. */
+           if (state->expire_time[tindx] < now + var_psc_dnsbl_ttl)
+               state->expire_time[tindx] = now + var_psc_dnsbl_ttl;
+       }
+    }
+
     /*
      * Terminate the greet delay if we're just waiting for DNSBL lookup to
      * complete. Don't call psc_early_event directly, that would result in a
@@ -272,6 +315,7 @@ void    psc_early_tests(PSC_STATE *state)
                              (char *) state);
     else
        state->dnsbl_index = -1;
+    state->dnsbl_score = NO_DNSBL_SCORE;
 
     /*
      * Wait for the client to respond or for DNS lookup to complete.
index 5b97ce0325b0a5c1586074781276fa6a495fbce3..c7472cc627d9bffb0139456df943fcf76f53c2ef 100644 (file)
@@ -268,9 +268,6 @@ const char *psc_print_state_flags(int flags, const char *context)
        /* unused */
        "WLIST_FAIL", PSC_STATE_FLAG_WLIST_FAIL,
 
-       "PENAL_UPDATE", PSC_STATE_FLAG_PENAL_UPDATE,
-       "PENAL_FAIL", PSC_STATE_FLAG_PENAL_FAIL,
-
        "PREGR_FAIL", PSC_STATE_FLAG_PREGR_FAIL,
        "PREGR_PASS", PSC_STATE_FLAG_PREGR_PASS,
        "PREGR_TODO", PSC_STATE_FLAG_PREGR_TODO,
index 57bfd69991d9e15f745799c0d96f0cbdc266a8ce..17b7a3926149a951c637d6a160d72a03c0c6a10c 100644 (file)
@@ -27,6 +27,9 @@
 /*     const char *helo;
 /*     const char *sender;
 /*     const char *rcpt;
+/*
+/*     const char *psc_test_name(tindx)
+/*     int     tindx;
 /* DESCRIPTION
 /*     The functions in this module overwrite the per-test expiration
 /*     time stamps and all flags bits.  Some functions are implemented
@@ -54,6 +57,9 @@
 /*     This may modify the time stamps for disabled tests.
 /*
 /*     psc_print_grey_key() prints a greylist lookup key.
+/*
+/*     psc_test_name() returns the name for the specified text
+/*     index.
 /* LICENSE
 /* .ad
 /* .fi
 
 #include <sys_defs.h>
 #include <stdio.h>                     /* sscanf */
+#include <stdlib.h>                    /* strtoul */
 
 /* Utility library. */
 
 #include <msg.h>
+#include <name_code.h>
 
 /* Global library. */
 
@@ -132,7 +140,6 @@ void    psc_new_tests(PSC_STATE *state)
     state->pipel_stamp = PSC_TIME_STAMP_NEW;
     state->nsmtp_stamp = PSC_TIME_STAMP_NEW;
     state->barlf_stamp = PSC_TIME_STAMP_NEW;
-    state->penal_stamp = PSC_TIME_STAMP_NEW;
 
     /*
      * Don't flag disabled tests as "todo", because there would be no way to
@@ -156,17 +163,10 @@ void    psc_parse_tests(PSC_STATE *state,
                                const char *stamp_str,
                                time_t time_value)
 {
-    unsigned long pregr_stamp;
-    unsigned long dnsbl_stamp;
-    unsigned long pipel_stamp;
-    unsigned long nsmtp_stamp;
-    unsigned long barlf_stamp;
-    unsigned long penal_stamp;
-
-#ifdef NONPROD
-    time_t  penalty_left;
-
-#endif
+    const char *start = stamp_str;
+    char   *cp;
+    time_t *time_stamps = state->expire_time;
+    time_t *sp;
 
     /*
      * We don't know what tests have expired or have never passed.
@@ -182,37 +182,19 @@ void    psc_parse_tests(PSC_STATE *state,
      * enabled tests, but the remote SMTP client has not yet passed all those
      * tests.
      */
-    switch (sscanf(stamp_str, "%lu;%lu;%lu;%lu;%lu;%lu",
-                  &pregr_stamp, &dnsbl_stamp, &pipel_stamp, &nsmtp_stamp,
-                  &barlf_stamp, &penal_stamp)) {
-    case 0:
-       pregr_stamp = PSC_TIME_STAMP_DISABLED;
-    case 1:
-       dnsbl_stamp = PSC_TIME_STAMP_DISABLED;
-    case 2:
-       pipel_stamp = PSC_TIME_STAMP_DISABLED;
-    case 3:
-       nsmtp_stamp = PSC_TIME_STAMP_DISABLED;
-    case 4:
-       barlf_stamp = PSC_TIME_STAMP_DISABLED;
-    case 5:
-       penal_stamp = PSC_TIME_STAMP_DISABLED;
-    default:
-       break;
+    for (sp = time_stamps; sp < time_stamps + PSC_TINDX_COUNT; sp++) {
+       *sp = strtoul(start, &cp, 10);
+       if (*start == 0 || (*cp != '\0' && *cp != ';') || errno == ERANGE)
+           *sp = PSC_TIME_STAMP_DISABLED;
+       if (*sp == PSC_TIME_STAMP_NEW)
+           state->flags |= PSC_STATE_FLAG_NEW;
+       if (msg_verbose)
+           msg_info("%s -> %lu", start, (unsigned long) *sp);
+       if (*cp == ';')
+           start = cp + 1;
+       else
+           start = cp;
     }
-    state->pregr_stamp = pregr_stamp;
-    state->dnsbl_stamp = dnsbl_stamp;
-    state->pipel_stamp = pipel_stamp;
-    state->nsmtp_stamp = nsmtp_stamp;
-    state->barlf_stamp = barlf_stamp;
-    state->penal_stamp = penal_stamp;
-
-    if (pregr_stamp == PSC_TIME_STAMP_NEW
-       || dnsbl_stamp == PSC_TIME_STAMP_NEW
-       || pipel_stamp == PSC_TIME_STAMP_NEW
-       || nsmtp_stamp == PSC_TIME_STAMP_NEW
-       || barlf_stamp == PSC_TIME_STAMP_NEW)
-       state->flags |= PSC_STATE_FLAG_NEW;
 
     /*
      * Don't flag disabled tests as "todo", because there would be no way to
@@ -270,41 +252,6 @@ void    psc_parse_tests(PSC_STATE *state,
            state->flags |= PSC_STATE_FLAG_DNSBL_TODO;
     }
 #endif
-
-    /*
-     * Apply unexpired penalty for past behavior.
-     * 
-     * XXX Before we can drop connections, change this function to return
-     * success/fail, to inform the caller that the state object no longer
-     * exists.
-     */
-#ifdef NONPROD
-    if ((penalty_left = state->penal_stamp - event_time()) > 0) {
-       msg_info("PENALTY %ld for %s",
-                (long) penalty_left, state->smtp_client_addr);
-       PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PENAL_FAIL);
-#if 0
-       switch (psc_penal_action) {
-       case PSC_ACT_DROP:
-           PSC_DROP_SESSION_STATE(state,
-                            "421 4.3.2 Service currently unavailable\r\n");
-           break;
-       case PSC_ACT_ENFORCE:
-#endif
-           PSC_ENFORCE_SESSION_STATE(state,
-                            "450 4.3.2 Service currently unavailable\r\n");
-#if 0
-           break;
-       case PSC_ACT_IGNORE:
-           PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_PENAL_FAIL);
-           break;
-       default:
-           msg_panic("%s: unknown penalty action value %d",
-                     myname, psc_penal_action);
-       }
-#endif
-    }
-#endif                                         /* NONPROD */
 }
 
 /* psc_print_tests - print postscreen cache record */
@@ -319,25 +266,6 @@ char   *psc_print_tests(VSTRING *buf, PSC_STATE *state)
     if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) == 0)
        msg_panic("%s: attempt to save a no-update record", myname);
 
-    /*
-     * Don't record a client as "passed" while subject to penalty. Be sure to
-     * produce correct PASS OLD/NEW logging.
-     * 
-     * XXX This needs to be refined - we should not reset the result of tests
-     * that were passed in previous sessions, otherwise a client may never
-     * pass a multi-stage test such as greylisting. One solution is to keep
-     * the original and updated time stamps around, and to save an updated
-     * time stamp only when the corresponding "pass" flag is raised.
-     */
-#ifdef NONPROD
-    if (state->flags & PSC_STATE_FLAG_PENAL_FAIL) {
-       state->pregr_stamp = state->dnsbl_stamp = state->pipel_stamp =
-           state->nsmtp_stamp = state->barlf_stamp =
-           ((state->flags & PSC_STATE_FLAG_NEW) ?
-            PSC_TIME_STAMP_NEW : PSC_TIME_STAMP_DISABLED);
-    }
-#endif
-
     /*
      * Give disabled tests a dummy time stamp so that we don't log a client
      * with "pass new" when some disabled test becomes enabled at some later
@@ -354,13 +282,12 @@ char   *psc_print_tests(VSTRING *buf, PSC_STATE *state)
     if (var_psc_barlf_enable == 0 && state->barlf_stamp == PSC_TIME_STAMP_NEW)
        state->barlf_stamp = PSC_TIME_STAMP_DISABLED;
 
-    vstring_sprintf(buf, "%lu;%lu;%lu;%lu;%lu;%lu",
+    vstring_sprintf(buf, "%lu;%lu;%lu;%lu;%lu",
                    (unsigned long) state->pregr_stamp,
                    (unsigned long) state->dnsbl_stamp,
                    (unsigned long) state->pipel_stamp,
                    (unsigned long) state->nsmtp_stamp,
-                   (unsigned long) state->barlf_stamp,
-                   (unsigned long) state->penal_stamp);
+                   (unsigned long) state->barlf_stamp);
     return (STR(buf));
 }
 
@@ -373,3 +300,23 @@ char   *psc_print_grey_key(VSTRING *buf, const char *client,
     return (STR(vstring_sprintf(buf, "%s/%s/%s/%s",
                                client, helo, sender, rcpt)));
 }
+
+/* psc_test_name - map test index to symbolic name */
+
+const char *psc_test_name(int tindx)
+{
+    const char *myname = "psc_test_name";
+    const NAME_CODE test_name_map[] = {
+       PSC_TNAME_PREGR, PSC_TINDX_PREGR,
+       PSC_TNAME_DNSBL, PSC_TINDX_DNSBL,
+       PSC_TNAME_PIPEL, PSC_TINDX_PIPEL,
+       PSC_TNAME_NSMTP, PSC_TINDX_NSMTP,
+       PSC_TNAME_BARLF, PSC_TINDX_BARLF,
+       0, -1,
+    };
+    const char *result;
+
+    if ((result = str_name_code(test_name_map, tindx)) == 0)
+       msg_panic("%s: bad index %d", myname, tindx);
+    return (result);
+}