]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20110501
authorWietse Venema <wietse@porcupine.org>
Sun, 1 May 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:20 +0000 (06:37 +0000)
35 files changed:
postfix/HISTORY
postfix/README_FILES/OVERVIEW
postfix/README_FILES/POSTSCREEN_README
postfix/WISHLIST
postfix/html/OVERVIEW.html
postfix/html/POSTSCREEN_README.html
postfix/html/postconf.1.html
postfix/html/postconf.5.html
postfix/html/smtpd.8.html
postfix/man/man1/postconf.1
postfix/man/man5/postconf.5
postfix/man/man8/smtpd.8
postfix/proto/OVERVIEW.html
postfix/proto/POSTSCREEN_README.html
postfix/proto/postconf.proto
postfix/src/cleanup/cleanup_milter.c
postfix/src/global/abounce.c
postfix/src/global/abounce.h
postfix/src/global/mail_version.h
postfix/src/global/smtp_stream.c
postfix/src/local/Makefile.in
postfix/src/local/bounce_workaround.c
postfix/src/local/mailbox.c
postfix/src/local/unknown.c
postfix/src/milter/milter8.c
postfix/src/oqmgr/qmgr_active.c
postfix/src/postconf/postconf.c
postfix/src/postscreen/postscreen.c
postfix/src/qmgr/qmgr_active.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_sasl_proto.c
postfix/src/util/Makefile.in
postfix/src/util/dict.h
postfix/src/util/dict_open.c
postfix/src/verify/verify.c

index 6b1ca98866be8298d3377ec04417db911bf78122..35735c497792ae28e4ec08cd7effc6c178b2401f 100644 (file)
@@ -15616,7 +15616,7 @@ Apologies for any names omitted.
        for the "virtual:" transport to "/etc/postfix/virtual:".
        Symptom reported by Christoph Anton Mitterer.
 
-20200102
+20100102
 
        Workaround: don't report bogus Berkeley DB close errors as
        fatal errors. All operations before close are already error
@@ -16753,3 +16753,54 @@ Apologies for any names omitted.
 
        Bitrot: text about queue ID reuse in the postsuper manpage.
        File: postsuper/postsuper.c.
+
+20110328
+
+       Cleanup: don't log warnings about socket shutdown() errors
+       after a connection breaks. Postfix calls shutdown() to avoid
+       unnecessary socket write timeouts. This is only an optimization,
+       and failure is not critical.  File: global/smtp_stream.c.
+
+20110411
+
+       Cleanup: postscreen(8) and verify(8) daemons now lock their
+       respective cache file exclusively upon open, to avoid massive
+       cache corruption by unsupported sharing. Files: util/dict.h,
+       util/dict_open.c, verify/verify.c, postscreen/postscreen.c.
+
+20110414
+
+       Bugfix (introduced with Postfix SASL patch 20000314): don't
+       reuse a server Cyrus SASL handle after authentication
+       failure. File: smtpd/smtpd_proto.c.
+
+20110418
+
+       Bugfix (introduced Postfix 2.3 and Postfix 2.7): the Milter
+       client reported some "file too large" errors as temporary
+       errors. Problem reported by Michael Tokarev. Files:
+       milter/milter8.c, cleanup/cleanup_milter.c.
+
+20110420
+
+       Performance: a high load of DSN success notification requests
+       could stall the queue manager. Solution: make the trace
+       client asynchronous, just like the bounce and defer clients.
+       Problem reported by Eduardo M. Stelmaszczyk of terra.com.br.
+       Files: global/abounce.[hc], *qmgr/qmgr_active.c (the
+       qmgr_active.c files are identical).
+
+20110421
+
+       Cleanup: updated abounce warning message, and added a safety
+       timeout to abounce() etc. requests. File: global/abounce.c.
+
+20110426
+
+       Bugfix (introduced in Postfix 1.1, duplicated in Postfix
+       2.3, unrelated mistake in Postfix 2.7): the local(8) delivery
+       agent ignored table lookup errors in mailbox_command_maps,
+       mailbox_transport_maps, fallback_transport_maps and (while
+       bouncing mail to alias) alias owner lookup. Problem reported
+       by William Ono. Files: local/command.c, local/mailbox.c,
+       local/unknown.c, local/bounce_workaround.c.
index ee271e61b9d861d12ef9a762a3ed98c76f044c8b..637ea9842087b1900f725efd2d614654bf8a8342 100644 (file)
@@ -370,8 +370,12 @@ queues.
     While postscreen(8) keeps the zombies away, more smtpd(8) processes remain
     available for legitimate clients.
 
+    postscreen(8) maintains a temporary whitelist for clients that pass its
+    tests; by allowing whitelisted clients to skip tests, postscreen(8)
+    minimizes its impact on legitimate email traffic.
+
     The postscreen(8) server is available with Postfix 2.8 and later. To keep
-    the implementation simple, postscreen(8) delegates DNS white/backlist
+    the implementation simple, postscreen(8) delegates DNS white/blacklist
     lookups to dnsblog(8) server processes, and delegates TLS encryption/
     decryption to tlsproxy(8) server processes. This delegation is invisible to
     the remote SMTP client, and is not shown in the diagram below.
index 19df31b0a8a70765c2dafc147983e80553b649c1..71fb3eb335224cd24bb6f5d893735aeda011931b 100644 (file)
@@ -9,6 +9,10 @@ connections at the same time. While a single postscreen(8) process keeps
 zombies away from Postfix SMTP server processes, more Postfix SMTP server
 processes remain available for legitimate clients.
 
+postscreen(8) maintains a temporary whitelist for clients that pass its tests;
+by allowing whitelisted clients to skip tests, postscreen(8) minimizes its
+impact on legitimate email traffic.
+
 postscreen(8) should not be used on SMTP ports that receive mail from end-user
 clients (MUAs). In a typical deployment, postscreen(8) is used on the "port 25"
 service, while MUA clients submit mail via the submission service.
@@ -83,10 +87,10 @@ focused on.
 G\bGe\ben\bne\ber\bra\bal\bl o\bop\bpe\ber\bra\bat\bti\bio\bon\bn
 
 The postscreen(8) triage process involves a number of tests, in the order as
-described below. Some tests introduce a delay of a few seconds. Once a client
-passes a test, its IP address is whitelisted from 24 hours for simple tests, to
-1 week for complex tests. Whitelisting minimizes the impact of postscreen(8)'s
-tests on legitimate mail clients.
+described below. Some tests introduce a delay of a few seconds. postscreen(8)
+maintains a temporary whitelist for clients that pass its tests; by allowing
+whitelisted clients to skip tests, postscreen(8) minimizes its impact on
+legitimate email traffic.
 
 By default, postscreen(8) hands off all connections to a Postfix SMTP server
 process after logging its findings. This mode is useful for non-destructive
@@ -448,14 +452,16 @@ d\bdr\bro\bop\bp (default for non-SMTP commands)
 
 O\bOt\bth\bhe\ber\br e\ber\brr\bro\bor\brs\bs
 
