]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.5.1-RC2 v2.5.1-RC2
authorWietse Venema <wietse@porcupine.org>
Sun, 10 Feb 2008 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 10 Feb 2018 19:49:41 +0000 (14:49 -0500)
postfix/HISTORY
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup.h
postfix/src/cleanup/cleanup_milter.c
postfix/src/cleanup/cleanup_state.c
postfix/src/global/cleanup_user.h
postfix/src/global/mail_version.h
postfix/src/milter/milter8.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_chat.c

index 4d830a156889369e7250846e3eaf89197196373e..a23b5eade3ab07638b0775a64b50f9656fc33d56 100644 (file)
@@ -14300,3 +14300,15 @@ Apologies for any names omitted.
        Workaround (introduced 20071204): update the wrong proxywrite
        process limit when upgrading an already installed default
        master.cf file.  File: conf/post-install.
+
+20080207
+
+       Cleanup: soft_bounce support for multi-line Milter replies.
+       File: src/milter/milter8.c.
+
+       Cleanup: preserve multi-line format of header/body Milter
+       replies. Files: cleanup/cleanup_milter.c, smtpd/smtpd.c.
+
+       Cleanup: multi-line support in SMTP server replies.  File:
+       smtpd/smtpd_chat.c.
+
index 577aa0a032c5bef5c784c760e387f5d0e93eafb3..a281ed553a47148f441332de60d75507a801ce94 100644 (file)
@@ -491,8 +491,10 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
     status = cleanup_flush(state);             /* in case state is modified */
     attr_print(src, ATTR_FLAG_NONE,
               ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
-              ATTR_TYPE_STR, MAIL_ATTR_WHY, state->reason ?
-              state->reason : "",
+              ATTR_TYPE_STR, MAIL_ATTR_WHY,
+              (state->flags & CLEANUP_FLAG_SMTP_REPLY)
+              && state->smtp_reply ? state->smtp_reply :
+              state->reason ? state->reason : "",
               ATTR_TYPE_END);
     cleanup_free(state);
 
index 500d31f5c009f4964ae396a7a265b4cfe084b925..514b72066f08d593c0c33071ccca5d2853be9fdc 100644 (file)
@@ -78,6 +78,7 @@ typedef struct CLEANUP_STATE {
     off_t   append_hdr_pt_target;      /* target of above record */
     ssize_t rcpt_count;                        /* recipient count */
     char   *reason;                    /* failure reason */
+    char   *smtp_reply;                        /* failure reason, SMTP-style */
     NVTABLE *attr;                     /* queue file attribute list */
     MIME_STATE *mime_state;            /* MIME state engine */
     int     mime_errs;                 /* MIME error flags */
index 7a76c52efe8eb5d6e34b7457ba950ae573602a2f..c9423c73e0c66897aa53fc253f1e3773f01c0ac7 100644 (file)
 #define STR(x)         vstring_str(x)
 #define LEN(x)         VSTRING_LEN(x)
 
+ /*
+  * Milter replies.
+  */
+#define CLEANUP_MILTER_SET_REASON(__state, __reason) do { \
+       if ((__state)->reason) \
+           myfree((__state)->reason); \
+       (__state)->reason = mystrdup(__reason); \
+       if ((__state)->smtp_reply) { \
+           myfree((__state)->smtp_reply); \
+           (__state)->smtp_reply = 0; \
+       } \
+    } while (0)
+
+#define CLEANUP_MILTER_SET_SMTP_REPLY(__state, __smtp_reply) do { \
+       if ((__state)->reason) \
+           myfree((__state)->reason); \
+       (__state)->reason = mystrdup(__smtp_reply + 4); \
+       printable((__state)->reason, '_'); \
+       if ((__state)->smtp_reply) \
+           myfree((__state)->smtp_reply); \
+       (__state)->smtp_reply = mystrdup(__smtp_reply); \
+    } while (0)
+
 /* cleanup_milter_set_error - set error flag from errno */
 
 static void cleanup_milter_set_error(CLEANUP_STATE *state, int err)
