]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.12-20260805 master
authorWietse Z Venema <wietse@porcupine.org>
Wed, 5 Aug 2026 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Thu, 6 Aug 2026 06:30:36 +0000 (16:30 +1000)
postfix/HISTORY
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/proto/postconf.proto
postfix/proto/stop
postfix/proto/stop.double-history
postfix/proto/stop.spell-cc
postfix/src/global/dict_mysql.c
postfix/src/global/mail_version.h
postfix/src/smtpd/smtpd.c
postfix/src/tls/tls_server.c

index f30d0ad8e5d2a066075999a9f926c31aa7f23d8d..8d9cfd50b6b143b4bfe2bb5c351ec9a411cb8b1f 100644 (file)
@@ -31865,6 +31865,24 @@ Apologies for any names omitted.
        client remained in the "accept this message" state, skipping
        Milter policy enforcement for the second message.
 
+20260805
+
+       Isolation: stamp Postfix SMTP server TLS session tickets
+       with their master.cf service name. With this, an SMTP server
+       defined in master.cf will no longer accept tickets issued
+       by a different SMTP server defined in the same master.cf
+       file. Fix by OpenAI security. File: tls_server.c.
+
+       Bug (defect introduced: Postfix 3.4, date: 20180805): SMTP
+       server command history memory exhaustion with a large number
+       of very small BDAT requests. Reported by OpenAI security.
+       File: smtpd.c.
+
+       Bug (defect introduced: Postfix 3.4, date: 20180303): the
+       MySQL client setting "tls_verify_cert = yes" had no effect
+       with Oracle MySQL 8 and later. Report and fix by OpenAI
+       Security. File: dict_mysql.c.
+
 TODO
 
        Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc.
index 7fc52ce1c97aa39c165d2e17dc0272d26afa9d0f..5b06a6a199d2e321ed30d38f7086bed62e1ddbbc 100644 (file)
@@ -18037,7 +18037,11 @@ requirements. </p>
 
 <p>
 The maximal number of lines in the Postfix SMTP server command history
-before it is flushed upon receipt of EHLO, RSET, or end of DATA.
+before it is flushed upon receipt of EHLO, RSET, or end of DATA. With
+Postfix &ge; 3.4 releases after 20260805, the history is flushed
+whenever it reaches the threshold. The <a href="postconf.5.html#notify_classes">notify_classes</a> parameter
+controls what command history may be reported in postmaster
+notification email.
 </p>
 
 
index 6ccde017c47042bd5656822eedbe940a5c44906a..e82fa36f4340045f06bd0c57c6c6278638c0b744 100644 (file)
@@ -12373,7 +12373,11 @@ requirements.
 This feature is available in Postfix >= 3.10.
 .SH smtpd_history_flush_threshold (default: 100)
 The maximal number of lines in the Postfix SMTP server command history
-before it is flushed upon receipt of EHLO, RSET, or end of DATA.
+before it is flushed upon receipt of EHLO, RSET, or end of DATA. With
+Postfix >= 3.4 releases after 20260805, the history is flushed
+whenever it reaches the threshold. The notify_classes parameter
+controls what command history may be reported in postmaster
+notification email.
 .SH smtpd_junk_command_limit (default: normal: 100, overload: 1)
 The number of junk commands (NOOP, VRFY, ETRN or RSET) that a remote
 SMTP client can send before the Postfix SMTP server starts to
index bdb60a9231c99d5d3d7c002e9b30e9cc321f9651..9659b335afc07393570897b978f88f343b7a259a 100644 (file)
@@ -6270,7 +6270,11 @@ smtpd_helo_restrictions = permit_mynetworks, reject_unknown_helo_hostname
 
 <p>
 The maximal number of lines in the Postfix SMTP server command history
-before it is flushed upon receipt of EHLO, RSET, or end of DATA.
+before it is flushed upon receipt of EHLO, RSET, or end of DATA. With
+Postfix &ge; 3.4 releases after 20260805, the history is flushed
+whenever it reaches the threshold. The notify_classes parameter
+controls what command history may be reported in postmaster
+notification email.
 </p>
 
 %PARAM smtpd_noop_commands 
index 671e3d6d2134026e919dc5f76147e69ec6e1a938..8fc534cc46e5e3f0f2c8784031ed85f5eaf2cddd 100644 (file)
@@ -1733,3 +1733,5 @@ optimizers
 resloop
 tokenized
 fortra
+OpenAI
+stateful
index a42ef13ec04e3817628a0223d92fbe267cacfc29..81e5e74c60432804b7d84a2779bb3640799d0b21 100644 (file)
@@ -267,3 +267,5 @@ proto  proto stop proto stop double cc
  support File smtpd smtpd c 
  sendmail sendmail c 
  postqueue postqueue c 
+ OpenAI Security File smtpd smtpd c 
+ by OpenAI Security File smtpd smtpd c 
index b6e5f5a8c8b68ac51e9e32d71b5d0796b84147aa..bee6c3842ce0488c2a239dc7b293b59654a05660 100644 (file)
@@ -1997,3 +1997,5 @@ jk
 unitext
 esmtpargs
 uncoded
+desynchronization
+xffffffff
index 482e6180d178e0ae9624fa03c1cae0cc88899289..10cd35ed897b4ef38458b353d904cffea2d14be7 100644 (file)
 #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50023
 #define DICT_MYSQL_SSL_VERIFY_SERVER_CERT MYSQL_OPT_SSL_VERIFY_SERVER_CERT
 #elif MYSQL_VERSION_ID >= 80000
