]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.7.5 v3.7.5
authorWietse Venema <wietse@porcupine.org>
Tue, 18 Apr 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Wed, 19 Apr 2023 04:42:24 +0000 (00:42 -0400)
postfix/HISTORY
postfix/postfix-env.sh
postfix/src/global/dict_mysql.c
postfix/src/global/mail_version.h
postfix/src/global/map_search.c
postfix/src/posttls-finger/posttls-finger.c
postfix/src/tls/tls_server.c
postfix/src/util/clean_env.c
postfix/src/util/split_nameval.c

index 10276c5652fe6718fab8cc11563bdc8c7049a436..d6dbb7444d984d7ed07898ce7b0beff8a01b023c 100644 (file)
@@ -26468,3 +26468,42 @@ Apologies for any names omitted.
        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.
+
+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.
index 9c0fe44cf20e2005745877ead267097fab40c41e..35f317534664b28e46b471f4c370309291c3390b 100644 (file)
@@ -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 "$@"
index d90bc090dafea1d95391db0600c7a5a8a322eedd..735e1959c9727da04e33b16c47ec1175cf61de86 100644 (file)
@@ -528,7 +528,7 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
 {
     HOST   *host;
     MYSQL_RES *first_result = 0;
-    int     query_error;
+    int     query_error = 1;
 
     /*
      * Helper to avoid spamming the log with warnings.
index 3a486ac197c0ea1109d2aa8520d78e17c140802d..3c7ac074a310f9d406c97aae2c934c2f60ab4573 100644 (file)
@@ -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.7.4"
+#define MAIL_RELEASE_DATE      "20230418"
+#define MAIL_VERSION_NUMBER    "3.7.5"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index be4b42b33e9a3c70bc7c49efc19ff570335b3968..b10f7d516829f802527ecf4f46ec627702d34b83 100644 (file)
@@ -158,7 +158,8 @@ const MAP_SEARCH *map_search_create(const char *map_spec)
        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 @@ int     main(int argc, char **argv)
        {"{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;
index 8b34444e9ebd69e185d5df0326493aaa8a7aae1c..502645cdc26bb1286c55110cfdfafd8b6bda0d21 100644 (file)
@@ -941,9 +941,9 @@ static int starttls(STATE *state)
                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);
 }
index cccfb8aebaec043edff37cb1a8620d56fbc4ecde..58517b5a83075fd5d7d871a12b51731c81541d77 100644 (file)
   */
 static const char server_session_id_context[] = "Postfix/TLS";
 
+#ifndef OPENSSL_NO_TLSEXT
+ /*
+  * We retain the cipher handle for the lifetime of the process.
+  */
+static const EVP_CIPHER *tkt_cipher;
+#endif
+
 #define GET_SID(s, v, lptr)    ((v) = SSL_SESSION_get_id((s), (lptr)))
 
 typedef const unsigned char *session_id_t;
@@ -293,7 +300,7 @@ static int new_server_session_cb(SSL *ssl, SSL_SESSION *session)
 #define TLS_TKT_ACCEPT 1               /* Ticket decryptable and re-usable */
 #define TLS_TKT_REISSUE        2               /* Ticket decryptable, not re-usable */
 
-#if defined(SSL_OP_NO_TICKET) && !defined(OPENSSL_NO_TLSEXT)
+#if !defined(OPENSSL_NO_TLSEXT)
 
 #if OPENSSL_VERSION_PREREQ(3,0)
 
@@ -303,13 +310,11 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
                         EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int create)
 {
     OSSL_PARAM params[3];
-    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 ((!ciph && (ciph = EVP_get_cipherbyname(var_tls_tkt_cipher)) == 0)
-       || (key = tls_mgr_key(create ? 0 : name, timeout)) == 0
+    if ((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);
 
@@ -323,13 +328,13 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
        return (create ? TLS_TKT_NOKEYS : TLS_TKT_STALE);
 
     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);
@@ -346,13 +351,11 @@ 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);
@@ -360,13 +363,13 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
     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);
@@ -530,18 +533,20 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
      * 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;
@@ -571,7 +576,6 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
 #endif
     if (!ticketable)
        off |= SSL_OP_NO_TICKET;
-#endif
 
     SSL_CTX_set_options(server_ctx, off);
 
index c6daffac378e71e9f294fad00c36a68570c59a6e..5ae55289901d715ec221d6e00c0712a5a7b719b2 100644 (file)
 /* 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 @@ void    clean_env(char **preserve_list)
     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 @@ void    update_env(char **preserve_list)
 {
     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.
index 0359f1a13aa11a60345aea4727655764cd7062ee..da74fcf526c9995f1cc311d9327177ed76295078 100644 (file)
@@ -81,7 +81,7 @@ const char *split_nameval(char *buf, char **name, char **value)
     } 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 '=' */