@@ -1402,25 +1425,17 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event,
         * CLEANUP_STAT_CONT and CLEANUP_STAT_DEFER both update the reason
         * attribute, but CLEANUP_STAT_DEFER takes precedence. It terminates
         * queue record processing, and prevents bounces from being sent.
-        * 
-        * XXX Multi-line replies are messy, We should eliminate not only the
-        * CRLF, but also the SMTP status and the enhanced status code that
-        * follows.
         */
     case '4':
-       if (state->reason)
-           myfree(state->reason);
-       ret = state->reason = mystrdup(resp + 4);
-       printable(state->reason, '_');
+       CLEANUP_MILTER_SET_SMTP_REPLY(state, resp);
+       ret = state->reason;
        state->errs |= CLEANUP_STAT_DEFER;
        action = "milter-reject";
        text = resp + 4;
        break;
     case '5':
-       if (state->reason)
-           myfree(state->reason);
-       ret = state->reason = mystrdup(resp + 4);
-       printable(state->reason, '_');
+       CLEANUP_MILTER_SET_SMTP_REPLY(state, resp);
+       ret = state->reason;
        state->errs |= CLEANUP_STAT_CONT;
        action = "milter-reject";
        text = resp + 4;
@@ -1596,9 +1611,7 @@ void    cleanup_milter_emul_rcpt(CLEANUP_STATE *state,
        msg_warn("%s: milter configuration error: can't reject recipient "
                 "in non-smtpd(8) submission", state->queue_id);
        msg_warn("%s: deferring delivery of this message", state->queue_id);
-       if (state->reason)
-           myfree(state->reason);
-       state->reason = mystrdup("4.3.5 Server configuration error");
+       CLEANUP_MILTER_SET_REASON(state, "4.3.5 Server configuration error");
        state->errs |= CLEANUP_STAT_DEFER;
     }
 }
index 9e584a66078bad8e5a1b93162603bd8eccd2bed7..ea8b13b1199faaecbb2e0d70f68de4e743d49e21 100644 (file)
@@ -97,6 +97,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
     state->append_hdr_pt_target = -1;
     state->rcpt_count = 0;
     state->reason = 0;
+    state->smtp_reply = 0;
     state->attr = nvtable_create(10);
     nvtable_update(state->attr, MAIL_ATTR_LOG_ORIGIN, MAIL_ATTR_ORG_LOCAL);
     state->mime_state = 0;
@@ -150,6 +151,8 @@ void    cleanup_state_free(CLEANUP_STATE *state)
     been_here_free(state->dups);
     if (state->reason)
        myfree(state->reason);
+    if (state->smtp_reply)
+       myfree(state->smtp_reply);
     nvtable_free(state->attr);
     if (state->mime_state)
        mime_state_free(state->mime_state);
index 9d399cde71e3585b3d437c04636e8c317dd83c46..e44f105ab5508cbfc25d7508de3098c7eb7eacc5 100644 (file)
@@ -22,6 +22,7 @@
 #define CLEANUP_FLAG_BCC_OK    (1<<4)  /* Ok to add auto-BCC addresses */
 #define CLEANUP_FLAG_MAP_OK    (1<<5)  /* Ok to map addresses */
 #define CLEANUP_FLAG_MILTER    (1<<6)  /* Enable Milter applications */
+#define CLEANUP_FLAG_SMTP_REPLY        (1<<7)  /* Enable SMTP reply */
 
 #define CLEANUP_FLAG_FILTER_ALL        (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_MILTER)
  /*
index 93a5389f7af2c75852ae3787457c1ff127f34240..3f5ed65afe0056a02eefc499cd0bd6f1c71aaf6b 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20080123"
-#define MAIL_VERSION_NUMBER    "2.5.1-RC1"
+#define MAIL_RELEASE_DATE      "20080210"
+#define MAIL_VERSION_NUMBER    "2.5.1-RC2"
 
 #ifdef SNAPSHOT
 # define MAIL_VERSION_DATE     "-" MAIL_RELEASE_DATE
index 238c1d10771e69a012685c25ec9d910cfc23f4ea..4a3abb96d849f7628d8e30054a3b17f82b6f6b4e 100644 (file)
@@ -83,7 +83,7 @@
 
 /* Global library. */
 
