]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2.6 v2.2.6
authorWietse Venema <wietse@porcupine.org>
Wed, 30 Nov 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 10 Feb 2018 21:11:43 +0000 (16:11 -0500)
38 files changed:
postfix/HISTORY
postfix/README_FILES/ADDRESS_REWRITING_README
postfix/README_FILES/MAILDROP_README
postfix/README_FILES/TLS_README
postfix/conf/access
postfix/html/ADDRESS_REWRITING_README.html
postfix/html/MAILDROP_README.html
postfix/html/TLS_README.html
postfix/html/access.5.html
postfix/man/man5/access.5
postfix/proto/ADDRESS_REWRITING_README.html
postfix/proto/MAILDROP_README.html
postfix/proto/TLS_README.html
postfix/proto/access
postfix/src/cleanup/cleanup_extracted.c
postfix/src/cleanup/cleanup_message.c
postfix/src/dns/dns.h
postfix/src/global/dict_mysql.c
postfix/src/global/dict_pgsql.c
postfix/src/global/mail_queue.c
postfix/src/global/mail_queue.h
postfix/src/global/mail_stream.c
postfix/src/global/mail_stream.h
postfix/src/global/mail_version.h
postfix/src/global/smtp_stream.h
postfix/src/lmtp/lmtp_chat.c
postfix/src/lmtp/lmtp_trouble.c
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/pickup/pickup.c
postfix/src/qmgr/qmgr_deliver.c
postfix/src/smtp/smtp_chat.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_trouble.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/tls/tls_misc.c
postfix/src/util/sane_accept.c
postfix/src/util/sys_defs.h

index 4cfc645a1eeb0a7213074457bedc6c01a2111d31..d17c89855c8dd8cdec6328193350797a819ea9f5 100644 (file)
@@ -10618,11 +10618,11 @@ Apologies for any names omitted.
 
 20050706
 
-       Robustness: the SMTP client now disables caching when it
-       is unable to communicate with the scache(8) connection
-       caching server, instead of looping forever and not delivering
-       mail. File: global/scache_clnt.c.  This code is back-ported
-       from the Postfix 2.3 snapshot release.
+       Robustness: the SMTP client now disables connection caching
+       when it is unable to communicate with the scache(8) server,
+       instead of looping forever and not delivering mail.  File:
+       global/scache_clnt.c.  This code is back-ported from the
+       Postfix 2.3 snapshot release.
 
        Portability: after sending a socket, the scache(8) server
        now waits for an ACK from the connection cache client before
@@ -10639,3 +10639,94 @@ Apologies for any names omitted.
        modules, but that results in too much change, and is not
        allowed in the stable release).  Files: tls/tls_scache.c,
        util/clean_env.c, util/vstring.h, smtpstone/qmqp-source.c.
+
+20050806
+
+       Workaround: accept(2) fails with EPROTO when the client
+       already disconnected (SunOS 5.5.1). File: sane_accept.c.
+
+20050815
+
+       Workaround: old Solaris compilers can't link an archive
+       without globally visible symbols. File: tls/tls_misc.c.
+
+20050922
+
+       Bugfix: the *SQL clients did not uniformly choose the
+       database host from the available pool of servers due to an
+       off-by-one error, so that the "last" available server was
+       not selected. Leandro Santi. Files: dict_mysql.c, dict_pgsql.c.
+
+20050929
+
+       Paranoia: don't ignore garbage in SMTP or LMTP server replies
+       when ESMTP command pipelining is turned on. For example,
+       after sending ".<CR><LF>QUIT<CR><LF>", Postfix could recognize
+       the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
+       garbage, causing mail to be lost. The SMTP and LMTP clients
+       now report a remote protocol error and defer delivery.
+       Files: smtp/smtp_chat.c, smtp/smtp_trouble.c, lmtp/lmtp_chat.c,
+       lmtp/lmtp_trouble.c.
+
+20051011
+
+       Bugfix: raise the "policy violation" flag when a client
+       request exceeds a concurrency or rate limit.  File:
+       smtpd/smtpd.c.
+
+       Bugfix (cut-and-paste error): don't reply with 421 (too
+       many MAIL FROM or RCPT TO commands) when we aren't closing
+       the connection.  File: smtpd/smtpd.c.
+
+20051013
+
+       Bugfix: don't do smtpd_end_of_data_restrictions after the
+       transaction failed due to, e.g., a write error.  File:
+       smtpd/smtpd.c.
+
+       Cleanup: the SMTP server now enforces the message_size_limit
+       even when the client did not send SIZE information with the
+       MAIL FROM command.  This protects before-queue content
+       filters against over-size messages.  File: smtpd/smtpd.c.
+
+20051105
+
+       Workaround: the next-hop logical destination information
+       for connection caching was reset only after a good non-TLS
+       connection, so that cached connections to non-TLS backup
+       servers could suck away traffic from TLS primary servers
+       (the Postfix SMTP client cannot cache an open TLS connection).
+       Found during code review. Fixing this requires more change
+       than is allowed in a stable release.  File: smtp/smtp_connect.c.
+
+20051108
+
+       Bugfix: two messages could get the same message ID due to
+       a race condition. This time window was increased when queue
+       file creation was postponed from MAIL FROM until the first
+       accepted RCPT TO.  The window is closed again. Found by
+       Victor. Files: global/mail_stream.c, global/mail_queue.c,
+       cleanup/cleanup_message.c. This code is back-ported from
+       the Postfix 2.3 snapshot release.
+
+20051119
+
+       Bugfix: the queue manager did not write a per-recipient
+       defer logfile record when the delivery agent crashed after
+       the initial handshake with the queue manager, and before
+       reporting the delivery status to the queue manager.  Files:
+       *qmgr/qmgr_deliver.c.
+
+20051126
+
+       Log warning when REDIRECT, FILTER, HOLD and DISCARD are
+       used in smtpd_etrn_restrictions. File: smtpd/smtpd_check.c.
+
+20051128
+
+       Bugfix: moved code around from one place to another to make
+       REDIRECT, FILTER, HOLD and DISCARD access(5) table actions
+       work in smtpd_end_of_data_restrictions.  PREPEND will not
+       be fixed; it must be specified before the message content
+       is received.  Files: smtpd/smtpd.c, smtpd/smtpd_check.c,
+       cleanup/cleanup_extracted.c, pickup/pickup.c.
index f433ec3a5b98b05173cc801ec10241b6b609205d..6004bbcef7f563fafa2ffff76cc2cf54ca2e34c0 100644 (file)
@@ -367,7 +367,7 @@ Example:
 
     /etc/postfix/master.cf:
         :10026      inet  n       -       n       -       -       smtpd
