A. Schulze via Postfix-users:
> 
> Hello,
> 
> We've an SMTP-Server, running intentionally with  
> "smtpd_tls_security_level = encrypt"
> 
> If an SMTP-Client fail to establish an TLS connection, the client  
> fallback to plaintext.
> That's nothing we could avoid.
> 
> What I see, is a session like this:
> 
> # swaks --from from@from.example --to to@to.example
> === Trying to.example:25...
> === Connected to to.example.
> <-  220 to.example ESMTP
>   -> EHLO from.example
> <-  250-to.example
> <-  250-SOMETHING
> <-  250 STARTTLS
>   -> MAIL FROM:<from@from.example>
> <** 530 5.7.0 Must issue a STARTTLS command first
>   -> QUIT
> <-  221 2.0.0 Bye
> 
> The response "Must issue a STARTTLS command first" is correct. But  
> it's hard for a SMTP client's admin to notice,
> an TLS session failed before. So I would like to see a response like
> "530 5.7.0 check why TLS wasn't established, maybe update yout client,  
> see https://example/more_text_here";
> 
> One would suggest to use smtpd_reject_footer. It's already used here  
> and it's generic for many different replys (with generic informations  
> about the SMTP-client in our case)
> 
> I know, there is an smtpd_recipient_restriction  
> "reject_plaintext_session" but I only found the option to change the  
> replycode (plaintext_reject_code)
> So, this doesn't help directly and it also may be an other layer...
> 
> Is there any other option than patching postfix' source code?

The options are Postfix 3.11 smtpd_reject_filter (supported),  
or backport (attached), or custom patch (not supported).

The attached backport is just code, not documentation.

        Wietse
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' 
'--exclude=INSTALL' --no-dereference -r -ur --new-file 
/var/tmp/postfix-3.11-20250624/src/global/mail_params.h 
./src/global/mail_params.h
--- /var/tmp/postfix-3.11-20250624/src/global/mail_params.h     2025-06-23 
16:35:19.000000000 -0400
+++ ./src/global/mail_params.h  2025-08-03 15:10:06.485751291 -0400
@@ -2568,7 +2568,8 @@
                                " $" VAR_SMTP_BODY_CHKS \
                                " $" VAR_SMTP_HEAD_CHKS \
                                " $" VAR_SMTP_MIME_CHKS \
-                               " $" VAR_SMTP_NEST_CHKS
+                               " $" VAR_SMTP_NEST_CHKS \
+                               " $" VAR_SMTPD_REJECT_FILTER_MAPS
 extern char *var_proxy_read_maps;
 
 #define VAR_PROXY_WRITE_MAPS   "proxy_write_maps"
@@ -4529,6 +4530,13 @@
 #define DEF_SMTPD_HIDE_CLIENT_SESSION  "no"
 extern int var_smtpd_hide_client_session;
 
+ /*
+  * SMTP server reject response filter.
+  */
+#define VAR_SMTPD_REJECT_FILTER_MAPS   "smtpd_reject_filter_maps"
+#define DEF_SMTPD_REJECT_FILTER_MAPS   ""
+extern char *var_smtpd_reject_filter_maps;
+
 /* LICENSE
 /* .ad
 /* .fi
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' 
'--exclude=INSTALL' --no-dereference -r -ur --new-file 
/var/tmp/postfix-3.11-20250624/src/smtpd/smtpd.c ./src/smtpd/smtpd.c
--- /var/tmp/postfix-3.11-20250624/src/smtpd/smtpd_chat.c       2021-10-02 
10:46:46.000000000 -0400
+++ ./src/smtpd/smtpd_chat.c    2025-08-03 15:27:57.097704332 -0400
@@ -112,8 +112,9 @@
 #include "smtpd_chat.h"
 
  /*
-  * Reject footer.
+  * Reject filter and footer maps.
   */
+static MAPS *smtpd_reject_filter_maps;
 static MAPS *smtpd_rej_ftr_maps;
 
 #define STR    vstring_str
@@ -129,6 +130,14 @@
        msg_panic("smtpd_chat_pre_jail_init: multiple calls");
 
     /*
+     * SMTP server reject filter.
+     */
+    if (*var_smtpd_reject_filter_maps)
+       smtpd_reject_filter_maps = maps_create(VAR_SMTPD_REJECT_FILTER_MAPS,
+                                        var_smtpd_reject_filter_maps,
+                                        DICT_FLAG_LOCK);
+
+    /*
      * SMTP server reject footer.
      */
     if (*var_smtpd_rej_ftr_maps)
@@ -206,6 +215,7 @@
     char   *cp;
     char   *next;
     char   *end;
+    const char *alt_reply;
     const char *footer;
 
     /*
@@ -215,8 +225,30 @@
     if (state->error_count >= var_smtpd_soft_erlim)
        sleep(delay = var_smtpd_err_sleep);
 
+    /*
+     * Postfix generates single-line reject responses, but Milters may
+     * generate multi-line rejects with the SMFIR_REPLYCODE request.
+     */
     vstring_vsprintf(state->buffer, format, ap);
-
+    cp = STR(state->buffer);
+    if ((*cp == '4' || *cp == '5')
+       && smtpd_reject_filter_maps != 0
+       && (alt_reply = maps_find(smtpd_reject_filter_maps, cp, 0)) != 0) {
+       const char *queue_id = state->queue_id ? state->queue_id : "NOQUEUE";
+
+       /* XXX Enforce this for each line of a multi-line reply. */
+       if ((alt_reply[0] != '4' && alt_reply[0] != '5')
+           || !ISDIGIT(alt_reply[1]) || !ISDIGIT(alt_reply[2])
+           || (alt_reply[3] != ' ' && alt_reply[3] != '-')
+           || (ISDIGIT(alt_reply[4]) && (alt_reply[4] != alt_reply[0]))) {
+           msg_warn("%s: ignoring invalid reject filter result: %s",
+                    queue_id, alt_reply);
+       } else {
+           msg_info("%s: reply filter in: %s", queue_id, cp);
+           msg_info("%s: reply filter out: %s", queue_id, alt_reply);
+           vstring_strcpy(state->buffer, alt_reply);
+       }
+    }
     if ((*(cp = STR(state->buffer)) == '4' || *cp == '5')
        && ((smtpd_rej_ftr_maps != 0
             && (footer = maps_find(smtpd_rej_ftr_maps, cp, 0)) != 0)
_______________________________________________
Postfix-users mailing list -- postfix-users@postfix.org
To unsubscribe send an email to postfix-users-le...@postfix.org

Reply via email to