-#include <mail_params.h>               /* var_line_limit */
+#include <mail_params.h>
 #include <mail_proto.h>
 #include <rec_type.h>
 #include <record.h>
@@ -1094,6 +1094,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
        char   *cp;
        char   *rp;
        char    ch;
+       char   *next;
 
        if (milter8_read_resp(milter, event, &cmd, &data_size) != 0)
            MILTER8_EVENT_BREAK(milter->def_reply);
@@ -1266,6 +1267,18 @@ static const char *milter8_event(MILTER8 *milter, int event,
                        break;
                }
            }
+           if (var_soft_bounce) {
+               for (cp = STR(milter->buf); /* void */ ; cp = next) {
+                   if (cp[0] == '5') {
+                       cp[0] = '4';
+                       if (cp[4] == '5')
+                           cp[4] = '4';
+                   }
+                   if ((next = strstr(cp, "\r\n")) == 0)
+                       break;
+                   next += 2;
+               }
+           }
            if (IN_CONNECT_EVENT(event)) {
 #ifdef LIBMILTER_AUTO_DISCONNECT
                milter8_close_stream(milter);
index 7588ea913bf603448ae7ce3a70c2d199339c0c16..35d1cf045dc646d73889b4817b516fbdcc9378e7 100644 (file)
@@ -1633,7 +1633,8 @@ static int mail_open_stream(SMTPD_STATE *state)
 
        smtpd_check_rewrite(state);
        cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL,
-                                            smtpd_input_transp_mask);
+                                            smtpd_input_transp_mask)
+           | CLEANUP_FLAG_SMTP_REPLY;
        state->dest = mail_stream_service(MAIL_CLASS_PUBLIC,
                                          var_cleanup_service);
        if (state->dest == 0
@@ -2864,6 +2865,11 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
      * 
      * See also: qmqpd.c
      */
+#define IS_SMTP_REJECT(s) \
+       (((s)[0] == '4' || (s)[0] == '5') \
+        && ISDIGIT((s)[1]) && ISDIGIT((s)[2]) \
+        && ((s)[3] == '\0' || (s)[3] == ' ' || (s)[3] == '-'))
+
     if (state->err == CLEANUP_STAT_OK) {
        state->error_count = 0;
        state->error_mask = 0;
@@ -2873,6 +2879,9 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
                             "250 2.0.0 Ok: queued as %s", state->queue_id);
        else
            smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+    } else if (why && IS_SMTP_REJECT(STR(why))) {
+       state->error_mask |= MAIL_ERROR_POLICY;
+       smtpd_chat_reply(state, "%s", STR(why));
     } else if ((state->err & CLEANUP_STAT_DEFER) != 0) {
        state->error_mask |= MAIL_ERROR_POLICY;
        detail = cleanup_stat_detail(CLEANUP_STAT_DEFER);
@@ -3766,7 +3775,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
      * we exclude xclient authorized hosts from event count/rate control.
      */
     if (var_smtpd_cntls_limit > 0
-       && (state->tls_context == 0 || state->tls_context->session_reused == 0)
+     && (state->tls_context == 0 || state->tls_context->session_reused == 0)
        && SMTPD_STAND_ALONE(state) == 0
        && !xclient_allowed
        && anvil_clnt
@@ -3779,7 +3788,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
                 rate, state->namaddr, state->service);
        if (state->tls_context)
            smtpd_chat_reply(state,
-                       "421 4.7.0 %s Error: too many new TLS sessions from %s",
+                   "421 4.7.0 %s Error: too many new TLS sessions from %s",
                             var_myhostname, state->namaddr);
        /* XXX Use regular return to signal end of session. */
        vstream_longjmp(state->client, SMTP_ERR_QUIET);
index 861192863efc32d7d6b63e3a3da19f6544467847..05ef1e507a0bb54fcbbb2493fc9ac01fe6f1b76c 100644 (file)
@@ -104,7 +104,8 @@ void    smtpd_chat_reset(SMTPD_STATE *state)
 
 /* smtp_chat_append - append record to SMTP transaction log */
 
-static void smtp_chat_append(SMTPD_STATE *state, char *direction)
+static void smtp_chat_append(SMTPD_STATE *state, char *direction,
+                                    const char *text)
 {
     char   *line;
 
@@ -113,7 +114,7 @@ static void smtp_chat_append(SMTPD_STATE *state, char *direction)
 
     if (state->history == 0)
        state->history = argv_alloc(10);
-    line = concatenate(direction, STR(state->buffer), (char *) 0);
+    line = concatenate(direction, text, (char *) 0);
     argv_add(state->history, line, (char *) 0);
     myfree(line);
 }
@@ -125,7 +126,7 @@ void    smtpd_chat_query(SMTPD_STATE *state)
     int     last_char;
 
     last_char = smtp_get(state->buffer, state->client, var_line_limit);
-    smtp_chat_append(state, "In:  ");
+    smtp_chat_append(state, "In:  ", STR(state->buffer));
     if (last_char != '\n')
        msg_warn("%s: request longer than %d: %.30s...",
                 state->namaddr, var_line_limit,
@@ -141,20 +142,9 @@ void    smtpd_chat_reply(SMTPD_STATE *state, const char *format,...)
 {
     va_list ap;
     int     delay = 0;
-
-    va_start(ap, format);
-    vstring_vsprintf(state->buffer, format, ap);
-    va_end(ap);
-    /* All 5xx replies must have a 5.xx.xx detail code. */
-    if (var_soft_bounce && STR(state->buffer)[0] == '5') {
-       STR(state->buffer)[0] = '4';
-       if (STR(state->buffer)[4] == '5')
-           STR(state->buffer)[4] = '4';
-    }
-    smtp_chat_append(state, "Out: ");
-
-    if (msg_verbose)
-       msg_info("> %s: %s", state->namaddr, STR(state->buffer));
+    char   *cp;
+    char   *next;
+    char   *end;
 
     /*
      * Slow down clients that make errors. Sleep-on-anything slows down
@@ -163,7 +153,35 @@ void    smtpd_chat_reply(SMTPD_STATE *state, const char *format,...)
     if (state->error_count >= var_smtpd_soft_erlim)
        sleep(delay = var_smtpd_err_sleep);
 
-    smtp_fputs(STR(state->buffer), LEN(state->buffer), state->client);
+    va_start(ap, format);
+    vstring_vsprintf(state->buffer, format, ap);
+    va_end(ap);
+    /* All 5xx replies must have a 5.xx.xx detail code. */
+    for (cp = STR(state->buffer), end = cp + strlen(STR(state->buffer));;) {
+       if (var_soft_bounce) {
+           if (cp[0] == '5') {
+               cp[0] = '4';
+               if (cp[4] == '5')
+                   cp[4] = '4';
+           }
+       }
+       /* This is why we use strlen() above instead of VSTRING_LEN(). */
+       if ((next = strstr(cp, "\r\n")) != 0) {
+           *next = 0;
+       } else {
+           next = end;
+       }
+       smtp_chat_append(state, "Out: ", cp);
+
+       if (msg_verbose)
+           msg_info("> %s: %s", state->namaddr, cp);
+
+       smtp_fputs(cp, next - cp, state->client);
+       if (next < end)
+           cp = next + 2;
+       else
+           break;
+    }
 
     /*
      * Flush unsent output if no I/O happened for a while. This avoids