]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.8-20100914
authorWietse Venema <wietse@porcupine.org>
Tue, 14 Sep 2010 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:36:31 +0000 (06:36 +0000)
23 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/DATABASE_README
postfix/README_FILES/POSTSCREEN_README
postfix/html/DATABASE_README.html
postfix/html/POSTSCREEN_README.html
postfix/html/postconf.5.html
postfix/html/postscreen.8.html
postfix/man/man5/postconf.5
postfix/man/man8/postscreen.8
postfix/proto/DATABASE_README.html
postfix/proto/POSTSCREEN_README.html
postfix/proto/postconf.proto
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/postscreen/postscreen.c
postfix/src/postscreen/postscreen.h
postfix/src/postscreen/postscreen_dnsbl.c
postfix/src/postscreen/postscreen_early.c
postfix/src/postscreen/postscreen_state.c
postfix/src/util/dict_thash.c
postfix/src/util/events.c
postfix/src/util/events.h

index a8b07760ba2f81b3c49a20e194d3062583c04e34..88762a3a42a17ef2941d51419ed7a5f8aaeb0389 100644 (file)
 -TPOSTMAP_KEY_STATE
 -TPOST_MAIL_STATE
 -TPRIVATE_STR_TABLE
+-TPS_CALL_BACK_ENTRY
 -TPS_DNSBL_HEAD
 -TPS_DNSBL_SCORE
 -TPS_DNSBL_SITE
index 2e4cf235d9762b33605ca94d51b13e574fdc4879..36a2f23296c9d28247ad090685d4baacd4410ec9 100644 (file)
@@ -15973,10 +15973,22 @@ Apologies for any names omitted.
 20100912
 
        Feature: bare newline detection in postscreen. Real spambots
-       don't make this mistake but poorly-written software often does.
-       File: postscreen/smtpd.c.
+       don't make this mistake anymore, but poorly-written software
+       still does.  File: postscreen/smtpd.c.
 
        Documentation: POSTSCREEN_README including instructions for
        turning postscreen(8) on without blocking mail, and more.
        Trimmed the text in the postscreen(8) manpage.  File:
        proto/POSTSCREEN_README.html, postscreen/postscreen.c.
+
+20100914
+
+       Cleanup: the "postscreen_greet_wait" delay now ends as soon
+       as both the pregreet and DNSBL tests complete (the postscreen
+       documentation mentions in history/credits that the program
+       started as a crude prototype).  The default postscreen_dnsbl_ttl
+       caching time is now reduced to 1h from 24h, allowing
+       postscreen to catch up on DNSBL updates more quickly. If
+       this increases the database update frequency too much then
+       we'll need to make dnsbl result non-cachable.  Files:
+       postscreen/postscreen_dnsbl.c, global/mail_params.h.
index 0e4e85d8b5f6dd99f2f04b1ef70f1549a7d37d7a..22d5801e6c7c0ea30c16ae507bbc96d8c3b7408f 100644 (file)
@@ -255,8 +255,8 @@ To find out what database types your Postfix system supports, use the "p\bpo\bos\bs
     t\bte\bex\bxt\bth\bha\bas\bsh\bh (read-only)
         This produces similar results as hash: files, except that you don't
         have to run the postmap(1) command before you can use the file, and
-        that it does not detect changes after the file is read. The lookup
-        table name is "texthash:filename", where the file name is taken
+        that texthash: does not detect changes after the file is read. The
+        lookup table name is "texthash:filename", where the file name is taken
         literally; no suffix is appended.
     u\bun\bni\bix\bx (read-only)
         A limited way to query the UNIX authentication database. The following
index c5ee1dad06c36782e89bab24508a1ffa1bbfb560..1e4077ac9584e4b1addb2f18c01333a504ead2c0 100644 (file)
@@ -5,25 +5,15 @@ P\bPo\bos\bst\btf\bfi\bix\bx P\bPo\bos\bst\bts\bsc\bcr\bre\bee\ben\bn H\bHo\bow\bwt\bto\bo
 I\bIn\bnt\btr\bro\bod\bdu\buc\bct\bti\bio\bon\bn
 
 The Postfix postscreen(8) server performs triage on multiple inbound SMTP
-connections in parallel. While one postscreen(8) process keeps spambots away
-from Postfix SMTP server processes, more Postfix SMTP server processes remain
-available for legitimate clients.
+connections in parallel. While a single postscreen(8) process keeps spambots
+away from Postfix SMTP server processes, more Postfix SMTP server processes
+remain available for legitimate clients.
 
 By doing these checks in a single postscreen(8) process, Postfix can avoid
 wasting one SMTP server process per connection. A side benefit of postscreen
 (8)'s DNSBL lookups is that DNS records are already cached before the Postfix
 SMTP server looks them up later.
 
-postscreen(8) maintains a temporary whitelist for clients that have passed a
-number of tests. When an SMTP client IP address is whitelisted, postscreen(8)
-hands off the connection immediately to a Postfix SMTP server process. This
-minimizes the overhead for legitimate mail.
-
-By default, postscreen(8) logs statistics and hands off every connection to a
-Postfix SMTP server process, while excluding clients in mynetworks from all
-tests (primarily, to avoid problems with non-standard SMTP implementations in
-network appliances). This mode is useful for non-destructive testing.
-
 Topics in this document:
 
   * Introduction
@@ -161,10 +151,14 @@ 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
-with:
+postscreen_whitelist_networks 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
 
 /etc/postfix/main.cf:
+    # Disable the teaser banner (try whitelisting first if you can).
     postscreen_greet_banner =
 
 When an SMTP client sends a command before the postscreen_greet_wait time has