-            -o receive_override_options=no_address_mapping
+            -o receive_override_options=no_address_mappings
 
 Note: do not specify whitespace around the "=" here.
 
@@ -440,7 +440,7 @@ Example:
 
     /etc/postfix/master.cf:
         :10026      inet  n       -       n       -       -       smtpd
-            -o receive_override_options=no_address_mapping
+            -o receive_override_options=no_address_mappings
 
 Note: do not specify whitespace around the "=" here.
 
@@ -476,7 +476,7 @@ Example:
 
     /etc/postfix/master.cf:
         :10026      inet  n       -       n       -       -       smtpd
-            -o receive_override_options=no_address_mapping
+            -o receive_override_options=no_address_mappings
 
 Note: do not specify whitespace around the "=" here.
 
@@ -525,7 +525,7 @@ Example:
 
     /etc/postfix/master.cf:
         :10026      inet  n       -       n       -       -       smtpd
-            -o receive_override_options=no_address_mapping
+            -o receive_override_options=no_address_mappings
 
 Note: do not specify whitespace around the "=" here.
 
index 36afd1e06b917ac0d5ffc074d07aaa75be989cdb..ca8580847b8375d20cca88ae872cf3e1817cd36b 100644 (file)
@@ -100,7 +100,7 @@ To enable maildrop delivery for specific users only, you can use the Postfix
 local(8) delivery agent's mailbox_command_maps feature:
 
     /etc/postfix/main.cf:
-        mailbox_command_maps = /etc/postfix/mailbox_commands
+        mailbox_command_maps = hash:/etc/postfix/mailbox_commands
 
     /etc/postfix/mailbox_commands:
         you    /path/to/maildrop -d ${USER}
index fd270b9cb95b5775addf04c98824629dd35e6c19..25d0aa43d312c1d67d92cff2ff72508c3f232e0c 100644 (file)
@@ -154,9 +154,9 @@ If you want the Postfix SMTP server to accept remote SMTP client certificates
 issued by these CAs, append the root certificate to $smtpd_tls_CAfile or
 install it in the $smtpd_tls_CApath directory. When you configure trust in a
 root CA, it is not necessary to explicitly trust intermediary CAs signed by the
-root CA, unless $smtpd_tls_verify_depth is less than the number of CAs in the
-certificate chain for the clients of interest. With a verify depth of 1 you can
-only verify certificates directly signed by a trusted CA, and all trusted
+root CA, unless $smtpd_tls_ccert_verifydepth is less than the number of CAs in
+the certificate chain for the clients of interest. With a verify depth of 1 you
+can only verify certificates directly signed by a trusted CA, and all trusted
 intermediary CAs need to be configured explicitly. With a verify depth of 2 you
 can verify clients signed by a root CA or a direct intermediary CA (so long as
 the client is correctly configured to supply its intermediate CA certificate).
@@ -192,7 +192,7 @@ $smtpd_tls_CApath directory needs to be accessible inside the optional chroot
 jail.
 
 When you configure Postfix to request client certificates (by setting
-$smtpd_tls_asck_ccert = yes), any certificates in $smtpd_tls_CAfile are sent to
+$smtpd_tls_ask_ccert = yes), any certificates in $smtpd_tls_CAfile are sent to
 the client, in order to allow it to choose an identity signed by a CA you
 trust. If no $smtpd_tls_CAfile is specified, no preferred CA list is sent, and
 the client is free to choose an identity signed by any CA. Many clients use a
index a424ea59876835eadae2333d4b29ad519b6a189f..79946780b99df664a2a11e166986aa6f4bb77c7d 100644 (file)
@@ -1,4 +1,4 @@
-# ACCESS(5)                                               ACCESS(5)
+# ACCESS(5)                                                            ACCESS(5)
 # 
 # NAME
 #        access - Postfix access table format
 #               Note:  this action does not support multi-line mes-
 #               sage headers.
 # 
+#               Note: this action must be used before  the  message
+#               content   is   received;   it  cannot  be  used  in
+#               smtpd_end_of_data_restrictions.
+# 
 #               This feature is available in Postfix 2.1 and later.
 # 
 #        REDIRECT user@domain
 #        user@ and domain constituent parts, nor is user+foo broken
 #        up into user and foo.
 # 
-#        Patterns are applied in the  order  as  specified  in  the
-#        table,  until  a  pattern is found that matches the search
+#        Patterns are applied in the order as specified in the  ta-
+#        ble,  until  a  pattern  is  found that matches the search
 #        string.
 # 
 #        Actions are the same as with indexed  file  lookups,  with
 # TCP-BASED TABLES
 #        This section describes how the table lookups  change  when
 #        lookups are directed to a TCP-based server. For a descrip-
-#        tion  of  the  TCP  client/server  lookup  protocol,   see
-#        tcp_table(5).   This  feature  is  not available up to and
-#        including Postfix version 2.2.
+#        tion of the TCP client/server lookup protocol, see tcp_ta-
+#        ble(5).  This feature is not available up to and including
+#        Postfix version 2.2.
 # 
 #        Each lookup operation uses the entire query  string  once.
 #        Depending  on  the  application,  that string is an entire
 #        P.O. Box 704
 #        Yorktown Heights, NY 10598, USA
 # 
-#                                                         ACCESS(5)
+#                                                                      ACCESS(5)
index 226d937beb5b2d40b94f082a231911beb3e443c1..8233562a8b3fc7c2903297a679f6d9bd541a17ce 100644 (file)
@@ -603,7 +603,7 @@ in the master.cf file.  This feature is available in Postfix version
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=no_address_mapping
+        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 </pre>
 </blockquote>
 
@@ -702,7 +702,7 @@ Postfix version 2.1 and later. </p>
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=no_address_mapping
+        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 </pre>
 </blockquote>
 
@@ -752,7 +752,7 @@ is available in Postfix version 2.1 and later. </p>
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=no_address_mapping
+        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 </pre>
 </blockquote>
 
@@ -816,7 +816,7 @@ in the master.cf file.  This feature is available in Postfix version
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=no_address_mapping
+        -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 </pre>
 </blockquote>
 
index bdf121caa149f6328cfb7392057b88522396e144..1216218c426f24eac8b19e5607bdeade4407d58b 100644 (file)
@@ -149,7 +149,7 @@ use the Postfix <a href="local.8.html">local(8)</a> delivery agent's <a href="po
 <blockquote>
 <pre>
 /etc/postfix/main.cf:
-    <a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a> = /etc/postfix/mailbox_commands
+    <a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a> = hash:/etc/postfix/mailbox_commands
 
 /etc/postfix/mailbox_commands:
     you    /path/to/maildrop -d ${USER}
index 8030a819de38eb2fc26aa3e7059c0152ea182dab..cf4b4c6e289d3c97caaf07f5fc9fa64b70259ae9 100644 (file)
@@ -262,7 +262,7 @@ the overhead of the TLS exchange. </p>
 certificates issued by these CAs, append the root certificate to
 $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> or install it in the $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> directory.  When
 you configure trust in a root CA, it is not necessary to explicitly trust
-intermediary CAs signed by the root CA, unless $smtpd_tls_verify_depth
+intermediary CAs signed by the root CA, unless $<a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a>
 is less than the number of CAs in the certificate chain for the clients
 of interest. With a verify depth of 1 you can only verify certificates
 directly signed by a trusted CA, and all trusted intermediary CAs need to
@@ -315,7 +315,7 @@ is needed. Thus, the $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApat
 accessible inside the optional chroot jail. </p>
 
 <p> When you configure Postfix to request client certificates (by
-setting $smtpd_tls_asck_ccert = yes), any certificates in
+setting $<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = yes), any certificates in
 $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> are sent to the client, in order to allow it to
 choose an identity signed by a CA you trust. If no $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>
 is specified, no preferred CA list is sent, and the client is free
index e60da0971f67722a67755fb4d99761ca33d6a4d9..412b9cd62863130201b2465df82d8355896736b3 100644 (file)
@@ -269,6 +269,10 @@ ACCESS(5)                                                            ACCESS(5)
               Note:  this action does not support multi-line mes-
               sage headers.
 
+              Note: this action must be used before  the  message
+              content   is   received;   it  cannot  be  used  in
+              <b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
+
               This feature is available in Postfix 2.1 and later.
 
        <b>REDIRECT</b> <i>user@domain</i>
index 7f9cfb82174ee339ca6ac8607244a8b2643695e1..c61a02696e95b383f8d8a9d0b33af05865ef78b7 100644 (file)
@@ -246,6 +246,9 @@ header appears before the second etc. prepended header.
 .sp
 Note: this action does not support multi-line message headers.
 .sp
+Note: this action must be used before the message content
+is received; it cannot be used in \fBsmtpd_end_of_data_restrictions\fR.
+.sp
 This feature is available in Postfix 2.1 and later.
 .IP "\fBREDIRECT \fIuser@domain\fR"
 After the message is queued, send the message to the specified
index 4955a6e8b6cd3c292fcb03fff7318852b072499b..57f7fa2a52e75eccfc3ba8023d57fd4099ebc50f 100644 (file)
@@ -603,7 +603,7 @@ in the master.cf file.  This feature is available in Postfix version
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o receive_override_options=no_address_mapping
+        -o receive_override_options=no_address_mappings
 </pre>
 </blockquote>
 
@@ -702,7 +702,7 @@ Postfix version 2.1 and later. </p>
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o receive_override_options=no_address_mapping
+        -o receive_override_options=no_address_mappings
 </pre>
 </blockquote>
 
@@ -752,7 +752,7 @@ is available in Postfix version 2.1 and later. </p>
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o receive_override_options=no_address_mapping
+        -o receive_override_options=no_address_mappings
 </pre>
 </blockquote>
 
@@ -816,7 +816,7 @@ in the master.cf file.  This feature is available in Postfix version
 <pre>
 /etc/postfix/master.cf:
     :10026      inet  n       -       n       -       -       smtpd
-        -o receive_override_options=no_address_mapping
+        -o receive_override_options=no_address_mappings
 </pre>
 </blockquote>
 
index 8ce2c402f53ba7b7b2af8e3b7a6e1edc26d450ff..e41e127f5fb1606dcc768e2d6cd90fd876914c94 100644 (file)
@@ -149,7 +149,7 @@ use the Postfix local(8) delivery agent's mailbox_command_maps feature:
 <blockquote>
 <pre>
 /etc/postfix/main.cf:
-    mailbox_command_maps = /etc/postfix/mailbox_commands
+    mailbox_command_maps = hash:/etc/postfix/mailbox_commands
 
 /etc/postfix/mailbox_commands:
     you    /path/to/maildrop -d ${USER}
index 6b2165685be1d750a8788efed9b3694214a1b575..04711f7ccd626566cf4c07f4c5785fc04af10c6e 100644 (file)
@@ -262,7 +262,7 @@ the overhead of the TLS exchange. </p>
 certificates issued by these CAs, append the root certificate to
 $smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory.  When
 you configure trust in a root CA, it is not necessary to explicitly trust
-intermediary CAs signed by the root CA, unless $smtpd_tls_verify_depth
+intermediary CAs signed by the root CA, unless $smtpd_tls_ccert_verifydepth
 is less than the number of CAs in the certificate chain for the clients
 of interest. With a verify depth of 1 you can only verify certificates
 directly signed by a trusted CA, and all trusted intermediary CAs need to
@@ -315,7 +315,7 @@ is needed. Thus, the $smtpd_tls_CApath directory needs to be
 accessible inside the optional chroot jail. </p>
 
 <p> When you configure Postfix to request client certificates (by
-setting $smtpd_tls_asck_ccert = yes), any certificates in
+setting $smtpd_tls_ask_ccert = yes), any certificates in
 $smtpd_tls_CAfile are sent to the client, in order to allow it to
 choose an identity signed by a CA you trust. If no $smtpd_tls_CAfile
 is specified, no preferred CA list is sent, and the client is free
index 405ba1f3f60171271c19c08f6da42a6f0ceb1277..26248d58de2dd7666d9bfb5eedfdd0b430d0a7e6 100644 (file)
 # .sp
 #      Note: this action does not support multi-line message headers.
 # .sp
+#      Note: this action must be used before the message content
+#      is received; it cannot be used in \fBsmtpd_end_of_data_restrictions\fR.
+# .sp
 #      This feature is available in Postfix 2.1 and later.
 # .IP "\fBREDIRECT \fIuser@domain\fR"
 #      After the message is queued, send the message to the specified