-When an SMTP client hangs up unexpectedly during any tests, postscreen(8) logs
-this as:
+When an SMTP client hangs up unexpectedly, postscreen(8) logs this as:
 
     H\bHA\bAN\bNG\bGU\bUP\bP a\baf\bft\bte\ber\br time f\bfr\bro\bom\bm [address]:port i\bin\bn test name
 
 Translation: the SMTP client at [address]:port disconnected unexpectedly, time
 seconds after the start of the test named test name.
 
+There is no punishment for hanging up. A client that hangs up without sending
+the QUIT command can still pass all postscreen(8) tests.
+
 The following errors are reported by the built-in SMTP engine. This engine
 never accepts mail, therefore it has per-session limits on the number of
 commands and on the session length.
index ebcbabc1eeb9550aa0f3a959c84030f18aa53a5e..f2a13b73f164d1d4ac248fbc86a852eb799f95a8 100644 (file)
@@ -11,11 +11,13 @@ Wish list:
        Don't forget Apple's code donation for fetching mail from
        IMAP server.
 
-       Simplify postscreen logic: set the noforward flag if the
-       client made an unforgivable error. Individual "fail" flags
-       are needed only to avoid logging the same offense multiple
-       times. Individual "pass" flags are still needed as proof
-       that the client didn't skip tests by hanging up early.
+       Simplify postscreen logic. Individual "fail" flags help to
+       avoid repeated testing/logging the same mistake.  Individual
+       "pass" flags provide evidence that the client didn't skip
+       tests by hanging up early. The current global "noforward"
+       flag implements the wrong model: instead we need an indicator
+       that a client has passed all tests or that all mistakes
+       were forgiven.
 
        In the SMTP server, check if the connection is closed before
        replying to ".", and discard the message if the reply can't
@@ -23,17 +25,14 @@ Wish list:
        duplication, and may even prevent the delivery of some spam.
        http://www.exim.org/lurker/message/20070416.103159.9d5ff0ce.en.html
 
+       Find out how to reproduce Berkeley DB bogus ENOENT errors.
+       postscreen does not log this with Berkeley DB 1 (FreeBSD
+       4..8), 4.7.25 (Ubuntu 9.04) and 4.8.24 (Ubuntu 10.04).
+
        postconf command-line option to show the compile-time
        settings (CCARGS, AUXLIBS) in case binary packages
        don't install the makedefs.out file.
 
-       propagate alias owner from pcre, regexp, cidr, texthash,
-       etc. databases, i.e. set the owner property at open time;
-       it can't be looked up at run-time with fstat(dict->stat_fd)
-       because there is no open file. What about *SQL, LDAP, etc.?
-       Maybe use the source of the configuration file? We can reuse
-       that to enforce root ownership of main/master.cf files.
-
        events.c: cache the side effects of file descriptor event
        enable/disable operations in user space, and do bulk kernel
        updates at event_loop() time.  This can eliminate costly
@@ -85,10 +84,6 @@ Wish list:
        This would apply to postmaster notices and bounce messages
        (DKIM), and address verification (BATV).
 
-       As postscreen implements more ESMTP keywords, need to copy
-       inter-operability features from smtpd to filter keywords
-       and command syntax.
-
        Consistency: in postconf.proto make <dt>..</dt> tags bold.
 
        postscreen(8): listen on multiple IP addresses and enforce
index 0f55aa157f03c69e5bab94defbfba3a076064904..1393e26d03a21d6bb438a2fc7d26ea9a23bd7d28 100644 (file)
@@ -737,9 +737,14 @@ those numbers were 92% and 95%, respectively.  While <a href="postscreen.8.html"
 keeps the zombies away, more <a href="smtpd.8.html">smtpd(8)</a> processes remain available
 for legitimate clients.  </p>
 
+<p> <a href="postscreen.8.html">postscreen(8)</a> maintains a temporary whitelist for clients that
+pass its tests; by allowing whitelisted clients to skip tests,
+<a href="postscreen.8.html">postscreen(8)</a> minimizes its impact on legitimate email traffic.
+</p>
+
 <p> The <a href="postscreen.8.html">postscreen(8)</a> server is available with Postfix 2.8 and
 later. To keep the implementation simple, <a href="postscreen.8.html">postscreen(8)</a> delegates
-DNS white/backlist lookups to <a href="dnsblog.8.html">dnsblog(8)</a> server processes, and
+DNS white/blacklist lookups to <a href="dnsblog.8.html">dnsblog(8)</a> server processes, and
 delegates TLS encryption/decryption to <a href="tlsproxy.8.html">tlsproxy(8)</a> server processes.
 This delegation is invisible to the remote SMTP client, and is not
 shown in the diagram below.  </p>
index d20d13672db6e1614ea379cb11baada69698e3d1..6b501fdeca780a3eddc3dc1461f241fff46185b6 100644 (file)
@@ -23,6 +23,11 @@ process keeps zombies away from Postfix SMTP server processes, more
 Postfix SMTP server processes remain available for legitimate
 clients. </p>
 
+<p> <a href="postscreen.8.html">postscreen(8)</a> maintains a temporary whitelist for clients that
+pass its tests; by allowing whitelisted clients to skip tests,
+<a href="postscreen.8.html">postscreen(8)</a> minimizes its impact on legitimate email traffic.
+</p>
+
 <p> <a href="postscreen.8.html">postscreen(8)</a> should not be used on SMTP ports that receive
 mail from end-user clients (MUAs). In a typical deployment,
 <a href="postscreen.8.html">postscreen(8)</a> is used on the "port 25" service, while MUA clients
@@ -121,10 +126,10 @@ and that is the problem that <a href="postscreen.8.html">postscreen(8)</a> is fo
 
 <p> The <a href="postscreen.8.html">postscreen(8)</a> triage process involves a number of tests,
 in the order as described below.  Some tests introduce a delay of
-a few seconds.  Once a client passes a test, its IP address is
-whitelisted from 24 hours for simple tests, to 1 week for complex
-tests.  Whitelisting minimizes the impact of <a href="postscreen.8.html">postscreen(8)</a>'s tests
-on legitimate mail clients. </p>
+a few seconds.  <a href="postscreen.8.html">postscreen(8)</a> maintains a temporary whitelist for
+clients that pass its tests; by allowing whitelisted clients to
+skip tests, <a href="postscreen.8.html">postscreen(8)</a> minimizes its impact on legitimate email
+traffic.  </p>
 
 <p> By default, <a href="postscreen.8.html">postscreen(8)</a> hands off all connections to a Postfix
 SMTP server process after logging its findings. This mode is useful
@@ -606,8 +611,8 @@ feature. </dd>
 
 <h2> <a name="other_error">Other errors</a> </h2>
 
-<p> When an SMTP client hangs up unexpectedly during any tests,
-<a href="postscreen.8.html">postscreen(8)</a> logs this as: </p>
+<p> When an SMTP client hangs up unexpectedly, <a href="postscreen.8.html">postscreen(8)</a> logs
+this as: </p>
 
 <pre>
     <b>HANGUP after</b> <i>time</i> <b>from</b> <i>[address]:port</i> <b>in</b> <i>test name</i>
@@ -617,6 +622,10 @@ feature. </dd>
 unexpectedly, <i>time</i> seconds after the start of the
 test named <i>test name</i>. </p>
 