index 5e2e59425db783baedac13916792f04b59d7e1fe..b2166e9cb96c396a7448727fef566c118716559e 100644 (file)
@@ -383,9 +383,9 @@ number.
 
 <dd> This produces similar results as hash: files, except that you
 don't have to run the <a href="postmap.1.html">postmap(1)</a> command before you can use the
-file, and that it does not detect changes after the file is read.
-The lookup table name is "texthash:filename", where the file name
-is taken literally; no suffix is appended. </dd>
+file, and that texthash: does not detect changes after the file is
+read.  The lookup table name is "texthash:filename", where the file
+name is taken literally; no suffix is appended. </dd>
 
 <dt> <b>unix</b> (read-only) </dt>
 
index a22148f6af4e6e9f3c123bfdeda312eea326b550..f76d1050c821faf459df5c6315220a7e24b284b3 100644 (file)
 <h2> <a name="intro">Introduction</a> </h2>
 
 <p> The Postfix <a href="postscreen.8.html">postscreen(8)</a> server performs triage on multiple
-inbound SMTP connections in parallel. While one <a href="postscreen.8.html">postscreen(8)</a> process
-keeps spambots away from Postfix SMTP server processes, more Postfix
-SMTP server processes remain available for legitimate clients. </p>
+inbound SMTP connections in parallel. While a single <a href="postscreen.8.html">postscreen(8)</a>
+process keeps spambots away from Postfix SMTP server processes,
+more Postfix SMTP server processes remain available for legitimate
+clients. </p>
 
 <p> By doing these checks in a single <a href="postscreen.8.html">postscreen(8)</a> process, Postfix
 can avoid wasting one SMTP server process per connection. A side
@@ -28,18 +29,6 @@ benefit of <a href="postscreen.8.html">postscreen(8)</a>'s DNSBL lookups is that
 already cached before the Postfix SMTP server looks them up later.
 </p>
 
-<p> <a href="postscreen.8.html">postscreen(8)</a> maintains a temporary whitelist for clients that
-have passed a number of tests. When an SMTP client IP address is
-whitelisted, <a href="postscreen.8.html">postscreen(8)</a> hands off the connection immediately to
-a Postfix SMTP server process. This minimizes the overhead for
-legitimate mail.  </p>
-
-<p> By default, <a href="postscreen.8.html">postscreen(8)</a> logs statistics and hands off every
-connection to a Postfix SMTP server process, while excluding clients
-in <a href="postconf.5.html#mynetworks">mynetworks</a> from all tests (primarily, to avoid problems with
-non-standard SMTP implementations in network appliances). This mode
-is useful for non-destructive testing. </p>
-
 <p> Topics in this document: </p>
 
 <ul>
@@ -222,10 +211,17 @@ SMTP clients that correctly implement the protocol.  </p>
 <p> To avoid problems with poorly-implemented SMTP engines in network
 appliances or network testing tools, either exclude them from all
 tests with the <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> feature or else specify
-an empty teaser banner with: </p>
+an empty teaser banner: </p>
+
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+    # Exclude broken clients by whitelisting. $<a href="postconf.5.html#mynetworks">mynetworks</a> is default.
+    <a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>, 192.168.254.0/24
+</pre>
 
 <pre>
 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
+    # Disable the teaser banner (try whitelisting first if you can).
     <a href="postconf.5.html#postscreen_greet_banner">postscreen_greet_banner</a> =
 </pre>
 
index 48630c66b10293e49eaf65fff25b63bcf159c115..43c79745e7dfc0a89b898b1a7d1c1e6621cbd822 100644 (file)
@@ -6854,10 +6854,10 @@ when it rejects mail.  When no mapping is found, the actual DNSBL
 domain will be used. </p>
 
 <p> For maximal stability it is best to use a file that is read
-into memory such as <a href="pcre_table.5.html">pcre</a>:, <a href="regexp_table.5.html">regexp</a>: or texthash: (a format similar
-to hash: except that there is no need to run <a href="postmap.1.html">postmap(1)</a> before the
-file can be used, and that it does not detect changes after the
-file is read). </p>
+into memory such as <a href="pcre_table.5.html">pcre</a>:, <a href="regexp_table.5.html">regexp</a>: or texthash: (texthash: is similar
+to hash:, except a) there is no need to run <a href="postmap.1.html">postmap(1)</a> before the
+file can be used, and b) texthash: does not detect changes after
+the file is read). </p>
 
 <p> Example: </p>
 
@@ -6950,7 +6950,7 @@ parameter. </p>
 </DD>
 
 <DT><b><a name="postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>
-(default: 1d)</b></DT><DD>
+(default: 1h)</b></DT><DD>
 
 <p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will cache results from
 a successful DNS blocklist test. During this time, the client IP address
@@ -7053,10 +7053,10 @@ one-letter suffix that specifies the time unit).  Time units: s
 
 <p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will wait for an SMTP
 client to send a command before its turn, and for DNS blocklist
