2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 13:18:12 +00:00

postfix-2.3.8-RC1

This commit is contained in:
Wietse Venema 2007-02-25 00:00:00 -05:00 committed by Viktor Dukhovni
parent 33178d66c7
commit 145cfd2e62
11 changed files with 224 additions and 41 deletions

View File

@ -12928,16 +12928,36 @@ Apologies for any names omitted.
Workaround: don't insert empty-line header/body separator
into malformed MIME attachments, to avoid breaking digital
signatures. This change introduces ambiguity. Postfix still
treats the remainder of the attachment as body content;
header_checks rules will not detect forbidden MIME types
inside a message/rfc822 attachment. With the empty-line
header/body separator no longer inserted by Postfix, other
software may process the malformed attachment differently,
and thus may become exposed to forbidden MIME types. This
is back-ported from Postfix 2.4. File: global/mime_state.c.
signatures. This change introduces ambiguity. As before,
Postfix treats the remainder of the attachment as body
content, and header_checks rules will not detect forbidden
MIME types inside a malformed message/rfc822 attachment.
With the empty-line header/body separator no longer inserted
by Postfix, other software may process the malformed
attachment differently, and thus may now become exposed to
forbidden MIME types. This is back-ported from Postfix
2.4. File: global/mime_state.c.
20070118
Bugfix: match lists didn't implement ![ipv6address]. Problem
reported by Paulo Pacheco. File: util/match_list.c.
20070224
Workaround: GNU POP3D creates a new mailbox and deletes the
old one. Postfix now backs off and retries delivery later,
instead of appending mail to a deleted file. File:
global/mbox_open.c.
20070225
Workaround: Disable SSL/TLS ciphers when the underlying
symmetric algorithm is not available in the OpenSSL crypto
library at the required bit strength. Problem observed with
SunOS 5.10's bundled OpenSSL 0.9.7 and AES 256. Also possible
with OpenSSL 0.9.8 and CAMELLIA 256. Root cause fixed in
upcoming OpenSSL 0.9.7m, 0.9.8e and 0.9.9 releases. Victor
Duchovni, Morgan Stanley. Files: src/smtp/smtp_proto.c,
src/smtpd/smtpd.c, src/tls/tls.h, src/tls/tls_client.c,
src/tls/tls_misc.c and src/tls/tls_server.c.

View File

@ -17,13 +17,15 @@ Incompatible changes with Postfix 2.3.7
Postfix no longer inserts an empty-line header/body separator into
malformed MIME attachments, to avoid breaking digital signatures.
This change introduces ambiguity. Postfix still treats the remainder
of the attachment as body content; header_checks rules will therefore
not detect forbidden MIME types inside a message/rfc822 attachment.
This change introduces ambiguity. As before, Postfix treats the
remainder of the attachment as body content, and header_checks rules
will not detect forbidden MIME types inside a malformed message/rfc822
attachment.
With the empty-line header/body separator no longer inserted by
Postfix, other software may process the malformed attachment
differently, and thus may become exposed to forbidden MIME types.
differently, and thus may now become exposed to forbidden MIME types
that they would not have been exposed to earlier.
Incompatible changes with Postfix 2.3.6
---------------------------------------

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 "20070130"
#define MAIL_VERSION_NUMBER "2.3.7"
#define MAIL_RELEASE_DATE "20070225"
#define MAIL_VERSION_NUMBER "2.3.8-RC1"
#ifdef SNAPSHOT
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@ -184,6 +184,26 @@ MBOX *mbox_open(const char *path, int flags, mode_t mode, struct stat * st,
return (0);
}
}
/*
* Sanity check: reportedly, GNU POP3D creates a new mailbox file and
* deletes the old one. This does not play well with software that opens
* the mailbox first and then locks it.
*
* To detect that GNU POP3D deletes the mailbox file we look at the target
* file hard-link count. Note that safe_open() guarantees a hard-link
* count of 1, so any change in this count is a sign of trouble.
*/
if (S_ISREG(st->st_mode)
&& (fstat(vstream_fileno(fp), st) < 0 || st->st_nlink != 1)) {
vstring_sprintf(why->reason, "target file status changed unexpectedly");
dsb_status(why, mbox_dsn(EAGAIN, def_dsn));
msg_warn("%s: file status changed unexpectedly", path);
if (locked & MBOX_DOT_LOCK)
dot_unlockfile(path);
vstream_fclose(fp);
return (0);
}
mp = (MBOX *) mymalloc(sizeof(*mp));
mp->path = mystrdup(path);
mp->fp = fp;

View File

@ -725,7 +725,7 @@ static int smtp_start_tls(SMTP_STATE *state)
vstring_sprintf_append(serverid, "&p=%s",
tls_protocol_names(VAR_SMTP_TLS_MAND_PROTO,
session->tls_protocols));
if (session->tls_level >= TLS_LEV_ENCRYPT && session->tls_cipherlist)
if (session->tls_level >= TLS_LEV_ENCRYPT)
vstring_sprintf_append(serverid, "&c=%s", session->tls_cipherlist);
tls_props.ctx = smtp_tls_ctx;

View File