+<p> There is no punishment for hanging up. A client that hangs up
+without sending the QUIT command can still pass all <a href="postscreen.8.html">postscreen(8)</a>
+tests. </p>
+
 <!--
 
 <p> While an unexpired penalty is in effect, an SMTP client is not
index 614b7b0ab4eefad1a5e22d764805da3faf34bd9a..1e351dcb6e9ebb113e183d0bb9d1b6ef5c967a85 100644 (file)
@@ -88,8 +88,8 @@ POSTCONF(1)                                                        POSTCONF(1)
               With  Postfix  version  2.8 and later, the <b>-e</b> is no
               longer needed.
 
-       <b>-h</b>     Show parameter values only, not the "<i>name = " label</i>
-              <i>that normally precedes the value.</i>
+       <b>-h</b>     Show parameter values only, not the "<i>name =</i> " label
+              that normally precedes the value.
 
        <b>-l</b>     List  the  names  of  all supported mailbox locking
               methods.  Postfix supports the following methods:
@@ -184,7 +184,7 @@ POSTCONF(1)                                                        POSTCONF(1)
 
               <b>static</b> (read-only)
                      A  table  that  always  returns  its name as
-                     lookup result.  For  example,  <b>static:foobar</b>
+                     lookup result.  For  example,  <b><a href="DATABASE_README.html#types">static</a>:foobar</b>
                      always  returns  the string <b>foobar</b> as lookup
                      result.
 
index 230106a9c678ca550c38a83e3f5120234088e57a..a9bf5e565298b02848f245b7fb4515f8ae3e3bc1 100644 (file)
@@ -5785,6 +5785,13 @@ content.  The usual C-like escape sequences are recognized: <tt>\a
 \b \f \n \r \t \v \<i>ddd</i></tt> (up to three octal digits) and
 <tt>\\</tt>. </p>
 
+<p> Note 1: this feature does not recognize text that requires MIME
+decoding. It inspects raw message content, just like <a href="postconf.5.html#header_checks">header_checks</a>
+and <a href="postconf.5.html#body_checks">body_checks</a>.  </p>
+
+<p> Note 2: this feature is disabled with "<a href="postconf.5.html#receive_override_options">receive_override_options</a>
+= <a href="postconf.5.html#no_header_body_checks">no_header_body_checks</a>".  </p>
+
 <p> Example: </p>
 
 <pre>
@@ -5819,6 +5826,13 @@ content.  The usual C-like escape sequences are recognized: <tt>\a
 \b \f \n \r \t \v \<i>ddd</i></tt> (up to three octal digits) and
 <tt>\\</tt>. </p>
 
+<p> Note 1: this feature does not recognize text that requires MIME
+decoding. It inspects raw message content, just like <a href="postconf.5.html#header_checks">header_checks</a>
+and <a href="postconf.5.html#body_checks">body_checks</a>.  </p>
+
+<p> Note 2: this feature is disabled with "<a href="postconf.5.html#receive_override_options">receive_override_options</a>
+= <a href="postconf.5.html#no_header_body_checks">no_header_body_checks</a>".  </p>
+
 <p> Example: </p>
 
 <pre>
index 9c7f4021e0f83f85759d9ca3b31f810d391bd6f8..adf5300f9c495820ce56186c07296cf593ba2dba 100644 (file)
@@ -158,7 +158,7 @@ SMTPD(8)                                                              SMTPD(8)
        <b><a href="postconf.5.html#smtpd_per_record_deadline">smtpd_per_record_deadline</a> (normal: no, overload: yes)</b>
               Change  the  behavior  of  the  <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a>  time
               limit, from a time limit per read or  write  system
-              call,  to  a time limit to read or write a complete
+              call, to a time limit to send or receive a complete
               record (an SMTP command line, SMTP  response  line,
               SMTP  message  content  line,  or TLS protocol mes-
               sage).
@@ -857,7 +857,7 @@ SMTPD(8)                                                              SMTPD(8)
        <b><a href="postconf.5.html#smtpd_per_record_deadline">smtpd_per_record_deadline</a> (normal: no, overload: yes)</b>
               Change  the  behavior  of  the  <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a>  time
               limit,  from  a time limit per read or write system
-              call, to a time limit to read or write  a  complete
+              call, to a time limit to send or receive a complete
               record  (an  SMTP command line, SMTP response line,
               SMTP message content line,  or  TLS  protocol  mes-
               sage).
index e5dd6949ab2b65f9bf5f5ddea56ce9c93bcca003..6e57e8d2ee2cb9084097af2b56560729df8dd9e1 100644 (file)
@@ -83,7 +83,7 @@ to protect shell metacharacters and whitespace.
 With Postfix version 2.8 and later, the \fB-e\fR is no
 longer needed.
 .IP \fB-h\fR
-Show parameter values only, not the "\fIname = " label
+Show parameter values only, not the "\fIname = \fR" label
 that normally precedes the value.
 .IP \fB-l\fR
 List the names of all supported mailbox locking methods.
index aa2c20f6d28c51f1f9b08acc92a7083bf38abc5f..50630574b917e85498c6bb32e6b7d225af1e7916 100644 (file)
@@ -3239,6 +3239,13 @@ content.  The usual C-like escape sequences are recognized: \ea
 \eb \ef \en \er \et \ev \e\fIddd\fR (up to three octal digits) and
 \e\e.
 .PP
+Note 1: this feature does not recognize text that requires MIME
+decoding. It inspects raw message content, just like header_checks
+and body_checks.
+.PP
+Note 2: this feature is disabled with "receive_override_options
+= no_header_body_checks".
+.PP
 Example:
 .PP
 .nf
@@ -3262,6 +3269,13 @@ content.  The usual C-like escape sequences are recognized: \ea
 \eb \ef \en \er \et \ev \e\fIddd\fR (up to three octal digits) and
 \e\e.
 .PP
+Note 1: this feature does not recognize text that requires MIME
+decoding. It inspects raw message content, just like header_checks
+and body_checks.
+.PP
+Note 2: this feature is disabled with "receive_override_options
+= no_header_body_checks".
+.PP
 Example:
 .PP
 .nf
index 0040a5329f283a541c05853dadd4ab8ab3f729bc..c8355b7f15b8a70c78bebe0f91c140f90472840a 100644 (file)
@@ -147,8 +147,8 @@ A mechanism to transform commands from remote SMTP clients.
 Available in Postfix version 2.9 and later:
 .IP "\fBsmtpd_per_record_deadline (normal: no, overload: yes)\fR"
 Change the behavior of the smtpd_timeout time limit, from a