-lookup results to arrive (default: 2 seconds under stress, 6 seconds
-normally).  This is done only when the SMTP client IP address is
-not permanently whitelisted, and when it has no cached decision.
-Specify a non-zero time value (an integral value plus an optional
+lookup results to arrive (default: up to 2 seconds under stress,
+up to 6 seconds otherwise).  <p>
+
+<p> Specify a non-zero time value (an integral value plus an optional
 one-letter suffix that specifies the time unit).  </p>
 
 <p> Time units: s (seconds), m (minutes), h (hours), d (days), w
index 4463dfb532c9edae3b26707ad575018a1b52c386..3e13d95ce9fa518d1afec81e4d9db3266e9a41c5 100644 (file)
@@ -14,10 +14,10 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
 
 <b>DESCRIPTION</b>
        The Postfix <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server performs triage on multi-
-       ple  inbound   SMTP   connections   in   parallel.   While
-       <a href="postscreen.8.html"><b>postscreen</b>(8)</a> keeps spambots away from Postfix SMTP server
-       processes,  more  Postfix  SMTP  server  processes  remain
-       available for legitimate clients.
+       ple inbound SMTP connections in parallel. While  a  single
+       <a href="postscreen.8.html"><b>postscreen</b>(8)</a>  process  keeps  spambots  away from Postfix
+       SMTP server processes, more Postfix SMTP server  processes
+       remain available for legitimate clients.
 
        <a href="postscreen.8.html"><b>postscreen</b>(8)</a>  maintains a temporary whitelist for clients
        that have passed a number of tests.  When an  SMTP  client
@@ -156,8 +156,8 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
               The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will wait for
               an SMTP client to send a command before  its  turn,
               and  for  DNS  blocklist  lookup  results to arrive
-              (default: 2 seconds under stress,  6  seconds  nor-
-              mally).
+              (default: up to 2 seconds under  stress,  up  to  6
+              seconds otherwise).
 
        <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
@@ -209,7 +209,7 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
               results  from a successful "bare newline" SMTP pro-
               tocol test.
 
-       <b><a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a> (1d)</b>
+       <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  cache
               results from a successful DNS blocklist test.
 
index dce9b81c5dcd283b99f39011cece274b385d0047..9712179a2061c955224ef4e6103d72002ce5ec35 100644 (file)
@@ -3858,10 +3858,10 @@ when it rejects mail.  When no mapping is found, the actual DNSBL
 domain will be used.
 .PP
 For maximal stability it is best to use a file that is read
-into memory such as pcre:, regexp: or texthash: (a format similar
-to hash: except that there is no need to run \fBpostmap\fR(1) before the
-file can be used, and that it does not detect changes after the
-file is read).
+into memory such as pcre:, regexp: or texthash: (texthash: is similar
+to hash:, except a) there is no need to run \fBpostmap\fR(1) before the
+file can be used, and b) texthash: does not detect changes after
+the file is read).
 .PP
 Example:
 .PP
@@ -3947,7 +3947,7 @@ its combined DNSBL score as defined with the postscreen_dnsbl_sites
 parameter.
 .PP
 This feature is available in Postfix 2.8.
-.SH postscreen_dnsbl_ttl (default: 1d)
+.SH postscreen_dnsbl_ttl (default: 1h)
 The amount of time that \fBpostscreen\fR(8) will cache results from
 a successful DNS blocklist test. During this time, the client IP address
 is excluded from this test. The default is relatively short, because a
@@ -4007,9 +4007,9 @@ This feature is available in Postfix 2.8.
 .SH postscreen_greet_wait (default: ${stress?2}${stress:6}s)
 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: 2 seconds under stress, 6 seconds
-normally).  This is done only when the SMTP client IP address is
-not permanently whitelisted, and when it has no cached decision.
+lookup results to arrive (default: up to 2 seconds under stress,
+up to 6 seconds otherwise).
+.PP
 Specify a non-zero time value (an integral value plus an optional
 one-letter suffix that specifies the time unit).
 .PP
index 8c49e61ceac19124b0bc588943ef236b3cd29246..152137589eb7199f3d15b2ba1604c7965ec52ab5 100644 (file)
@@ -13,10 +13,10 @@ Postfix SMTP triage server
 .ad
 .fi
 The Postfix \fBpostscreen\fR(8) server performs triage on
-multiple inbound SMTP connections in parallel. While
-\fBpostscreen\fR(8) keeps spambots away from Postfix SMTP
-server processes, more Postfix SMTP server processes remain
-available for legitimate clients.
+multiple inbound SMTP connections in parallel. While a
+single \fBpostscreen\fR(8) process keeps spambots away from
+Postfix SMTP server processes, more Postfix SMTP server
+processes remain available for legitimate clients.
 
 \fBpostscreen\fR(8) maintains a temporary whitelist for
 clients that have passed a number of tests.  When an SMTP
@@ -151,8 +151,8 @@ that they speak before their turn (pre-greet).
 .IP "\fBpostscreen_greet_wait (${stress?2}${stress:6}s)\fR"
 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: 2 seconds under stress, 6 seconds
-normally).
+lookup results to arrive (default: up to 2 seconds under stress,
+up to 6 seconds otherwise).
 .IP "\fBpostscreen_helo_required ($smtpd_helo_required)\fR"
 Require that a remote SMTP client sends HELO or EHLO before
 commencing a MAIL transaction.
@@ -190,7 +190,7 @@ temporary whitelist entry before it is removed.
 .IP "\fBpostscreen_bare_newline_ttl (30d)\fR"
 The amount of time that \fBpostscreen\fR(8) will cache results from
 a successful "bare newline" SMTP protocol test.
-.IP "\fBpostscreen_dnsbl_ttl (1d)\fR"
+.IP "\fBpostscreen_dnsbl_ttl (1h)\fR"
 The amount of time that \fBpostscreen\fR(8) will cache results from
 a successful DNS blocklist test.
 .IP "\fBpostscreen_greet_ttl (1d)\fR"
index 63e30ff2aae09cf3f0daffbbc991725a1d6f8dcb..e1541a985a1c79cdb2d7fdc9a8c970a6e718187f 100644 (file)
@@ -383,9 +383,9 @@ number.
 
 <dd> This produces similar results as hash: files, except that you
 don't have to run the postmap(1) command before you can use the
