]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.12-20260713
authorWietse Z Venema <wietse@porcupine.org>
Mon, 13 Jul 2026 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Tue, 14 Jul 2026 09:38:14 +0000 (19:38 +1000)
postfix/HISTORY
postfix/src/global/mail_version.h
postfix/src/tlsproxy/tlsproxy_state.c
postfix/src/util/clean_ascii_cntrl_space.c
postfix/src/util/dict_nisplus.c
postfix/src/util/inet_connect.c
postfix/src/util/nbbio.c
postfix/src/util/nbbio.h

index 0445d7a1aadfa31ba4b613fc93a92f3db6625057..92aa81bcca226a4cd836a29a820bc877a9bc1f0d 100644 (file)
@@ -31688,6 +31688,35 @@ Apologies for any names omitted.
        bytes of unused VSTRING buffer space. Suggested by Qualys,
        assisted by Claude Mythos Preview. File: qmqpd.c.
 
+20260713
+
+       Read after free (no privilege escalation) in debug logging
+       in dict_tcp.c, xsasl_dovecot_server.c, master_wakeup.c
+       (defect introduced: Postfix 2.2, date: 20050117). Reported
+       by Qualys, assisted by Claude Mythos Preview. File:
+       util/inet_connect.c.
+
+       Code hygiene: in a NIS+ lookup table name, enforce the '%s'
+       substitution syntax (defect introduced: Postfix 2.2, date:
+       20041018). NIS+ support was removed with Solaris 10.
+       Suggested by Qualys, assisted by Claude Mythos Preview.
+       File: dict_nisplus.c.
+
+       Code hygiene: in clean_ascii_cntrl_space(), don't assume
+       that input will always be null-terminated. Reported by
+       Qualys, assisted by Claude Mythos Preview. File:
+       clean_ascii_cntrl_space.c.
+
+       Code hygiene: in tlsproxy(8), initialize state->ssl_last_err
+       as SSL_ERROR_NONE, instead of the mymalloc() default value
+       (-1). Suggested by Qualys, assisted by Claude Mythos
+       Preview. File: tlsproxy_state.c.
+
+       Bug (defect introduced: Postfix 2.8, date: 20110102): while
+       tearing down a TLS session, tlsproxy(8) closed the same
+       file descriptor twice (without any adverse effect). Files:
+       nbbio.[hc].
+
 TODO
 
        Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc.
index b516b12cbb5b46767c92d69c249e8daa882c6561..7e43f5231d7256ea10ed9c978216803453e1546c 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      "20260710"
+#define MAIL_RELEASE_DATE      "20260713"
 #define MAIL_VERSION_NUMBER    "3.12"
 
 #ifdef SNAPSHOT
index a821066834a0d80fb954a0aa0c5241a1e85d1bd6..d62b614057e5141c957a9b6e1f17a93012afbad0 100644 (file)
@@ -124,6 +124,8 @@ TLSP_STATE *tlsp_state_create(const char *service,
     state->client_params = 0;
     state->client_init_props = 0;
     state->client_start_props = 0;
+    /* 200606 Qualys+Mythos: explicit initialization. */
+    state->ssl_last_err = SSL_ERROR_NONE;
 
     return (state);
 }
index 81f2ee53f3abea8173fd99fa982f4dc26c5afda3..8e7045f19d01198cb3e0abea4cd3dd4fa9347522 100644 (file)
@@ -71,7 +71,8 @@ char   *clean_ascii_cntrl_space(VSTRING *result, const char *str, ssize_t len)
        ch = *(unsigned char *) cp;
        if (ISCNTRL(ch))
            ch = ' ';
-       if (ch == ' ' && (prev_ch == ' ' || cp[1] == 0))
+       /* 202606 Qualys_Mythos: don't assume input is null-terminated. */
+       if (ch == ' ' && (prev_ch == ' ' || cp >= str_end - 1))
            continue;
        VSTRING_ADDCH(result, ch);
        prev_ch = ch;
index e14cdd0c48b3eb23b0c896a8ded23a507edc8a17..d83a6253cda2487d4a26fb034c39169eb7ca1e5b 100644 (file)
@@ -252,6 +252,7 @@ DICT   *dict_nisplus_open(const char *map, int open_flags, int dict_flags)
     const char *myname = "dict_nisplus_open";
     DICT_NISPLUS *dict_nisplus;
     char   *col_field;
