]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20050627
authorWietse Venema <wietse@porcupine.org>
Mon, 27 Jun 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:17 +0000 (06:31 +0000)
25 files changed:
postfix/HISTORY
postfix/html/lmtp.8.html
postfix/html/postconf.5.html
postfix/html/smtp-sink.1.html
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/man/man1/smtp-sink.1
postfix/man/man5/postconf.5
postfix/man/man8/lmtp.8
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/proto/postconf.proto
postfix/src/cleanup/cleanup_message.c
postfix/src/global/mail_version.h
postfix/src/lmtp/lmtp.c
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp_session.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpstone/smtp-sink.c
postfix/src/util/attr_print0.c
postfix/src/util/attr_print64.c
postfix/src/util/attr_print_plain.c
postfix/src/util/attr_scan0.c
postfix/src/util/attr_scan64.c
postfix/src/util/attr_scan_plain.c

index fc09adcf066539180142ff86747ba99ad7bc7d4d..a7d0460eba00b7aa4f509816a69dd5ecdddb512a 100644 (file)
@@ -10931,8 +10931,34 @@ Apologies for any names omitted.
        util/attr_print0.c, global/dsb_scan.c, global/dsn_print.c,
        global/rcpt_buf,c global/rcpt_print.c, global/deliver_pass.c.
 
+       Added delegated attribute scan/print function support to
+       the base64 and plain attribute I/O encodings. Files:
+       util/attr_scan_plain.c util/attr_print_plain.c.
+
+20040624
+
+       Added "." to the list commands that smtp-sink can "break"
+       (by disconnecting, or by responding with a 4XX or 5XX reply
+       code). File: smtpstone/smtp-sink.c.
+
+20040625
+
+       Safety: allow only 4.x.x and 5.x.x enhanced status codes
+       in header/body_checks REJECT actions. File:
+       cleanup/cleanup_message.c.
+
+20050627
+
+       Code cleanup: generalized the smtp-sink code that simulates
+       server errors. File: smtpstone/smtp-sink.c.
+
 Open problems:
 
+       Look for systems with XPG basename() declared in <libgen.h>,
+       and prepare for phasing out the Postfix-supplied one.
+       Beware, however, that XPG basename() takes (char *), and
+       not (const char *) because it may change its argument.
+
        Laptop friendliness: make the qmgr remember when the next
        deferred queue scan needs to be done, and have the pickup
        server stat() the maildrop directory before searching it.
index df7235987deeff1cf442e69f3b4ab249d2bcc5f7..1802920c34d93853d7368c7610a02a3d8c1d2644 100644 (file)
@@ -281,11 +281,16 @@ LMTP(8)                                                                LMTP(8)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
-       Alterations for LMTP by:
+       Modifications for LMTP by:
        Philip A. Prindeville
        Mirapoint, Inc.
        USA.
 
+       SASL support originally by:
+       Till Franke
+       SuSE Rhein/Main AG
+       65760 Eschborn, Germany
+
        Additional work on LMTP by:
        Amos Gouaux
        University of Texas at Dallas
index 626d09d2e2347feff2601f03774e06598e27d61d..9e280791a76744edebfd94a7c378388fd74acccb 100644 (file)
@@ -6206,7 +6206,7 @@ The default time unit is s (seconds).
 <p>
 The maximal number of MX (mail exchanger) IP addresses that can
 result from mail exchanger lookups, or zero (no limit). Prior to
-Postfix 2.3, this limit was disabled.
+Postfix 2.3, this limit was disabled by default.
 </p>
 
 <p>
index e773ad591e2f940ca3e55385822b3f1bd39183e5..6110c80655e7e62dbae951ec394f64135cdf5c25 100644 (file)
@@ -50,6 +50,12 @@ SMTP-SINK(1)                                                      SMTP-SINK(1)
               Reject the specified commands  with  a  hard  (5xx)
               error code.  This option implies <b>-p</b>.
 
+              Examples  of  commands  are HELO, EHLO, LHLO, MAIL,
+              RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT. Separate
+              command  names  by  white  space or commas, and use
+              quotes to protect white space from the shell.  Com-
+              mand names are case-insensitive.
+
        <b>-F</b>     Disable XFORWARD support.
 
        <b>-h</b> <i>hostname</i>
@@ -73,21 +79,34 @@ SMTP-SINK(1)                                                      SMTP-SINK(1)
               Disconnect (without replying) after  receiving  one
               of the specified commands.
 
+              Examples  of  commands  are HELO, EHLO, LHLO, MAIL,
+              RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT. Separate
+              command  names  by  white  space or commas, and use
+              quotes to protect white space from the shell.  Com-
+              mand names are case-insensitive.
+
        <b>-r</b> <i>command,command,...</i>
               Reject  the  specified  commands  with a soft (4xx)
               error code.  This option implies <b>-p</b>.
 
+              Examples of commands are HELO,  EHLO,  LHLO,  MAIL,
+              RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT. Separate
+              command names by white space  or  commas,  and  use
+              quotes  to protect white space from the shell. Com-
+              mand names are case-insensitive.
+
        <b>-s</b> <i>command,command,...</i>