-file, and that it does not detect changes after the file is read.
-The lookup table name is "texthash:filename", where the file name
-is taken literally; no suffix is appended. </dd>
+file, and that texthash: does not detect changes after the file is
+read.  The lookup table name is "texthash:filename", where the file
+name is taken literally; no suffix is appended. </dd>
 
 <dt> <b>unix</b> (read-only) </dt>
 
index cbfaa53ed541c306f75b070757b547e023753795..eea09e73548fca30c5dc67c5d2afc274245058fb 100644 (file)
 <h2> <a name="intro">Introduction</a> </h2>
 
 <p> The Postfix postscreen(8) server performs triage on multiple
-inbound SMTP connections in parallel. While one postscreen(8) process
-keeps spambots away from Postfix SMTP server processes, more Postfix
-SMTP server processes remain available for legitimate clients. </p>
+inbound SMTP connections in parallel. While a single postscreen(8)
+process keeps spambots away from Postfix SMTP server processes,
+more Postfix SMTP server processes remain available for legitimate
+clients. </p>
 
 <p> By doing these checks in a single postscreen(8) process, Postfix
 can avoid wasting one SMTP server process per connection. A side
@@ -28,18 +29,6 @@ benefit of postscreen(8)'s DNSBL lookups is that DNS records are
 already cached before the Postfix SMTP server looks them up later.
 </p>
 
-<p> postscreen(8) maintains a temporary whitelist for clients that
-have passed a number of tests. When an SMTP client IP address is
-whitelisted, postscreen(8) hands off the connection immediately to
-a Postfix SMTP server process. This minimizes the overhead for
-legitimate mail.  </p>
-
-<p> By default, postscreen(8) logs statistics and hands off every
-connection to a Postfix SMTP server process, while excluding clients
-in mynetworks from all tests (primarily, to avoid problems with
-non-standard SMTP implementations in network appliances). This mode
-is useful for non-destructive testing. </p>
-
 <p> Topics in this document: </p>
 
 <ul>
@@ -222,10 +211,17 @@ SMTP clients that correctly implement the protocol.  </p>
 <p> To avoid problems with poorly-implemented SMTP engines in network
 appliances or network testing tools, either exclude them from all
 tests with the postscreen_whitelist_networks feature or else specify
-an empty teaser banner with: </p>
+an empty teaser banner: </p>
+
+<pre>
+/etc/postfix/main.cf:
+    # Exclude broken clients by whitelisting. $mynetworks is default.
+    postscreen_whitelist_networks = $mynetworks, 192.168.254.0/24
+</pre>
 
 <pre>
 /etc/postfix/main.cf:
+    # Disable the teaser banner (try whitelisting first if you can).
     postscreen_greet_banner =
 </pre>
 
index 749f2086d8a382061f3e0f4ca2bf63f9707842bf..5f37e1a3e07dd54e156addb14d49a463c905efdf 100644 (file)
@@ -12592,10 +12592,10 @@ seconds. </p>
 
 <p> 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: 2 seconds under stress, 6 seconds
-normally).  This is done only when the SMTP client IP address is
-not permanently whitelisted, and when it has no cached decision.
-Specify a non-zero time value (an integral value plus an optional
+lookup results to arrive (default: up to 2 seconds under stress,
+up to 6 seconds otherwise).  <p>
+
+<p> Specify a non-zero time value (an integral value plus an optional
 one-letter suffix that specifies the time unit).  </p>
 
 <p> Time units: s (seconds), m (minutes), h (hours), d (days), w
@@ -13040,7 +13040,7 @@ protocol engine.  </p>
 
 <p> This feature is available in Postfix 2.8.  </p>
 
-%PARAM postscreen_dnsbl_ttl 1d
+%PARAM postscreen_dnsbl_ttl 1h
 
 <p> The amount of time that postscreen(8) will cache results from
 a successful DNS blocklist test. During this time, the client IP address
@@ -13209,10 +13209,10 @@ when it rejects mail.  When no mapping is found, the actual DNSBL
 domain will be used. </p>
 
 <p> For maximal stability it is best to use a file that is read
-into memory such as pcre:, regexp: or texthash: (a format similar
-to hash: except that there is no need to run postmap(1) before the
-file can be used, and that it does not detect changes after the
-file is read). </p>
+into memory such as pcre:, regexp: or texthash: (texthash: is similar
+to hash:, except a) there is no need to run postmap(1) before the
+file can be used, and b) texthash: does not detect changes after
+the file is read). </p>
 
 <p> Example: </p>
 
index 2635123d5816c08cca0de34d4f8811832c33feed..6ccf575534e7b521fae466e8aec6ff5317c26755 100644 (file)
@@ -3272,7 +3272,7 @@ extern char *var_ps_dnsbl_enable;
 extern char *var_ps_dnsbl_action;
 
 #define VAR_PS_DNSBL_TTL       "postscreen_dnsbl_ttl"
-#define DEF_PS_DNSBL_TTL       "1d"
+#define DEF_PS_DNSBL_TTL       "1h"
 extern int var_ps_dnsbl_ttl;
 
 #define        VAR_PS_DNSBL_REPLY      "postscreen_dnsbl_reply_map"
index 33fe9315ecec3d9849b59d81e540809c0dbfdb3c..47369cd68a356b60f0238b6eb4a8ac45a82f1694 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      "20100913"
+#define MAIL_RELEASE_DATE      "20100914"
 #define MAIL_VERSION_NUMBER    "2.8"
 
 #ifdef SNAPSHOT
