diff --git a/postfix/.indent.pro b/postfix/.indent.pro index dd38a0277..86d18924c 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -254,7 +254,6 @@ -TXSASL_SERVER -TXSASL_SERVER_IMPL -TXSASL_SERVER_IMPL_INFO --Tcipher_probe -Tregex_t -Tregmatch_t -Tsasl_conn_t diff --git a/postfix/HISTORY b/postfix/HISTORY index 4aee528f3..6168ce6ca 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -12926,17 +12926,18 @@ Apologies for any names omitted. frame upon configuration error or table lookup error. Victor Duchovni. Files: smtpd/smtpd_check.c. - Workaround: don't insert header/body blank line separator + Workaround: don't insert empty-line header/body separator into malformed MIME attachments, to avoid breaking digital - signatures. File: global/mime_state.c. + 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. 20070118 Bugfix: match lists didn't implement ![ipv6address]. Problem reported by Paulo Pacheco. File: util/match_list.c. - -200070129 - - Workaround: OpenSSL falsely concludes that AES256 support - is present when only AES128 is available. Code by Victor - Duchovni. File: tls/tls_misc.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 6a0f931f6..929e14e5b 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -11,6 +11,20 @@ instead, a new snapshot is released. The mail_release_date configuration parameter (format: yyyymmdd) specifies the release date of a stable release or snapshot release. +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. + +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. + Incompatible changes with Postfix 2.3.6 --------------------------------------- diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 887cc48be..2f4251817 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20070129" -#define MAIL_VERSION_NUMBER "2.3.7-RC3" +#define MAIL_RELEASE_DATE "20070130" +#define MAIL_VERSION_NUMBER "2.3.7" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 8f6a00f14..dad89aae9 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -210,7 +210,6 @@ smtp_chat.o: ../../include/dsn.h smtp_chat.o: ../../include/dsn_buf.h smtp_chat.o: ../../include/dsn_util.h smtp_chat.o: ../../include/htable.h -smtp_chat.o: ../../include/int_filt.h smtp_chat.o: ../../include/line_wrap.h smtp_chat.o: ../../include/mail_addr.h smtp_chat.o: ../../include/mail_error.h diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index 1f8dab64c..5c5d63470 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -716,7 +716,6 @@ int smtp_ext_prop_mask; * OpenSSL client state. */ SSL_CTX *smtp_tls_ctx; -int smtp_tls_mand_level; #endif @@ -880,18 +879,6 @@ static void pre_init(char *unused_name, char **unused_argv) props.CAfile = var_smtp_tls_CAfile; props.CApath = var_smtp_tls_CApath; - /* - * If the administrator set an invalid grade, use "medium" instead. - * The TLS library requires a valid setting. - */ - smtp_tls_mand_level = tls_cipher_level(var_smtp_tls_mand_ciph); - if (smtp_tls_mand_level == TLS_CIPHER_NONE) { - smtp_tls_mand_level = TLS_CIPHER_MEDIUM; - msg_warn("invalid '%s' value '%s', using 'medium'", - strcmp(var_procname, "smtp") == 0 ? - VAR_SMTP_TLS_MAND_CIPH : VAR_LMTP_TLS_MAND_CIPH, - var_smtp_tls_mand_ciph); - } smtp_tls_ctx = tls_client_init(&props); smtp_tls_list_init(); #else diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 98989805c..af397d711 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -168,7 +168,6 @@ extern int smtp_ext_prop_mask; /* address externsion propagation */ #ifdef USE_TLS extern SSL_CTX *smtp_tls_ctx; /* client-side TLS engine */ -extern int smtp_tls_mand_level; /* TLS_CIPHER_EXPORT, ... */ #endif diff --git a/postfix/src/smtp/smtp_session.c b/postfix/src/smtp/smtp_session.c index d042840e5..abb32789b 100644 --- a/postfix/src/smtp/smtp_session.c +++ b/postfix/src/smtp/smtp_session.c @@ -355,7 +355,7 @@ static void set_cipherlist(SMTP_SESSION *session, int cipher_level, int lmtp) case TLS_LEV_ENCRYPT: also_exclude = "eNULL"; if (cipher_level == TLS_CIPHER_NONE) - cipher_level = smtp_tls_mand_level; + cipher_level = tls_cipher_level(var_smtp_tls_mand_ciph); mand_exclude = var_smtp_tls_mand_excl; break; @@ -363,14 +363,22 @@ static void set_cipherlist(SMTP_SESSION *session, int cipher_level, int lmtp) case TLS_LEV_SECURE: also_exclude = "aNULL"; if (cipher_level == TLS_CIPHER_NONE) - cipher_level = smtp_tls_mand_level; + cipher_level = tls_cipher_level(var_smtp_tls_mand_ciph); mand_exclude = var_smtp_tls_mand_excl; break; } - cipherlist = tls_cipher_list(cipher_level, TLS_CIPH_EXCL_LIST, - exclude, mand_exclude, also_exclude, - TLS_CIPH_EXCL_END); + cipherlist = tls_cipher_list(cipher_level, exclude, mand_exclude, + also_exclude, TLS_END_EXCLUDE); + if (cipherlist == 0) { + msg_warn("unknown '%s' value '%s' ignored, using 'medium'", + lmtp ? VAR_LMTP_TLS_MAND_CIPH : VAR_SMTP_TLS_MAND_CIPH, + var_smtp_tls_mand_ciph); + cipherlist = tls_cipher_list(TLS_CIPHER_MEDIUM, exclude, mand_exclude, + also_exclude, TLS_END_EXCLUDE); + if (cipherlist == 0) + msg_panic("NULL medium cipherlist"); + } session->tls_cipherlist = mystrdup(cipherlist); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 9fa60e9ef..16f71294b 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -4226,7 +4226,6 @@ static void pre_jail_init(char *unused_name, char **unused_argv) if (use_tls) { #ifdef USE_TLS tls_server_props props; - ARGV *cipher_exclusions; int havecert; int oknocert; int wantcert; @@ -4272,44 +4271,32 @@ static void pre_jail_init(char *unused_name, char **unused_argv) if (!enforce_tls && var_smtpd_tls_req_ccert) msg_warn("Can't require client certs unless TLS is required"); - if (havecert || oknocert) { - cipher_exclusions = argv_alloc(3); - argv_add(cipher_exclusions, var_smtpd_tls_excl_ciph, ARGV_END); - if (wantcert) - argv_add(cipher_exclusions, "aNULL", ARGV_END); + props.cipherlist = + tls_cipher_list(enforce_tls ? + tls_cipher_level(var_smtpd_tls_mand_ciph) : + TLS_CIPHER_EXPORT, + var_smtpd_tls_excl_ciph, + havecert ? "" : "aRSA aDSS", + wantcert ? "aNULL" : "", + enforce_tls ? var_smtpd_tls_mand_excl : + TLS_END_EXCLUDE, + TLS_END_EXCLUDE); - /* - * Detect problem configurations early, a certificate-less - * handshake can't use ciphers that need server certificates, - * so we want to fail now while setting up the cipherlist, - * not later. Also this detects any conflict between wantcert - * and !havecert. - */ - if (!havecert) - argv_add(cipher_exclusions, "aRSA", "aDSS", ARGV_END); - if (enforce_tls) { - argv_add(cipher_exclusions, - var_smtpd_tls_mand_excl, ARGV_END); - - /* - * If the administrator set an invalid grade, use - * "medium" instead. The TLS library requires a valid - * setting. - */ - props.cipher_level = - tls_cipher_level(var_smtpd_tls_mand_ciph); - if (props.cipher_level == TLS_CIPHER_NONE) { - props.cipher_level = TLS_CIPHER_MEDIUM; - msg_warn("invalid '%s' value '%s', using 'medium'", - VAR_SMTPD_TLS_MAND_CIPH, - var_smtpd_tls_mand_ciph); - } - } else - props.cipher_level = TLS_CIPHER_EXPORT; - props.cipher_exclusions = cipher_exclusions->argv; + if (props.cipherlist == 0) { + msg_warn("unknown '%s' value '%s' ignored, using 'export'", + VAR_SMTPD_TLS_MAND_CIPH, var_smtpd_tls_mand_ciph); + props.cipherlist = + tls_cipher_list(TLS_CIPHER_EXPORT, + var_smtpd_tls_excl_ciph, + havecert ? "" : "aRSA aDSS", + wantcert ? "aNULL" : "", + enforce_tls ? var_smtpd_tls_mand_excl : + TLS_END_EXCLUDE, + TLS_END_EXCLUDE); + } + if (havecert || oknocert) smtpd_tls_ctx = tls_server_init(&props); - argv_free(cipher_exclusions); - } else if (enforce_tls) + else if (enforce_tls) msg_fatal("No server certs available. TLS can't be enabled"); else msg_warn("No server certs available. TLS won't be enabled"); diff --git a/postfix/src/tls/Makefile.in b/postfix/src/tls/Makefile.in index f0bc15572..8b8d254bf 100644 --- a/postfix/src/tls/Makefile.in +++ b/postfix/src/tls/Makefile.in @@ -89,7 +89,6 @@ depend: $(MAKES) @$(EXPORT) make -f Makefile.in Makefile 1>&2 # do not edit below this line - it is generated by 'make depend' -tls_bio_ops.o: ../../include/argv.h tls_bio_ops.o: ../../include/iostuff.h tls_bio_ops.o: ../../include/msg.h tls_bio_ops.o: ../../include/name_code.h @@ -100,7 +99,6 @@ tls_bio_ops.o: ../../include/vstream.h tls_bio_ops.o: ../../include/vstring.h tls_bio_ops.o: tls.h tls_bio_ops.o: tls_bio_ops.c -tls_certkey.o: ../../include/argv.h tls_certkey.o: ../../include/msg.h tls_certkey.o: ../../include/name_code.h tls_certkey.o: ../../include/name_mask.h @@ -124,7 +122,6 @@ tls_client.o: ../../include/vstring.h tls_client.o: tls.h tls_client.o: tls_client.c tls_client.o: tls_mgr.h -tls_dh.o: ../../include/argv.h tls_dh.o: ../../include/msg.h tls_dh.o: ../../include/name_code.h tls_dh.o: ../../include/name_mask.h @@ -134,7 +131,6 @@ tls_dh.o: ../../include/vstream.h tls_dh.o: ../../include/vstring.h tls_dh.o: tls.h tls_dh.o: tls_dh.c -tls_level.o: ../../include/argv.h tls_level.o: ../../include/name_code.h tls_level.o: ../../include/name_mask.h tls_level.o: ../../include/sys_defs.h @@ -155,7 +151,6 @@ 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 @@ -195,7 +190,6 @@ tls_prng_file.o: ../../include/mymalloc.h tls_prng_file.o: ../../include/sys_defs.h tls_prng_file.o: tls_prng.h tls_prng_file.o: tls_prng_file.c -tls_rsa.o: ../../include/argv.h tls_rsa.o: ../../include/name_code.h tls_rsa.o: ../../include/name_mask.h tls_rsa.o: ../../include/sys_defs.h @@ -217,7 +211,6 @@ tls_scache.o: ../../include/vstream.h tls_scache.o: ../../include/vstring.h tls_scache.o: tls_scache.c tls_scache.o: tls_scache.h -tls_seed.o: ../../include/argv.h tls_seed.o: ../../include/msg.h tls_seed.o: ../../include/name_code.h tls_seed.o: ../../include/name_mask.h @@ -244,7 +237,6 @@ tls_server.o: ../../include/vstring.h tls_server.o: tls.h tls_server.o: tls_mgr.h tls_server.o: tls_server.c -tls_session.o: ../../include/argv.h tls_session.o: ../../include/msg.h tls_session.o: ../../include/mymalloc.h tls_session.o: ../../include/name_code.h @@ -255,7 +247,6 @@ tls_session.o: ../../include/vstream.h tls_session.o: ../../include/vstring.h tls_session.o: tls.h tls_session.o: tls_session.c -tls_stream.o: ../../include/argv.h tls_stream.o: ../../include/iostuff.h tls_stream.o: ../../include/msg.h tls_stream.o: ../../include/name_code.h @@ -266,7 +257,6 @@ tls_stream.o: ../../include/vstream.h tls_stream.o: ../../include/vstring.h tls_stream.o: tls.h tls_stream.o: tls_stream.c -tls_verify.o: ../../include/argv.h tls_verify.o: ../../include/msg.h tls_verify.o: ../../include/mymalloc.h tls_verify.o: ../../include/name_code.h diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index ef6799712..f13702327 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -56,7 +56,6 @@ extern NAME_CODE tls_level_table[]; #include #include #include -#include #define TLS_BIO_BUFSIZE 8192 @@ -129,10 +128,8 @@ extern NAME_CODE tls_cipher_level_table[]; #define tls_cipher_level(str) \ name_code(tls_cipher_level_table, NAME_CODE_FLAG_NONE, (str)) -#define TLS_CIPH_EXCL_ARRAY 1 -#define TLS_CIPH_EXCL_LIST 2 -#define TLS_CIPH_EXCL_END ((char *) 0) -extern const char *tls_cipher_list(int, int,...); +#define TLS_END_EXCLUDE ((char *)0) +extern const char *tls_cipher_list(int,...); /* * tls_client.c @@ -184,8 +181,7 @@ typedef struct { const char *dkey_file; const char *CAfile; const char *CApath; - int cipher_level; /* TLS_CIPHER_EXPORT, ... */ - char **cipher_exclusions; + const char *cipherlist; int protocols; /* protocols, 0 => all */ const char *dh1024_param_file; const char *dh512_param_file; diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c index 6ecac330b..0680ee0cd 100644 --- a/postfix/src/tls/tls_client.c +++ b/postfix/src/tls/tls_client.c @@ -718,12 +718,13 @@ TLScontext_t *tls_client_start(const tls_client_start_props *props) * the caller to salt the session lookup key with the cipher list, so * that sessions found in the cache are always acceptable. */ - 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); - } + 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. diff --git a/postfix/src/tls/tls_misc.c b/postfix/src/tls/tls_misc.c index e0a1d832b..f87389819 100644 --- a/postfix/src/tls/tls_misc.c +++ b/postfix/src/tls/tls_misc.c @@ -18,9 +18,8 @@ /* /* long tls_bug_bits() /* -/* const char *tls_cipher_list(cipher_level, options, ...) +/* const char *tls_cipher_list(cipher_level, ...) /* int cipher_level; -/* int options; /* /* void tls_print_errors() /* @@ -57,10 +56,7 @@ /* 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 -/* upon each call. The options argument specifies how exceptions -/* are specified: TLS_CIPH_EXCL_ARRAY (null-terminated character -/* pointer array) or TLS_CIPH_EXCL_LIST (variadic parameter -/* list terminated with TLS_CIPH_EXCL_END). +/* upon each call. /* /* tls_print_errors() queries the OpenSSL error stack, /* logs the error messages, and clears the error stack. @@ -155,41 +151,6 @@ NAME_CODE tls_cipher_level_table[] = { 0, TLS_CIPHER_NONE, }; -typedef struct { - char *algorithm; - char *exclusion; -} cipher_probe; - -static cipher_probe cipher_probe_list[] = { - - /* - * Check for missing AES256, OpenSSL only checks for AES128, and then - * enables both, because they only have one "is AES" boolean flag in the - * cipher property mask. The implementation cannot distinguish between - * AES128 and AES256. When some O/S distributions play games with - * libcrypto and exclude just the AES256 ciphers, they break the OpenSSL - * cipherlist construction code, with clients and servers potentially - * negotiating unimplemented ciphers. - * - * This problem is peculiar to AES, which is not a single cipher, but a - * family of related ciphers. The other OpenSSL symmetric ciphers are - * atomic, either implemented or not. We expect that future ciphers will - * either also be atomic, or will have one property bit per family member - * and will be filtered accurately by OpenSSL. - * - * If all else fails, this table can be expanded :-( - * - * XXX: the probe for AES256 is enclosed in #ifdef. OpenSSL 0.9.6 and and - * earlier don't have AES 256, this requires 0.9.7 or later. We recommend - * against use of 0.9.6, it has open issues solved in 0.9.7l and 0.9.8d, - * but we are not yet prepared to drop support for 0.9.6. - */ -#ifdef SN_aes_256_cbc - SN_aes_256_cbc, SSL_TXT_AES "+HIGH", -#endif - 0, 0, -}; - /* * Parsed OpenSSL version number. */ @@ -203,19 +164,15 @@ typedef struct { /* tls_cipher_list - Cipherlist for given grade, less exclusions */ -const char *tls_cipher_list(int cipher_level, int options,...) +const char *tls_cipher_list(int cipher_level,...) { const char *myname = "tls_cipher_list"; static VSTRING *buf; - static ARGV *exclude_unavailable; - cipher_probe *probe; - int i; va_list ap; const char *exclude; char *tok; char *save; char *cp; - char **ex_array = 0; buf = buf ? buf : vstring_alloc(10); VSTRING_RESET(buf); @@ -236,30 +193,17 @@ const char *tls_cipher_list(int cipher_level, int options,...) case TLS_CIPHER_NULL: vstring_strcpy(buf, var_tls_null_clist); break; + case TLS_CIPHER_NONE: + return 0; default: msg_panic("%s: invalid cipher grade: %d", myname, cipher_level); } + if (VSTRING_LEN(buf) == 0) msg_panic("%s: empty cipherlist", myname); - /* - * Exclude ciphers that clueless distributions leave out of libcrypto. - */ - if (exclude_unavailable == 0) { - exclude_unavailable = argv_alloc(1); - for (probe = cipher_probe_list; probe->algorithm; ++probe) - if (!EVP_get_cipherbyname(probe->algorithm)) - argv_add(exclude_unavailable, probe->exclusion, (char *) 0); - } - for (i = 0; i < exclude_unavailable->argc; ++i) - vstring_sprintf_append(buf, ":!%s", exclude_unavailable->argv[i]); - - va_start(ap, options); - if (options == TLS_CIPH_EXCL_ARRAY) - ex_array = va_arg(ap, char **); - else if (options != TLS_CIPH_EXCL_LIST) - msg_panic("%s: bad argument list option: %d", myname, options); - while ((exclude = ex_array ? *ex_array++ : va_arg(ap, char *)) != 0) { + va_start(ap, cipher_level); + while ((exclude = va_arg(ap, char *)) != 0) { if (*exclude == '\0') continue; save = cp = mystrdup(exclude); diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c index 720cbcfcd..3c6dac341 100644 --- a/postfix/src/tls/tls_server.c +++ b/postfix/src/tls/tls_server.c @@ -249,7 +249,6 @@ SSL_CTX *tls_server_init(const tls_server_props *props) int verify_flags = SSL_VERIFY_NONE; SSL_CTX *server_ctx; int cachable; - const char *cipher_list; /* See skeleton at OpenSSL apps/s_server.c. */ @@ -329,14 +328,12 @@ SSL_CTX *tls_server_init(const tls_server_props *props) /* * Override the default cipher list with our own list. */ - cipher_list = tls_cipher_list(props->cipher_level, TLS_CIPH_EXCL_ARRAY, - props->cipher_exclusions); - if (SSL_CTX_set_cipher_list(server_ctx, cipher_list) == 0) { - tls_print_errors(); - msg_warn("Invalid cipherlist: %s", cipher_list); - SSL_CTX_free(server_ctx); /* 200411 */ - return (0); - } + 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); + } /* * Load the CA public key certificates for both the server cert and for