-              Log the named commands  to  syslogd.   Examples  of
-              commands  that  can be logged are HELO, EHLO, LHLO,
-              MAIL, RCPT, VRFY, RSET, NOOP,  and  QUIT.  Separate
-              command  names  by  white  space or commas, and use
-              quotes to protect white space from the shell.  Com-
+              Log the named commands to syslogd.
+
+              Examples of commands are HELO,  EHLO,  LHLO,  MAIL,
+              RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT. Separate
+              command names by white space  or  commas,  and  use
+              quotes  to protect white space from the shell. Com-
               mand names are case-insensitive.
 
        <b>-t</b> <i>timeout</i> (default: 100)
               Limit the time for receiving a command or sending a
-              response.  The time limit is specified in  seconds.
+              response.   The time limit is specified in seconds.
 
        <b>-v</b>     Show the SMTP conversations.
 
@@ -96,7 +115,7 @@ SMTP-SINK(1)                                                      SMTP-SINK(1)
               mand.
 
        [<b>inet:</b>][<i>host</i>]:<i>port</i>
-              Listen on  network  interface  <i>host</i>  (default:  any
+              Listen  on  network  interface  <i>host</i>  (default: any
               interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
               specified in numeric or symbolic form.
 
@@ -104,14 +123,14 @@ SMTP-SINK(1)                                                      SMTP-SINK(1)
               Listen on the UNIX-domain socket at <i>pathname</i>.
 
        <i>backlog</i>
-              The maximum length the  queue  of  pending  connec-
+              The  maximum  length  the  queue of pending connec-
               tions, as defined by the <b>listen</b>(2) system call.
 
 <b>SEE ALSO</b>
        <a href="smtp-source.1.html">smtp-source(1)</a>, SMTP/LMTP message generator
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index be81081f0d3759a9b5d568e523b93dae4e7db664..4b1d90606e6425b2070a78f8f5cea76c9ffc1752 100644 (file)
@@ -523,6 +523,11 @@ SMTP(8)                                                                SMTP(8)
        Coventry,
        CV1 4LY, United Kingdom.
 
+       SASL support originally by:
+       Till Franke
+       SuSE Rhein/Main AG
+       65760 Eschborn, Germany
+
        Connection caching in cooperation with:
        Victor Duchovni
        Morgan Stanley
index 433712dbe49992cd69f7496694cdd8e9a188878c..37208aa0aa7a95bc77c9b2084ee4fce5e33bdf83 100644 (file)
@@ -962,6 +962,11 @@ SMTPD(8)                                                              SMTPD(8)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
+       SASL support originally by:
+       Till Franke
+       SuSE Rhein/Main AG
+       65760 Eschborn, Germany
+
        TLS support originally by:
        Lutz Jaenicke
        BTU Cottbus
index ddbd2812f96c235c800850f6220c7d88007f7c35..77cd22c5e3614be16b36a2607679598b0178a590 100644 (file)
@@ -49,6 +49,11 @@ Do not announce ENHANCEDSTATUSCODES support.
 .IP "\fB-f \fIcommand,command,...\fR"
 Reject the specified commands with a hard (5xx) error code.
 This option implies \fB-p\fR.
+.sp
+Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+DATA, ., RSET, NOOP, and QUIT. Separate command names by
+white space or commas, and use quotes to protect white space
+from the shell. Command names are case-insensitive.
 .IP \fB-F\fR
 Disable XFORWARD support.
 .IP "\fB-h\fI hostname\fR"
@@ -66,15 +71,26 @@ a CISCO PIX system. Implies \fB-e\fR.
 .IP "\fB-q \fIcommand,command,...\fR"
 Disconnect (without replying) after receiving one of the
 specified commands.
+.sp
+Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+DATA, ., RSET, NOOP, and QUIT. Separate command names by
+white space or commas, and use quotes to protect white space
+from the shell. Command names are case-insensitive.
 .IP "\fB-r \fIcommand,command,...\fR"
 Reject the specified commands with a soft (4xx) error code.
 This option implies \fB-p\fR.
+.sp
+Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+DATA, ., RSET, NOOP, and QUIT. Separate command names by
+white space or commas, and use quotes to protect white space
+from the shell. Command names are case-insensitive.
 .IP "\fB-s \fIcommand,command,...\fR"
 Log the named commands to syslogd.
-Examples of commands that can be logged are HELO, EHLO, LHLO, MAIL,
-RCPT, VRFY, RSET, NOOP, and QUIT. Separate command names by white
-space or commas, and use quotes to protect white space from the
-shell. Command names are case-insensitive.
+.sp
+Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+DATA, ., RSET, NOOP, and QUIT. Separate command names by
+white space or commas, and use quotes to protect white space
+from the shell. Command names are case-insensitive.
 .IP "\fB-t \fItimeout\fR (default: 100)"
 Limit the time for receiving a command or sending a response.
 The time limit is specified in seconds.
index c0fe6d3bf784d23215fb013a6ad4b6020a3680b8..9f144a0cfc866f96aa2923503703168a69adb341 100644 (file)
@@ -3437,7 +3437,7 @@ The default time unit is s (seconds).
 .SH smtp_mx_address_limit (default: 5)
 The maximal number of MX (mail exchanger) IP addresses that can
 result from mail exchanger lookups, or zero (no limit). Prior to
-Postfix 2.3, this limit was disabled.
+Postfix 2.3, this limit was disabled by default.
 .PP
 This feature is available in Postfix 2.1 and later.
 .SH smtp_mx_session_limit (default: 2)
index 3874e254c9ef0622517f08f20f97bc5b0524cac0..8f220203905182055ecf2c42b6d3b9195e593dd6 100644 (file)
@@ -259,11 +259,16 @@ IBM T.J. Watson Research
 P.O. Box 704
 Yorktown Heights, NY 10598, USA
 
-Alterations for LMTP by:
+Modifications for LMTP by:
 Philip A. Prindeville
 Mirapoint, Inc.
 USA.
 
+SASL support originally by:
+Till Franke
+SuSE Rhein/Main AG
+65760 Eschborn, Germany
+
 Additional work on LMTP by:
 Amos Gouaux
 University of Texas at Dallas
index 29f41ca175edd8ffa1956ff1f0a3a02d41dbbd17..9459f0e7d42a5ae98b0da0d3ab16db47b5940af2 100644 (file)
@@ -429,6 +429,11 @@ Canal Basin,
 Coventry,
 CV1 4LY, United Kingdom.
 
+SASL support originally by:
+Till Franke
+SuSE Rhein/Main AG
+65760 Eschborn, Germany
+
 Connection caching in cooperation with:
 Victor Duchovni
 Morgan Stanley
index 4c4121318cc43dcab0bb25a43c512478da10c23c..a07f82035f103ededd2a4d629e7a246f60995fbe 100644 (file)
@@ -779,6 +779,11 @@ IBM T.J. Watson Research
 P.O. Box 704
 Yorktown Heights, NY 10598, USA
 
+SASL support originally by:
+Till Franke
+SuSE Rhein/Main AG
+65760 Eschborn, Germany
+
 TLS support originally by:
 Lutz Jaenicke
 BTU Cottbus
index ffdc3f8dbceb81c646d8066ca61b7cd52cbc2923..16bc0f1c2776161d5f8fd47659a27ff4cb324c45 100644 (file)
@@ -3829,7 +3829,7 @@ The default time unit is s (seconds).
 <p>
 The maximal number of MX (mail exchanger) IP addresses that can
 result from mail exchanger lookups, or zero (no limit). Prior to
-Postfix 2.3, this limit was disabled.
+Postfix 2.3, this limit was disabled by default.
 </p>
 
 <p>
index f8524f74962053de8ecf2be486f94eb0989a2dbd..127870f0fe053fec1c9988c490fe9df5b93ebd5f 100644 (file)
@@ -315,6 +315,11 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context,
        if (state->reason == 0) {
            if (*optional_text) {
                state->reason = dsn_prepend("5.7.1", optional_text);
+               if (*state->reason != '4' && *state->reason != '5') {
+                   msg_warn("bad DSN action in %s -- need 4.x.x or 5.x.x", 
+                             optional_text);
+                   *state->reason = '4';
+               }
            } else {
                detail = cleanup_stat_detail(CLEANUP_STAT_CONT);
                state->reason = dsn_prepend(detail->dsn, detail->text);
index 0993eae726b01e865ed1aad7c68f8303648d3cc0..b9c6453aba3aba9c87a9d624f8f0d2cbd0e17c0f 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      "20050623"
+#define MAIL_RELEASE_DATE      "20050627"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #define VAR_MAIL_VERSION       "mail_version"
index 16712c879e0ee43f9fac2321fc5b439dfc17bfd1..f095c8a6df10890da042be5e056069cfd9661f42 100644 (file)
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
 /*
-/*     Alterations for LMTP by:
+/*     Modifications for LMTP by:
 /*     Philip A. Prindeville
 /*     Mirapoint, Inc.
 /*     USA.
 /*
+/*     SASL support originally by:
+/*     Till Franke
+/*     SuSE Rhein/Main AG
+/*     65760 Eschborn, Germany
+/*
 /*     Additional work on LMTP by:
 /*     Amos Gouaux
 /*     University of Texas at Dallas
index 5f7693092f36fcc86e64e479f3dcefcb82ffe7e1..c2944f7375524775a63eacccaa2e6ed4bc080f67 100644 (file)
 /*     Coventry,
 /*     CV1 4LY, United Kingdom.
 /*
+/*     SASL support originally by:
+/*     Till Franke
+/*     SuSE Rhein/Main AG
+/*     65760 Eschborn, Germany
+/*
 /*     Connection caching in cooperation with:
 /*     Victor Duchovni
 /*     Morgan Stanley
index 993f342cc7fdfec126061c133caa5bc4fcc2e541..f9d338708a9f24f613fe19117b902724987f59a1 100644 (file)
@@ -355,7 +355,7 @@ int     smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
     /*
      * Append the passivated SASL attributes.
      */
-#ifdef USE_SASL
+#ifdef notdef
     if (smtp_sasl_enable)
        smtp_sasl_passivate(endp_prop, session);
 #endif
@@ -460,7 +460,7 @@ SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
     /*
      * Re-activate the SASL attributes.
      */
-#ifdef USE_SASL
+#ifdef notdef
     if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) {
        vstream_fdclose(session->stream);
        session->stream = 0;
index e52224fb53bd14ff76ea6457f10c7b88b2991686..772509932ebb3dbb96553b3fc92a393b351a24c2 100644 (file)
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
 /*
+/*     SASL support originally by:
+/*     Till Franke
+/*     SuSE Rhein/Main AG
+/*     65760 Eschborn, Germany
+/*
 /*     TLS support originally by:
 /*     Lutz Jaenicke
 /*     BTU Cottbus
@@ -1435,8 +1440,12 @@ static int extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg,
     }
 
     /*
-     * Report trouble. Log a warning only if we are going to sleep+reject so
-     * that attackers can't flood our logfiles.
+     * Report trouble. XXX Should log a warning only if we are going to
+     * sleep+reject so that attackers can't flood our logfiles.
+     * 
+     * XXX Unfortunately, the sleep-before-reject feature had to be abandoned
+     * (at least for small error counts) because servers were DOS-ing
+     * themselves when flooded by backscatter traffic.
      */
     if (naddr > 1
        || (strict_rfc821 && (non_addr || *STR(arg->vstrval) != '<'))) {
@@ -1503,8 +1512,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      * XXX 2821 pedantism: Section 4.1.2 says that SMTP servers that receive a
      * command in which invalid character codes have been employed, and for
      * which there are no other reasons for rejection, MUST reject that
-     * command with a 501 response. So much for the principle of "be liberal
-     * in what you accept, be strict in what you send".
+     * command with a 501 response. Postfix attempts to be 8-bit clean.
      */
     if (var_helo_required && state->helo_name == 0) {
        state->error_mask |= MAIL_ERROR_POLICY;
@@ -2448,6 +2456,7 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "501 5.1.3 Bad recipient address syntax");
        return (-1);
     }
+    /* Not: state->addr_buf */
     if (SMTPD_STAND_ALONE(state) == 0
        && (err = smtpd_check_rcpt(state, argv[1].strval)) != 0) {
        smtpd_chat_reply(state, "%s", err);
@@ -2555,8 +2564,11 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg
      * When the "." and quit replies are pipelined, make sure they are
      * flushed now, to avoid repeated mail deliveries in case of a crash in
      * the "clean up before disconnect" code.
+     * 
+     * XXX When this was added in Postfix 2.1 we used vstream_fflush(). As of
+     * Postfix 2.3 we use smtp_flush() for better error reporting.
      */
-    vstream_fflush(state->client);
+    smtp_flush(state->client);
     return (0);
 }
 
@@ -2945,7 +2957,7 @@ static void chat_reset(SMTPD_STATE *state, int threshold)
 
 #ifdef USE_TLS
 
-/* smtpd_start_tls -turn on TLS or force disconnect */
+/* smtpd_start_tls - turn on TLS or force disconnect */
 
 static void smtpd_start_tls(SMTPD_STATE *state)
 {
@@ -2961,10 +2973,10 @@ static void smtpd_start_tls(SMTPD_STATE *state)
      * verification unless TLS is required.
      */
     state->tls_context =
-    tls_server_start(smtpd_tls_ctx, state->client,
-                    var_smtpd_starttls_tmout,
-                    state->name, state->addr, &(state->tls_info),
-                    (var_smtpd_tls_req_ccert && state->tls_enforce_tls));
+       tls_server_start(smtpd_tls_ctx, state->client,
+                        var_smtpd_starttls_tmout,
+                        state->name, state->addr, &(state->tls_info),
+                      (var_smtpd_tls_req_ccert && state->tls_enforce_tls));
 
     /*
      * When the TLS handshake fails, the conversation is in an unknown state.
@@ -3493,12 +3505,13 @@ static void post_jail_init(char *unused_name, char **unused_argv)
      * recipient checks, address mapping, header_body_checks?.
      */
     smtpd_input_transp_mask =
-    input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
+       input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
 
     /*
      * Sanity checks. The queue_minfree value should be at least as large as
      * (process_limit * message_size_limit) but that is unpractical, so we
-     * arbitrarily pick a number and require twice the message size limit.
+     * arbitrarily pick a small multiple of the per-message size limit. This
+     * helps to avoid many unneeded (re)transmissions.
      */
     if (var_queue_minfree > 0
        && var_message_limit > 0
index 4a6c3d7cd391124916af1bb8bb1888e3461d5186..a497885c1db5665a75e0e9555cbe70e0f18508dc 100644 (file)
 /* .IP "\fB-f \fIcommand,command,...\fR"
 /*     Reject the specified commands with a hard (5xx) error code.
 /*     This option implies \fB-p\fR.
+/* .sp
+/*     Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+/*     DATA, ., RSET, NOOP, and QUIT. Separate command names by
+/*     white space or commas, and use quotes to protect white space
+/*     from the shell. Command names are case-insensitive.
 /* .IP \fB-F\fR
 /*     Disable XFORWARD support.
 /* .IP "\fB-h\fI hostname\fR"
 /* .IP "\fB-q \fIcommand,command,...\fR"
 /*     Disconnect (without replying) after receiving one of the
 /*     specified commands.
+/* .sp
+/*     Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+/*     DATA, ., RSET, NOOP, and QUIT. Separate command names by
+/*     white space or commas, and use quotes to protect white space
+/*     from the shell. Command names are case-insensitive.
 /* .IP "\fB-r \fIcommand,command,...\fR"
 /*     Reject the specified commands with a soft (4xx) error code.
 /*     This option implies \fB-p\fR.
+/* .sp
+/*     Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+/*     DATA, ., RSET, NOOP, and QUIT. Separate command names by
+/*     white space or commas, and use quotes to protect white space
+/*     from the shell. Command names are case-insensitive.
 /* .IP "\fB-s \fIcommand,command,...\fR"
 /*     Log the named commands to syslogd.
-/*     Examples of commands that can be logged are HELO, EHLO, LHLO, MAIL,
-/*     RCPT, VRFY, RSET, NOOP, and QUIT. Separate command names by white
-/*     space or commas, and use quotes to protect white space from the
-/*     shell. Command names are case-insensitive.
+/* .sp
+/*     Examples of commands are HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+/*     DATA, ., RSET, NOOP, and QUIT. Separate command names by
+/*     white space or commas, and use quotes to protect white space
+/*     from the shell. Command names are case-insensitive.
 /* .IP "\fB-t \fItimeout\fR (default: 100)"
 /*     Limit the time for receiving a command or sending a response.
 /*     The time limit is specified in seconds.
@@ -141,6 +157,7 @@ typedef struct SINK_STATE {
     int     data_state;
     int     (*read_fn) (struct SINK_STATE *);
     int     rcpts;
+    char   *push_back_ptr;
 } SINK_STATE;
 
 #define ST_ANY                 0
@@ -150,6 +167,10 @@ typedef struct SINK_STATE {
 #define ST_CR_LF_DOT_CR                4
 #define ST_CR_LF_DOT_CR_LF     5
 
+#define PUSH_BACK_PEEK(state)          (*(state)->push_back_ptr != 0)
+#define PUSH_BACK_GET(state)           (*(state)->push_back_ptr++)
+#define PUSH_BACK_SET(state, text)     ((state)->push_back_ptr = (text))
+
 static int var_tmout = 100;
 static int var_max_line_length = 2048;
 static char *var_myhostname;
@@ -170,6 +191,25 @@ static int disable_xclient;
 static int disable_xforward;
 static int disable_enh_status;
 
+#define SOFT_ERROR_RESP                "450 4.3.0 Error: command failed"
+#define HARD_ERROR_RESP                "500 5.3.0 Error: command failed"
+
+/* hard_err_resp - generic hard error response */
+
+static void hard_err_resp(SINK_STATE *state)
+{
+    smtp_printf(state->stream, HARD_ERROR_RESP);
+    smtp_flush(state->stream);
+}
+
+/* soft_err_resp - generic soft error response */
+
+static void soft_err_resp(SINK_STATE *state)
+{
+    smtp_printf(state->stream, SOFT_ERROR_RESP);
+    smtp_flush(state->stream);
+}
+
 /* ehlo_response - respond to EHLO command */
 
 static void ehlo_response(SINK_STATE *state)
@@ -244,6 +284,32 @@ static void data_event(int unused_event, char *context)
     data_response(state);
 }
 
+/* dot_resp_hard - hard error response to . command */
+
+static void dot_resp_hard(SINK_STATE *state)
+{
+    if (enable_lmtp) {
+       while (state->rcpts-- > 0)      /* XXX this could block */
+           smtp_printf(state->stream, HARD_ERROR_RESP);
+    } else {
+       smtp_printf(state->stream, HARD_ERROR_RESP);
+    }
+    smtp_flush(state->stream);
+}
+
+/* dot_resp_soft - soft error response to . command */
+
+static void dot_resp_soft(SINK_STATE *state)
+{
+    if (enable_lmtp) {
+       while (state->rcpts-- > 0)      /* XXX this could block */
+           smtp_printf(state->stream, SOFT_ERROR_RESP);
+    } else {
+       smtp_printf(state->stream, SOFT_ERROR_RESP);
+    }
+    smtp_flush(state->stream);
+}
+
 /* dot_response - response to . command */
 
 static void dot_response(SINK_STATE *state)
@@ -312,9 +378,7 @@ static int data_read(SINK_STATE *state)
        else
            state->data_state = ST_ANY;
        if (state->data_state == ST_CR_LF_DOT_CR_LF) {
-           if (msg_verbose)
-               msg_info(".");
-           dot_response(state);
+           PUSH_BACK_SET(state, ".\r\n");
            state->read_fn = command_read;
            state->data_state = ST_ANY;
            break;
@@ -337,6 +401,8 @@ static int data_read(SINK_STATE *state)
 typedef struct SINK_COMMAND {
     char   *name;
     void    (*response) (SINK_STATE *);
+    void    (*hard_response) (SINK_STATE *);
+    void    (*soft_response) (SINK_STATE *);
     int     flags;
 } SINK_COMMAND;
 
@@ -347,19 +413,20 @@ typedef struct SINK_COMMAND {
 #define FLAG_DISCONNECT        (1<<4)          /* disconnect */
 
 static SINK_COMMAND command_table[] = {
-    "helo", helo_response, 0,
-    "ehlo", ehlo_response, 0,
-    "lhlo", ehlo_response, 0,
-    "xclient", ok_response, FLAG_ENABLE,
-    "xforward", ok_response, FLAG_ENABLE,
-    "auth", ok_response, FLAG_ENABLE,
-    "mail", mail_response, FLAG_ENABLE,
-    "rcpt", rcpt_response, FLAG_ENABLE,
-    "data", data_response, FLAG_ENABLE,
-    "rset", ok_response, FLAG_ENABLE,
-    "noop", ok_response, FLAG_ENABLE,
-    "vrfy", ok_response, FLAG_ENABLE,
-    "quit", quit_response, FLAG_ENABLE,
+    "helo", helo_response, hard_err_resp, soft_err_resp, 0,
+    "ehlo", ehlo_response, hard_err_resp, soft_err_resp, 0,
+    "lhlo", ehlo_response, hard_err_resp, soft_err_resp, 0,
+    "xclient", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "xforward", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "auth", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "mail", mail_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "rcpt", rcpt_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "data", data_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    ".", dot_response, dot_resp_hard, dot_resp_soft, FLAG_ENABLE,
+    "rset", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "noop", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "vrfy", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
+    "quit", quit_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
     0,
 };
 
@@ -428,8 +495,11 @@ static int command_read(SINK_STATE *state)
      * A read may result in EOF, but is never supposed to time out - a time
      * out means that we were trying to read when no data was available.
      */
+#define NEXT_CHAR(state) \
+    (PUSH_BACK_PEEK(state) ? PUSH_BACK_GET(state) : VSTREAM_GETC(state->stream))
+
     for (;;) {
-       if ((ch = VSTREAM_GETC(state->stream)) == VSTREAM_EOF)
+       if ((ch = NEXT_CHAR(state)) == VSTREAM_EOF)
            return (-1);
 
        /*
@@ -467,7 +537,7 @@ static int command_read(SINK_STATE *state)
         * instead of peek_fd() (which uses ioctl FIONREAD). Workaround added
         * 20020604.
         */
-       if (vstream_peek(state->stream) <= 0
+       if (PUSH_BACK_PEEK(state) == 0 && vstream_peek(state->stream) <= 0
            && readable(vstream_fileno(state->stream)) <= 0)
            return (0);
     }
@@ -501,21 +571,19 @@ static int command_read(SINK_STATE *state)
        smtp_flush(state->stream);
        return (0);
     }
+    /* We use raw syslog. Sanitize data content and length. */
+    if (cmdp->flags & FLAG_SYSLOG)
+       syslog(LOG_INFO, "%s %.100s", command, printable(ptr, '?'));
     if (cmdp->flags & FLAG_DISCONNECT)
        return (-1);
     if (cmdp->flags & FLAG_HARD_ERR) {
-       smtp_printf(state->stream, "500 5.3.0 Error: command failed");
-       smtp_flush(state->stream);
+       cmdp->hard_response(state);
        return (0);
     }
     if (cmdp->flags & FLAG_SOFT_ERR) {
-       smtp_printf(state->stream, "450 4.3.0 Error: command failed");
-       smtp_flush(state->stream);
+       cmdp->soft_response(state);
        return (0);
     }
-    /* We use raw syslog. Sanitize data content and length. */
-    if (cmdp->flags & FLAG_SYSLOG)
-       syslog(LOG_INFO, "%s %.100s", command, printable(ptr, '?'));
     if (cmdp->response == data_response && fixed_delay > 0) {
        event_request_timer(data_event, (char *) state, fixed_delay);
     } else {
@@ -582,7 +650,7 @@ static void read_event(int unused_event, char *context)
                return;
            }
        }
-    } while (vstream_peek(state->stream) > 0);
+    } while (PUSH_BACK_PEEK(state) != 0 || vstream_peek(state->stream) > 0);
 
     /*
      * Reset the idle timer. Wait until the next input event, or until the
@@ -633,6 +701,7 @@ static void connect_event(int unused_event, char *context)
        state->buffer = vstring_alloc(1024);
        state->read_fn = command_read;
        state->data_state = ST_ANY;
+       PUSH_BACK_SET(state, "");
        smtp_timeout_setup(state->stream, var_tmout);
 
        /*
index 4d9c4e97e69037560ffe48c3cc62641a29f2ac42..26a6a394fb79118840fdc8899ece6ffcd999a897 100644 (file)
@@ -56,7 +56,8 @@
 /*     length, and an attribute value pointer.
 /* .IP "ATTR_TYPE_FUNC (ATTR_PRINT_SLAVE_FN, void *)"
 /*     This argument is followed by a function pointer and generic data
-/*     pointer.
+/*     pointer. The caller-specified function returns whatever the
+/*     specified attribute printing function returns.
 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
 /*     The content of the table is sent as a sequence of string-valued
index cb13b0bfcaf4feb2a7b24932a6cd583a33fe18f0..4d4704310180aa967ab2b432c49b9f661000b42e 100644 (file)
 /* .IP "ATTR_TYPE_STR (char *, char *)"
 /*     This argument is followed by an attribute name and a null-terminated
 /*     string.
+/* .IP "ATTR_TYPE_FUNC (ATTR_PRINT_SLAVE_FN, void *)"
+/*     This argument is followed by a function pointer and generic data
+/*     pointer. The caller-specified function returns whatever the
+/*     specified attribute printing function returns.
 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
 /*     The content of the table is sent as a sequence of string-valued
@@ -142,6 +146,8 @@ int     attr_vprint64(VSTREAM *fp, int flags, va_list ap)
     HTABLE_INFO **ht_info_list;
     HTABLE_INFO **ht;
     int     len_val;
+    ATTR_PRINT_SLAVE_FN print_fn;
+    void   *print_arg;
 
     /*
      * Sanity check.
@@ -196,6 +202,11 @@ int     attr_vprint64(VSTREAM *fp, int flags, va_list ap)
            if (msg_verbose)
                msg_info("send attr %s = [data %d bytes]", attr_name, len_val);
            break;
+       case ATTR_TYPE_FUNC:
+           print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN);
+           print_arg = va_arg(ap, void *);
+           print_fn(attr_print64, fp, flags | ATTR_FLAG_MORE, print_arg);
+           break;
        case ATTR_TYPE_HASH:
            ht_info_list = htable_list(va_arg(ap, HTABLE *));
            for (ht = ht_info_list; *ht; ht++) {
index 4568bc938d3556c965f5d7ae51e631d3bbd36f9b..5fb6b6684452ffa81223512bb15e8fcba407e32b 100644 (file)
 /* .IP "ATTR_TYPE_DATA (char *, int, char *)"
 /*     This argument is followed by an attribute name, an attribute value
 /*     length, and a pointer to attribute value.
+/* .IP "ATTR_TYPE_FUNC (ATTR_PRINT_SLAVE_FN, void *)"
+/*     This argument is followed by a function pointer and generic data
+/*     pointer. The caller-specified function returns whatever the
+/*     specified attribute printing function returns.
 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
 /*     The content of the table is sent as a sequence of string-valued
@@ -112,6 +116,8 @@ int     attr_vprint_plain(VSTREAM *fp, int flags, va_list ap)
     HTABLE_INFO **ht;
     static VSTRING *base64_buf;
     int     len_val;
+    ATTR_PRINT_SLAVE_FN print_fn;
+    void   *print_arg;
 
     /*
      * Sanity check.
@@ -157,6 +163,11 @@ int     attr_vprint_plain(VSTREAM *fp, int flags, va_list ap)
            if (msg_verbose)
                msg_info("send attr %s = [data %d bytes]", attr_name, len_val);
            break;
+       case ATTR_TYPE_FUNC:
+           print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN);
+           print_arg = va_arg(ap, void *);
+           print_fn(attr_print_plain, fp, flags | ATTR_FLAG_MORE, print_arg);
+           break;
        case ATTR_TYPE_HASH:
            ht_info_list = htable_list(va_arg(ap, HTABLE *));
            for (ht = ht_info_list; *ht; ht++) {
index bf00c64c9a8b696de951362030a74a3cd83c9654..27f60a685712f57cab3d2881c7f80929d1d49dd4 100644 (file)
@@ -95,7 +95,8 @@
 /*     This argument is followed by an attribute name and a VSTRING pointer.
 /* .IP "ATTR_TYPE_FUNC (ATTR_SCAN_SLAVE_FN, void *)"
 /*     This argument is followed by a function pointer and a generic data
-/*     pointer.
+/*     pointer. The caller-specified function returns < 0 in case of
+/*     error.
 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
 /*     All further input attributes are processed as string attributes.
index b6cce996da52f633b67fa574048d10d86d668f87..8cf4808129db67102509e78240fbe670e26e3031 100644 (file)
@@ -47,7 +47,7 @@
 /*     characters. The formatting rules aim to make implementations in PERL
 /*     and other languages easy.
 /*
-/*      Normally, attributes must be received in the sequence as specified with
+/*     Normally, attributes must be received in the sequence as specified with
 /*     the attr_scan64() argument list.  The input stream may contain additional
 /*     attributes at any point in the input stream, including additional
 /*     instances of requested attributes.
 /*     This argument is followed by an attribute name and a VSTRING pointer.
 /* .IP "ATTR_TYPE_DATA (char *, VSTRING *)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
+/* .IP "ATTR_TYPE_FUNC (ATTR_SCAN_SLAVE_FN, void *)"
+/*     This argument is followed by a function pointer and a generic data
+/*     pointer. The caller-specified function returns < 0 in case of
+/*     error.
 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
 /*     All further input attributes are processed as string attributes.
 static int attr_scan64_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
 {
     static VSTRING *base64_buf = 0;
+
 #if 0
     extern int var_line_limit;         /* XXX */
     int     limit = var_line_limit * 4;
+
 #endif
     int     ch;
 
@@ -254,6 +260,8 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
     HTABLE *hash_table;
     int     ch;
     int     conversions;
+    ATTR_SCAN_SLAVE_FN scan_fn;
+    void   *scan_arg;
 
     /*
      * Sanity check.
@@ -295,7 +303,7 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
                if (va_arg(ap, int) !=ATTR_TYPE_END)
                    msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END",
                              myname);
-           } else {
+           } else if (wanted_type != ATTR_TYPE_FUNC) {
                wanted_name = va_arg(ap, char *);
            }
        }
@@ -303,7 +311,7 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
        /*
         * Locate the next attribute of interest in the input stream.
         */
-       for (;;) {
+       while (wanted_type != ATTR_TYPE_FUNC) {
 
            /*
             * Get the name of the next attribute. Hitting EOF is always bad.
@@ -419,6 +427,12 @@ int     attr_vscan64(VSTREAM *fp, int flags, va_list ap)
                return (-1);
            }
            break;
+       case ATTR_TYPE_FUNC:
+           scan_fn = va_arg(ap, ATTR_SCAN_SLAVE_FN);
+           scan_arg = va_arg(ap, void *);
+           if (scan_fn(attr_scan64, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
+               return (-1);
+           break;
        case ATTR_TYPE_HASH:
            if (ch != ':') {
                msg_warn("missing value for string attribute %s from %s",
index ba2be79703b38c61d38a7bf556d9fa7b23190bc7..79c119cf578f816673b0dead546dde67ea3b72ce 100644 (file)
@@ -45,7 +45,7 @@
 /*     characters. The formatting rules aim to make implementations in PERL
 /*     and other languages easy.
 /*
-/*      Normally, attributes must be received in the sequence as specified
+/*     Normally, attributes must be received in the sequence as specified
 /*     with the attr_scan_plain() argument list.  The input stream may
 /*     contain additional attributes at any point in the input stream,
 /*     including additional instances of requested attributes.
 /*     This argument is followed by an attribute name and a VSTRING pointer.
 /* .IP "ATTR_TYPE_DATA (char *, VSTRING *)"
 /*     This argument is followed by an attribute name and a VSTRING pointer.
+/* .IP "ATTR_TYPE_FUNC (ATTR_SCAN_SLAVE_FN, void *)"
+/*     This argument is followed by a function pointer and a generic data
+/*     pointer. The caller-specified function returns < 0 in case of
+/*     error.
 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
 /*     All further input attributes are processed as string attributes.
@@ -166,6 +170,7 @@ static int attr_scan_plain_string(VSTREAM *fp, VSTRING *plain_buf,
 #if 0
     extern int var_line_limit;         /* XXX */
     int     limit = var_line_limit * 4;
+
 #endif
     int     ch;
 
@@ -268,6 +273,8 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
     HTABLE *hash_table;
     int     ch;
     int     conversions;
+    ATTR_SCAN_SLAVE_FN scan_fn;
+    void   *scan_arg;
 
     /*
      * Sanity check.
@@ -309,7 +316,7 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
                if (va_arg(ap, int) !=ATTR_TYPE_END)
                    msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END",
                              myname);
-           } else {
+           } else if (wanted_type != ATTR_TYPE_FUNC) {
                wanted_name = va_arg(ap, char *);
            }
        }
@@ -317,7 +324,7 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
        /*
         * Locate the next attribute of interest in the input stream.
         */
-       for (;;) {
+       while (wanted_type != ATTR_TYPE_FUNC) {
 
            /*
             * Get the name of the next attribute. Hitting EOF is always bad.
@@ -361,12 +368,7 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
        }
 
        /*
-        * Do the requested conversion. If the target attribute is a
-        * non-array type, disallow sending a multi-valued attribute, and
-        * disallow sending no value. If the target attribute is an array
-        * type, allow the sender to send a zero-element array (i.e. no value
-        * at all). XXX Need to impose a bound on the number of array
-        * elements.
+        * Do the requested conversion.
         */
        switch (wanted_type) {
        case ATTR_TYPE_NUM:
@@ -413,6 +415,12 @@ int     attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
                                           "input attribute value")) < 0)
                return (-1);
            break;
+       case ATTR_TYPE_FUNC:
+           scan_fn = va_arg(ap, ATTR_SCAN_SLAVE_FN);
+           scan_arg = va_arg(ap, void *);
+           if (scan_fn(attr_scan_plain, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
+               return (-1);
+           break;
        case ATTR_TYPE_HASH:
            if (ch != '=') {
                msg_warn("missing value for string attribute %s from %s",