index cca2ae06643a0fdfa87822ed9f001f867248c64e..2026c09195bac3e17f4c0c22928cef20834feccf 100644 (file)
@@ -7,10 +7,10 @@
 /*     \fBpostscreen\fR [generic Postfix daemon options]
 /* DESCRIPTION
 /*     The Postfix \fBpostscreen\fR(8) server performs triage on
-/*     multiple inbound SMTP connections in parallel. While
-/*     \fBpostscreen\fR(8) keeps spambots away from Postfix SMTP
-/*     server processes, more Postfix SMTP server processes remain
-/*     available for legitimate clients.
+/*     multiple inbound SMTP connections in parallel. While a
+/*     single \fBpostscreen\fR(8) process keeps spambots away from
+/*     Postfix SMTP server processes, more Postfix SMTP server
+/*     processes remain available for legitimate clients.
 /*
 /*     \fBpostscreen\fR(8) maintains a temporary whitelist for
 /*     clients that have passed a number of tests.  When an SMTP
 /* .IP "\fBpostscreen_greet_wait (${stress?2}${stress:6}s)\fR"
 /*     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: 2 seconds under stress, 6 seconds
-/*     normally).
+/*     lookup results to arrive (default: up to 2 seconds under stress,
+/*     up to 6 seconds otherwise).
 /* .IP "\fBpostscreen_helo_required ($smtpd_helo_required)\fR"
 /*     Require that a remote SMTP client sends HELO or EHLO before
 /*     commencing a MAIL transaction.
 /* .IP "\fBpostscreen_bare_newline_ttl (30d)\fR"
 /*     The amount of time that \fBpostscreen\fR(8) will cache results from
 /*     a successful "bare newline" SMTP protocol test.
-/* .IP "\fBpostscreen_dnsbl_ttl (1d)\fR"
+/* .IP "\fBpostscreen_dnsbl_ttl (1h)\fR"
 /*     The amount of time that \fBpostscreen\fR(8) will cache results from
 /*     a successful DNS blocklist test.
 /* .IP "\fBpostscreen_greet_ttl (1d)\fR"
@@ -843,7 +843,7 @@ int     main(int argc, char **argv)
        0,
     };
     static const CONFIG_NINT_TABLE nint_table[] = {
-       VAR_PS_POST_QLIMIT, DEF_PS_POST_QLIMIT, &var_ps_post_queue_limit, 10, 0,
+       VAR_PS_POST_QLIMIT, DEF_PS_POST_QLIMIT, &var_ps_post_queue_limit, 5, 0,
        VAR_PS_PRE_QLIMIT, DEF_PS_PRE_QLIMIT, &var_ps_pre_queue_limit, 10, 0,
        0,
     };
index 2c357e737987adb84ff2f4eee358093ac878edc9..4dc351c6a55376cd3a38a42347a4720f19ba0ab9 100644 (file)
@@ -78,21 +78,33 @@ typedef struct {
   * Important: every MUMBLE_TODO flag must have a MUMBLE_PASS flag, such that
   * MUMBLE_PASS == PS_STATE_FLAGS_TODO_TO_PASS(MUMBLE_TODO).
   * 
-  * MUMBLE_TODO flags must not be cleared once they are raised. The code in
-  * ps_conclude() depends on this when it decides that all unfinished tests
-  * are completed.
+  * MUMBLE_TODO flags must not be cleared once raised. The _TODO_TO_PASS and
+  * _TODO_TO_DONE macros depend on this to decide that a group of tests is
+  * passed or completed.
+  * 
+  * MUMBLE_DONE flags are used for "early" tests that have final results.
+  * 
+  * MUMBLE_SKIP flags are used for "deep" tests where the client messed up.
+  * These flags look like MUMBLE_DONE but they are different. Deep tests can
+  * tentatively pass, but can still fail later in a session. The "ignore"
+  * action introduces an additional complication. MUMBLE_PASS indicates
+  * either that a deep test passed tentatively, or that the test failed but
+  * 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".
   */
 #define PS_STATE_FLAGS_TODO_TO_PASS(todo_flags) ((todo_flags) >> 1)
+#define PS_STATE_FLAGS_TODO_TO_DONE(todo_flags) ((todo_flags) << 1)
 
- /* Room here for one more before-handshake test. */
-
-#define PS_STATE_FLAG_PREGR_FAIL       (1<<10) /* failed pregreet test */
-#define PS_STATE_FLAG_PREGR_PASS       (1<<11) /* passed pregreet test */
-#define PS_STATE_FLAG_PREGR_TODO       (1<<12) /* pregreet test expired */
+#define PS_STATE_FLAG_PREGR_FAIL       (1<<8)  /* failed pregreet test */
+#define PS_STATE_FLAG_PREGR_PASS       (1<<9)  /* passed pregreet test */
+#define PS_STATE_FLAG_PREGR_TODO       (1<<10) /* pregreet test expired */
+#define PS_STATE_FLAG_PREGR_DONE       (1<<11) /* decision is final */
 
-#define PS_STATE_FLAG_DNSBL_FAIL       (1<<13) /* failed DNSBL test */
-#define PS_STATE_FLAG_DNSBL_PASS       (1<<14) /* passed DNSBL test */
-#define PS_STATE_FLAG_DNSBL_TODO       (1<<15) /* DNSBL test expired */
+#define PS_STATE_FLAG_DNSBL_FAIL       (1<<12) /* failed DNSBL test */
+#define PS_STATE_FLAG_DNSBL_PASS       (1<<13) /* passed DNSBL test */
+#define PS_STATE_FLAG_DNSBL_TODO       (1<<14) /* DNSBL test expired */
+#define PS_STATE_FLAG_DNSBL_DONE       (1<<15) /* decision is final */
 
  /* Room here for one more after-handshake test. */
 