-time limit per read or write system call, to a time limit to read
-or write a complete record (an SMTP command line, SMTP response
+time limit per read or write system call, to a time limit to send
+or receive a complete record (an SMTP command line, SMTP response
 line, SMTP message content line, or TLS protocol message).
 .SH "ADDRESS REWRITING CONTROLS"
 .na
@@ -684,8 +684,8 @@ time unit.
 Available in Postfix version 2.9 and later:
 .IP "\fBsmtpd_per_record_deadline (normal: no, overload: yes)\fR"
 Change the behavior of the smtpd_timeout time limit, from a
-time limit per read or write system call, to a time limit to read
-or write a complete record (an SMTP command line, SMTP response
+time limit per read or write system call, to a time limit to send
+or receive a complete record (an SMTP command line, SMTP response
 line, SMTP message content line, or TLS protocol message).
 .SH "TARPIT CONTROLS"
 .na
index 7b34b4d6979bae5dd81642c9645330a21bc80bb1..fc62ce1787e99fb940790998c1d73cd850f652d5 100644 (file)
@@ -737,9 +737,14 @@ those numbers were 92% and 95%, respectively.  While postscreen(8)
 keeps the zombies away, more smtpd(8) processes remain available
 for legitimate clients.  </p>
 
+<p> postscreen(8) maintains a temporary whitelist for clients that
+pass its tests; by allowing whitelisted clients to skip tests,
+postscreen(8) minimizes its impact on legitimate email traffic.
+</p>
+
 <p> The postscreen(8) server is available with Postfix 2.8 and
 later. To keep the implementation simple, postscreen(8) delegates
-DNS white/backlist lookups to dnsblog(8) server processes, and
+DNS white/blacklist lookups to dnsblog(8) server processes, and
 delegates TLS encryption/decryption to tlsproxy(8) server processes.
 This delegation is invisible to the remote SMTP client, and is not
 shown in the diagram below.  </p>
index a86a7fd485dd3583daaca8c5f2535fe23ecf820b..c3249e6e80e37a6dc03ce63bade0605c36db19da 100644 (file)
@@ -23,6 +23,11 @@ process keeps zombies away from Postfix SMTP server processes, more
 Postfix SMTP server processes remain available for legitimate
 clients. </p>
 
+<p> postscreen(8) maintains a temporary whitelist for clients that
+pass its tests; by allowing whitelisted clients to skip tests,
+postscreen(8) minimizes its impact on legitimate email traffic.
+</p>
+
 <p> postscreen(8) should not be used on SMTP ports that receive
 mail from end-user clients (MUAs). In a typical deployment,
 postscreen(8) is used on the "port 25" service, while MUA clients
@@ -121,10 +126,10 @@ and that is the problem that postscreen(8) is focused on.  </p>
 
 <p> The postscreen(8) triage process involves a number of tests,
 in the order as described below.  Some tests introduce a delay of
-a few seconds.  Once a client passes a test, its IP address is
-whitelisted from 24 hours for simple tests, to 1 week for complex
-tests.  Whitelisting minimizes the impact of postscreen(8)'s tests
-on legitimate mail clients. </p>
+a few seconds.  postscreen(8) maintains a temporary whitelist for
+clients that pass its tests; by allowing whitelisted clients to
+skip tests, postscreen(8) minimizes its impact on legitimate email
+traffic.  </p>
 
 <p> By default, postscreen(8) hands off all connections to a Postfix
 SMTP server process after logging its findings. This mode is useful
@@ -606,8 +611,8 @@ feature. </dd>
 
 <h2> <a name="other_error">Other errors</a> </h2>
 
-<p> When an SMTP client hangs up unexpectedly during any tests,
-postscreen(8) logs this as: </p>
+<p> When an SMTP client hangs up unexpectedly, postscreen(8) logs
+this as: </p>
 
 <pre>
     <b>HANGUP after</b> <i>time</i> <b>from</b> <i>[address]:port</i> <b>in</b> <i>test name</i>
@@ -617,6 +622,10 @@ postscreen(8) logs this as: </p>
 unexpectedly, <i>time</i> seconds after the start of the
 test named <i>test name</i>. </p>
 
+<p> There is no punishment for hanging up. A client that hangs up
+without sending the QUIT command can still pass all postscreen(8)
+tests. </p>
+
 <!--
 
 <p> While an unexpired penalty is in effect, an SMTP client is not
index 11ba89459d46d31664cf76b106add01cabcc9dca..c88ae25d997409cd716ad1bb81258cb47298945a 100644 (file)
@@ -9606,6 +9606,13 @@ content.  The usual C-like escape sequences are recognized: <tt>\a
 \b \f \n \r \t \v \<i>ddd</i></tt> (up to three octal digits) and
 <tt>\\</tt>. </p>
 
+<p> Note 1: this feature does not recognize text that requires MIME
+decoding. It inspects raw message content, just like header_checks
+and body_checks.  </p>
+
+<p> Note 2: this feature is disabled with "receive_override_options
+= no_header_body_checks".  </p>
+
 <p> Example: </p>
 
 <pre>
@@ -9621,6 +9628,13 @@ content.  The usual C-like escape sequences are recognized: <tt>\a
 \b \f \n \r \t \v \<i>ddd</i></tt> (up to three octal digits) and
 <tt>\\</tt>. </p>
 
+<p> Note 1: this feature does not recognize text that requires MIME
+decoding. It inspects raw message content, just like header_checks
+and body_checks.  </p>
+
+<p> Note 2: this feature is disabled with "receive_override_options
+= no_header_body_checks".  </p>
+
 <p> Example: </p>
 
 <pre>
index 0fc9282c63f80ee78a942af1daf1426a3d90d868..e29feebed52ed6e6ae22d729a3e961950219b8f5 100644 (file)
 
 /*#define msg_verbose  2*/
 
+static void cleanup_milter_set_error(CLEANUP_STATE *, int);
+
 #define STR(x)         vstring_str(x)
 #define LEN(x)         VSTRING_LEN(x)
 
@@ -431,8 +433,7 @@ static void cleanup_milter_hbc_add_meta_records(CLEANUP_STATE *state)
      * later.
      */
     if ((new_meta_offset = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) {
-       msg_warn("%s: seek file %s: %m", myname, cleanup_path);
-       state->errs |= CLEANUP_STAT_WRITE;
+       cleanup_milter_set_error(state, errno);
        return;
     }
     if (state->filter != 0)
@@ -452,8 +453,7 @@ static void cleanup_milter_hbc_add_meta_records(CLEANUP_STATE *state)
      * value with the location of the new meta record.
      */
     if (vstream_fseek(state->dst, state->append_meta_pt_offset, SEEK_SET) < 0) {
-       msg_warn("%s: seek file %s: %m", myname, cleanup_path);
-       state->errs |= CLEANUP_STAT_WRITE;
+       cleanup_milter_set_error(state, errno);
        return;
     }
     cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
index 8c31694265aebbab6f26e49cff91f31f97684e8c..76abd0bd6774be5d2abf3879bfde26e8a32a10f8 100644 (file)
@@ -2,7 +2,7 @@
 /* NAME
 /*     abounce 3
 /* SUMMARY
-/*     asynchronous bounce/defer service client
+/*     asynchronous bounce/defer/trace service client
 /* SYNOPSIS
 /*     #include <abounce.h>
 /*
 /*     int     dsn_ret;
 /*     void    (*callback)(int status, char *context);
 /*     char    *context;
+/*
+/*     void    atrace_flush(flags, queue, id, encoding, sender,
+/*                             dsn_envid, dsn_ret, callback, context)
+/*     int     flags;
+/*     const char *queue;
+/*     const char *id;
+/*     const char *encoding;
+/*     const char *sender;
+/*     const char *dsn_envid;
+/*     int     dsn_ret;
+/*     void    (*callback)(int status, char *context);
+/*     char    *context;
 /* DESCRIPTION
 /*     This module implements an asynchronous interface to the
-/*     bounce/defer service for submitting sender notifications
+/*     bounce/defer/trace service for submitting sender notifications
 /*     without waiting for completion of the request.
 /*
 /*     abounce_flush() bounces the specified message to
 /*     the specified sender, including the defer log that was
 /*     built with defer_append().
 /*
+/*     atrace_flush() returns the specified message to the specified
+/*     sender, including the message delivery record log that was
+/*     built with vtrace_append().
+/*
 /*     Arguments:
 /* .IP flags
 /*     The bitwise OR of zero or more of the following (specify
@@ -183,6 +199,27 @@ typedef struct {
     VSTREAM *fp;                       /* server I/O handle */
 } ABOUNCE;
 
+ /*
+  * Encapsulate common code.
+  */
+#define ABOUNCE_EVENT_ENABLE(fd, callback, context, timeout) do { \
+       event_enable_read((fd), (callback), (context)); \
+       event_request_timer((callback), (context), (timeout)); \
+    } while (0)
+
+#define ABOUNCE_EVENT_DISABLE(fd, callback, context) do { \
+       event_cancel_timer((callback), (context)); \
+       event_disable_readwrite(fd); \
+    } while (0)
+
+ /*
+  * If we set the reply timeout too short, then we make the problem worse by
+  * increasing overload. With 1000s timeout mail will keep flowing, but there
+  * will be a large number of blocked bounce processes, and some resource is
+  * likely to run out.
+  */
+#define ABOUNCE_TIMEOUT        1000
+
 /* abounce_done - deliver status to application and clean up pseudo thread */
 
 static void abounce_done(ABOUNCE *ap, int status)
