Le dim. 12 janv. 2020 à 21:28, Wietse Venema <wie...@porcupine.org> a écrit :
> Viktor Dukhovni:
> > My instinct was to suggest that the filter goes first, and then the
> > footer gets added, but usability rather depends on how the pending
> > multi-line response is presented to the filter.  If it is easy for the
> > filter to match and selectively retain the footer, then you're probably
> > right and the filter should have the final say.  If, on the other hand,
> > it becomes hard to selectively retain the footer, then I'd be tempted to
> > add it last.
> >
> > The "\c" trick no longer works once the footer is combined with the
> > original text, because (at least in principle) by that point the
> > original text could have a verbatim "\c" in it, that is not intended to
> > become a line-break.
>
> \c in a reply filter? I don't see any need for any special
> sequences other than ${number} which is already supported.

My opinion is mostly the same : if we introduce a new
smtpd_reject_filter_maps parameter it would be executed first : the
purpose is indeed to replace hard-coded internal message by another
one at first.

Secondly, if the reply message currently processed has not been
replaced the code would check smtpd_reject_footer_maps and apply the
footer if the message match. My thinking is that an administrator have
to choose between selective replacement and selective footer, there is
no really need to execute both : you can do it all at once with
smtpd_reject_filter_maps (and managing the sequence of the two would
be hard to debug : does the second regexp applies before or after text
replacement ?)

Thirdly, like the current behavior of postfix, smtpd_reject_footer
must not be executed if smtpd_reject_footer_maps has matched, however
whatever the execution of smtpd_reject_filter_maps the
smtpd_reject_footer is executed ! we don't want to repeat ourself by
adding a common footer to all the replacement text.

Here is an example :
smtpd_reject_footer_maps =
regexp:$postfix_config_dir/amend_smtpd_responses.regexp
smtpd_reject_filter_maps =
regexp:$postfix_config_dir/replace_smtpd_responses.regexp
smtpd_reject_footer = \c. Pour assistance, appelez-le 800-555-0101.

amend_smtpd_responses.regexp:
   # this file add a footer to the reply with the same error message
but in french

   # only for the example, this regexp is ignored because
smtpd_reject_filter_maps define the same rule
   # 550 5.1.1 <f...@domain.tld>: Recipient address rejected: User unknown
   /^550 5.1.1 (<[^>]*>):/     $1: Adresse destinataire invalide.
   # 504 5.5.2 <foo@domain>: Sender address rejected: need
fully-qualified address
   /^504 5.5.2 (<[^>]*>):/     $1: Emetteur invalide.

replace_smtpd_responses.regexp :
   # this file replace hard-coded error message by french one
   # 550 5.1.1 <f...@domain.tld>: Recipient address rejected: User unknown
   /^550 5.1.1 (<[^>]*>):/     $1: Adresse destinataire invalide.

The result for unknown recipient :
   rcpt to:<fkldk...@example.com>
   554 5.7.1 <fkldkfdl@example>: Adresse destinataire invalide.  Pour
assistance, appelez-le 800-555-0101.

> So we need a canonical multiline representation before we can even
> think about filtering SMTP server replies. It's probably going to
> be embedded \r\n sequences, with smtpd_chat_reply() implementing
> the filter-then-footer or footer-then-filter, and then splitting
> the multiline text into separate lines, before doing output and
> appending to the session history.
I've no opinion about that, I think that the change don't break
anything (replacing everything starting after the first SMTP error
code and its following SMTP extended status code)

Below an extract of the proposed code :
src/global/smtp_reply_footer.[ch] are renamed into
src/global/smtp_reply_filter.[ch] with 2 public functions
smtp_reply_filter() and smtp_reply_footer() and 95% of the common code
in internal function smtp_reply_alter.

diff --git a/src/smtpd/smtpd_chat.c b/src/smtpd/smtpd_chat.c
index 63795b8..af0f69f 100644
--- a/src/smtpd/smtpd_chat.c
+++ b/src/smtpd/smtpd_chat.c
@@ -102,7 +102,7 @@
 #include <maps.h>
 #include <post_mail.h>
 #include <mail_error.h>