@@ -142,6 +154,8 @@ typedef struct {
  /*
   * Separate aggregates for early tests and deep tests.
   */
+#define PS_STATE_FLAG_EARLY_DONE \
+       (PS_STATE_FLAG_PREGR_DONE | PS_STATE_FLAG_DNSBL_DONE)
 #define PS_STATE_FLAG_EARLY_TODO \
        (PS_STATE_FLAG_PREGR_TODO | PS_STATE_FLAG_DNSBL_TODO)
 #define PS_STATE_FLAG_EARLY_PASS \
@@ -359,7 +373,7 @@ extern void ps_cache_update(DICT_CACHE *, const char *, const char *);
   */
 extern void ps_dnsbl_init(void);
 extern int ps_dnsbl_retrieve(const char *, const char **);
-extern void ps_dnsbl_request(const char *);
+extern void ps_dnsbl_request(const char *, void (*) (int, char *), char *);
 
  /*
   * postscreen_tests.c
index 1016ea65b856e00b3f2288a4a99a7813ec407b87..f40520f8e1335808b0d5c16b4157f5b7b5d41db8 100644 (file)
@@ -8,8 +8,10 @@
 /*
 /*     void    ps_dnsbl_init(void)
 /*
-/*     void    ps_dnsbl_request(client_addr)
+/*     void    ps_dnsbl_request(client_addr, callback, context)
 /*     char    *client_addr;
+/*     void    (*callback)(int, char *);
+/*     char    *context;
 /*
 /*     int     ps_dnsbl_retrieve(client_addr, dnsbl_name)
 /*     char    *client_addr;
 /*
 /*     ps_dnsbl_request() requests a blocklist score for the
 /*     specified client IP address and increments the reference
-/*     count. The request completes in the background. The
-/*     client IP address must be in inet_ntop(3) output format.
+/*     count.  The request completes in the background. The client
+/*     IP address must be in inet_ntop(3) output format.  The
+/*     callback argument specifies a function that is called when
+/*     the requested result is available. The context is passed
+/*     on to the callback function. The callback should ignore its
+/*     first argument (it exists for compatibility with Postfix
+/*     generic event infrastructure).
 /*
 /*     ps_dnsbl_retrieve() retrieves the result score requested with
 /*     ps_dnsbl_request() and decrements the reference count. It
@@ -100,20 +107,64 @@ typedef struct PS_DNSBL_SITE {
  /*
   * Per-client DNSBL scores.
   * 
-  * One remote SMTP client may make parallel connections and thereby trigger
-  * parallel blocklist score requests. We combine identical requests under
-  * the client IP address in a single reference-counted entry. The reference
-  * count goes up with each score request, and it goes down with each score
-  * retrieval.
+  * Some SMTP clients make parallel connections. This can trigger parallel
+  * blocklist score requests when the pre-handshake delays of the connections
+  * overlap.
+  * 
+  * We combine requests for the same score under the client IP address in a
+  * single reference-counted entry. The reference count goes up with each
+  * request for a score, and it goes down with each score retrieval. Each
+  * score has one or more requestors that need to be notified when the result
+  * is ready, so that postscreen can terminate a pre-handshake delay when all
+  * pre-handshake tests are completed.
   */
 static HTABLE *dnsbl_score_cache;      /* indexed by client address */
 
+typedef struct {
+    void    (*callback) (int, char *); /* generic call-back routine */
+    char   *context;                   /* generic call-back argument */
+} PS_CALL_BACK_ENTRY;
+
 typedef struct {
     const char *dnsbl;                 /* one contributing DNSBL */
     int     total;                     /* combined blocklist score */
     int     refcount;                  /* score reference count */
+    int     pending_lookups;           /* nr of DNS requests in flight */
+    /* Call-back table support. */
+    int     index;                     /* next table index */
+    int     limit;                     /* last valid index */
+    PS_CALL_BACK_ENTRY table[1];       /* actually a bunch */
 } PS_DNSBL_SCORE;
 
+#define PS_CALL_BACK_INIT(sp) do { \
+       (sp)->limit = 0; \
+       (sp)->index = 0; \
+    } while (0)
+
+#define PS_CALL_BACK_EXTEND(hp, sp) do { \
+       if ((sp)->index >= (sp)->limit) { \
+           int _count_ = ((sp)->limit ? (sp)->limit * 2 : 5); \
+           (hp)->value = myrealloc((char *) (sp), sizeof(*(sp)) + \
+                                   _count_ * sizeof((sp)->table)); \
+           (sp) = (PS_DNSBL_SCORE *) (hp)->value; \
+           (sp)->limit = _count_; \
+       } \
+    } while (0)
+
+#define PS_CALL_BACK_ENTER(sp, fn, ctx) do { \
+       PS_CALL_BACK_ENTRY *_cb_ = (sp)->table + (sp)->index++; \
+       _cb_->callback = (fn); \
+       _cb_->context = (ctx); \
+    } while (0)
+
+#define PS_CALL_BACK_NOTIFY(sp, ev) do { \
+       PS_CALL_BACK_ENTRY *_cb_; \
+       for (_cb_ = (sp)->table; _cb_ < (sp)->table + (sp)->index; _cb_++) \
+           _cb_->callback((ev), _cb_->context); \
+    } while (0)
+
+#define PS_NULL_EVENT  (0)
+
  /*
   * Per-request state.
   * 
@@ -306,32 +357,68 @@ static void ps_dnsbl_receive(int event, char *context)
        }
        if (reply_argv != 0)
            argv_free(reply_argv);
+    } else {
+       msg_warn("%s: unexpected event: %d", myname, event);
     }
+
+    /*
+     * We're done with this stream. Notify the requestor(s) that the result
+     * is ready to be picked up. If this call isn't made, clients have to sit
+     * out the entire pre-handshake delay.
+     */
+    score->pending_lookups -= 1;
+    if (score->pending_lookups == 0)
+       PS_CALL_BACK_NOTIFY(score, PS_NULL_EVENT);
+
     vstream_fclose(stream);
 }
 
 /* ps_dnsbl_request  - send dnsbl query, increment reference count */
 