@@ -192,6 +229,8 @@ static void abounce_done(ABOUNCE *ap, int status)
        msg_info("%s: status=deferred (%s failed)", ap->id,
                 ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
                 ap->command == BOUNCE_CMD_WARN ? "delay warning" :
+                ap->command == BOUNCE_CMD_VERP ? "verp" :
+                ap->command == BOUNCE_CMD_TRACE ? "trace" :
                 "whatever");
     ap->callback(status, ap->context);
     myfree(ap->id);
@@ -200,15 +239,16 @@ static void abounce_done(ABOUNCE *ap, int status)
 
 /* abounce_event - resume pseudo thread after server reply event */
 
-static void abounce_event(int unused_event, char *context)
+static void abounce_event(int event, char *context)
 {
     ABOUNCE *ap = (ABOUNCE *) context;
     int     status;
 
-    event_disable_readwrite(vstream_fileno(ap->fp));
-    abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_STRICT,
-                              ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
-                              ATTR_TYPE_END) == 1 ? status : -1);
+    ABOUNCE_EVENT_DISABLE(vstream_fileno(ap->fp), abounce_event, context);
+    abounce_done(ap, (event != EVENT_TIME
+                     && attr_scan(ap->fp, ATTR_FLAG_STRICT,
+                                  ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
+                                  ATTR_TYPE_END) == 1) ? status : -1);
 }
 
 /* abounce_request_verp - suspend pseudo thread until server reply event */
@@ -220,7 +260,7 @@ static void abounce_request_verp(const char *class, const char *service,
                                         const char *sender,
                                         const char *dsn_envid,
                                         int dsn_ret,
-                                        const char *verp,
+                                        const char *verp,
                                         ABOUNCE_FN callback,
                                         char *context)
 {
@@ -250,7 +290,8 @@ static void abounce_request_verp(const char *class, const char *service,
                   ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp,
                   ATTR_TYPE_END) == 0
        && vstream_fflush(ap->fp) == 0) {
-       event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
+       ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, 
+                            (char *) ap, ABOUNCE_TIMEOUT);
     } else {
        abounce_done(ap, -1);
     }
@@ -266,7 +307,7 @@ void    abounce_flush_verp(int flags, const char *queue, const char *id,
 {
     abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service,
                         BOUNCE_CMD_VERP, flags, queue, id, encoding,
-                        sender, dsn_envid, dsn_ret, verp, callback, context);
+                      sender, dsn_envid, dsn_ret, verp, callback, context);
 }
 
 /* adefer_flush_verp - asynchronous defer flush */
@@ -280,7 +321,7 @@ void    adefer_flush_verp(int flags, const char *queue, const char *id,
     flags |= BOUNCE_FLAG_DELRCPT;
     abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service,
                         BOUNCE_CMD_VERP, flags, queue, id, encoding,
-                        sender, dsn_envid, dsn_ret, verp, callback, context);
+                      sender, dsn_envid, dsn_ret, verp, callback, context);
 }
 
 /* abounce_request - suspend pseudo thread until server reply event */
@@ -317,7 +358,8 @@ static void abounce_request(const char *class, const char *service,
                   ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret,
                   ATTR_TYPE_END) == 0
        && vstream_fflush(ap->fp) == 0) {
-       event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
+       ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, 
+                            (char *) ap, ABOUNCE_TIMEOUT);
     } else {
        abounce_done(ap, -1);
     }
@@ -359,3 +401,15 @@ void    adefer_warn(int flags, const char *queue, const char *id,
                    flags, queue, id, encoding, sender, dsn_envid, dsn_ret,
                    callback, context);
 }
+
+/* atrace_flush - asynchronous trace flush */
+
+void    atrace_flush(int flags, const char *queue, const char *id,
+                            const char *encoding, const char *sender,
+                            const char *dsn_envid, int dsn_ret,
+                            ABOUNCE_FN callback, char *context)
+{
+    abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
+                   flags, queue, id, encoding, sender, dsn_envid, dsn_ret,
+                   callback, context);
+}
index 521499cf38e04ec6af790c95d4e386c2c7deb789..dc4264b6b871efff7e87b45aa02ee82d2754e2a8 100644 (file)
@@ -24,6 +24,7 @@ typedef void (*ABOUNCE_FN) (int, char *);
 extern void abounce_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *);
 extern void adefer_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *);
 extern void adefer_warn(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *);
+extern void atrace_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *);
 
 extern void abounce_flush_verp(int, const char *, const char *, const char *, const char *, const char *, int, const char *, ABOUNCE_FN, char *);
 extern void adefer_flush_verp(int, const char *, const char *, const char *, const char *, const char *, int, const char *, ABOUNCE_FN, char *);
index 5f209744842cb4998799b8b22c7c05432c5d24a3..6327695a6d2a987fed0289a8a44af208cd4ffeb6 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      "20110323"
+#define MAIL_RELEASE_DATE      "20110501"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index ecbc09c307e1417dead5f08b0ef189b648991afb..385a831d77d2bd68f0c7574a0f3bbb0f4f05117d 100644 (file)
@@ -195,9 +195,9 @@ static NORETURN smtp_longjmp(VSTREAM *stream, int err, const char *context)
      */
     if (msg_verbose)
        msg_info("%s: %s", context, err == SMTP_ERR_TIME ? "timeout" : "EOF");
