2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +00:00

postfix-3.6.3

This commit is contained in:
Wietse Venema
2021-11-07 00:00:00 -05:00
committed by Viktor Dukhovni
parent cab3653e62
commit 87d99adba5
16 changed files with 145 additions and 22 deletions

View File

@@ -25612,3 +25612,85 @@ Apologies for any names omitted.
was comparing memory addresses instead of queue file names.
It now properly compares strings. Reported by Mehmet Avcioglu.
File: global/record.c.
20210811
Bitrot: OpenSSL 3.x requires const. File: tls/tls_misc.c.
20210925
Bugfix (bug introduced: Postfix 2.10): postconf -x produced
incorrect output, because different functions were implicitly
sharing a buffer for intermediate results. Reported
by raf, root cause analysis by Viktor Dukhovni. File:
postconf/postconf_builtin.c.
20211022
Bugfix (introduced: Postfix 3.6): the known_tcp_ports setting
had no effect. Reported by Peter. The feature wasn't fully
implemented. Files: config_known_tcp_ports.c, mail_params.c,
posttls-finger/posttls-finger.c, smtp/smtp_connect.c,
util/find_inet.c, util/myaddrinfo.c.
20211025
Bugfix (introduced: Postfix 3.6): mangled warning where a
hostname and warning message run together. Viktor Dukhovni.
File: tls/tls_dane.c.
20211030
Bugfix (problem introduced: Postfix 2.11): check_ccert_access
worked as expected, but produced a spurious warning when
Postfix was built without SASL support. Fix by Brad Barden.
File: smtpd/smtpd_check.c.
20211105
Bugfix (introduced: Postfix 2.4): queue file corruption
after a Milter (for example, MIMEDefang) made a request to
replace the message body with a copy of that message body
plus additional text (for example, a SpamAssassin report).
The most likely impacts were a) the queue manager reporting
a fatal error resulting in email delivery delays, or b) the
queue manager reporting the corruption and moving the message
to the corrupt queue for damaged messages.
However, a determined adversary could craft an email message
that would trigger the bug, and insert a content filter
destination or a redirect email address into its queue file.
Postfix would then deliver the message headers there, in
most cases without delivering the message body. With enough
experimentation, an attacker could make Postfix deliver
both the message headers and body.
The details of a successful attack depend on the Milter
implementation, and on the Postfix and Milter configuration
details; these can be determined remotely through
experimentation. Failed experiments may be detected when
the queue manager terminates with a fatal error, or when
the queue manager moves damaged files to the "corrupt" queue
as evidence.
Technical details: when Postfix executes a "replace body"
Milter request it will reuse queue file storage that was
used by the existing email message body. If the new body
is larger, Postfix will append body content to the end of
the queue file. The corruption happened when a Milter (for
example, MIMEDefang) made a request to replace the body of
a message with a new body that contained a copy of the
original body plus some new text, and the original body
contained a line longer than $line_length_limit bytes (for
example, an image encoded in base64 without hard or soft
line breaks). In queue files, Postfix stores a long text
line as multiple records with up to $line_length_limit bytes
each. Unfortunately, Postfix's "replace body" support did
not account for the additional queue file space needed to
store the second etc. record headers. And thus, the last
record(s) of a long text line could overwrite one or more
queue file records immediately after the space that was
previously occupied by the original message body.
Problem report by Benoît Panizzon.

View File