@ -4293,6 +4293,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
enforce_tls ? var_smtpd_tls_mand_excl :
TLS_END_EXCLUDE,
TLS_END_EXCLUDE);
if (props.cipherlist == 0)
msg_panic("NULL export cipherlist");
}
if (havecert || oknocert)
smtpd_tls_ctx = tls_server_init(&props);

View File

@ -151,6 +151,7 @@ tls_mgr.o: ../../include/vstream.h
tls_mgr.o: ../../include/vstring.h
tls_mgr.o: tls_mgr.c
tls_mgr.o: tls_mgr.h
tls_misc.o: ../../include/argv.h
tls_misc.o: ../../include/msg.h
tls_misc.o: ../../include/mymalloc.h
tls_misc.o: ../../include/name_code.h

View File

@ -130,6 +130,7 @@ extern NAME_CODE tls_cipher_level_table[];
#define TLS_END_EXCLUDE ((char *)0)
extern const char *tls_cipher_list(int,...);
extern const char *tls_set_cipher_list(SSL_CTX *, const char *);
/*
* tls_client.c

View File

@ -626,6 +626,15 @@ TLScontext_t *tls_client_start(const tls_client_start_props *props)
if (props->log_level >= 1)
msg_info("setting up TLS connection to %s", props->host);
/*
* Before we create an SSL, update the SSL_CTX cipherlist if necessary.
*/
if (tls_set_cipher_list(props->ctx, props->cipherlist) == 0) {
msg_warn("Invalid cipherlist \"%s\": aborting TLS session",
props->cipherlist);
return (0);
}
/*
* Allocate a new TLScontext for the new connection and get an SSL
* structure. Add the location of TLScontext to the SSL to later retrieve
@ -710,24 +719,13 @@ TLScontext_t *tls_client_start(const tls_client_start_props *props)
}
/*
* Per session cipher selection for sessions with mandatory encryption
* Try to load an existing session from the TLS session cache.
*
* By the time a TLS client is negotiating ciphers it has already offered to
* re-use a session, it is too late to renege on the offer. So we must
* not attempt to re-use sessions whose ciphers are too weak. We expect
* the caller to salt the session lookup key with the cipher list, so
* that sessions found in the cache are always acceptable.
*/
if (props->cipherlist != 0)
if (SSL_set_cipher_list(TLScontext->con, props->cipherlist) == 0) {
msg_warn("Could not set cipherlist: %s", props->cipherlist);
tls_print_errors();
tls_free_context(TLScontext);
return (0);
}
/*
* Try to load an existing session from the TLS session cache.
*
* XXX To avoid memory leaks we must always call SSL_SESSION_free() after
* calling SSL_set_session(), regardless of whether or not the session

View File

@ -18,6 +18,10 @@
/*
/* long tls_bug_bits()
/*
/* const char *tls_set_cipher_list(ssl_ctx, cipher_list)
/* SSL_CTX *ssl_ctx;
/* char *cipher_list;
/*
/* const char *tls_cipher_list(cipher_level, ...)
/* int cipher_level;
/*
@ -53,6 +57,11 @@
/* for the run-time library. Some of the bug work-arounds are
/* not appropriate for some library versions.
/*
/* tls_set_cipher_list() updates the cipher list of the specified SSL
/* context. Returns the new cipherlist on success, otherwise logs a
/* suitable warning and returns 0. The storage for the return value
/* is overwritted with each call.
/*
/* tls_cipher_list() generates a cipher list from the specified
/* grade, minus any ciphers specified via a null-terminated
/* list of string-valued exclusions. The result is overwritten
@ -104,6 +113,7 @@
#include <mymalloc.h>
#include <vstring.h>
#include <stringops.h>
#include <argv.h>
/* TLS library. */
@ -162,6 +172,134 @@ typedef struct {
int status;
} TLS_VINFO;
/*
* OpenSSL adopted the cipher selection patch, so we don't expect any more
* broken ciphers other than AES and CAMELLIA.
*/
typedef struct {
char *ssl_name;
int alg_bits;
char *evp_name;
} cipher_probe_t;
static cipher_probe_t cipher_probes[] = {
"AES", 256, "AES-256-CBC",
"CAMELLIA", 256, "CAMELLIA-256-CBC",
0, 0, 0,
};
/* tls_exclude_missing - Append exclusions for missing ciphers */
static void tls_exclude_missing(SSL_CTX *ctx, VSTRING *buf)
{
const char *myname = "tls_exclude_missing";
static ARGV *exclude; /* Cached */
SSL *s = 0;
STACK_OF(SSL_CIPHER) * ciphers;
SSL_CIPHER *c;
cipher_probe_t *probe;
int alg_bits;
int num;
int i;
/*
* Process a list of probes which specify:
*
* An SSL cipher-suite name for a family of ciphers that use the same
* symmetric algorithm at two or more key sizes, typically 128/256 bits.
*
* The key size (typically 256) that OpenSSL fails check, and assumes is
* available when another key size (typically 128) is usable.
*
* The OpenSSL name of the symmetric algorithm associated with the SSL
* cipher-suite. Typically, this is MUMBLE-256-CBC, where "MUMBLE" is the
* name of the SSL cipher-suite that use the MUMBLE symmetric algorithm.
* On systems that support the required encryption algorithm, the name is
* listed in the output of "openssl list-cipher-algorithms".
*
* When an encryption algorithm is not available at the given key size but
* the corresponding OpenSSL cipher-suite contains ciphers that have have
* this key size, the problem ciphers are explicitly disabled in Postfix.
* The list is cached in the static "exclude" array.
*/
if (exclude == 0) {
exclude = argv_alloc(1);
/*
* Iterate over the probe list
*/
for (probe = cipher_probes; probe->ssl_name; ++probe) {
/* No exclusions if evp_name is a valid algorithm */
if (EVP_get_cipherbyname(probe->evp_name))
continue;
/*
* Sadly there is no SSL_CTX_get_ciphers() interface, so we are
* forced to allocate and free an SSL object. Fatal error if we
* can't allocate the SSL object.
*/
ERR_clear_error();
if (s == 0 && (s = SSL_new(ctx)) == 0) {
tls_print_errors();
msg_fatal("%s: error allocating SSL object", myname);
}
/*
* Cipher is not supported by libcrypto, nothing to do if also
* not supported by libssl. Flush the OpenSSL error stack.
*
* XXX: There may be additional places in pre-existing code where
* SSL errors are generated and ignored, that require a similar
* "flush". Better yet, is to always flush before calls that run
* tls_print_errors() on failure.
*
* Contrary to documentation, on SunOS 5.10 SSL_set_cipher_list()
* returns success with no ciphers selected, when this happens
* SSL_get_ciphers() produces a stack with 0 elements!
*/
if (SSL_set_cipher_list(s, probe->ssl_name) == 0
|| (ciphers = SSL_get_ciphers(s)) == 0
|| (num = sk_SSL_CIPHER_num(ciphers)) == 0) {
ERR_clear_error(); /* flush any generated errors */
continue;
}
for (i = 0; i < num; ++i) {
c = sk_SSL_CIPHER_value(ciphers, i);
(void) SSL_CIPHER_get_bits(c, &alg_bits);
if (alg_bits == probe->alg_bits)
argv_add(exclude, SSL_CIPHER_get_name(c), ARGV_END);
}
}
if (s != 0)
SSL_free(s);
}
for (i = 0; i < exclude->argc; ++i)
vstring_sprintf_append(buf, ":!%s", exclude->argv[i]);
}
/* tls_set_cipher_list - Set SSL_CTX cipher list */
const char *tls_set_cipher_list(SSL_CTX *ssl_ctx, const char *spec)
{
static VSTRING *buf;
const char *ex_spec;
if (buf == 0)
buf = vstring_alloc(10);
vstring_strcpy(buf, spec);
tls_exclude_missing(ssl_ctx, buf);
ex_spec = vstring_str(buf);
ERR_clear_error();
if (SSL_CTX_set_cipher_list(ssl_ctx, ex_spec) != 0)
return (ex_spec);
tls_print_errors();
return (0);
}
/* tls_cipher_list - Cipherlist for given grade, less exclusions */
const char *tls_cipher_list(int cipher_level,...)
@ -196,9 +334,16 @@ const char *tls_cipher_list(int cipher_level,...)
case TLS_CIPHER_NONE:
return 0;
default:
/*
* The caller MUST provide a valid cipher grade
*/
msg_panic("%s: invalid cipher grade: %d", myname, cipher_level);
}
/*
* The base lists for each grade can't be empty.
*/
if (VSTRING_LEN(buf) == 0)
msg_panic("%s: empty cipherlist", myname);
@ -207,22 +352,16 @@ const char *tls_cipher_list(int cipher_level,...)
if (*exclude == '\0')
continue;
save = cp = mystrdup(exclude);
while ((tok = mystrtok(&cp, "\t\n\r ,")) != 0) {
while ((tok = mystrtok(&cp, "\t\n\r ,:")) != 0) {
/*
* Can't exclude ciphers that start with modifiers, or
* multi-element (":" separated) ciphers.
* Can't exclude ciphers that start with modifiers.
*/
if (strchr("!+-@", *tok)) {
msg_warn("%s: can't exclude '!+-@' modifiers, '%s' ignored",
myname, tok);
continue;
}
if (strchr(tok, ':')) {
msg_warn("%s: can't exclude compound ciphers, '%s' ignored",
myname, tok);
continue;
}
vstring_sprintf_append(buf, ":!%s", tok);
}
myfree(save);

View File

@ -328,11 +328,11 @@ SSL_CTX *tls_server_init(const tls_server_props *props)
/*
* Override the default cipher list with our own list.
*/
if (*props->cipherlist != 0)
if (SSL_CTX_set_cipher_list(server_ctx, props->cipherlist) == 0) {
tls_print_errors();
SSL_CTX_free(server_ctx); /* 200411 */
return (0);
if (tls_set_cipher_list(server_ctx, props->cipherlist) == 0) {
SSL_CTX_free(server_ctx);
msg_warn("Invalid cipherlist \"%s\": disabling TLS support",
props->cipherlist);
return (0); /* Already logged */
}
/*