index 097abcef5e1597ceab1d36d66a680b8a77e45f19..614ff01f168c5a4e5056455e0be172b63537cbe4 100644 (file)
@@ -95,14 +95,22 @@ void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
                                          const char *buf, int len)
 {
     const char *encoding;
-    const char generated_by_cleanup[] = {
-       REC_TYPE_FILT, REC_TYPE_RDR, REC_TYPE_ATTR,
-       REC_TYPE_RRTO, REC_TYPE_ERTO, 0,
-    };
+    int     extra_opts;
 
     if (msg_verbose)
        msg_info("extracted envelope %c %.*s", type, len, buf);
 
+    if (type == REC_TYPE_FLGS) {
+       /* Not part of queue file format. */
+       extra_opts = atol(buf);
+       if (extra_opts & ~CLEANUP_FLAG_MASK_EXTRA)
+           msg_warn("%s: ignoring bad extra flags: 0x%x",
+                    state->queue_id, extra_opts);
+       else
+           state->flags |= extra_opts;
+       return;
+    }
+
     if (strchr(REC_TYPE_EXTRACT, type) == 0) {
        msg_warn("%s: message rejected: "
                 "unexpected record type %d in extracted envelope",
@@ -179,14 +187,8 @@ void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
     if (state->flags & CLEANUP_FLAG_INRCPT)
        /* Tell qmgr that recipient records are mixed with other information. */
        state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER;
-    if (strchr(generated_by_cleanup, type) != 0) {
-       /* Use our own header/body info instead. */
-       return;
-    } else {
-       /* Pass on other non-recipient record. */
-       cleanup_out(state, type, buf, len);
-       return;
-    }
+    cleanup_out(state, type, buf, len);
+    return;
 }
 
 /* cleanup_extracted_finish - process one extracted envelope record */
index 029f70688874009d3580160d71b195ecd72208b6..e456f0b47d736ada10c5b7adffb587df5a784a79 100644 (file)
@@ -564,6 +564,7 @@ static void cleanup_header_done_callback(void *context)
     char    time_stamp[1024];          /* XXX locale dependent? */
     struct tm *tp;
     TOK822 *token;
+    time_t  tv;
 
     /*
      * Add a missing (Resent-)Message-Id: header. The message ID gives the
@@ -573,10 +574,17 @@ static void cleanup_header_done_callback(void *context)
      * 
      * XXX It is the queue ID non-inode bits that prevent messages from getting
      * the same Message-Id within the same second.
+     * 
+     * XXX An arbitrary amount of time may pass between the start of the mail
+     * transaction and the creation of a queue file. Since we guarantee queue
+     * ID uniqueness only within a second, we must ensure that the time in
+     * the message ID matches the queue ID creation time, as long as we use
+     * the queue ID in the message ID.
      */
     if ((state->headers_seen & (1 << (state->resent[0] ?
                           HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
-       tp = gmtime(&state->time);
+       tv = state->handle->ctime.tv_sec;
+       tp = gmtime(&tv);
        strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
        cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>",
                state->resent, time_stamp, state->queue_id, var_myhostname);
index 90a45b82c7c3dfb7995200b3b2a00e33a700877e..c57114c6fe57afe38f4596620ffb13a0a9963b70 100644 (file)
@@ -19,6 +19,9 @@
 #ifdef RESOLVE_H_NEEDS_STDIO_H
 #include <stdio.h>
 #endif
+#ifdef RESOLVE_H_NEEDS_NAMESER8_COMPAT_H
+#include <nameser8_compat.h>
+#endif
 #include <resolv.h>
 
  /*
index e16d22933e46148c0de92400c7d86049341535d5..3f85338fa0fa7079651e639b41e11998ee9ae596 100644 (file)
@@ -393,12 +393,8 @@ static HOST *dict_mysql_find_host(PLMYSQL *PLDB, unsigned stat, unsigned type)
     }
 
     if (count) {
-       /*
-        * Calling myrand() can deplete the random pool.
-        * Don't rely on the optimizer to weed out the call
-        * when count == 1.
-        */
-       idx = (count > 1) ? 1 + (count - 1) * (double) myrand() / RAND_MAX : 1;
+       idx = (count > 1) ?
+           1 + count * (double) myrand() / (1.0 + RAND_MAX) : 1;
 
        for (i = 0; i < PLDB->len_hosts; i++) {
            if (dict_mysql_check_stat(PLDB->db_hosts[i], stat, type, t) &&
index 025cb6b376af97317fe64406c539eb8f6e1ce6cc..9fe6768bfebc592dc1e8197ce674414fc146dccf 100644 (file)
@@ -388,12 +388,8 @@ static HOST *dict_pgsql_find_host(PLPGSQL *PLDB, unsigned stat, unsigned type)
     }
 
     if (count) {
-       /*
-        * Calling myrand() can deplete the random pool.
-        * Don't rely on the optimizer to weed out the call
-        * when count == 1.
-        */
-       idx = (count > 1) ? 1 + (count - 1) * (double) myrand() / RAND_MAX : 1;
+       idx = (count > 1) ?
+           1 + count * (double) myrand() / (1.0 + RAND_MAX) : 1;
 
        for (i = 0; i < PLDB->len_hosts; i++) {
            if (dict_pgsql_check_stat(PLDB->db_hosts[i], stat, type, t) &&
index 9068955c32921c13a46408e89d330ecf81e0f848..89da51b479aaebc3fd87d661ac939c0eeb213700 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <mail_queue.h>
 /*
-/*     VSTREAM *mail_queue_enter(queue_name, mode)
+/*     VSTREAM *mail_queue_enter(queue_name, mode, tp)
 /*     const char *queue_name;
 /*     int     mode;
+/*     struct timeval *tp;
 /*
 /*     VSTREAM *mail_queue_open(queue_name, queue_id, flags, mode)
 /*     const char *queue_name;
@@ -53,7 +54,9 @@
 /*     id is the file base name, see VSTREAM_PATH().  Queue ids are
 /*     relatively short strings and are recycled in the course of time.
 /*     The only guarantee given is that on a given machine, no two queue
-/*     entries will have the same queue ID at the same time.
+/*     entries will have the same queue ID at the same time. The tp
+/*     argument, if not a null pointer, receives the time stamp that
+/*     corresponds with the queue ID.
 /*
 /*     mail_queue_open() opens the named queue file. The \fIflags\fR
 /*     and \fImode\fR arguments are as with open(2). The result is a
@@ -304,7 +307,8 @@ int     mail_queue_id_ok(const char *queue_id)
 
 /* mail_queue_enter - make mail queue entry with locally-unique name */
 
-VSTREAM *mail_queue_enter(const char *queue_name, int mode)
+VSTREAM *mail_queue_enter(const char *queue_name, int mode,
+                                 struct timeval * tp)
 {
     char   *myname = "mail_queue_enter";
     static VSTRING *id_buf;
@@ -326,7 +330,8 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode)
        path_buf = vstring_alloc(10);
        temp_path = vstring_alloc(100);
     }
-    GETTIMEOFDAY(&tv);
+    if (tp == 0)
+       tp = &tv;
 
     /*
      * Create a file with a temporary name that does not collide. The process
@@ -338,13 +343,12 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode)
      * If someone is racing against us, try to win.
      */
     for (;;) {
+       GETTIMEOFDAY(tp);
        vstring_sprintf(temp_path, "%s/%d.%d", queue_name,
-                       (int) tv.tv_usec, pid);
+                       (int) tp->tv_usec, pid);
        if ((fd = open(STR(temp_path), O_RDWR | O_CREAT | O_EXCL, mode)) >= 0)
            break;
        if (errno == EEXIST || errno == EISDIR) {
-           if ((int) ++tv.tv_usec < 0)
-               tv.tv_usec = 0;
            continue;
        }
        msg_warn("%s: create file %s: %m", myname, STR(temp_path));
@@ -364,7 +368,6 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode)
      * If someone is racing against us, try to win.
      */
     file_id = get_file_id(fd);
-    GETTIMEOFDAY(&tv);
 
     /*
      * XXX Some systems seem to have clocks that correlate with process
@@ -374,20 +377,12 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode)
      * prevents multiple messages from getting the same Message-ID value.
      */
     for (count = 0;; count++) {
-       vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id);
+       GETTIMEOFDAY(tp);
+       vstring_sprintf(id_buf, "%05X%s", (int) tp->tv_usec, file_id);
        mail_queue_path(path_buf, queue_name, STR(id_buf));
-#if 0
-       if (access(STR(path_buf), X_OK) == 0) { /* collision. */
-           if ((int) ++tv.tv_usec < 0)
-               tv.tv_usec = 0;
-           continue;
-       }
-#endif
        if (sane_rename(STR(temp_path), STR(path_buf)) == 0)    /* success */
            break;
        if (errno == EPERM || errno == EISDIR) {/* collision. weird. */
-           if ((int) ++tv.tv_usec < 0)
-               tv.tv_usec = 0;
            continue;
        }
        if (errno != ENOENT || mail_queue_mkdirs(STR(path_buf)) < 0) {
index b3d692821d440b3d3a13744d08f7f2b9f749ba74..e9f7655e6c6f359eec0beb98caa0608aec085365 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * System library.
+  */
+#include <sys/time.h>
+
  /*
   * Utility library.
   */
@@ -37,7 +42,7 @@
 #define MAIL_QUEUE_STAT_READY  (S_IRUSR | S_IWUSR | S_IXUSR)
 #define MAIL_QUEUE_STAT_CORRUPT        (S_IRUSR)
 
-extern struct VSTREAM *mail_queue_enter(const char *, int);
+extern struct VSTREAM *mail_queue_enter(const char *, int, struct timeval *);
 extern struct VSTREAM *mail_queue_open(const char *, const char *, int, int);
 extern int mail_queue_rename(const char *, const char *, const char *);
 extern int mail_queue_remove(const char *, const char *);
index 6edeea7ad857b046561993f69344c8b6f8737d6d..4930a6a5c97809d8d2000ad5a03f80e539f0dad1 100644 (file)
@@ -10,6 +10,7 @@
 /* .in +4
 /*             VSTREAM *stream;
 /*             char    *id;
+/*             struct timeval ctime;
 /*             private members...
 /* .in -4
 /*     } MAIL_STREAM;
@@ -264,10 +265,11 @@ int     mail_stream_finish(MAIL_STREAM *info, VSTRING *why)
 MAIL_STREAM *mail_stream_file(const char *queue, const char *class,
                                      const char *service, int mode)
 {
+    struct timeval tv;
     MAIL_STREAM *info;
     VSTREAM *stream;
 
-    stream = mail_queue_enter(queue, 0600 | mode);
+    stream = mail_queue_enter(queue, 0600 | mode, &tv);
     if (msg_verbose)
        msg_info("open %s", VSTREAM_PATH(stream));
 
@@ -280,6 +282,7 @@ MAIL_STREAM *mail_stream_file(const char *queue, const char *class,
     info->class = mystrdup(class);
     info->service = mystrdup(service);
     info->mode = mode;
+    info->ctime = tv;
     return (info);
 }
 
index a1e64f13ec7df2b0eb8480f189c67f5cdfba0e98..f1c393b5abfcf160c973dc230e2e6693cbc299e0 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * System library.
+  */
+#include <sys/time.h>
+
  /*
   * Utility library.
   */
@@ -34,6 +39,7 @@ struct MAIL_STREAM {
     char   *class;                     /* trigger class */
     char   *service;                   /* trigger service */
     int     mode;                      /* additional permissions */
+    struct timeval ctime;              /* creation time */
 };
 
 extern MAIL_STREAM *mail_stream_file(const char *, const char *, const char *, int);
index 5fcf512bc018cbc557df929d42e9b2a7f72a6fe8..f402600a1e0518dde7f1382fe20996e04e658178 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20050719"
-#define MAIL_VERSION_NUMBER    "2.2.5"
+#define MAIL_RELEASE_DATE      "20051130"
+#define MAIL_VERSION_NUMBER    "2.2.6"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #ifdef SNAPSHOT
index cbd0f7aba0e81b638962f751322fc2e522fbed8a..0d31fa676607c6d00a44b0510fca9b9fc7fd2ce5 100644 (file)
@@ -28,6 +28,7 @@
   */
 #define SMTP_ERR_EOF   1               /* unexpected client disconnect */
 #define SMTP_ERR_TIME  2               /* time out */
+#define SMTP_ERR_PROTO 3               /* protocol (application) */
 
 extern void smtp_timeout_setup(VSTREAM *, int);
 extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
index b063771382b6d0f27895e574f70da13af323e81b..7a0c31d9d9d0c141ea2741c5e56f2a13c763f170 100644 (file)
@@ -222,7 +222,21 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state)
            if (*cp == ' ' || *cp == 0)
                break;
        }
+
+       /*
+        * XXX Do not ignore garbage when ESMTP command pipelining is turned
+        * on. After sending ".<CR><LF>QUIT<CR><LF>", Postfix might recognize
+        * the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
+        * garbage, causing mail to be lost. Instead, make a long jump so
+        * that all recipients of multi-recipient mail get consistent
+        * treatment.
+        */
        state->error_mask |= MAIL_ERROR_PROTOCOL;
+       if (state->features & LMTP_FEATURE_PIPELINING) {
+           msg_warn("non-LMTP response from %s: %.100s",
+                    session->namaddr, STR(state->buffer));
+           vstream_longjmp(session->stream, SMTP_ERR_PROTO);
+       }
     }
     if (three_digs != 0)
        rdata.code = atoi(STR(state->buffer));
index b9d1ce5001c29413206adc54fd848056a6342cdf..c58192edef96f9400f94811f60784086883bfbbd 100644 (file)
@@ -296,6 +296,10 @@ int     lmtp_stream_except(LMTP_STATE *state, int code, char *description)
        vstring_sprintf(why, "conversation with %s timed out while %s",
                        session->namaddr, description);
        break;
+    case SMTP_ERR_PROTO:
+       vstring_sprintf(why, "remote protocol error in reply from %s while %s",
+                       session->namaddr, description);
+       break;
     }
 
     /*
index 058aa8a5599e105eeb45731047675545355c86ae..8b724b1ec832353dabd923b6850328945f84a20d 100644 (file)
@@ -210,6 +210,8 @@ static void qmgr_deliver_update(int unused_event, char *context)
     QMGR_MESSAGE *message = entry->message;
     VSTRING *reason = vstring_alloc(1);
     int     status;
+    QMGR_RCPT *recipient;
+    int     nrcpt;
 
     /*
      * The message transport has responded. Stop the watchdog timer.
@@ -239,6 +241,21 @@ static void qmgr_deliver_update(int unused_event, char *context)
        qmgr_transport_throttle(transport, "unknown mail transport error");
        msg_warn("transport %s failure -- see a previous warning/fatal/panic logfile record for the problem description",
                 transport->name);
+
+       /*
+        * Assume the worst and write a defer logfile record for each
+        * recipient. This omission was already present in the first queue
+        * manager implementation of 199703, and was fixed 200511.
+        * 
+        * Don't move this queue entry back to the todo queue so that
+        * qmgr_defer_transport() can update the defer log. The queue entry
+        * is still hot, and making it cold would involve duplicating most
+        * but not all code at the end of this routine. That's too tricky.
+        */
+       for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) {
+           recipient = entry->rcpt_list.info + nrcpt;
+           qmgr_defer_recipient(message, recipient, transport->reason);
+       }
        qmgr_defer_transport(transport, transport->reason);
     }
 
@@ -264,7 +281,7 @@ static void qmgr_deliver_update(int unused_event, char *context)
      * No problems detected. Mark the transport and queue as alive. The queue
      * itself won't go away before we dispose of the current queue entry.
      */
-    if (VSTRING_LEN(reason) == 0) {
+    if (status != DELIVER_STAT_CRASH && VSTRING_LEN(reason) == 0) {
        qmgr_transport_unthrottle(transport);
        qmgr_queue_unthrottle(queue);
     }
index 2272a3c74783b76040aa35788b55d87fe726a66a..6f73c55794d73e6875757a4f64cd042cb83b6b79 100644 (file)
@@ -230,9 +230,25 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info,
         * XXX Workaround: REC_TYPE_FILT (used in envelopes) == REC_TYPE_CONT
         * (used in message content).
         */
-       if (type == REC_TYPE_FILT && *expected != REC_TYPE_CONTENT[0])
-           /* Use our own content filter settings instead. */
-           continue;
+       if (*expected != REC_TYPE_CONTENT[0]) {
+           if (type == REC_TYPE_FILT)
+               /* Discard FILTER record after "postsuper -r". */
+               continue;
+           if (type == REC_TYPE_RDR)
+               /* Discard REDIRECT record after "postsuper -r". */
+               continue;
+       }
+       if (*expected == REC_TYPE_EXTRACT[0]) {
+           if (type == REC_TYPE_RRTO)
+               /* Discard return-receipt record after "postsuper -r". */
+               continue;
+           if (type == REC_TYPE_ERTO)
+               /* Discard errors-to record after "postsuper -r". */
+               continue;
+           if (type == REC_TYPE_ATTR)
+               /* Discard other/header/body action after "postsuper -r". */
+               continue;
+       }
 
        /*
         * XXX Force an empty record when the queue file content begins with
index 28463a0e651495ad77a33fab73c83817bb6f4738..e92872b3723c9fb0a6117ebc0aa4543a4ddaf8c7 100644 (file)
@@ -215,6 +215,8 @@ static void qmgr_deliver_update(int unused_event, char *context)
     QMGR_MESSAGE *message = entry->message;
     VSTRING *reason = vstring_alloc(1);
     int     status;
+    QMGR_RCPT *recipient;
+    int     nrcpt;
 
     /*
      * The message transport has responded. Stop the watchdog timer.
@@ -244,6 +246,21 @@ static void qmgr_deliver_update(int unused_event, char *context)
        qmgr_transport_throttle(transport, "unknown mail transport error");
        msg_warn("transport %s failure -- see a previous warning/fatal/panic logfile record for the problem description",
                 transport->name);
+
+       /*
+        * Assume the worst and write a defer logfile record for each
+        * recipient. This omission was already present in the first queue
+        * manager implementation of 199703, and was fixed 200511.
+        * 
+        * Don't move this queue entry back to the todo queue so that
+        * qmgr_defer_transport() can update the defer log. The queue entry
+        * is still hot, and making it cold would involve duplicating most
+        * but not all code at the end of this routine. That's too tricky.
+        */
+       for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) {
+           recipient = entry->rcpt_list.info + nrcpt;
+           qmgr_defer_recipient(message, recipient, transport->reason);
+       }
        qmgr_defer_transport(transport, transport->reason);
     }
 
@@ -269,7 +286,7 @@ static void qmgr_deliver_update(int unused_event, char *context)
      * No problems detected. Mark the transport and queue as alive. The queue
      * itself won't go away before we dispose of the current queue entry.
      */
-    if (VSTRING_LEN(reason) == 0) {
+    if (status != DELIVER_STAT_CRASH && VSTRING_LEN(reason) == 0) {
        qmgr_transport_unthrottle(transport);
        qmgr_queue_unthrottle(queue);
     }
index 2270f774179ff2e053d9f17d3db45e627e59e779..db694c06260b9c415aa7a7c6c61da51692190982 100644 (file)
@@ -245,7 +245,21 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session)
            if (*cp == ' ' || *cp == 0)
                break;
        }