-void    ps_dnsbl_request(const char *client_addr)
+void    ps_dnsbl_request(const char *client_addr,
+                                void (*callback) (int, char *),
+                                char *context)
 {
     const char *myname = "ps_dnsbl_request";
     int     fd;
     VSTREAM *stream;
     HTABLE_INFO **ht;
     PS_DNSBL_SCORE *score;
+    HTABLE_INFO *hash_node;
 
     /*
-     * Avoid duplicate effort when this lookup is already in progress. We
-     * store a reference-counted DNSBL score under its client IP address. We
-     * increment the reference count with each request, and decrement the
-     * reference count with each retrieval.
+     * Some spambots make several connections at nearly the same time,
+     * causing their pregreet delays to overlap. Such connections can share
+     * the efforts of DNSBL lookup.
+     * 
+     * We store a reference-counted DNSBL score under its client IP address. We
+     * increment the reference count with each score request, and decrement
+     * the reference count with each score retrieval.
      * 
-     * XXX Notify the requestor as soon as all DNS replies are in, to avoid
-     * unnecessary delay when we only need the DNSBL score.
+     * Do not notify the requestor NOW when the DNS replies are already in.
+     * Reason: we must not make a backwards call while we are still in the
+     * middle of executing the corresponding forward call. Instead we create
+     * a zero-delay timer request and call the notification function from
+     * there.
+     * 
+     * ps_dnsbl_request() could instead return a result value to indicate that
+     * the DNSBL score is already available, but that would complicate the
+     * caller with two different notification code paths: one asynchronous
+     * code path via the callback invocation, and one synchronous code path
+     * via the ps_dnsbl_request() result value. That would be a source of
+     * future bugs.
      */
-    if ((score = (PS_DNSBL_SCORE *)
-        htable_find(dnsbl_score_cache, client_addr)) != 0) {
+    if ((hash_node = htable_locate(dnsbl_score_cache, client_addr)) != 0) {
+       score = (PS_DNSBL_SCORE *) hash_node->value;
        score->refcount += 1;
+       PS_CALL_BACK_EXTEND(hash_node, score);
+       PS_CALL_BACK_ENTER(score, callback, context);
+       if (msg_verbose > 1)
+           msg_info("%s: reuse blocklist score for %s refcount=%d pending=%d",
+                    myname, client_addr, score->refcount,
+                    score->pending_lookups);
+       if (score->pending_lookups == 0)
+           event_request_timer(callback, context, EVENT_NULL_DELAY);
        return;
     }
     if (msg_verbose > 1)
@@ -339,6 +426,9 @@ void    ps_dnsbl_request(const char *client_addr)
     score = (PS_DNSBL_SCORE *) mymalloc(sizeof(*score));
     score->total = 0;
     score->refcount = 1;
+    score->pending_lookups = 0;
+    PS_CALL_BACK_INIT(score);
+    PS_CALL_BACK_ENTER(score, callback, context);
     (void) htable_enter(dnsbl_score_cache, client_addr, (char *) score);
 
     /*
@@ -350,7 +440,7 @@ void    ps_dnsbl_request(const char *client_addr)
     for (ht = dnsbl_site_list; *ht; ht++) {
        if ((fd = LOCAL_CONNECT("private/" DNSBL_SERVICE, NON_BLOCKING, 1)) < 0) {
            msg_warn("%s: connect to " DNSBL_SERVICE " service: %m", myname);
-           return;
+           continue;
        }
        stream = vstream_fdopen(fd, O_RDWR);
        attr_print(stream, ATTR_FLAG_NONE,
@@ -360,10 +450,11 @@ void    ps_dnsbl_request(const char *client_addr)
        if (vstream_fflush(stream) != 0) {
            msg_warn("%s: error sending to " DNSBL_SERVICE " service: %m", myname);
            vstream_fclose(stream);
-           return;
+           continue;
        }
        PS_READ_EVENT_REQUEST(vstream_fileno(stream), ps_dnsbl_receive,
                              (char *) stream, DNSBLOG_TIMEOUT);
+       score->pending_lookups += 1;
     }
 }
 
index e6ed4d9746bd62175ad976e4d8fac3fd4fd6981a..4cf380f50fc960542e22441aaec079321320f9d1 100644 (file)
@@ -195,14 +195,49 @@ static void ps_early_event(int event, char *context)
            msg_panic("%s: unknown pregreet action value %d",
                      myname, ps_pregr_action);
        }
-       if (elapsed > PS_EFF_GREET_WAIT)
-           elapsed = PS_EFF_GREET_WAIT;
-       event_request_timer(ps_early_event, context,
-                           PS_EFF_GREET_WAIT - elapsed);
+
+       /*
+        * Terminate the greet delay if we're just waiting for the pregreet
+        * test to complete. It is safe to call ps_early_event directly,
+        * since we are already in that function.
+        * 
+        * XXX After this code passes all tests, swap around the two blocks in
+        * this switch statement and fall through from EVENT_READ into
+        * EVENT_TIME, instead of calling ps_early_event recursively.
+        */
+       state->flags |= PS_STATE_FLAG_PREGR_DONE;
+       if (elapsed >= PS_EFF_GREET_WAIT
+           || ((state->flags & PS_STATE_FLAG_EARLY_DONE)
+               == PS_STATE_FLAGS_TODO_TO_DONE(state->flags & PS_STATE_FLAG_EARLY_TODO)))
+           ps_early_event(EVENT_TIME, context);
+       else
+           event_request_timer(ps_early_event, context,
+                               PS_EFF_GREET_WAIT - elapsed);
        return;
     }
 }
 
