2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 21:55:20 +00:00

postfix-3.6.8

This commit is contained in:
Wietse Venema
2023-01-21 00:00:00 -05:00
committed by Viktor Dukhovni
parent 80207ab39e
commit b30b024aa3
13 changed files with 176 additions and 42 deletions

View File

@@ -25795,3 +25795,65 @@ Apologies for any names omitted.
Cleanup: Postfix 3.6.6 introduced a missing msg_panic()
argument (in code that never executes). File:
cleanup/cleanup_milter.c.
20221125
Bugfix (introduced: Postfix 3.6): the Postfix TLS client
logged a TLS connection as 'Untrusted' instead of 'Trusted',
when a matching DANE record was found but the MX RRset was
insecure. Fix by Viktor Dukhovni. File: tls/tls_client.c.
20221128
Bugfix (introduced: Postfix 2.2): the smtpd_proxy_client
code mis-parsed the last XFORWARD attribute name in the
SMTP server's EHLO response. The result was that the
smtpd_proxy_client code failed to forward the IDENT attribute.
Fix by Andreas Weigel. File: smtpd/smtpd_proxy.c.
20221201
Portability: LINUX6 support. Files: makedefs, util/sys_defs.h.
20221207
Workaround: OpenSSL 3.x EVP_get_digestbyname() can return
lazily bound handles that may fail to work when one attempts
to use them, because no provider search happens until one
constructs an actual operation context. In sufficiently
hostile configurations, Postfix could mistakenly believe
that an algorithm is available, when in fact it is not. A
similar workaround may be needed for EVP_get_cipherbyname().
Fix by Viktor Dukhovni. Files: tls/tls.h, tls/tls_dane.c,
tls/tls_fprint.c, tls/tls_misc.c.
Bugfix (introduced: Postfix 2.11): the checkok() macro in
tls/tls_fprint.c evaluated its argument unconditionally;
it should evaluate the argument only if there was no prior
error. Found during code review. File: tls/tls_fprint.c.
20221215
Foolproofing: postscreen segfault with postscreen_dnsbl_threshold
< 1. It should reject such input with a fatal error instead.
Discovered by Benny Pedersen. File: postscreen/postscreen.c.
20230103
Bugfix (introduced: Postfix 2.7): the verify daemon logged
a garbled cache name when terminating a cache scan in
progress. Reported by Phil Biggs, fix by Viktor Dukhovni.
File: util/dict_cache.c.
Bitrot: fixes for linker warnings from newer Darwin (MacOS)
versions. Viktor Dukhovni. File: makedefs.
20230115
Workaround for a breaking change in OpenSSL 3: always turn
on SSL_OP_IGNORE_UNEXPECTED_EOF, to avoid warning messages
and missed opportunities for TLS session reuse. This is
safe because the SMTP protocol implements application-level
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.

View File