-    if (vstream_wr_error(stream)
-       && shutdown(vstream_fileno(stream), SHUT_WR) < 0)
-       msg_warn("shutdown: %m");
+    if (vstream_wr_error(stream))
+       /* Don't report ECONNRESET (hangup), EINVAL (already shut down), etc. */
+       (void) shutdown(vstream_fileno(stream), SHUT_WR);
     vstream_longjmp(stream, err);
 }
 
index 544993de52dc4390b00a7324cb2c6c83f94b2414..291664b5aab7bae35163c558147cc6e8af8d577d 100644 (file)
@@ -106,6 +106,7 @@ bounce_workaround.o: ../../include/attr.h
 bounce_workaround.o: ../../include/been_here.h
 bounce_workaround.o: ../../include/bounce.h
 bounce_workaround.o: ../../include/canon_addr.h
+bounce_workaround.o: ../../include/defer.h
 bounce_workaround.o: ../../include/deliver_request.h
 bounce_workaround.o: ../../include/delivered_hdr.h
 bounce_workaround.o: ../../include/dict.h
index 13af3434e1c66586bb39ae41c7941793c3892a3e..6938f3d509739dcc348a727f7d5a10aed4ed2158 100644 (file)
@@ -77,6 +77,7 @@
 #include <strip_addr.h>
 #include <stringops.h>
 #include <bounce.h>
+#include <defer.h>
 #include <split_addr.h>
 #include <canon_addr.h>
 
@@ -97,6 +98,7 @@ int     bounce_workaround(LOCAL_STATE state)
        char   *stripped_recipient;
        char   *owner_alias;
        const char *owner_expansion;
+       int     saved_dict_errno;
 
 #define FIND_OWNER(lhs, rhs, addr) { \
        lhs = concatenate("owner-", addr, (char *) 0); \
@@ -104,8 +106,9 @@ int     bounce_workaround(LOCAL_STATE state)
        rhs = maps_find(alias_maps, lhs, DICT_FLAG_NONE); \
     }
 
+       dict_errno = 0;
        FIND_OWNER(owner_alias, owner_expansion, state.msg_attr.rcpt.address);
