diff --git a/postfix/HISTORY b/postfix/HISTORY
index e443a8627..3824d470b 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -25919,3 +25919,13 @@ Apologies for any names omitted.
Additional postcat flags for debuging a corrupted queue
file (-s: skip to offset; -r: don't follow pointer records).
File: postcat/postcat.c.
+
+20211110
+
+ Minor edits of 20211107 postcat changes. File: postcat.c.
+
+ Regression prevention: added sanity check in the queue file
+ editing code. File: cleanup/cleanup_body_edit.c
+
+ Regression prevention: copied a queue file record typecheck
+ from the pickup daemon. Files: *qmgr/qmgr_message.c.
diff --git a/postfix/WISHLIST b/postfix/WISHLIST
index 9bbb46f43..0985ec034 100644
--- a/postfix/WISHLIST
+++ b/postfix/WISHLIST
@@ -1,7 +1,7 @@
Wish list:
- Fix the body_edit_lockout safety: turn it on when editing,
- and turn if off when done.
+ proxy_read_maps needs a dedicated matcher that looks
+ inside pipemap:{}. Maybe steal some code from postconf.
Add a pointer to
http://mmogilvi.users.sourceforge.net/software/oauthbearer.html
diff --git a/postfix/html/postcat.1.html b/postfix/html/postcat.1.html
index 2928522d8..1a5c7af1d 100644
--- a/postfix/html/postcat.1.html
+++ b/postfix/html/postcat.1.html
@@ -55,12 +55,14 @@ POSTCAT(1) POSTCAT(1)
-r Print records in file order, don't follow pointer records.
- This feature is available in Postfix 3.7 and later. IP "-s off-
- set" Skip to the specified queue file offset.
+ This feature is available in Postfix 3.7 and later.
- This feature is available in Postfix 2.0 and later.
+ -s offset
+ Skip to the specified queue file offset.
- -v Enable verbose logging for debugging purposes. Multiple -v
+ This feature is available in Postfix 3.7 and later.
+
+ -v Enable verbose logging for debugging purposes. Multiple -v
options make the software increasingly verbose.
DIAGNOSTICS
@@ -71,19 +73,19 @@ POSTCAT(1) POSTCAT(1)
Directory with Postfix configuration files.
CONFIGURATION PARAMETERS
- The following main.cf parameters are especially relevant to this pro-
+ The following main.cf parameters are especially relevant to this pro-
gram.
- The text below provides only a parameter summary. See postconf(5) for
+ The text below provides only a parameter summary. See postconf(5) for
more details including examples.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and master.cf con-
+ The default location of the Postfix main.cf and master.cf con-
figuration files.
import_environment (see 'postconf -d' output)
- The list of environment parameters that a privileged Postfix
- process will import from a non-Postfix parent process, or
+ The list of environment parameters that a privileged Postfix
+ process will import from a non-Postfix parent process, or
name=value environment overrides.
queue_directory (see 'postconf -d' output)
diff --git a/postfix/man/man1/postcat.1 b/postfix/man/man1/postcat.1
index 78c7521fc..eb3025ba1 100644
--- a/postfix/man/man1/postcat.1
+++ b/postfix/man/man1/postcat.1
@@ -56,10 +56,10 @@ This feature is available in Postfix 2.0 and later.
Print records in file order, don't follow pointer records.
This feature is available in Postfix 3.7 and later.
-IP "\fB-s \fIoffset\fR"
+.IP "\fB\-s \fIoffset\fR"
Skip to the specified queue file offset.
-This feature is available in Postfix 2.0 and later.
+This feature is available in Postfix 3.7 and later.
.IP \fB\-v\fR
Enable verbose logging for debugging purposes. Multiple \fB\-v\fR
options make the software increasingly verbose.
diff --git a/postfix/src/cleanup/cleanup_body_edit.c b/postfix/src/cleanup/cleanup_body_edit.c
index 2fff1bcad..3d4e8668b 100644
--- a/postfix/src/cleanup/cleanup_body_edit.c
+++ b/postfix/src/cleanup/cleanup_body_edit.c
@@ -210,6 +210,13 @@ int cleanup_body_edit_write(CLEANUP_STATE *state, int rec_type,
CLEANUP_OUT_BUF(state, rec_type, buf);
curr_rp->write_offs = vstream_ftell(state->dst);
+ /*
+ * Sanity check.
+ */
+ if (curr_rp->len > 0
+ && curr_rp->write_offs > curr_rp->start + curr_rp->len)
+ msg_panic("%s: write past end of body segment", myname);
+
return (0);
}
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index b74f005e5..0ca8b7734 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -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 "20211107"
+#define MAIL_RELEASE_DATE "20211113"
#define MAIL_VERSION_NUMBER "3.7"
#ifdef SNAPSHOT
diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c
index ea5561561..96409ceb7 100644
--- a/postfix/src/oqmgr/qmgr_message.c
+++ b/postfix/src/oqmgr/qmgr_message.c
@@ -324,6 +324,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
char *dsn_orcpt = 0;
int n;
int have_log_client_attr = 0;
+ static const char env_rec_types[] = REC_TYPE_ENVELOPE REC_TYPE_EXTRACT;
+ static const char extra_rec_type[] = {REC_TYPE_XTRA, 0};
+ const char *expected_rec_types;
/*
* Initialize. No early returns or we have a memory leak.
@@ -371,12 +374,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
* mailing lists.
*/
for (;;) {
+ expected_rec_types = env_rec_types;
if ((curr_offset = vstream_ftell(message->fp)) < 0)
msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
if (curr_offset == message->data_offset && curr_offset > 0) {
if (vstream_fseek(message->fp, message->data_size, SEEK_CUR) < 0)
msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
curr_offset += message->data_size;
+ expected_rec_types = extra_rec_type;
}
rec_type = rec_get_raw(message->fp, buf, 0, REC_FLAG_NONE);
start = vstring_str(buf);
@@ -393,6 +398,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
message->queue_id);
break;
}
+ if (strchr(expected_rec_types, rec_type) == 0) {
+ msg_warn("Unexpected record type '%c' at offset %ld",
+ rec_type, (long) curr_offset);
+ rec_type = REC_TYPE_ERROR;
+ break;
+ }
if (rec_type == REC_TYPE_END) {
message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
break;
@@ -406,7 +417,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
*/
if (rec_type == REC_TYPE_ATTR) {
if ((error_text = split_nameval(start, &name, &value)) != 0) {
- msg_warn("%s: ignoring bad attribute: %s: %.200s",
+ msg_warn("%s: bad attribute record: %s: %.200s",
message->queue_id, error_text, start);
rec_type = REC_TYPE_ERROR;
break;
diff --git a/postfix/src/postcat/postcat.c b/postfix/src/postcat/postcat.c
index 2a8257965..9411f9e26 100644
--- a/postfix/src/postcat/postcat.c
+++ b/postfix/src/postcat/postcat.c
@@ -46,14 +46,14 @@
/* of taking the names literally.
/*
/* This feature is available in Postfix 2.0 and later.
-/*.IP \fB-r\fR
+/* .IP \fB-r\fR
/* Print records in file order, don't follow pointer records.
/*
/* This feature is available in Postfix 3.7 and later.
-/* IP "\fB-s \fIoffset\fR"
+/* .IP "\fB-s \fIoffset\fR"
/* Skip to the specified queue file offset.
/*
-/* This feature is available in Postfix 2.0 and later.
+/* This feature is available in Postfix 3.7 and later.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
@@ -204,8 +204,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
/*
* See if this is a plausible file.
*/
- if (start_offset == 0 && (flags & PC_FLAG_RAW) == 0
- && (ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
+ if (start_offset == 0 && (ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
if (!strchr(REC_TYPE_ENVELOPE, ch)) {
msg_warn("%s: input is not a valid queue file", VSTREAM_PATH(fp));
return;
@@ -519,7 +518,7 @@ int main(int argc, char **argv)
flags |= PC_FLAG_RAW;
break;
case 's':
- if (!alldig(optarg) || (start_offset = atol(optarg)) <= 0)
+ if (!alldig(optarg) || (start_offset = atol(optarg)) < 0)
msg_fatal("bad offset: %s", optarg);
break;
case 'v':
diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c
index 02a739111..8b5631d41 100644
--- a/postfix/src/qmgr/qmgr_message.c
+++ b/postfix/src/qmgr/qmgr_message.c
@@ -347,6 +347,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
char *dsn_orcpt = 0;
int n;
int have_log_client_attr = 0;
+ static const char env_rec_types[] = REC_TYPE_ENVELOPE REC_TYPE_EXTRACT;
+ static const char extra_rec_type[] = {REC_TYPE_XTRA, 0};
+ const char *expected_rec_types;
/*
* Initialize. No early returns or we have a memory leak.
@@ -411,12 +414,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
* mailing lists.
*/
for (;;) {
+ expected_rec_types = env_rec_types;
if ((curr_offset = vstream_ftell(message->fp)) < 0)
msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
if (curr_offset == message->data_offset && curr_offset > 0) {
if (vstream_fseek(message->fp, message->data_size, SEEK_CUR) < 0)
msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
curr_offset += message->data_size;
+ expected_rec_types = extra_rec_type;
}
rec_type = rec_get_raw(message->fp, buf, 0, REC_FLAG_NONE);
start = vstring_str(buf);
@@ -433,6 +438,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
message->queue_id);
break;
}
+ if (strchr(expected_rec_types, rec_type) == 0) {
+ msg_warn("Unexpected record type '%c' at offset %ld",
+ rec_type, (long) curr_offset);
+ rec_type = REC_TYPE_ERROR;
+ break;
+ }
if (rec_type == REC_TYPE_END) {
message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
break;
@@ -446,7 +457,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
*/
if (rec_type == REC_TYPE_ATTR) {
if ((error_text = split_nameval(start, &name, &value)) != 0) {
- msg_warn("%s: ignoring bad attribute: %s: %.200s",
+ msg_warn("%s: bad attribute record: %s: %.200s",
message->queue_id, error_text, start);
rec_type = REC_TYPE_ERROR;
break;