@@ -568,7 +568,7 @@ EOF
: ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
: ${PLUGIN_LD="${CC-gcc} -shared"}
;;
Linux.[345].*) SYSTYPE=LINUX$RELEASE_MAJOR
Linux.[3456].*) SYSTYPE=LINUX$RELEASE_MAJOR
case "$CCARGS" in
*-DNO_DB*) ;;
*-DHAS_DB*) ;;
@@ -710,6 +710,12 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543
?.*|10.*) ;;
*) SYSLIBS="$SYSLIBS -lresolv";;
esac
# Darwin 21 linker without additional coaxing complains about
# -Wl,-undefined,dynamic_lookup
case $RELEASE in
2[1-9].*|[3-9]?.*) NOFIXUP="-Wl,-no_fixup_chains ";;
*) NOFIXUP="";;
esac
# kqueue and/or poll are broken in MacOS X 10.5 (Darwin 9).
# kqueue works in Mac OS X 10.8 (Darwin 12).
case $RELEASE in
@@ -717,12 +723,12 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543
esac
: ${SHLIB_CFLAGS=-fPIC}
: ${SHLIB_SUFFIX=.dylib}
: ${SHLIB_LD='cc -shared -Wl,-flat_namespace -Wl,-undefined,dynamic_lookup -Wl,-install_name,@rpath/${LIB}'}
: ${SHLIB_LD="cc -shared -Wl,-flat_namespace ${NOFIXUP}-Wl,-undefined,dynamic_lookup "'-Wl,-install_name,@rpath/${LIB}'}
: ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'}
# In MacOS/X 10.11.x /bin/sh unsets DYLD_LIBRARY_PATH, so we
# have export it into postfix-install indirectly!
: ${SHLIB_ENV="DYLD_LIBRARY_PATH=`pwd`/lib SHLIB_ENV_VAR=DYLD_LIBRARY_PATH SHLIB_ENV_VAL=`pwd`/lib"}
: ${PLUGIN_LD='cc -shared -Wl,-flat_namespace -Wl,-undefined,dynamic_lookup'}
: ${PLUGIN_LD="cc -shared -Wl,-flat_namespace ${NOFIXUP}-Wl,-undefined,dynamic_lookup"}
;;
dcosx.1*) SYSTYPE=DCOSX1
RANLIB=echo

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 "20221007"
#define MAIL_VERSION_NUMBER "3.6.7"
#define MAIL_RELEASE_DATE "20230121"
#define MAIL_VERSION_NUMBER "3.6.8"
#ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@@ -1174,7 +1174,7 @@ int main(int argc, char **argv)
0,
};
static const CONFIG_INT_TABLE int_table[] = {
VAR_PSC_DNSBL_THRESH, DEF_PSC_DNSBL_THRESH, &var_psc_dnsbl_thresh, 0, 0,
VAR_PSC_DNSBL_THRESH, DEF_PSC_DNSBL_THRESH, &var_psc_dnsbl_thresh, 1, 0,
VAR_PSC_CMD_COUNT, DEF_PSC_CMD_COUNT, &var_psc_cmd_count, 1, 0,
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
0,

View File

@@ -388,7 +388,7 @@ static int smtpd_proxy_connect(SMTPD_STATE *state)
*/
server_xforward_features = 0;
lines = STR(proxy->reply);
while ((words = mystrtok(&lines, "\n")) != 0) {
while ((words = mystrtok(&lines, "\r\n")) != 0) {
if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t")) != 0) {
if (strcasecmp(word, XFORWARD_CMD) == 0)
while ((word = mystrtok(&words, " \t")) != 0)

View File

@@ -367,6 +367,13 @@ extern void tls_param_init(void);
#define SSL_OP_NO_TLSv1_3 0L /* Noop */
#endif
/*
* Always used when defined, SMTP has no truncation attacks.
*/
#ifndef SSL_OP_IGNORE_UNEXPECTED_EOF
#define SSL_OP_IGNORE_UNEXPECTED_EOF 0L
#endif
#define TLS_KNOWN_PROTOCOLS \
( TLS_PROTOCOL_SSLv2 | TLS_PROTOCOL_SSLv3 | TLS_PROTOCOL_TLSv1 \
| TLS_PROTOCOL_TLSv1_1 | TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3 )
@@ -383,7 +390,8 @@ extern void tls_param_init(void);
* just exposed via hex codes or named elements of tls_ssl_options.
*/
#define TLS_SSL_OP_MANAGED_BITS \
(SSL_OP_CIPHER_SERVER_PREFERENCE | TLS_SSL_OP_PROTOMASK(~0))
(SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_IGNORE_UNEXPECTED_EOF | \
TLS_SSL_OP_PROTOMASK(~0))
extern int tls_proto_mask_lims(const char *, int *, int *);
@@ -627,6 +635,7 @@ extern TLS_TLSA *tlsa_prepend(TLS_TLSA *, uint8_t, uint8_t, uint8_t,
/*
* tls_fprint.c
*/
extern const EVP_MD *tls_digest_byname(const char *, EVP_MD_CTX **);
extern char *tls_digest_encode(const unsigned char *, int);
extern char *tls_cert_fprint(X509 *, const char *);
extern char *tls_pkey_fprint(X509 *, const char *);

View File

@@ -324,6 +324,7 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
* checks are now performed internally in OpenSSL.
*/
if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) {
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
if (TLScontext->must_fail) {
msg_panic("%s: cert valid despite trust init failure",
TLScontext->namaddr);
@@ -352,8 +353,7 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
TLScontext->namaddr, peername);
tls_dane_log(TLScontext);
}
} else
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
}
}
/*
@@ -713,6 +713,15 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
}
tls_dane_digest_init(client_ctx, fpt_alg);
/*
* Presently we use TLS only with SMTP where truncation attacks are not
* possible as a result of application framing. If we ever use TLS in
* some other application protocol where truncation could be relevant,
* we'd need to disable truncation detection conditionally, or explicitly
* clear the option in that code path.
*/
off |= SSL_OP_IGNORE_UNEXPECTED_EOF;
/*
* Protocol selection is destination dependent, so we delay the protocol
* selection options to the per-session SSL object.

View File

@@ -823,7 +823,7 @@ int tls_dane_enable(TLS_SESS_STATE *TLScontext)
/* tls_dane_digest_init - configure supported DANE digests */
void tls_dane_digest_init(SSL_CTX *ctx, const EVP_MD * fpt_alg)
void tls_dane_digest_init(SSL_CTX *ctx, const EVP_MD *fpt_alg)
{
dane_mtype mtypes[256];
char *cp;
@@ -930,7 +930,7 @@ void tls_dane_digest_init(SSL_CTX *ctx, const EVP_MD * fpt_alg)
}
mtypes[codepoint].ord = ++ord;
if ((mtypes[codepoint].alg = EVP_get_digestbyname(algname)) == 0) {
if ((mtypes[codepoint].alg = tls_digest_byname(algname, NULL)) == 0) {
msg_warn("%s: digest algorithm \"%s\"(%d) unknown",
VAR_TLS_DANE_DIGESTS, algname, codepoint);
continue;
@@ -1132,11 +1132,11 @@ static void load_tlsa_args(SSL *ssl, char *argv[])
case 0:
break;
case 1:
if ((md = EVP_get_digestbyname(LN_sha256)) == 0)
if ((md = tls_digest_byname(LN_sha256, NULL)) == 0)
msg_fatal("Digest %s not found", LN_sha256);
break;
case 2:
if ((md = EVP_get_digestbyname(LN_sha512)) == 0)
if ((md = tls_digest_byname(LN_sha512, NULL)) == 0)
msg_fatal("Digest %s not found", LN_sha512);
break;
default:

View File

@@ -6,6 +6,10 @@
/* SYNOPSIS
/* #include <tls.h>
/*
/* EVP_MD *tls_digest_byname(const char *mdalg, EVP_MD_CTX **mdctxPtr)
/* const char *mdalg;
/* EVP_MD_CTX **mdctxPtr;
/*
/* char *tls_serverid_digest(TLScontext, props, ciphers)
/* TLS_SESS_STATE *TLScontext;
/* const TLS_CLIENT_START_PROPS *props;
@@ -23,6 +27,13 @@
/* X509 *peercert;
/* const char *mdalg;
/* DESCRIPTION
/* tls_digest_byname() constructs, and optionally returns, an EVP_MD_CTX
/* handle for performing digest operations with the algorithm named by the
/* mdalg parameter. The return value is non-null on success, and holds a
/* digest algorithm handle. If the mdctxPtr argument is non-null the
/* created context is returned to the caller, who is then responsible for
/* deleting it by calling EVP_MD_ctx_free() once it is no longer needed.
/*
/* tls_digest_encode() converts a binary message digest to a hex ASCII
/* format with ':' separators between each pair of hex digits.
/* The return value is dynamically allocated with mymalloc(),
@@ -50,6 +61,8 @@
/* free it with myfree().
/*
/* Arguments:
/* .IP mdalg
/* A digest algorithm name, such as "sha256".
/* .IP peercert
/* Server or client X.509 certificate.
/* .IP md_buf
@@ -60,6 +73,9 @@
/* Name of a message digest algorithm suitable for computing secure
/* (1st pre-image resistant) message digests of certificates. For now,
/* md5, sha1, or member of SHA-2 family if supported by OpenSSL.
/* .IP mdctxPtr
/* Pointer to an (EVP_MD_CTX *) handle, or NULL if only probing for
/* algorithm support without immediate use in mind.
/* .IP buf
/* Input data for the message digest algorithm mdalg.
/* .IP len
@@ -114,7 +130,7 @@
static const char hexcodes[] = "0123456789ABCDEF";
#define checkok(ret) (ok &= ((ret) ? 1 : 0))
#define checkok(stillok) (ok = ok && (stillok))
#define digest_object(p) digest_data((unsigned char *)(p), sizeof(*(p)))
#define digest_data(p, l) checkok(digest_bytes(mdctx, (p), (l)))
#define digest_string(s) checkok(digest_chars(mdctx, (s)))
@@ -182,6 +198,44 @@ static int tls_digest_tlsa(EVP_MD_CTX *mdctx, TLS_TLSA *tlsa)
return (ok);
}
/* tls_digest_byname - test availability or prepare to use digest */
const EVP_MD *tls_digest_byname(const char *mdalg, EVP_MD_CTX **mdctxPtr)
{
const EVP_MD *md;
EVP_MD_CTX *mdctx = NULL;
int ok = 1;
/*
* In OpenSSL 3.0, because of dynamically variable algorithm providers,
* there is a time-of-check/time-of-use issue that means that abstract
* algorithm handles returned by EVP_get_digestbyname() can (and not
* infrequently do) return ultimately unusable algorithms, to check for
* actual availability, one needs to use the new EVP_MD_fetch() API, or
* indirectly check usability by creating a concrete context. We take the
* latter approach here (works for 1.1.1 without #ifdef).
*
* Note that EVP_MD_CTX_{create,destroy} were renamed to, respectively,
* EVP_MD_CTX_{new,free} in OpenSSL 1.1.0.
*/
checkok(md = EVP_get_digestbyname(mdalg));
/*
* Sanity check: Newer shared libraries could (hypothetical ABI break)
* allow larger digests, we avoid such poison algorithms.
*/
checkok(EVP_MD_size(md) <= EVP_MAX_MD_SIZE);
checkok(mdctx = EVP_MD_CTX_new());
checkok(EVP_DigestInit_ex(mdctx, md, NULL));
if (ok && mdctxPtr != 0)
*mdctxPtr = mdctx;
else
EVP_MD_CTX_free(mdctx);
return (ok ? md : 0);
}
/* tls_serverid_digest - suffix props->serverid with parameter digest */
char *tls_serverid_digest(TLS_SESS_STATE *TLScontext,
@@ -189,7 +243,6 @@ char *tls_serverid_digest(TLS_SESS_STATE *TLScontext,
const char *ciphers)
{
EVP_MD_CTX *mdctx;
const EVP_MD *md;
const char *mdalg;
unsigned char md_buf[EVP_MAX_MD_SIZE];
unsigned int md_len;
@@ -205,17 +258,17 @@ char *tls_serverid_digest(TLS_SESS_STATE *TLScontext,
* default digest, but DANE requires sha256 and sha512, so if we must
* fall back to our default digest, DANE support won't be available. We
* panic if the fallback algorithm is not available, as it was verified
* available in tls_client_init() and must not simply vanish.
* available in tls_client_init() and must not simply vanish. Our
* provider set is not expected to change once the OpenSSL library is
* initialized.
*/
if ((md = EVP_get_digestbyname(mdalg = "sha256")) == 0
&& (md = EVP_get_digestbyname(mdalg = props->mdalg)) == 0)
msg_panic("digest algorithm \"%s\" not found", mdalg);
if (tls_digest_byname(mdalg = LN_sha256, &mdctx) == 0
&& tls_digest_byname(mdalg = props->mdalg, &mdctx) == 0)
msg_panic("digest algorithm \"%s\" not found", props->mdalg);
/* Salt the session lookup key with the OpenSSL runtime version. */
sslversion = OpenSSL_version_num();
mdctx = EVP_MD_CTX_create();
checkok(EVP_DigestInit_ex(mdctx, md, NULL));
digest_string(props->helo ? props->helo : "");
digest_object(&sslversion);
digest_string(props->protocols);
@@ -306,18 +359,15 @@ char *tls_digest_encode(const unsigned char *md_buf, int md_len)
static char *tls_data_fprint(const unsigned char *buf, int len, const char *mdalg)
{
EVP_MD_CTX *mdctx;
const EVP_MD *md;
EVP_MD_CTX *mdctx = NULL;
unsigned char md_buf[EVP_MAX_MD_SIZE];
unsigned int md_len;
int ok = 1;
/* Previously available in "init" routine. */
if ((md = EVP_get_digestbyname(mdalg)) == 0)
if (tls_digest_byname(mdalg, &mdctx) == 0)
msg_panic("digest algorithm \"%s\" not found", mdalg);
mdctx = EVP_MD_CTX_create();
checkok(EVP_DigestInit_ex(mdctx, md, NULL));
digest_data(buf, len);
checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
EVP_MD_CTX_destroy(mdctx);

View File

@@ -1513,25 +1513,13 @@ long tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi,
const EVP_MD *tls_validate_digest(const char *dgst)
{
const EVP_MD *md_alg;
unsigned int md_len;
/*
* If the administrator specifies an unsupported digest algorithm, fail
* now, rather than in the middle of a TLS handshake.
*/
if ((md_alg = EVP_get_digestbyname(dgst)) == 0) {
if ((md_alg = tls_digest_byname(dgst, NULL)) == 0)
msg_warn("Digest algorithm \"%s\" not found", dgst);
return (0);
}
/*
* Sanity check: Newer shared libraries may use larger digests.
*/
if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
msg_warn("Digest algorithm \"%s\" output size %u too large",
dgst, md_len);
return (0);
}
return md_alg;
}

View File

@@ -461,6 +461,15 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
if (scache_timeout <= 0)
cachable = 0;
/*
* Presently we use TLS only with SMTP where truncation attacks are not
* possible as a result of application framing. If we ever use TLS in
* some other application protocol where truncation could be relevant,
* we'd need to disable truncation detection conditionally, or explicitly
* clear the option in that code path.
*/
off |= SSL_OP_IGNORE_UNEXPECTED_EOF;
/*
* Protocol work-arounds, OpenSSL version dependent.
*/

View File

@@ -659,8 +659,8 @@ void dict_cache_close(DICT_CACHE *cp)
/*
* Destroy the DICT_CACHE object.
*/
myfree(cp->name);
dict_cache_control(cp, DICT_CACHE_CTL_INTERVAL, 0, DICT_CACHE_CTL_END);
myfree(cp->name);
dict_close(cp->db);
if (cp->saved_curr_key)
myfree(cp->saved_curr_key);

View File

@@ -749,7 +749,8 @@ extern int initgroups(const char *, int);
/*
* LINUX.
*/
#if defined(LINUX2) || defined(LINUX3) || defined(LINUX4) || defined(LINUX5)
#if defined(LINUX2) || defined(LINUX3) || defined(LINUX4) || defined(LINUX5) \
|| defined(LINUX6)
#define SUPPORTED
#define UINT32_TYPE unsigned int
#define UINT16_TYPE unsigned short