+
+       /*
+        * XXX Do not ignore garbage when ESMTP command pipelining is turned
+        * on. After sending ".<CR><LF>QUIT<CR><LF>", Postfix might recognize
+        * the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
+        * garbage, causing mail to be lost. Instead, make a long jump so
+        * that all recipients of multi-recipient mail get consistent
+        * treatment.
+        */
        session->error_mask |= MAIL_ERROR_PROTOCOL;
+       if (session->features & SMTP_FEATURE_PIPELINING) {
+           msg_warn("non-SMTP response from %s: %s",
+                    session->namaddr, STR(session->buffer));
+           vstream_longjmp(session->stream, SMTP_ERR_PROTO);
+       }
     }
     if (three_digs != 0)
        rdata.code = atoi(STR(session->buffer));
index 24474ca06198e67972cd8893c1485ca6883eae6e..1fcae1f2ffbcce8d9725cd6a559dad7f2a62b6b3 100644 (file)
@@ -358,12 +358,36 @@ static void smtp_cleanup_session(SMTP_STATE *state)
      * XXX Should not cache TLS sessions unless we are using a single-session,
      * in-process, cache. And if we did, we should passivate VSTREAM objects
      * in addition to passivating SMTP_SESSION objects.
+     * 
+     * XXX Workaround. If this host spoke TLS, connection caching was already
+     * turned off for this session by smtp_tls_start(). However, this alone
+     * does not distinguish between "good TLS connection" and "bad
+     * connection".
+     * 
+     * In the case of "bad connection" to a primary host we want to store the
+     * first good alternate connection under the logical next-hop destination
+     * name name. In the case of a good primary TLS connection that would not
+     * make sense: the Postfix cache would prefer non-TLS secondary hosts
+     * over TLS-enabled primary hosts!
+     * 
+     * The real fix is to have three-valued connection caching state: "do
+     * cache", "don't cache", and "bad connection", but that involves more
+     * change than is allowed in a stable release.
+     * 
+     * To distinguish good TLS connections from bad connections we reset the
+     * logical next-hop state, so that we won't cache connections to
+     * less-preferred MX hosts under the logical next-hop destination.
      */
     if (session->reuse_count > 0) {
        smtp_save_session(state);
        if (HAVE_NEXTHOP_STATE(state))
            FREE_NEXTHOP_STATE(state);
     } else {
+#ifdef USE_TLS
+       if (session->tls_context)
+           if (HAVE_NEXTHOP_STATE(state))
+               FREE_NEXTHOP_STATE(state);
+#endif
        smtp_session_free(session);
     }
     state->session = 0;