-#include <smtp_reply_footer.h>
+#include <smtp_reply_filter.h>

 /* Application-specific. */

@@ -111,8 +111,9 @@
 #include "smtpd_chat.h"

  /*
-  * Reject footer.
+  * Reject replacement and footer.
   */
+static MAPS *smtpd_rej_flt_maps;
 static MAPS *smtpd_rej_ftr_maps;

 #define STR    vstring_str
@@ -128,12 +129,16 @@ void    smtpd_chat_pre_jail_init(void)
        msg_panic("smtpd_chat_pre_jail_init: multiple calls");

     /*
-     * SMTP server reject footer.
+     * SMTP server reject replacement and footer.
      */
     if (*var_smtpd_rej_ftr_maps)
        smtpd_rej_ftr_maps = maps_create(VAR_SMTPD_REJ_FTR_MAPS,
                                         var_smtpd_rej_ftr_maps,
                                         DICT_FLAG_LOCK);
+    if (*var_smtpd_rej_flt_maps)
+        smtpd_rej_flt_maps = maps_create(VAR_SMTPD_REJ_FLT_MAPS,
+                                         var_smtpd_rej_flt_maps,
+                                         DICT_FLAG_LOCK);
 }

 /* smtp_chat_reset - reset SMTP transaction log */
@@ -205,7 +210,8 @@ void    vsmtpd_chat_reply(SMTPD_STATE *state,
const char *format, va_list ap)
     char   *cp;
     char   *next;
     char   *end;
-    const char *footer;
+    const char *footer = 0;
+    const char *replacement;

     /*
      * Slow down clients that make errors. Sleep-on-anything slows down
@@ -216,12 +222,19 @@ void    vsmtpd_chat_reply(SMTPD_STATE *state,
const char *format, va_list ap)

     vstring_vsprintf(state->buffer, format, ap);

-    if ((*(cp = STR(state->buffer)) == '4' || *cp == '5')
-       && ((smtpd_rej_ftr_maps != 0
+    if (*(cp = STR(state->buffer)) == '4' || *cp == '5') {
+       if (smtpd_rej_flt_maps != 0
+            && (replacement = maps_find(smtpd_rej_flt_maps, cp, 0)) != 0)
+           smtp_reply_filter(state->buffer, 0, replacement,
STR(smtpd_expand_filter),
+                             smtpd_expand_lookup, (void *) state);
+       else if (smtpd_rej_ftr_maps != 0
             && (footer = maps_find(smtpd_rej_ftr_maps, cp, 0)) != 0)
-           || *(footer = var_smtpd_rej_footer) != 0))
-       smtp_reply_footer(state->buffer, 0, footer, STR(smtpd_expand_filter),
-                         smtpd_expand_lookup, (void *) state);
+           smtp_reply_footer(state->buffer, 0, footer,
STR(smtpd_expand_filter),
+                          smtpd_expand_lookup, (void *) state);
+       if (footer == 0 && *(footer = var_smtpd_rej_footer) != 0)
+           smtp_reply_footer(state->buffer, 0, footer,
STR(smtpd_expand_filter),
+                             smtpd_expand_lookup, (void *) state);
+    }


diff --git a/src/global/mail_params.h b/src/global/mail_params.h
index 1f4c207..2fe0d0d 100644
--- a/src/global/mail_params.h
+++ b/src/global/mail_params.h
@@ -4009,6 +4009,10 @@ extern char *var_smtpd_rej_footer;
 #define DEF_SMTPD_REJ_FTR_MAPS ""
 extern char *var_smtpd_rej_ftr_maps;

+#define VAR_SMTPD_REJ_FLT_MAPS  "smtpd_reject_filter_maps"
+#define DEF_SMTPD_REJ_FLT_MAPS  ""
+extern char *var_smtpd_rej_flt_maps;
+

Sébastien

Reply via email to