[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1035466: bullseye-pu: package postfix/3.5.18-0+deb11u1



Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu

This is another in the usual series of upstream bugfix releases that we
provide as stable updates.  There no other changes.

[ Reason ]
Mostly these are long-term defects.  The check_ccert_access bug is a
regression for Debian from Buster.  See below for details.

[ Impact ]
User will still suffer from the bugs listed below.  The long form
name=value changes reduce the risk of inadvertent misconfiguration by an
administrator.

[ Tests ]
The postfix has an extensive autopkgtest, which passes with this update.
Additionally, I have a locally built version of the package running in
production without issue.

[ Risks ]
Risk is trivial.  Upstream has an excellent history with these updates
and no issues with it have been reported upstream.

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]

Here is the draft d/changelog entries that describes all the changes
which impact Linux (I left a MacOS portability change off):

postfix (3.5.19-0+deb11u1) UNRELEASED; urgency=medium

  [Wietse Venema]

  * 3.5.19
    - Portability: the EVP_get_digestbyname change broke OpenSSL
      1.0.2 support. File: tls/tls.h.

    - Bugfix (introduced: Postfix 3.4): the posttls-finger command
      failed to detect that a connection was resumed in the case
      that a server did not return a certificate. Viktor Dukhovni.
      File: posttls-finger/posttls-finger.c.

    - Workaround: OpenSSL 3.x EVP_get_cipherbyname() can return
      lazily-bound handles. Postfix now checks that the expected
      functionality will be available instead of failing later.
      Fix by Viktor Dukhovni. File: tls/tls_server.c.

    - Bugfix (introduced: Postfix 3.5): check_ccert_access did
      not parse inline map specifications. Report and fix by Sean
      Gallagher. File: global/map_search.c.

    - Safety: the long form "{ name = value }" in import_environment
      or export_environment is not documented, but accepted, and
      it was stored in the process environment as the invalid
      form "name = value", thus not setting or overriding an entry
      for "name". This form is now stored as the expected
      "name=value". Found during code maintenance. Also refined
      the "missing attribute name" detection. Files: clean_env.c,
      split_nameval.c.

      Bugfix (introduced: Postfix 3.2): the MySQL client could
      return "not found" instead of "error" during the time that
      all MySQL server connections were turned down after error.
      Found during code maintenance. File: global/dict_mysql.c.

 -- Scott Kitterman <scott@kitterman.com>  Sun, 30 Apr 2023 14:24:06 -0400

[ Other info ]
The changes in this update are also in Unstable in 3.7.5-1 (the changes
in 3.7.5-2 are not relevant for bullseye).

Scott K
diff -Nru postfix-3.5.18/debian/changelog postfix-3.5.19/debian/changelog
--- postfix-3.5.18/debian/changelog	2023-01-21 20:17:03.000000000 -0500
+++ postfix-3.5.19/debian/changelog	2023-04-30 14:24:06.000000000 -0400
@@ -1,3 +1,41 @@
+postfix (3.5.19-0+deb11u1) UNRELEASED; urgency=medium
+
+  [Wietse Venema]
+
+  * 3.5.19
+    - Portability: the EVP_get_digestbyname change broke OpenSSL
+      1.0.2 support. File: tls/tls.h.
+
+    - Bugfix (introduced: Postfix 3.4): the posttls-finger command
+      failed to detect that a connection was resumed in the case
+      that a server did not return a certificate. Viktor Dukhovni.
+      File: posttls-finger/posttls-finger.c.
+
+    - Workaround: OpenSSL 3.x EVP_get_cipherbyname() can return
+      lazily-bound handles. Postfix now checks that the expected
+      functionality will be available instead of failing later.
+      Fix by Viktor Dukhovni. File: tls/tls_server.c.
+
+    - Bugfix (introduced: Postfix 3.5): check_ccert_access did
+      not parse inline map specifications. Report and fix by Sean
+      Gallagher. File: global/map_search.c.
+
+    - Safety: the long form "{ name = value }" in import_environment
+      or export_environment is not documented, but accepted, and
+      it was stored in the process environment as the invalid
+      form "name = value", thus not setting or overriding an entry
+      for "name". This form is now stored as the expected
+      "name=value". Found during code maintenance. Also refined
+      the "missing attribute name" detection. Files: clean_env.c,
+      split_nameval.c.
+
+      Bugfix (introduced: Postfix 3.2): the MySQL client could
+      return "not found" instead of "error" during the time that
+      all MySQL server connections were turned down after error.
+      Found during code maintenance. File: global/dict_mysql.c. 
+
+ -- Scott Kitterman <scott@kitterman.com>  Sun, 30 Apr 2023 14:24:06 -0400
+
 postfix (3.5.18-0+deb11u1) bullseye; urgency=medium
 
   [Wietse Venema]