-       if (owner_expansion == 0
+       if ((saved_dict_errno = dict_errno) == 0 && owner_expansion == 0
            && (stripped_recipient = strip_addr(state.msg_attr.rcpt.address,
                                                (char **) 0,
                                                *var_rcpt_delim)) != 0) {
@@ -113,13 +116,17 @@ int     bounce_workaround(LOCAL_STATE state)
            FIND_OWNER(owner_alias, owner_expansion, stripped_recipient);
            myfree(stripped_recipient);
        }
-       if (owner_expansion != 0) {
+       if ((saved_dict_errno = dict_errno) == 0 && owner_expansion != 0) {
            canon_owner = canon_addr_internal(vstring_alloc(10),
                                              var_exp_own_alias ?
                                              owner_expansion : owner_alias);
            SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
        }
        myfree(owner_alias);
+       if (saved_dict_errno != 0)
+           /* At this point, canon_owner == 0. */
+           return (defer_append(BOUNCE_FLAGS(state.request),
+                                BOUNCE_ATTR(state.msg_attr)));
     }
 
     /*
index d35ef66b4cf33f5b6564135c96f325ecd5cb333f..58b01f79f2fb8f14fdab84ccf42ed893d9d66302 100644 (file)
@@ -278,6 +278,7 @@ int     deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
        transp_maps = maps_create(VAR_MBOX_TRANSP_MAPS, var_mbox_transp_maps,
                                  DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB);
     /* The -1 is a hint for the down-stream deliver_completed() function. */
+    dict_errno = 0;
     if (*var_mbox_transp_maps
        && (map_transport = maps_find(transp_maps, state.msg_attr.user,
                                      DICT_FLAG_NONE)) != 0) {
@@ -285,6 +286,11 @@ int     deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
        *statusp = deliver_pass(MAIL_CLASS_PRIVATE, map_transport,
                                state.request, &state.msg_attr.rcpt);
        return (YES);
+    } else if (dict_errno != 0) {
+       /* Details in the logfile. */
+       dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
+       *statusp = DEL_STAT_DEFER;
+       return (YES);
     }
     if (*var_mailbox_transport) {
        state.msg_attr.rcpt.offset = -1L;
@@ -319,10 +325,15 @@ int     deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
        cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps,
                               DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
 
+    dict_errno = 0;
     if (*var_mailbox_cmd_maps
        && (map_command = maps_find(cmd_maps, state.msg_attr.user,
                                    DICT_FLAG_NONE)) != 0) {
        status = deliver_command(state, usr_attr, map_command);
+    } else if (dict_errno != 0) {
+       /* Details in the logfile. */
+       dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
+       status = DEL_STAT_DEFER;
     } else if (*var_mailbox_command) {
        status = deliver_command(state, usr_attr, var_mailbox_command);
     } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') {
index 068f9eed2683ca44e59e069861112e9a2e5c42e8..eb5bbf25054ef29e75512f0b08d0dd60b59c0e01 100644 (file)
@@ -110,12 +110,17 @@ int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
        transp_maps = maps_create(VAR_FBCK_TRANSP_MAPS, var_fbck_transp_maps,
                                  DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB);
     /* The -1 is a hint for the down-stream deliver_completed() function. */
+    dict_errno = 0;
     if (*var_fbck_transp_maps
        && (map_transport = maps_find(transp_maps, state.msg_attr.user,
                                      DICT_FLAG_NONE)) != 0) {
        state.msg_attr.rcpt.offset = -1L;
        return (deliver_pass(MAIL_CLASS_PRIVATE, map_transport,
                             state.request, &state.msg_attr.rcpt));
+    } else if (dict_errno != 0) {
+       /* Details in the logfile. */
+       dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
+       return (DEL_STAT_DEFER);
     }
     if (*var_fallback_transport) {
        state.msg_attr.rcpt.offset = -1L;
index 3aa5cbb972a0035cb5080c7a3772a892950c2c88..35accb022cc37fb631e3861d27041aa19add02fe 100644 (file)
@@ -2500,6 +2500,7 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile,
     int     mime_errs = 0;
     MILTER_MSG_CONTEXT msg_ctx;
     VSTRING *buf;
+    int     saved_errno;
 
     switch (milter->state) {
     case MILTER8_STAT_ERROR:
@@ -2513,8 +2514,12 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile,
        if (msg_verbose)
            msg_info("%s: message to milter %s", myname, milter->m.name);
        if (vstream_fseek(qfile, data_offset, SEEK_SET) < 0) {
+           saved_errno = errno;
            msg_warn("%s: vstream_fseek %s: %m", myname, VSTREAM_PATH(qfile));
-           return ("450 4.3.0 Queue file write error");
+           /* XXX This should be available from cleanup_strerror.c. */
+           return (saved_errno == EFBIG ?
+                   "552 5.3.4 Message file too big" :
+                   "451 4.3.0 Queue file write error");
        }
        msg_ctx.milter = milter;
        msg_ctx.eoh_macros = eoh_macros;
index eeec88d3b40d81dbc4f57d157af5db7bd799dd70..eea9d71d0c6c3e1604736ef2fcd1a2320d745583 100644 (file)
   */
 static void qmgr_active_done_2_bounce_flush(int, char *);
 static void qmgr_active_done_2_generic(QMGR_MESSAGE *);
+static void qmgr_active_done_25_trace_flush(int, char *);
+static void qmgr_active_done_25_generic(QMGR_MESSAGE *);
 static void qmgr_active_done_3_defer_flush(int, char *);
 static void qmgr_active_done_3_defer_warn(int, char *);
 static void qmgr_active_done_3_generic(QMGR_MESSAGE *);
@@ -336,10 +338,8 @@ static void qmgr_active_done_2_bounce_flush(int status, char *context)
 
 static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
 {
-    const char *myname = "qmgr_active_done_2_generic";
     const char *path;
     struct stat st;
-    int     status;
 
     /*
      * A delivery agent marks a queue file as corrupt by changing its
@@ -372,10 +372,6 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
     }
 
     /*
-     * As a temporary implementation, synchronously inform the sender of
-     * trace information. This will block for 10 seconds when the qmgr FIFO
-     * is full.
-     * 
      * XXX With multi-recipient mail, some recipients may have NOTIFY=SUCCESS
      * and others not. Depending on what subset of recipients are delivered,
      * a trace file may or may not be created. Even when the last partial
@@ -388,18 +384,45 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
      */
     if ((message->tflags & (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD))
        || (message->rflags & QMGR_READ_FLAG_NOTIFY_SUCCESS)) {
-       status = trace_flush(message->tflags,
-                            message->queue_name,
-                            message->queue_id,
-                            message->encoding,
-                            message->sender,
-                            message->dsn_envid,
-                            message->dsn_ret);
-       if (status == 0 && message->tflags_offset)
-           qmgr_message_kill_record(message, message->tflags_offset);
-       message->flags |= status;
+       atrace_flush(message->tflags,
+                    message->queue_name,
+                    message->queue_id,
+                    message->encoding,
+                    message->sender,
+                    message->dsn_envid,
+                    message->dsn_ret,
+                    qmgr_active_done_25_trace_flush,
+                    (char *) message);
+       return;
     }
 
+    /*
+     * Asynchronous processing does not reach this point.
+     */
+    qmgr_active_done_25_generic(message);
+}
+
+/* qmgr_active_done_25_trace_flush - continue after atrace_flush() completion */
+
+static void qmgr_active_done_25_trace_flush(int status, char *context)
+{
+    QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+    /*
+     * Process atrace_flush() status and continue processing.
+     */
+    if (status == 0 && message->tflags_offset)
+       qmgr_message_kill_record(message, message->tflags_offset);
+    message->flags |= status;
+    qmgr_active_done_25_generic(message);
+}
+
+/* qmgr_active_done_25_generic - continue processing */
+
+static void qmgr_active_done_25_generic(QMGR_MESSAGE *message)
+{
+    const char *myname = "qmgr_active_done_25_generic";
+
     /*
      * If we get to this point we have tried all recipients for this message.
      * If the message is too old, try to bounce it.
index 403add01fbfd1534bd7d489a9d5aee9235db987b..2ba32f1063ac4a989d40c6f1ad10a581ca9795e2 100644 (file)
@@ -77,7 +77,7 @@
 /*     With Postfix version 2.8 and later, the \fB-e\fR is no
 /*     longer needed.
 /* .IP \fB-h\fR
-/*     Show parameter values only, not the "\fIname = " label
+/*     Show parameter values only, not the "\fIname = \fR" label
 /*     that normally precedes the value.
 /* .IP \fB-l\fR
 /*     List the names of all supported mailbox locking methods.
index 60996317896c00ee08aab5ffa7f1dac6b827f3be..6b5fc3008beeeacacf84e99ebac4de4386099175 100644 (file)
@@ -876,7 +876,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
      * 
      * Start the cache maintenance pseudo thread after dropping privileges.
      */
-#define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
+#define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \
+           DICT_FLAG_OPEN_LOCK)
 
     if (*var_psc_cache_map)
        psc_cache_map =
index eeec88d3b40d81dbc4f57d157af5db7bd799dd70..eea9d71d0c6c3e1604736ef2fcd1a2320d745583 100644 (file)
   */
 static void qmgr_active_done_2_bounce_flush(int, char *);
 static void qmgr_active_done_2_generic(QMGR_MESSAGE *);
+static void qmgr_active_done_25_trace_flush(int, char *);
+static void qmgr_active_done_25_generic(QMGR_MESSAGE *);
 static void qmgr_active_done_3_defer_flush(int, char *);
 static void qmgr_active_done_3_defer_warn(int, char *);
 static void qmgr_active_done_3_generic(QMGR_MESSAGE *);
@@ -336,10 +338,8 @@ static void qmgr_active_done_2_bounce_flush(int status, char *context)
 
 static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
 {
-    const char *myname = "qmgr_active_done_2_generic";
     const char *path;
     struct stat st;
-    int     status;
 
     /*
      * A delivery agent marks a queue file as corrupt by changing its
@@ -372,10 +372,6 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
     }
 
     /*
-     * As a temporary implementation, synchronously inform the sender of
-     * trace information. This will block for 10 seconds when the qmgr FIFO
-     * is full.
-     * 
      * XXX With multi-recipient mail, some recipients may have NOTIFY=SUCCESS
      * and others not. Depending on what subset of recipients are delivered,
      * a trace file may or may not be created. Even when the last partial
@@ -388,18 +384,45 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
      */
     if ((message->tflags & (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD))
        || (message->rflags & QMGR_READ_FLAG_NOTIFY_SUCCESS)) {
-       status = trace_flush(message->tflags,
-                            message->queue_name,
-                            message->queue_id,
-                            message->encoding,
-                            message->sender,
-                            message->dsn_envid,
-                            message->dsn_ret);
-       if (status == 0 && message->tflags_offset)
-           qmgr_message_kill_record(message, message->tflags_offset);
-       message->flags |= status;
+       atrace_flush(message->tflags,
+                    message->queue_name,
+                    message->queue_id,
+                    message->encoding,
+                    message->sender,
+                    message->dsn_envid,
+                    message->dsn_ret,
+                    qmgr_active_done_25_trace_flush,
+                    (char *) message);
+       return;
     }
 
+    /*
+     * Asynchronous processing does not reach this point.
+     */
+    qmgr_active_done_25_generic(message);
+}
+
+/* qmgr_active_done_25_trace_flush - continue after atrace_flush() completion */
+
+static void qmgr_active_done_25_trace_flush(int status, char *context)
+{
+    QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+    /*
+     * Process atrace_flush() status and continue processing.
+     */
+    if (status == 0 && message->tflags_offset)
+       qmgr_message_kill_record(message, message->tflags_offset);
+    message->flags |= status;
+    qmgr_active_done_25_generic(message);
+}
+
+/* qmgr_active_done_25_generic - continue processing */
+
+static void qmgr_active_done_25_generic(QMGR_MESSAGE *message)
+{
+    const char *myname = "qmgr_active_done_25_generic";
+
     /*
      * If we get to this point we have tried all recipients for this message.
      * If the message is too old, try to bounce it.
index 0ffa1ee41e9db1f06de69158b30844a129dfbcc2..93e42e3cc70fa39ff2a36f1c48214b9392e21d99 100644 (file)
@@ -181,6 +181,7 @@ typedef struct {
 
 #define SMTPD_FLAG_HANGUP         (1<<0)       /* 421/521 disconnect */
 #define SMTPD_FLAG_ILL_PIPELINING  (1<<1)      /* inappropriate pipelining */
+#define SMTPD_FLAG_AUTH_USED      (1<<2)       /* don't reuse SASL state */
 
 #define SMTPD_MASK_MAIL_KEEP           ~0      /* keep all after MAIL reset */
 
index f419dc6bbcb8874f03d3fe9b0ecb8ffa96464944..823e988863a58403e65031d17c11f5c0882fe326 100644 (file)
@@ -184,6 +184,24 @@ int     smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        return (-1);
     }
 
+    /* Don't reuse the SASL handle after authentication failure. */
+#ifndef XSASL_TYPE_CYRUS
+#define XSASL_TYPE_CYRUS       "cyrus"
+#endif
+    if (state->flags & SMTPD_FLAG_AUTH_USED) {
+       smtpd_sasl_deactivate(state);
+#ifdef USE_TLS
+       if (state->tls_context != 0)
+           smtpd_sasl_activate(state, VAR_SMTPD_SASL_TLS_OPTS,
+                               var_smtpd_sasl_tls_opts);
+       else
+#endif
+           smtpd_sasl_activate(state, VAR_SMTPD_SASL_OPTS,
+                               var_smtpd_sasl_opts);
+    } else if (strcmp(var_smtpd_sasl_type, XSASL_TYPE_CYRUS) == 0) {
+       state->flags |= SMTPD_FLAG_AUTH_USED;
+    }
+
     /*
      * All authentication failures shall be logged. The 5xx reply code from
      * the SASL authentication routine triggers tar-pit delays, which help to
index d28d1aaacf934a443acec0a515f3ebce51f1b39a..13c4048aa133197598299fdee6f25a019a28246c 100644 (file)
@@ -747,6 +747,13 @@ auto_clnt.o: split_at.h
 auto_clnt.o: sys_defs.h
 auto_clnt.o: vbuf.h
 auto_clnt.o: vstream.h
+base32_code.o: base32_code.c
+base32_code.o: base32_code.h
+base32_code.o: msg.h
+base32_code.o: mymalloc.h
+base32_code.o: sys_defs.h
+base32_code.o: vbuf.h
+base32_code.o: vstring.h
 base64_code.o: base64_code.c
 base64_code.o: base64_code.h
 base64_code.o: msg.h
@@ -957,6 +964,7 @@ dict_open.o: dict_thash.h
 dict_open.o: dict_unix.h
 dict_open.o: htable.h
 dict_open.o: msg.h
+dict_open.o: myflock.h
 dict_open.o: mymalloc.h
 dict_open.o: split_at.h
 dict_open.o: stringops.h
@@ -1318,7 +1326,6 @@ mask_addr.o: msg.h
 mask_addr.o: sys_defs.h
 match_list.o: argv.h
 match_list.o: dict.h
-match_list.o: htable.h
 match_list.o: match_list.c
 match_list.o: match_list.h
 match_list.o: match_ops.h
@@ -1333,8 +1340,6 @@ match_list.o: vstring_vstream.h
 match_ops.o: argv.h
 match_ops.o: cidr_match.h
 match_ops.o: dict.h
-match_ops.o: htable.h
-match_ops.o: match_list.h
 match_ops.o: match_ops.c
 match_ops.o: match_ops.h
 match_ops.o: msg.h
@@ -1797,6 +1802,8 @@ vstring_vstream.o: vstream.h
 vstring_vstream.o: vstring.h
 vstring_vstream.o: vstring_vstream.c
 vstring_vstream.o: vstring_vstream.h
+watchdog.o: events.h
+watchdog.o: iostuff.h
 watchdog.o: killme_after.h
 watchdog.o: msg.h
 watchdog.o: mymalloc.h
index fb9efb5fcd4055207698188801f2c77f487eaa2e..e8449491dbf316dc5e2d9a25f4fd5eee77738b6b 100644 (file)
@@ -80,6 +80,7 @@ extern DICT *dict_debug(DICT *);
 #define DICT_FLAG_FOLD_FIX     (1<<14) /* case-fold key with fixed-case map */
 #define DICT_FLAG_FOLD_MUL     (1<<15) /* case-fold key with multi-case map */
 #define DICT_FLAG_FOLD_ANY     (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
+#define DICT_FLAG_OPEN_LOCK    (1<<16) /* open file with exclusive lock */
 
  /* IMPORTANT: Update the dict_mask[] table when the above changes */
 
index 9e1358f495f0008668ca96290f27e1c45f92a814..766fa00987cc81e507d95d1986d454336f940c09 100644 (file)
 /* .IP DICT_FLAG_LOCK
 /*     With maps where this is appropriate, acquire an exclusive lock
 /*     before writing, and acquire a shared lock before reading.
+/* .IP DICT_FLAG_OPEN_LOCK
+/*     With maps where this is appropriate, acquire an exclusive
+/*     lock upon open, and report a fatal run-time error if the
+/*     table is already locked.
 /* .IP DICT_FLAG_FOLD_FIX
 /*     With databases whose lookup fields are fixed-case strings,
 /*     fold the search key to lower case before accessing the
 #include <stringops.h>
 #include <split_at.h>
 #include <htable.h>
+#include <myflock.h>
 
  /*
   * lookup table for available map types.
@@ -313,6 +318,16 @@ DICT   *dict_open3(const char *dict_type, const char *dict_name,
        msg_fatal("opening %s:%s %m", dict_type, dict_name);
     if (msg_verbose)
        msg_info("%s: %s:%s", myname, dict_type, dict_name);
+    /* XXX the choice between wait-for-lock or no-wait is hard-coded. */
+    if (dict->lock_fd >= 0 && (dict_flags & DICT_FLAG_OPEN_LOCK) != 0) {
+       if (dict_flags & DICT_FLAG_LOCK)
+           msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
+                     myname, dict_type, dict_name);
+       if (myflock(dict->lock_fd, INTERNAL_LOCK,
+                   MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
+           msg_fatal("%s:%s: unable to get exclusive lock: %m",
+                     dict_type, dict_name);
+    }
     return (dict);
 }
 
index a1a1535f7afb59ecfb04b58e0f08a99b07500951..271d01f2c7487fd65927f65b0f76d03be14d9a07 100644 (file)
@@ -664,7 +664,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
      * 
      * Start the cache cleanup thread after permanently dropping privileges.
      */
-#define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE)
+#define VERIFY_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE \
+           | DICT_FLAG_OPEN_LOCK)
 
     saved_mask = umask(022);
     verify_map =