From: Wietse Venema Date: Thu, 7 Feb 2008 05:00:00 +0000 (-0500) Subject: postfix-2.6-20080207 X-Git-Tag: v2.6.0-RC1~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e00b8f6fd86e0d0236e7818f3fbe2743727042d;p=thirdparty%2Fpostfix.git postfix-2.6-20080207 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index bc5012440..4724653a9 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -14315,3 +14315,22 @@ Apologies for any names omitted. Workaround: pick up a missing data_directory setting from main.cf when "postfix start" is invoked with an obsolete postfix command. 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: nicer multi-line support in the SMTP server. File: + smtpd/smtpd_chat.c. + + SAFETY: postfix-script, postfix-files and post-install are + moved away from /etc/postfix to $daemon_directory. There + were too many accidents where people clobbered these files + with versions from an older Postfix release and ended up + with an unusable Postfix setup. Files: postfix-install, + Makefile.in, postfix/postfix.c, conf/postfix-files, + conf/postfix-script, conf/post-install. diff --git a/postfix/Makefile.in b/postfix/Makefile.in index 5dadb462c..6e68539d0 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -10,6 +10,7 @@ DIRS = src/util src/global src/dns src/tls src/xsasl src/milter src/master \ src/postsuper src/qmqpd src/spawn src/flush src/verify \ src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr MANDIRS = proto man html +LIBEXEC = libexec/post-install libexec/postfix-files libexec/postfix-script default: update @@ -28,6 +29,17 @@ update printfck tests root_tests: (set -e; echo "[$$i]"; cd $$i; $(MAKE) $(OPTS) $@ MAKELEVEL=) || exit 1; \ done +update: $(LIBEXEC) + +libexec/post-install: conf/post-install + ln -f $? $@ + +libexec/postfix-files: conf/postfix-files + ln -f $? $@ + +libexec/postfix-script: conf/postfix-script + ln -f $? $@ + manpages: set -e; for i in $(MANDIRS); do \ (set -e; echo "[$$i]"; cd $$i; $(MAKE) -f Makefile.in $(OPTS) MAKELEVEL=) || exit 1; \ diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 190b2fb49..fb9c93e08 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -16,3 +16,13 @@ Incompatibility with Postfix 2.4 and earlier If you upgrade from Postfix 2.4 or earlier, read RELEASE_NOTES-2.5 before proceeding. + +Incompatible changes with snapshot 20080207 +=========================================== + +According to discussions on the mailing list, too many people are +breaking newly installed Postfix by overwriting the new /etc/postfix +files with versions from an older release, and end up with a broken +configuration that cannot repair itself. For this reason, postfix-script, +postfix-files and post-install are moved away from /etc/postfix to +$daemon_directory. diff --git a/postfix/conf/post-install b/postfix/conf/post-install index c09fdfa32..29e3d9616 100644 --- a/postfix/conf/post-install +++ b/postfix/conf/post-install @@ -9,7 +9,7 @@ # SUMMARY # Postfix post-installation script # SYNOPSIS -# post-install [name=value] command ... +# postfix post-install [name=value] command ... # DESCRIPTION # The post-install script performs the finishing touch of a Postfix # installation, after the executable programs and configuration @@ -40,14 +40,14 @@ # Arguments # .IP create-missing # Create missing queue directories with ownerships and permissions -# according to the contents of $config_directory/postfix-files, using +# according to the contents of $daemon_directory/postfix-files, using # the mail_owner and setgid_group parameter settings from the command # line, process environment or from the installed main.cf file. # # This is required at Postfix start-up time. # .IP set-permissions # Set all file/directory ownerships and permissions according to the -# contents of $config_directory/postfix-files, using the mail_owner +# contents of $daemon_directory/postfix-files, using the mail_owner # and setgid_group parameter settings from the command line, process # environment or from the installed main.cf file. Implies create-missing. # @@ -56,7 +56,7 @@ # settings after Postfix is already installed. # .IP upgrade-permissions # Update ownership and permission of existing files/directories as -# specified in $config_directory/postfix-files, using the mail_owner +# specified in $daemon_directory/postfix-files, using the mail_owner # and setgid_group parameter settings from the command line, process # environment or from the installed main.cf file. Implies create-missing. # @@ -90,7 +90,7 @@ # copy the configuration files from the primary Postfix instance to # a secondary configuration directory and execute: # -# post-install config_directory=secondary-config-directory \e +# postfix post-install config_directory=secondary-config-directory \e # .in +4 # queue_directory=secondary-queue-directory \e # .br @@ -106,7 +106,7 @@ # To upgrade a secondary Postfix installation on the same machine, # execute: # -# post-install config_directory=secondary-config-directory \e +# postfix post-install config_directory=secondary-config-directory \e # .in +4 # upgrade-permissions upgrade-configuration # INSTALLATION PARAMETER INPUT METHODS @@ -173,7 +173,7 @@ # postfix-install(1) Postfix primary installation script. # FILES # $config_directory/main.cf, Postfix installation parameters. -# $config_directory/postfix-files, installation control file. +# $daemon_directory/postfix-files, installation control file. # $config_directory/install.cf, obsolete configuration file. # LICENSE # .ad @@ -258,8 +258,8 @@ test -d "$config_directory" || { exit 1 } -test -f $config_directory/postfix-files || { - echo $0: Error: $config_directory/postfix-files is not a file. 1>&2 +test -f $daemon_directory/postfix-files || { + echo $0: Error: $daemon_directory/postfix-files is not a file. 1>&2 exit 1 } @@ -412,10 +412,10 @@ test -n "$override" && { || exit 1 } -# Use file/directory status information in $config_directory/postfix-files. +# Use file/directory status information in $daemon_directory/postfix-files. test -n "$create" && { - exec <$config_directory/postfix-files || exit 1 + exec <$daemon_directory/postfix-files || exit 1 while IFS=: read path type owner group mode flags junk do IFS="$BACKUP_IFS" @@ -429,7 +429,7 @@ test -n "$create" && { case $type in [hl]) continue;; [df]) ;; - *) echo unknown type $type for $path in $config_directory/postfix-files1>&2; exit 1;; + *) echo unknown type $type for $path in $daemon_directory/postfix-files1>&2; exit 1;; esac # Expand $name, and canonicalize null fields. for name in path owner group flags diff --git a/postfix/conf/postfix-files b/postfix/conf/postfix-files index 9bd905f8c..f3632a45d 100644 --- a/postfix/conf/postfix-files +++ b/postfix/conf/postfix-files @@ -62,6 +62,9 @@ $queue_directory/public:d:$mail_owner:$setgid_group:710:uc $queue_directory/pid:d:root:-:755:uc $queue_directory/saved:d:$mail_owner:-:700:ucr $queue_directory/trace:d:$mail_owner:-:700:ucr +$daemon_directory/postfix-script:f:root:-:755 +$daemon_directory/postfix-files:f:root:-:644 +$daemon_directory/post-install:f:root:-:755 $daemon_directory/anvil:f:root:-:755 $daemon_directory/bounce:f:root:-:755 $daemon_directory/cleanup:f:root:-:755 @@ -118,16 +121,16 @@ $config_directory/main.cf:f:root:-:644:p $config_directory/makedefs.out:f:root:-:644 $config_directory/master.cf:f:root:-:644:p $config_directory/pcre_table:f:root:-:644:o -$config_directory/postfix-files:f:root:-:644 +$config_directory/postfix-files:f:root:-:644:o $config_directory/regexp_table:f:root:-:644:o $config_directory/relocated:f:root:-:644:p $config_directory/tcp_table:f:root:-:644:o $config_directory/transport:f:root:-:644:p $config_directory/virtual:f:root:-:644:p -$config_directory/postfix-script:f:root:-:755 +$config_directory/postfix-script:f:root:-:755:o $config_directory/postfix-script-sgid:f:root:-:755:o $config_directory/postfix-script-nosgid:f:root:-:755:o -$config_directory/post-install:f:root:-:755 +$config_directory/post-install:f:root:-:755:o $manpage_directory/man1/mailq.1:f:root:-:644 $manpage_directory/man1/newaliases.1:f:root:-:644 $manpage_directory/man1/postalias.1:f:root:-:644 diff --git a/postfix/conf/postfix-script b/postfix/conf/postfix-script index 8c1efd789..4635f865c 100644 --- a/postfix/conf/postfix-script +++ b/postfix/conf/postfix-script @@ -94,12 +94,12 @@ start) then rm -f $queue_directory/quick-start else - $config_directory/postfix-script check-fatal || { + $daemon_directory/postfix-script check-fatal || { $FATAL Postfix integrity check failed! exit 1 } # Foreground this so it can be stopped. All inodes are cached. - $config_directory/postfix-script check-warn + $daemon_directory/postfix-script check-warn fi $INFO starting the Postfix mail system $daemon_directory/master & @@ -117,7 +117,7 @@ drain) quick-stop) - $config_directory/postfix-script stop + $daemon_directory/postfix-script stop touch $queue_directory/quick-start ;; @@ -173,8 +173,8 @@ flush) check) - $config_directory/postfix-script check-fatal || exit 1 - $config_directory/postfix-script check-warn + $daemon_directory/postfix-script check-fatal || exit 1 + $daemon_directory/postfix-script check-warn exit 0 ;; @@ -192,7 +192,7 @@ status) check-fatal) # This command is NOT part of the public interface. - $SHELL $config_directory/post-install create-missing || { + $SHELL $daemon_directory/post-install create-missing || { $FATAL unable to create missing queue directories exit 1 } @@ -283,13 +283,13 @@ check-warn) ;; set-permissions|upgrade-configuration) - $config_directory/post-install create-missing "$@" + $daemon_directory/post-install create-missing "$@" ;; post-install) # Currently not part of the public interface. shift - $config_directory/post-install "$@" + $daemon_directory/post-install "$@" ;; /*) diff --git a/postfix/html/postfix.1.html b/postfix/html/postfix.1.html index cd1f1e3de..f31564ebf 100644 --- a/postfix/html/postfix.1.html +++ b/postfix/html/postfix.1.html @@ -201,9 +201,9 @@ POSTFIX(1) POSTFIX(1) FILES /etc/postfix/main.cf, Postfix configuration parameters /etc/postfix/master.cf, Postfix daemon processes - /etc/postfix/postfix-files, file/directory permissions - /etc/postfix/postfix-script, administrative commands - /etc/postfix/post-install, post-installation configuration + $daemon_directory/postfix-files, file/directory permissions + $daemon_directory/postfix-script, administrative commands + $daemon_directory/post-install, post-installation configuration SEE ALSO Commands: diff --git a/postfix/man/man1/postfix.1 b/postfix/man/man1/postfix.1 index 4d46606e9..72918c627 100644 --- a/postfix/man/man1/postfix.1 +++ b/postfix/man/man1/postfix.1 @@ -164,9 +164,9 @@ records, so that "smtpd" becomes, for example, "postfix/smtpd". .nf /etc/postfix/main.cf, Postfix configuration parameters /etc/postfix/master.cf, Postfix daemon processes -/etc/postfix/postfix-files, file/directory permissions -/etc/postfix/postfix-script, administrative commands -/etc/postfix/post-install, post-installation configuration +$daemon_directory/postfix-files, file/directory permissions +$daemon_directory/postfix-script, administrative commands +$daemon_directory/post-install, post-installation configuration .SH "SEE ALSO" .na .nf diff --git a/postfix/postfix-install b/postfix/postfix-install index b8286a5d4..f936b81a0 100644 --- a/postfix/postfix-install +++ b/postfix/postfix-install @@ -151,7 +151,7 @@ # post-install(1) post-installation procedure # FILES # $config_directory/main.cf, Postfix installation configuration. -# $config_directory/postfix-files, installation control file. +# $daemon_directory/postfix-files, installation control file. # $config_directory/install.cf, obsolete configuration file. # LICENSE # .ad @@ -586,7 +586,7 @@ fi # Install files, using information from the postfix-files file. -exec < conf/postfix-files || exit 1 +exec < libexec/postfix-files || exit 1 while IFS=: read path type owner group mode flags junk do IFS="$BACKUP_IFS" @@ -682,7 +682,7 @@ do test "$readme_directory" = "no" || compare_or_replace $mode "$owner" "$group" README_FILES/$file \ $README_DIRECTORY/$file || exit 1;; - *) echo $0: Error: unknown entry $path in conf/postfix-files 1>&2 + *) echo $0: Error: unknown entry $path in libexec/postfix-files 1>&2 exit 1;; esac) || exit 1 continue;; @@ -713,7 +713,7 @@ do ) || exit 1 continue;; - *) echo $0: Error: unknown type $type for $path in conf/postfix-files 1>&2 + *) echo $0: Error: unknown type $type for $path in libexec/postfix-files 1>&2 exit 1;; esac diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 577aa0a03..a281ed553 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -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); diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 500d31f5c..e56511453 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -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 */ @@ -121,6 +122,29 @@ typedef struct CLEANUP_STATE { #define CLEANUP_FLAG_WARN_SEEN (1<<17) /* REC_TYPE_WARN record seen */ #define CLEANUP_FLAG_END_SEEN (1<<18) /* REC_TYPE_END record seen */ + /* + * Milter replies. + */ +#define CLEANUP_MILTER_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_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) + /* * Mappings. */ diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index 7a76c52ef..7c5fc9393 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -1402,25 +1402,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_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_SMTP_REPLY(state, resp); + ret = state->reason; state->errs |= CLEANUP_STAT_CONT; action = "milter-reject"; text = resp + 4; @@ -1596,9 +1588,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_REASON(state, "4.3.5 Server configuration error"); state->errs |= CLEANUP_STAT_DEFER; } } diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 9e584a660..ea8b13b11 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -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); diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index 9d399cde7..e44f105ab 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -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) /* diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 67e334fff..86acee7dc 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20080201" +#define MAIL_RELEASE_DATE "20080207" #define MAIL_VERSION_NUMBER "2.6" #ifdef SNAPSHOT diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index 238c1d107..be79cd8bc 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -83,7 +83,7 @@ /* Global library. */ -#include /* var_line_limit */ +#include #include #include #include @@ -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; } } + for (cp = STR(milter->buf); /* void */ ; cp = next) { + if (var_soft_bounce) { + 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); diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index cc65212da..23a0c37cb 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -151,8 +151,8 @@ static int test_reply(SMFICTX *ctx, int code) (void) fflush(stdout); /* In case output redirected. */ if (code == SMFIR_REPLYCODE) { - if (smfi_setreply(ctx, reply_code, reply_dsn, reply_message) == MI_FAILURE) - fprintf(stderr, "smfi_setreply failed\n"); + if (smfi_setmlreply(ctx, reply_code, reply_dsn, reply_message, reply_message, (char *) 0) == MI_FAILURE) + fprintf(stderr, "smfi_setmlreply failed\n"); printf("test_reply %s\n", reply_code); return (reply_code[0] == '4' ? SMFIS_TEMPFAIL : SMFIS_REJECT); } else { diff --git a/postfix/src/postfix/postfix.c b/postfix/src/postfix/postfix.c index 13eb9a681..3b9154ca1 100644 --- a/postfix/src/postfix/postfix.c +++ b/postfix/src/postfix/postfix.c @@ -152,9 +152,9 @@ /* FILES /* /etc/postfix/main.cf, Postfix configuration parameters /* /etc/postfix/master.cf, Postfix daemon processes -/* /etc/postfix/postfix-files, file/directory permissions -/* /etc/postfix/postfix-script, administrative commands -/* /etc/postfix/post-install, post-installation configuration +/* $daemon_directory/postfix-files, file/directory permissions +/* $daemon_directory/postfix-script, administrative commands +/* $daemon_directory/post-install, post-installation configuration /* SEE ALSO /* Commands: /* postalias(1), create/update/query alias database @@ -466,7 +466,7 @@ int main(int argc, char **argv) /* * Run the management script with as process name ourself. */ - script = concatenate(var_config_dir, "/postfix-script", (char *) 0); + script = concatenate(var_daemon_dir, "/postfix-script", (char *) 0); execvp(script, argv + optind - 1); msg_fatal("%s: %m", script); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 7588ea913..35d1cf045 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -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); diff --git a/postfix/src/smtpd/smtpd_chat.c b/postfix/src/smtpd/smtpd_chat.c index 861192863..f7445d66c 100644 --- a/postfix/src/smtpd/smtpd_chat.c +++ b/postfix/src/smtpd/smtpd_chat.c @@ -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,34 @@ 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