diff -Nru postfix-3.5.18/HISTORY postfix-3.5.19/HISTORY
--- postfix-3.5.18/HISTORY	2023-01-21 15:34:23.000000000 -0500
+++ postfix-3.5.19/HISTORY	2023-04-18 15:41:50.000000000 -0400
@@ -25215,3 +25215,47 @@
 	framing, and is therefore not affected by TLS truncation
 	attacks. Fix by Viktor Dukhovni. Files: tls/tls.h, tls_client.c,
 	tls/tls_server.c.
+
+20230125
+
+	Portability: the EVP_get_digestbyname change broke OpenSSL
+	1.0.2 support. File: tls/tls.h.
+
+20230127
+
+	Bugfix (introduced: Postfix 3.4): the posttls-finger command
+	failed to detect that a connection was resumed in the case
+	that a server did not return a certificate. Viktor Dukhovni.
+	File: posttls-finger/posttls-finger.c.
+
+	Workaround: OpenSSL 3.x EVP_get_cipherbyname() can return
+	lazily-bound handles. Postfix now checks that the expected
+	functionality will be available instead of failing later.
+	Fix by Viktor Dukhovni. File: tls/tls_server.c.
+
+	Portability: MacOS support for the postfix-env.sh test
+	script.
+
+20230314
+
+	Bugfix (introduced: Postfix 3.5): check_ccert_access did
+	not parse inline map specifications. Report and fix by Sean
+	Gallagher. File: global/map_search.c.
+
+20230330
+
+	Safety: the long form "{ name = value }" in import_environment
+	or export_environment is not documented, but accepted, and
+	it was stored in the process environment as the invalid
+	form "name = value", thus not setting or overriding an entry
+	for "name". This form is now stored as the expected
+	"name=value". Found during code maintenance. Also refined
+	the "missing attribute name" detection. Files: clean_env.c,
+	split_nameval.c.
+
+20230418
+
+	Bugfix (introduced: Postfix 3.2): the MySQL client could
+	return "not found" instead of "error" during the time that
+	all MySQL server connections were turned down after error.
+	Found during code maintenance. File: global/dict_mysql.c.
diff -Nru postfix-3.5.18/postfix-env.sh postfix-3.5.19/postfix-env.sh
--- postfix-3.5.18/postfix-env.sh	2014-06-25 12:58:34.000000000 -0400
+++ postfix-3.5.19/postfix-env.sh	2023-01-28 10:55:58.000000000 -0500
@@ -2,4 +2,4 @@
 
 # Run a program with the new shared libraries instead of the installed ones.
 