+/* ps_early_dnsbl_event - cancel pregreet timer if waiting for DNS only */
+
+static void ps_early_dnsbl_event(int unused_event, char *context)
+{
+    const char *myname = "ps_early_dnsbl_event";
+    PS_STATE *state = (PS_STATE *) context;
+
+    if (msg_verbose)
+       msg_info("%s: notify %s:%s", myname, PS_CLIENT_ADDR_PORT(state));
+
+    /*
+     * Terminate the greet delay if we're just waiting for DNSBL lookup to
+     * complete. Don't call ps_early_event directly, that would result in a
+     * dangling pointer.
+     */
+    state->flags |= PS_STATE_FLAG_DNSBL_DONE;
+    if ((state->flags & PS_STATE_FLAG_EARLY_DONE)
+    == PS_STATE_FLAGS_TODO_TO_DONE(state->flags & PS_STATE_FLAG_EARLY_TODO))
+       event_request_timer(ps_early_event, context, EVENT_NULL_DELAY);
+}
+
 /* ps_early_tests - start the early (before protocol) tests */
 
 void    ps_early_tests(PS_STATE *state)
@@ -231,7 +266,8 @@ void    ps_early_tests(PS_STATE *state)
      * Run a DNS blocklist query.
      */
     if ((state->flags & PS_STATE_FLAG_DNSBL_TODO) != 0)
-       ps_dnsbl_request(state->smtp_client_addr);
+       ps_dnsbl_request(state->smtp_client_addr, ps_early_dnsbl_event,
+                           (char *) state);
 
     /*
      * Wait for the client to respond or for DNS lookup to complete.
index b449f957a410dcfa0c7c6ee93603552109cb8120..06a037fabc9642c9dc9b0a8c319717776a723419 100644 (file)
@@ -227,10 +227,12 @@ const char *ps_print_state_flags(int flags, const char *context)
        "PREGR_FAIL", PS_STATE_FLAG_PREGR_FAIL,
        "PREGR_PASS", PS_STATE_FLAG_PREGR_PASS,
        "PREGR_TODO", PS_STATE_FLAG_PREGR_TODO,
+       "PREGR_DONE", PS_STATE_FLAG_PREGR_DONE,
 
        "DNSBL_FAIL", PS_STATE_FLAG_DNSBL_FAIL,
        "DNSBL_PASS", PS_STATE_FLAG_DNSBL_PASS,
        "DNSBL_TODO", PS_STATE_FLAG_DNSBL_TODO,
+       "DNSBL_DONE", PS_STATE_FLAG_DNSBL_DONE,
 
        "PIPEL_FAIL", PS_STATE_FLAG_PIPEL_FAIL,
        "PIPEL_PASS", PS_STATE_FLAG_PIPEL_PASS,
index 116ab5bca34c406b8dfbe67f02f115b292e48bcd..c6fb9818438978d51a07db9b0473e9211d9e824d 100644 (file)
@@ -169,7 +169,7 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
     dict_thash->dict.lookup = dict_thash_lookup;
     dict_thash->dict.sequence = dict_thash_sequence;
     dict_thash->dict.close = dict_thash_close;
-    dict_thash->dict.flags = dict_flags | DICT_FLAG_FIXED;
+    dict_thash->dict.flags = dict_flags | DICT_FLAG_DUP_WARN | DICT_FLAG_FIXED;
     if (dict_flags & DICT_FLAG_FOLD_FIX)
        dict_thash->dict.fold_buf = vstring_alloc(10);
     dict_thash->info = 0;
index 50751db961be0abf003675b5d44bc1023c90da7c..c8cc6aeca73856549609f8e76df370c37cdc0d33 100644 (file)
@@ -61,7 +61,8 @@
 /*     event_request_timer() causes the specified callback function to
 /*     be called with the specified context argument after \fIdelay\fR
 /*     seconds, or as soon as possible thereafter. The delay should
-/*     not be negative.
+/*     not be negative (the manifest EVENT_NULL_DELAY provides for
+/*     convenient zero-delay notification).
 /*     The event argument is equal to EVENT_TIME.
 /*     Only one timer request can be active per (callback, context) pair.
 /*     Calling event_request_timer() with an existing (callback, context)
index 200f7594b0d7fe9e6ec2b0a3b1a7c5cdbb895b2b..6ea89119a7581b3ff88dcee381b81c2c1054154c 100644 (file)
@@ -45,8 +45,9 @@ extern void event_fork(void);
  /*
   * Dummies.
   */
-#define EVENT_NULL_TYPE        0
+#define EVENT_NULL_TYPE                (0)
 #define EVENT_NULL_CONTEXT     ((char *) 0)
+#define EVENT_NULL_DELAY       (0)
 
 /* LICENSE
 /* .ad