+    const char *cp;
 
     /*
      * Sanity check.
@@ -284,7 +285,12 @@ DICT   *dict_nisplus_open(const char *map, int open_flags, int dict_flags)
      * other attributes must specify fixed values. The reason for using ';'
      * is that the comma character is special in main.cf. When no column
      * number is given at the end of the map name, we use a default column.
+     * 
+     * 2026506 Qualys+Mythos: enforce template substution syntax.
      */
+    if ((cp = strchr(map, '%')) == 0 || strncmp(cp, "%s", 2) != 0
+       || strchr(cp + 2, '%') != 0)
+       msg_fatal("bad '%%' substitution syntax in NIS+ map name: %s", map);
     dict_nisplus->template = mystrdup(map);
     translit(dict_nisplus->template, ";", ",");
     if ((col_field = strstr(dict_nisplus->template, ".:")) != 0) {
index 02a3962ad38b6f06bc86dfa9eb3c549b127d28da..b1a09c334054917864e8eb833376279591b2a1f0 100644 (file)
@@ -115,8 +115,9 @@ int     inet_connect(const char *addr, int block_mode, int timeout)
         * Safety net.
         */
        if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+           /* 202606 Qualys+Mythos: myfree() above frees 'host' and 'port'. */
            msg_info("skipping address family %d for host %s",
-                    res->ai_family, host);
+                    res->ai_family, addr);
            continue;
        }
        found++;
index e9ccc387825a351101581905d2e0cd397855470f..f3666baf36ed5fadae677eefe61f5ef23ae7e224 100644 (file)
@@ -31,6 +31,9 @@
 /*     NBBIO   *np;
 /*     int     timeout;
 /*
+/*     void    nbbio_own_fd(np)
+/*     NBBIO   *np;
+/*
 /*     int     NBBIO_ACTIVE_FLAGS(np)
 /*     NBBIO   *np;
 /*
@@ -71,8 +74,8 @@
 /*     with the application-specified context.
 /*
 /*     nbbio_free() terminates any pseudothreads associated with
-/*     the named buffer pair, closes the stream, and destroys the
-/*     buffer pair.
+/*     the named buffer pair, closes the stream if it is owned, and
+/*     destroys the buffer pair.
 /*
 /*     nbbio_enable_read() enables a read pseudothread (if one
 /*     does not already exist) for the named buffer pair, and
 /*     buffer liveness. It is no error to call this function while
 /*     no read/write pseudothread is enabled.
 /*
+/*     nbbio_own_fd() makes the NBBIO owner of the file descriptor.
+/*
 /*     NBBIO_ERROR_FLAGS() returns the error flags for the named buffer
 /*     pair: zero or more of NBBIO_FLAG_EOF (read EOF), NBBIO_FLAG_ERROR
 /*     (read/write error) or NBBIO_FLAG_TIMEOUT (time limit
@@ -374,7 +379,9 @@ NBBIO  *nbbio_create(int fd, ssize_t bufsize, const char *label,
 void    nbbio_free(NBBIO *np)
 {
     nbbio_disable_readwrite(np);
-    (void) close(np->fd);
+    /* 202606 Qualys+Mythos: close decriptor only if owner. */
+    if (np->flags & NBBIO_FLAG_OWN_FD)
+       (void) close(np->fd);
     myfree(np->label);
     myfree(np->read_buf);
     myfree(np->write_buf);
index d1d2b0ef7328f93162bc44a2c35677fd89b9fcb0..cb681acc4b2c740f72c67fa9a5c9096fc37327b9 100644 (file)
@@ -41,6 +41,7 @@ typedef struct {
 #define NBBIO_FLAG_EOF         (1<<2)
 #define NBBIO_FLAG_ERROR       (1<<3)
 #define NBBIO_FLAG_TIMEOUT     (1<<4)
+#define NBBIO_FLAG_OWN_FD      (1<<5)
 
 #define NBBIO_OP_NAME(np) \
        (((np)->flags & NBBIO_FLAG_READ) ? "read" : \
@@ -64,6 +65,8 @@ typedef struct {
 #define NBBIO_ACTIVE_FLAGS(np)         ((np)->flags & NBBIO_MASK_ACTIVE)
 #define NBBIO_ERROR_FLAGS(np)          ((np)->flags & NBBIO_MASK_ERROR)
 
+#define nbbio_own_fd(np)               ((np)->flags |= NBBIO_FLAG_OWN_FD)
+
 extern NBBIO *nbbio_create(int, ssize_t, const char *, NBBIO_ACTION, void *);
 extern void nbbio_free(NBBIO *);
 extern void nbbio_enable_read(NBBIO *, int);