index 1d8ba27e3da0c8d1fdddc515eb2309303e8037d5..23f49c5ca1ba3a4a731c7dbf3380bbd226c8eef7 100644 (file)
@@ -386,6 +386,10 @@ int     smtp_stream_except(SMTP_STATE *state, int code, char *description)
        vstring_sprintf(why, "conversation with %s timed out while %s",
                        session->namaddr, description);
        break;
+    case SMTP_ERR_PROTO:
+       vstring_sprintf(why, "remote protocol error in reply from %s while %s",
+                       session->namaddr, description);
+       break;
     }
 
     /*
index 756a4cd93ff2540b3ce78a95c5d9c4ecf773b2f4..8d02bd3cf4099b6773d9b864f05483b416e65657 100644 (file)
@@ -1493,8 +1493,9 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        && anvil_clnt_mail(anvil_clnt, state->service, state->addr,
                           &rate) == ANVIL_STAT_OK
        && rate > var_smtpd_cmail_limit) {
-       smtpd_chat_reply(state, "421 %s Error: too much mail from %s",
-                        var_myhostname, state->addr);
+       state->error_mask |= MAIL_ERROR_POLICY;
+       smtpd_chat_reply(state, "450 Error: too much mail from %s",
+                        state->addr);
        msg_warn("Message delivery request rate limit exceeded: %d from %s for service %s",
                 rate, state->namaddr, state->service);
        return (-1);
@@ -1702,8 +1703,9 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        && anvil_clnt_rcpt(anvil_clnt, state->service, state->addr,
                           &rate) == ANVIL_STAT_OK
        && rate > var_smtpd_crcpt_limit) {
-       smtpd_chat_reply(state, "421 %s Error: too many recipients from %s",
-                        var_myhostname, state->addr);
+       state->error_mask |= MAIL_ERROR_POLICY;
+       smtpd_chat_reply(state, "450 Error: too many recipients from %s",
+                        state->addr);
        msg_warn("Recipient address rate limit exceeded: %d from %s for service %s",
                 rate, state->namaddr, state->service);
        return (-1);
@@ -1919,17 +1921,13 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
     /*
      * Flush out any access table actions that are delegated to the cleanup
      * server, and that may trigger before we accept the first valid
-     * recipient.
+     * recipient. There will be more after end-of-data.
      * 
      * Terminate the message envelope segment. Start the message content
      * segment, and prepend our own Received: header. If there is only one
      * recipient, list the recipient address.
      */
     if (state->cleanup) {
-       if (state->saved_filter)
-           rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", state->saved_filter);
-       if (state->saved_redirect)
-           rec_fprintf(state->cleanup, REC_TYPE_RDR, "%s", state->saved_redirect);
        if (state->saved_flags)
            rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", state->saved_flags);
        rec_fputs(state->cleanup, REC_TYPE_MESG, "");
@@ -2042,13 +2040,18 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
        if (prev_rec_type != REC_TYPE_CONT && *start == '.'
            && (state->proxy == 0 ? (++start, --len) == 0 : len == 1))
            break;
-       state->act_size += len + 2;
-       if (state->err == CLEANUP_STAT_OK
-           && out_record(out_stream, curr_rec_type, start, len) < 0)
-           state->err = out_error;
+       if (state->err == CLEANUP_STAT_OK) {
+           state->act_size += len + 2;
+           if (var_message_limit > 0 && state->act_size > var_message_limit)
+               state->err = CLEANUP_STAT_SIZE;
+           else if (out_record(out_stream, curr_rec_type, start, len) < 0)
+               state->err = out_error;
+       }
     }
     state->where = SMTPD_AFTER_DOT;