-#define DICT_MYSQL_SSL_VERIFY_SERVER_CERT MYSQL_OPT_SSL_MODE
+/* 202607 OpenAI: MYSQL_OPT_SSL_MODE is an enum, not a bool. */
+#define DICT_MYSQL_SSL_MODE MYSQL_OPT_SSL_MODE
 #endif
 
  /*
@@ -172,7 +173,7 @@ typedef struct {
     char   *tls_CAfile;
     char   *tls_CApath;
     char   *tls_ciphers;
-#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
+#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT) || defined(DICT_MYSQL_SSL_MODE)
     int     tls_verify_cert;
 #endif
     int     require_result_set;
@@ -602,6 +603,11 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
  */
 static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
 {
+#if defined(DICT_MYSQL_SSL_MODE)
+    enum mysql_ssl_mode ssl_mode;
+
+#endif
+
     if ((host->db = mysql_init(NULL)) == NULL)
        msg_fatal("dict_mysql: insufficient memory");
     if (dict_mysql->option_file)
@@ -629,7 +635,19 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
                      dict_mysql->tls_CAfile, dict_mysql->tls_CApath,
                      dict_mysql->tls_ciphers);
 #endif
-#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
+#if defined(DICT_MYSQL_SSL_MODE)
+    if (dict_mysql->tls_verify_cert != -1) {
+       /* MYSQL_OPT_SSL_MODE enum values are not Boolean values. */
+       ssl_mode = dict_mysql->tls_verify_cert ? SSL_MODE_VERIFY_IDENTITY :
+           SSL_MODE_PREFERRED;
+       if (mysql_options(host->db, DICT_MYSQL_SSL_MODE, &ssl_mode) != 0) {
+           msg_warn("dict_mysql: could not set TLS mode for host %s: %s",
+                    host->hostname, mysql_error(host->db));
+           plmysql_down_host(host, dict_mysql->retry_interval);
+           return;
+       }
+    }
+#elif defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
     if (dict_mysql->tls_verify_cert != -1)
        mysql_options(host->db, DICT_MYSQL_SSL_VERIFY_SERVER_CERT,
                      &dict_mysql->tls_verify_cert);
@@ -705,7 +723,7 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
     dict_mysql->tls_CAfile = cfg_get_str(p, "tls_CAfile", NULL, 0, 0);
     dict_mysql->tls_CApath = cfg_get_str(p, "tls_CApath", NULL, 0, 0);
     dict_mysql->tls_ciphers = cfg_get_str(p, "tls_ciphers", NULL, 0, 0);
-#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
+#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT) || defined(DICT_MYSQL_SSL_MODE)
     dict_mysql->tls_verify_cert = cfg_get_bool(p, "tls_verify_cert", -1);
 #endif
     dict_mysql->require_result_set = cfg_get_bool(p, "require_result_set", 1);
index 3267bc3b98487e82c11736668642dfe991e6a668..585b82df62b993123ce24ef40e60a2a44bb58ef6 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      "20260804"
+#define MAIL_RELEASE_DATE      "20260805"
 #define MAIL_VERSION_NUMBER    "3.12"
 
 #ifdef SNAPSHOT
index 56b947e9f342bb93391581098e906b7fbac2db52..c8519a72baa5729423363a26b4547731273268f6 100644 (file)
@@ -6116,6 +6116,8 @@ static void smtpd_proto(SMTPD_STATE *state)
        for (;;) {
            if (state->flags & SMTPD_FLAG_HANGUP)
                break;
+           /* Flush the command history if it becomes large. */
+           chat_reset(state, var_smtpd_hist_thrsh);
            smtp_stream_setup(state->client, var_smtpd_tmout,
                              var_smtpd_req_deadline, 0);
            if (state->error_count >= var_smtpd_hard_erlim) {
index 30b7ddfb01acdef4538ec099817657828310d781..e4c1d3c6db3b466bd6be02f3923b0008986256c3 100644 (file)
@@ -819,6 +819,11 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
     const char *cipher_list;
     TLS_APPL_STATE *app_ctx = props->ctx;
     int     log_mask;
+    /* 202607 OpenAI: isolate session tickets by master.cf service name. */ 
+    EVP_MD_CTX *sessid_ctx_md = 0;
+    unsigned char sessid_ctx[EVP_MAX_MD_SIZE];
+    unsigned int sessid_ctx_len;
+    static const char sessid_ctx_label[] = "Postfix/TLS serverid";
 
     /*
      * Convert user loglevel to internal logmask.
@@ -876,6 +881,29 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
     TLScontext->stream = props->stream;
     TLScontext->mdalg = props->mdalg;
 
+    /*
+     * The serverid already partitions stateful sessions in the tlsmgr
+     * session cache. Apply the same partition to stateless sessions; all
+     * services in one Postfix instance share the tlsmgr ticket keys.
+     */
+    if (tls_digest_byname(LN_sha256, &sessid_ctx_md) == 0
+       || EVP_DigestUpdate(sessid_ctx_md, sessid_ctx_label,
+                           sizeof(sessid_ctx_label)) != 1
+       || EVP_DigestUpdate(sessid_ctx_md, props->serverid,
+                           strlen(props->serverid) + 1) != 1
+       || EVP_DigestFinal_ex(sessid_ctx_md, sessid_ctx, &sessid_ctx_len) != 1
+       || sessid_ctx_len > SSL_MAX_SID_CTX_LENGTH
+       || SSL_set_session_id_context(TLScontext->con, sessid_ctx,
+                                     sessid_ctx_len) != 1) {
+       msg_warn("Could not set TLS session ID context");
+       tls_print_errors();
+       if (sessid_ctx_md)
+           EVP_MD_CTX_destroy(sessid_ctx_md);
+       tls_free_context(TLScontext);
+       return (0);
+    }
+    EVP_MD_CTX_destroy(sessid_ctx_md);
+
     if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
        msg_warn("Could not set application data for 'TLScontext->con'");
        tls_print_errors();