@@ -207,7 +207,7 @@ int cleanup_body_edit_write(CLEANUP_STATE *state, int rec_type,
/*
* Finally, output the queue file record.
*/
CLEANUP_OUT_BUF(state, REC_TYPE_NORM, buf);
CLEANUP_OUT_BUF(state, rec_type, buf);
curr_rp->write_offs = vstream_ftell(state->dst);
return (0);

View File

@@ -1836,7 +1836,8 @@ static const char *cleanup_del_rcpt(void *context, const char *ext_rcpt)
/* cleanup_repl_body - replace message body */
static const char *cleanup_repl_body(void *context, int cmd, VSTRING *buf)
static const char *cleanup_repl_body(void *context, int cmd, int rec_type,
VSTRING *buf)
{
const char *myname = "cleanup_repl_body";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
@@ -1848,7 +1849,7 @@ static const char *cleanup_repl_body(void *context, int cmd, VSTRING *buf)
*/
switch (cmd) {
case MILTER_BODY_LINE:
if (cleanup_body_edit_write(state, REC_TYPE_NORM, buf) < 0)
if (cleanup_body_edit_write(state, rec_type, buf) < 0)
return (cleanup_milter_error(state, errno));
break;
case MILTER_BODY_START:

View File

@@ -58,6 +58,8 @@ void config_known_tcp_ports(const char *source, const char *settings)
ARGV *association;
char **cpp;
clear_known_tcp_ports();
/*
* The settings is in the form of associations separated by comma. Split
* it into separate associations.

View File

@@ -237,6 +237,7 @@
#include <own_inet_addr.h>
#include <mail_params.h>
#include <compat_level.h>
#include <config_known_tcp_ports.h>
/*
* Special configuration variables.
@@ -922,6 +923,11 @@ void mail_params_init()
#endif
util_utf8_enable = var_smtputf8_enable;
/*
* Configure the known TCP port mappings.
*/
config_known_tcp_ports(VAR_KNOWN_TCP_PORTS, var_known_tcp_ports);
/*
* What protocols should we attempt to support? The result is stored in
* the global inet_proto_table variable.

View 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 "20210724"
#define MAIL_VERSION_NUMBER "3.6.2"
#define MAIL_RELEASE_DATE "20211107"
#define MAIL_VERSION_NUMBER "3.6.3"
#ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@@ -100,7 +100,7 @@ typedef const char *(*MILTER_DEL_HEADER_FN) (void *, ssize_t, const char *);
typedef const char *(*MILTER_EDIT_FROM_FN) (void *, const char *, const char *);
typedef const char *(*MILTER_EDIT_RCPT_FN) (void *, const char *);
typedef const char *(*MILTER_EDIT_RCPT_PAR_FN) (void *, const char *, const char *);
typedef const char *(*MILTER_EDIT_BODY_FN) (void *, int, VSTRING *);
typedef const char *(*MILTER_EDIT_BODY_FN) (void *, int, int, VSTRING *);
typedef struct MILTERS {
MILTER *milter_list; /* linked list of Milters */

View File

@@ -1147,10 +1147,12 @@ static const char *milter8_event(MILTER8 *milter, int event,
if (edit_resp == 0 && LEN(body_line_buf) > 0)
edit_resp = parent->repl_body(parent->chg_context,
MILTER_BODY_LINE,
REC_TYPE_NORM,
body_line_buf);
if (edit_resp == 0)
edit_resp = parent->repl_body(parent->chg_context,
MILTER_BODY_END,
/* unused*/ 0,
(VSTRING *) 0);
body_edit_lockout = 1;
vstring_free(body_line_buf);
@@ -1546,6 +1548,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
body_line_buf = vstring_alloc(var_line_limit);
edit_resp = parent->repl_body(parent->chg_context,
MILTER_BODY_START,
/* unused */ 0,
(VSTRING *) 0);
}
/* Extract lines from the on-the-wire CRLF format. */
@@ -1559,9 +1562,18 @@ static const char *milter8_event(MILTER8 *milter, int event,
LEN(body_line_buf) - 1);
edit_resp = parent->repl_body(parent->chg_context,
MILTER_BODY_LINE,
REC_TYPE_NORM,
body_line_buf);
VSTRING_RESET(body_line_buf);
} else {
/* Preserves \r if not followed by \n. */
if (LEN(body_line_buf) == var_line_limit) {
edit_resp = parent->repl_body(parent->chg_context,
MILTER_BODY_LINE,
REC_TYPE_CONT,
body_line_buf);
VSTRING_RESET(body_line_buf);
}
VSTRING_ADDCH(body_line_buf, ch);
}
}

View File

@@ -247,6 +247,7 @@ static const char *pcf_check_mydomainname(void)
static const char *pcf_mynetworks(void)
{
static const char *networks;
VSTRING *exp_buf;
const char *junk;
/*
@@ -255,10 +256,12 @@ static const char *pcf_mynetworks(void)
if (networks)
return (networks);
exp_buf = vstring_alloc(100);
if (var_inet_interfaces == 0) {
if ((pcf_cmd_mode & PCF_SHOW_DEFS)
|| (junk = mail_conf_lookup_eval(VAR_INET_INTERFACES)) == 0)
junk = pcf_expand_parameter_value((VSTRING *) 0, pcf_cmd_mode,
junk = pcf_expand_parameter_value(exp_buf, pcf_cmd_mode,
DEF_INET_INTERFACES,
(PCF_MASTER_ENT *) 0);
var_inet_interfaces = mystrdup(junk);
@@ -266,7 +269,7 @@ static const char *pcf_mynetworks(void)
if (var_mynetworks_style == 0) {
if ((pcf_cmd_mode & PCF_SHOW_DEFS)
|| (junk = mail_conf_lookup_eval(VAR_MYNETWORKS_STYLE)) == 0)
junk = pcf_expand_parameter_value((VSTRING *) 0, pcf_cmd_mode,
junk = pcf_expand_parameter_value(exp_buf, pcf_cmd_mode,
DEF_MYNETWORKS_STYLE,
(PCF_MASTER_ENT *) 0);
var_mynetworks_style = mystrdup(junk);
@@ -274,12 +277,13 @@ static const char *pcf_mynetworks(void)
if (var_inet_protocols == 0) {
if ((pcf_cmd_mode & PCF_SHOW_DEFS)
|| (junk = mail_conf_lookup_eval(VAR_INET_PROTOCOLS)) == 0)
junk = pcf_expand_parameter_value((VSTRING *) 0, pcf_cmd_mode,
junk = pcf_expand_parameter_value(exp_buf, pcf_cmd_mode,
DEF_INET_PROTOCOLS,
(PCF_MASTER_ENT *) 0);
var_inet_protocols = mystrdup(junk);
(void) inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
}
vstring_free(exp_buf);
return (networks = mystrdup(mynetworks()));
}

View File

@@ -1488,12 +1488,14 @@ static char *parse_destination(char *destination, char *def_service,
/*
* Convert service to port number, network byte order.
*/
service = (char *) filter_known_tcp_port(service);
if (alldig(service)) {
if ((port = atoi(service)) >= 65536 || port == 0)
msg_fatal("bad network port in destination: %s", destination);
msg_fatal("bad network port: %s for destination: %s",
service, destination);
*portp = htons(port);
} else {
if ((sp = getservbyname(filter_known_tcp_port(service), protocol)) != 0)
if ((sp = getservbyname(service, protocol)) != 0)
*portp = sp->s_port;
else if (strcmp(service, "smtp") == 0)
*portp = htons(25);

View File

@@ -356,12 +356,14 @@ static char *smtp_parse_destination(char *destination, char *def_service,
/*
* Convert service to port number, network byte order.
*/
service = (char *) filter_known_tcp_port(service);
if (alldig(service)) {
if ((port = atoi(service)) >= 65536 || port == 0)
msg_fatal("bad network port in destination: %s", destination);
msg_fatal("bad network port: %s for destination: %s",
service, destination);
*portp = htons(port);
} else {
if ((sp = getservbyname(filter_known_tcp_port(service), protocol)) == 0)
if ((sp = getservbyname(service, protocol)) == 0)
msg_fatal("unknown service: %s/%s", service, protocol);
*portp = sp->s_port;
}

View File

@@ -4374,8 +4374,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
}
} else if (is_map_command(state, name, CHECK_CCERT_ACL, &cpp)) {
status = check_ccert_access(state, *cpp, def_acl);
#ifdef USE_SASL_AUTH
} else if (is_map_command(state, name, CHECK_SASL_ACL, &cpp)) {
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable) {
if (state->sasl_username && state->sasl_username[0])
status = check_sasl_access(state, *cpp, def_acl);

View File

@@ -392,7 +392,7 @@ static void tlsa_carp(const char *s1, const char *s2, const char *s3,
vstring_sprintf(top, "...");
}
msg_warn("%s%s%s%s: %u %u %u %s%s%s", s1, s2, s3, s4, u, s, m, STR(top),
msg_warn("%s%s%s %s: %u %u %u %s%s%s", s1, s2, s3, s4, u, s, m, STR(top),
dlen > MAX_DUMP_BYTES ? "..." : "",
dlen > MAX_DUMP_BYTES ? STR(bot) : "");
}
@@ -807,13 +807,13 @@ int tls_dane_enable(TLS_SESS_STATE *TLScontext)
continue;
}
if (ret == 0) {
tlsa_carp(TLScontext->namaddr, ": ", "", "unusable TLSA RR",
tlsa_carp(TLScontext->namaddr, ":", "", "unusable TLSA RR",
tp->usage, tp->selector, tp->mtype, tp->data,
tp->length);
continue;
}
/* Internal problem in OpenSSL */
tlsa_carp(TLScontext->namaddr, ": ", "", "error loading trust settings",
tlsa_carp(TLScontext->namaddr, ":", "", "error loading trust settings",
tp->usage, tp->selector, tp->mtype, tp->data, tp->length);
tls_print_errors();
return (-1);

View File

@@ -883,7 +883,7 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
EVP_PKEY *peer_pkey = 0;
#ifndef OPENSSL_NO_EC
EC_KEY *eckey;
const EC_KEY *eckey;
#endif

View File

@@ -85,12 +85,13 @@ int find_inet_port(const char *service, const char *protocol)
struct servent *sp;
int port;
service = filter_known_tcp_port(service);
if (alldig(service) && (port = atoi(service)) != 0) {
if (port < 0 || port > 65535)
msg_fatal("bad port number: %s", service);
return (htons(port));
} else {
if ((sp = getservbyname(filter_known_tcp_port(service), protocol)) == 0)
if ((sp = getservbyname(service, protocol)) == 0)
msg_fatal("unknown service: %s/%s", service, protocol);
return (sp->s_port);
}

View File

@@ -271,6 +271,7 @@ static int find_service(const char *service, int socktype)
const char *proto;
unsigned port;
service = filter_known_tcp_port(service);
if (alldig(service)) {
port = atoi(service);
return (port < 65536 ? htons(port) : -1);
@@ -282,7 +283,7 @@ static int find_service(const char *service, int socktype)
} else {
return (-1);
}
if ((sp = getservbyname(filter_known_tcp_port(service), proto)) != 0) {
if ((sp = getservbyname(service, proto)) != 0) {
return (sp->s_port);
} else {
return (-1);
@@ -445,7 +446,12 @@ int hostname_to_sockaddr_pf(const char *hostname, int pf,
}
#endif
}
err = getaddrinfo(hostname, filter_known_tcp_port(service), &hints, res);
if (service) {
service = filter_known_tcp_port(service);
if (alldig(service))
hints.ai_flags |= AI_NUMERICSERV;
}
err = getaddrinfo(hostname, service, &hints, res);
#if defined(BROKEN_AI_NULL_SERVICE)
if (service == 0 && err == 0) {
struct addrinfo *r;
@@ -561,7 +567,12 @@ int hostaddr_to_sockaddr(const char *hostaddr, const char *service,
}
#endif
}
err = getaddrinfo(hostaddr, filter_known_tcp_port(service), &hints, res);
if (service) {
service = filter_known_tcp_port(service);
if (alldig(service))
hints.ai_flags |= AI_NUMERICSERV;
}
err = getaddrinfo(hostaddr, service, &hints, res);
#if defined(BROKEN_AI_NULL_SERVICE)
if (service == 0 && err == 0) {
struct addrinfo *r;