-    if (SMTPD_STAND_ALONE(state) == 0 && (err = smtpd_check_eod(state)) != 0) {
+    if (state->err == CLEANUP_STAT_OK
+       && SMTPD_STAND_ALONE(state) == 0
+       && (err = smtpd_check_eod(state)) != 0) {
        smtpd_chat_reply(state, "%s", err);
        if (state->proxy) {
            smtpd_proxy_close(state);
@@ -2074,8 +2077,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
            if (state->err == CLEANUP_STAT_OK &&
                *STR(state->proxy_buffer) != '2')
                state->err = CLEANUP_STAT_CONT;
-       } else {
-           state->error_mask |= MAIL_ERROR_SOFTWARE;
+       } else if (state->err != CLEANUP_STAT_SIZE) {
            state->err |= CLEANUP_STAT_PROXY;
            vstring_sprintf(state->proxy_buffer,
                            "451 Error: queue file write error");
@@ -2083,13 +2085,28 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
     }
 
     /*
-     * Send the end-of-segment markers and finish the queue file record
-     * stream.
+     * Flush out access table actions that are delegated to the cleanup
+     * server. There is similar code at the beginning of the DATA command.
+     * 
+     * Send the end-of-segment markers and finish the queue file record stream.
      */
     else {
+       if (state->err == CLEANUP_STAT_OK) {
+           rec_fputs(state->cleanup, REC_TYPE_XTRA, "");
+           if (state->saved_filter)
+               rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s",
+                           state->saved_filter);
+           if (state->saved_redirect)
+               rec_fprintf(state->cleanup, REC_TYPE_RDR, "%s",
+                           state->saved_redirect);
+           if (state->saved_flags)
+               rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d",
+                           state->saved_flags);
+           if (vstream_ferror(state->cleanup))
+               state->err = CLEANUP_STAT_WRITE;
+       }
        if (state->err == CLEANUP_STAT_OK)
-           if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0
-               || rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
+           if (rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
                || vstream_fflush(state->cleanup))
                state->err = CLEANUP_STAT_WRITE;
        if (state->err == 0) {
@@ -2979,6 +2996,7 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
            && anvil_clnt_connect(anvil_clnt, service, state->addr,
                                  &count, &crate) == ANVIL_STAT_OK) {
            if (var_smtpd_cconn_limit > 0 && count > var_smtpd_cconn_limit) {
+               state->error_mask |= MAIL_ERROR_POLICY;
                smtpd_chat_reply(state, "421 %s Error: too many connections from %s",
                                 var_myhostname, state->addr);
                msg_warn("Connection concurrency limit exceeded: %d from %s for service %s",
index 5e59e2b9cbf8a9d32b782c947ff53be28d645896..4d57edcc50eb4a93de144c1586838602534ad51a 100644 (file)
@@ -1748,6 +1748,15 @@ static int can_delegate_action(SMTPD_STATE *state, const char *table,
                 table, VAR_SMTPD_PROXY_FILT, action);
        return (0);
     }
+
+    /*
+     * ETRN does not receive mail so we can't store queue file records.
+     */
+    if (strcmp(state->where, "ETRN") == 0) {
+       msg_warn("access table %s: action %s is unavailable in %s",
+                table, action, VAR_ETRN_CHECKS);
+       return (0);
+    }
     return (not_in_client_helo(state, table, action, reply_class));
 }
 
@@ -1955,6 +1964,11 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
        if (not_in_client_helo(state, table, "PREPEND", reply_class) == 0)
            return (SMTPD_CHECK_DUNNO);
 #endif
+       if (strcmp(state->where, SMTPD_AFTER_DOT) == 0) {
+           msg_warn("access table %s: action PREPEND must be used before %s",
+                    table, VAR_EOD_CHECKS);
+           return (SMTPD_CHECK_DUNNO);
+       }
        if (*cmd_text == 0 || is_header(cmd_text) == 0) {
            msg_warn("access map %s entry \"%s\" requires header: text",
                     table, datum);
index 03976abc7132e9eca33553f4d6545581b763d804..e0a1b15d30bd9bd9bb23dae6ec74c9aa97203bd7 100644 (file)
@@ -227,4 +227,11 @@ long    tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi,
     return (ret);
 }
 
+#else
+
+ /*
+  * Broken linker workaround.
+  */
+int     tls_dummy_for_broken_linkers;
+
 #endif
index 30a3d8533e1413e68567cd523591305619446d53..a4560c2c5c4d827b7b8ebfbe1e34da8f21370397 100644 (file)
@@ -59,6 +59,9 @@ int     sane_accept(int sock, struct sockaddr * sa, SOCKADDR_SIZE *len)
        EWOULDBLOCK,
        ENOBUFS,                        /* HPUX11 */
        ECONNABORTED,
+#ifdef EPROTO
+       EPROTO,                         /* SunOS 5.5.1 */
+#endif
        0,
     };
     int     count;
@@ -71,6 +74,10 @@ int     sane_accept(int sock, struct sockaddr * sa, SOCKADDR_SIZE *len)
      * hosed beyond recovery. There is no point treating this as a beneficial
      * error result because the program would go into a tight loop.
      * 
+     * XXX Solaris 2.5.1 accept() returns EPROTO when a TCP client has
+     * disconnected in the mean time. Since there is no connection, it is
+     * safe to map the error code onto EAGAIN.
+     * 
      * XXX LINUX < 2.1 accept() wakes up before the three-way handshake is
      * complete, so it can fail with ECONNRESET and other "false alarm"
      * indications.
index c358db320750e9831b52c02f85c8a0934988577d..4bddae4106cc246a511deb88d04f4c682bd92d81 100644 (file)
@@ -50,7 +50,7 @@
 #endif
 #define GETTIMEOFDAY(t)        gettimeofday(t,(struct timezone *) 0)
 #define ROOT_PATH      "/bin:/usr/bin:/sbin:/usr/sbin"
-#if (defined(__NetBSD_Version__) && __NetBSD_Version__ > 200040000)
+#if (defined(__NetBSD_Version__) && __NetBSD_Version__ > 299000900)
 # define USE_STATVFS
 # define STATVFS_IN_SYS_STATVFS_H
 #else
 #define SOCKOPT_SIZE   socklen_t
 #endif
 
-#if __NetBSD_Version__ >= 200060000    /* 2.0F */
+#if __NetBSD_Version__ >= 299000900    /* 2.99.9 */
 #define HAS_CLOSEFROM
 #endif
 
 #define DEF_DB_TYPE    "hash"
 #define ALIAS_DB_MAP   "hash:/etc/aliases"
 #define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
+#define RESOLVE_H_NEEDS_NAMESER8_COMPAT_H
 #define ROOT_PATH      "/bin:/usr/bin:/sbin:/usr/sbin"
 #define USE_STATFS
 #define STATFS_IN_SYS_MOUNT_H