-LD_LIBRARY_PATH=`pwd`/lib exec "$@"
+LD_LIBRARY_PATH=`pwd`/lib DYLD_LIBRARY_PATH=`pwd`/lib exec "$@"
diff -Nru postfix-3.5.18/src/global/dict_mysql.c postfix-3.5.19/src/global/dict_mysql.c
--- postfix-3.5.18/src/global/dict_mysql.c	2018-08-25 19:10:33.000000000 -0400
+++ postfix-3.5.19/src/global/dict_mysql.c	2023-04-18 15:38:40.000000000 -0400
@@ -528,7 +528,7 @@
 {
     HOST   *host;
     MYSQL_RES *first_result = 0;
-    int     query_error;
+    int     query_error = 1;
 
     /*
      * Helper to avoid spamming the log with warnings.
diff -Nru postfix-3.5.18/src/global/mail_version.h postfix-3.5.19/src/global/mail_version.h
--- postfix-3.5.18/src/global/mail_version.h	2023-01-21 15:44:18.000000000 -0500
+++ postfix-3.5.19/src/global/mail_version.h	2023-04-18 16:39:35.000000000 -0400
@@ -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	"20230121"
-#define MAIL_VERSION_NUMBER	"3.5.18"
+#define MAIL_RELEASE_DATE	"20230418"
+#define MAIL_VERSION_NUMBER	"3.5.19"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -Nru postfix-3.5.18/src/global/map_search.c postfix-3.5.19/src/global/map_search.c
--- postfix-3.5.18/src/global/map_search.c	2022-10-07 15:19:14.000000000 -0400
+++ postfix-3.5.19/src/global/map_search.c	2023-03-14 19:41:45.000000000 -0400
@@ -158,7 +158,8 @@
 	if ((heap_err = extpar(&bp, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) {
 	    msg_warn("malformed map specification: '%s'", heap_err);
 	    MAP_SEARCH_CREATE_RETURN(0);
-	} else if ((map_type_name = mystrtok(&bp, CHARS_COMMA_SP)) == 0) {
+	} else if ((map_type_name = mystrtokq(&bp, CHARS_COMMA_SP,
+					      CHARS_BRACE)) == 0) {
 	    msg_warn("empty map specification: '%s'", map_spec);
 	    MAP_SEARCH_CREATE_RETURN(0);
 	}
@@ -308,6 +309,7 @@
 	{"{type:name {search_order=one, two}}", 1, "type:name", "\01\02"},
 	{"{type:name {search_order=one, two, bad}}", 0, 0, 0},
 	{"{inline:{a=b} {search_order=one, two}}", 1, "inline:{a=b}", "\01\02"},
+	{"{inline:{a=b, c=d} {search_order=one, two}}", 1, "inline:{a=b, c=d}", "\01\02"},
 	{0},
     };
     TEST_CASE *test_case;
diff -Nru postfix-3.5.18/src/posttls-finger/posttls-finger.c postfix-3.5.19/src/posttls-finger/posttls-finger.c
--- postfix-3.5.18/src/posttls-finger/posttls-finger.c	2020-08-21 19:17:03.000000000 -0400
+++ postfix-3.5.19/src/posttls-finger/posttls-finger.c	2023-01-27 15:57:29.000000000 -0500
@@ -933,9 +933,9 @@
 		print_trust_info(state);
 	    state->log_mask &= ~(TLS_LOG_CERTMATCH | TLS_LOG_PEERCERT |
 				 TLS_LOG_VERBOSE | TLS_LOG_UNTRUSTED);
-	    state->log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY;
-	    tls_update_app_logmask(state->tls_ctx, state->log_mask);
 	}
+	state->log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY;
+	tls_update_app_logmask(state->tls_ctx, state->log_mask);
     }
     return (0);
 }
diff -Nru postfix-3.5.18/src/tls/tls.h postfix-3.5.19/src/tls/tls.h
--- postfix-3.5.18/src/tls/tls.h	2023-01-21 16:00:03.000000000 -0500
+++ postfix-3.5.19/src/tls/tls.h	2023-01-28 10:42:43.000000000 -0500
@@ -84,6 +84,16 @@
 #define ssl_cipher_stack_t STACK_OF(SSL_CIPHER)
 #define ssl_comp_stack_t STACK_OF(SSL_COMP)
 
+ /*-
+  * Official way to check minimum OpenSSL API version from 3.0 onward.
+  * We simply define it false for all prior versions, where we typically also
+  * need the patch level to determine API compatibility.
+  */
+#ifndef OPENSSL_VERSION_PREREQ
+#define OPENSSL_VERSION_PREREQ(m,n) 0
+#endif
+
+
 #if (OPENSSL_VERSION_NUMBER < 0x1000200fUL)
 #error "OpenSSL releases prior to 1.0.2 are no longer supported"
 #endif
@@ -109,6 +119,8 @@
 #define TLS_method SSLv23_method
 #define TLS_client_method SSLv23_client_method
 #define TLS_server_method SSLv23_server_method
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
 #endif
 
  /* Backwards compatibility with OpenSSL < 1.1.1 */
diff -Nru postfix-3.5.18/src/tls/tls_server.c postfix-3.5.19/src/tls/tls_server.c
--- postfix-3.5.18/src/tls/tls_server.c	2023-01-21 16:00:03.000000000 -0500
+++ postfix-3.5.19/src/tls/tls_server.c	2023-01-28 10:42:43.000000000 -0500
@@ -164,6 +164,13 @@
   */
 static const char server_session_id_context[] = "Postfix/TLS";
 
+#ifndef OPENSSL_NO_TLSEXT
+ /*
+  * We retain the cipher handle for lifetime of the process, it is not freed.
+  */
+static const EVP_CIPHER *tkt_cipher;
+#endif
+
 #define GET_SID(s, v, lptr)	((v) = SSL_SESSION_get_id((s), (lptr)))
 
  /* OpenSSL 1.1.0 bitrot */
@@ -299,19 +306,17 @@
 
 /* ticket_cb - configure tls session ticket encrypt/decrypt context */
 
-#if defined(SSL_OP_NO_TICKET) && !defined(OPENSSL_NO_TLSEXT)
+#if !defined(OPENSSL_NO_TLSEXT)
 
 static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
 		          EVP_CIPHER_CTX * ctx, HMAC_CTX * hctx, int create)
 {
     static const EVP_MD *sha256;
-    static const EVP_CIPHER *ciph;
     TLS_TICKET_KEY *key;
     TLS_SESS_STATE *TLScontext = SSL_get_ex_data(con, TLScontext_index);
     int     timeout = ((int) SSL_CTX_get_timeout(SSL_get_SSL_CTX(con))) / 2;
 
     if ((!sha256 && (sha256 = EVP_sha256()) == 0)
-	|| (!ciph && (ciph = EVP_get_cipherbyname(var_tls_tkt_cipher)) == 0)
 	|| (key = tls_mgr_key(create ? 0 : name, timeout)) == 0
 	|| (create && RAND_bytes(iv, TLS_TICKET_IVLEN) <= 0))
 	return (create ? TLS_TKT_NOKEYS : TLS_TKT_STALE);
@@ -319,13 +324,13 @@
     HMAC_Init_ex(hctx, key->hmac, TLS_TICKET_MACLEN, sha256, NOENGINE);
 
     if (create) {
-	EVP_EncryptInit_ex(ctx, ciph, NOENGINE, key->bits, iv);
+	EVP_EncryptInit_ex(ctx, tkt_cipher, NOENGINE, key->bits, iv);
 	memcpy((void *) name, (void *) key->name, TLS_TICKET_NAMELEN);
 	if (TLScontext->log_mask & TLS_LOG_CACHE)
 	    msg_info("%s: Issuing session ticket, key expiration: %ld",
 		     TLScontext->namaddr, (long) key->tout);
     } else {
-	EVP_DecryptInit_ex(ctx, ciph, NOENGINE, key->bits, iv);
+	EVP_DecryptInit_ex(ctx, tkt_cipher, NOENGINE, key->bits, iv);
 	if (TLScontext->log_mask & TLS_LOG_CACHE)
 	    msg_info("%s: Decrypting session ticket, key expiration: %ld",
 		     TLScontext->namaddr, (long) key->tout);
@@ -495,18 +500,20 @@
      * Add SSL_OP_NO_TICKET when the timeout is zero or library support is
      * incomplete.
      */
-#ifdef SSL_OP_NO_TICKET
 #ifndef OPENSSL_NO_TLSEXT
     ticketable = (*var_tls_tkt_cipher && scache_timeout > 0
 		  && !(off & SSL_OP_NO_TICKET));
     if (ticketable) {
-	const EVP_CIPHER *ciph;
-
-	if ((ciph = EVP_get_cipherbyname(var_tls_tkt_cipher)) == 0
-	    || EVP_CIPHER_mode(ciph) != EVP_CIPH_CBC_MODE
-	    || EVP_CIPHER_iv_length(ciph) != TLS_TICKET_IVLEN
-	    || EVP_CIPHER_key_length(ciph) < TLS_TICKET_IVLEN
-	    || EVP_CIPHER_key_length(ciph) > TLS_TICKET_KEYLEN) {
+#if OPENSSL_VERSION_PREREQ(3,0)
+	tkt_cipher = EVP_CIPHER_fetch(NULL, var_tls_tkt_cipher, NULL);
+#else
+	tkt_cipher = EVP_get_cipherbyname(var_tls_tkt_cipher);
+#endif
+	if (tkt_cipher == 0
+	    || EVP_CIPHER_mode(tkt_cipher) != EVP_CIPH_CBC_MODE
+	    || EVP_CIPHER_iv_length(tkt_cipher) != TLS_TICKET_IVLEN
+	    || EVP_CIPHER_key_length(tkt_cipher) < TLS_TICKET_IVLEN
+	    || EVP_CIPHER_key_length(tkt_cipher) > TLS_TICKET_KEYLEN) {
 	    msg_warn("%s: invalid value: %s; session tickets disabled",
 		     VAR_TLS_TKT_CIPHER, var_tls_tkt_cipher);
 	    ticketable = 0;
@@ -532,7 +539,6 @@
 #endif
     if (!ticketable)
 	off |= SSL_OP_NO_TICKET;
-#endif
 
     SSL_CTX_set_options(server_ctx, off);
 
diff -Nru postfix-3.5.18/src/util/clean_env.c postfix-3.5.19/src/util/clean_env.c
--- postfix-3.5.18/src/util/clean_env.c	2017-12-27 17:29:45.000000000 -0500
+++ postfix-3.5.19/src/util/clean_env.c	2023-04-17 15:45:56.000000000 -0400
@@ -50,9 +50,11 @@
 /* Utility library. */
 
 #include <msg.h>
+#include <mymalloc.h>
 #include <argv.h>
 #include <safe.h>
 #include <clean_env.h>
+#include <stringops.h>
 
 /* clean_env - clean up the environment */
 
@@ -62,20 +64,27 @@
     ARGV   *save_list;
     char   *value;
     char  **cpp;
-    char   *eq;
+    char   *copy;
+    char   *key;
+    char   *val;
+    const char *err;
 
     /*
      * Preserve or specify selected environment variables.
      */
-#define STRING_AND_LENGTH(x, y) (x), (ssize_t) (y)
-
     save_list = argv_alloc(10);
-    for (cpp = preserve_list; *cpp; cpp++)
-	if ((eq = strchr(*cpp, '=')) != 0)
-	    argv_addn(save_list, STRING_AND_LENGTH(*cpp, eq - *cpp),
-		      STRING_AND_LENGTH(eq + 1, strlen(eq + 1)), (char *) 0);
-	else if ((value = safe_getenv(*cpp)) != 0)
+    for (cpp = preserve_list; *cpp; cpp++) {
+	if (strchr(*cpp, '=') != 0) {
+	    copy = mystrdup(*cpp);
+	    err = split_nameval(copy, &key, &val);
+	    if (err != 0)
+		msg_fatal("clean_env: %s in: %s", err, *cpp);
+	    argv_add(save_list, key, val, (char *) 0);
+	    myfree(copy);
+	} else if ((value = safe_getenv(*cpp)) != 0) {
 	    argv_add(save_list, *cpp, value, (char *) 0);
+	}
+    }
 
     /*
      * Truncate the process environment, if available. On some systems
@@ -103,16 +112,25 @@
 {
     char  **cpp;
     ARGV   *save_list;
-    char   *eq;
+    char   *copy;
+    char   *key;
+    char   *val;
+    const char *err;
 
     /*
      * Extract name=value settings.
      */
     save_list = argv_alloc(10);
-    for (cpp = preserve_list; *cpp; cpp++)
-	if ((eq = strchr(*cpp, '=')) != 0)
-	    argv_addn(save_list, STRING_AND_LENGTH(*cpp, eq - *cpp),
-		      STRING_AND_LENGTH(eq + 1, strlen(eq + 1)), (char *) 0);
+    for (cpp = preserve_list; *cpp; cpp++) {
+	if (strchr(*cpp, '=') != 0) {
+	    copy = mystrdup(*cpp);
+	    err = split_nameval(copy, &key, &val);
+	    if (err != 0)
+		msg_fatal("update_env: %s in: %s", err, *cpp);
+	    argv_add(save_list, key, val, (char *) 0);
+	    myfree(copy);
+	}
+    }
 
     /*
      * Apply name=value settings.
diff -Nru postfix-3.5.18/src/util/split_nameval.c postfix-3.5.19/src/util/split_nameval.c
--- postfix-3.5.18/src/util/split_nameval.c	2013-11-07 17:06:23.000000000 -0500
+++ postfix-3.5.19/src/util/split_nameval.c	2023-04-17 15:45:56.000000000 -0400
@@ -81,7 +81,7 @@
     } while (0)
 
     SKIP(buf, np, ISSPACE(*np));		/* find name begin */
-    if (*np == 0)
+    if (*np == 0 || *np == '=')
 	return ("missing attribute name");
     SKIP(np, ep, !ISSPACE(*ep) && *ep != '=');	/* find name end */
     SKIP(ep, cp, ISSPACE(*cp));			/* skip blanks before '=' */

Reply to: