2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-09-01 22:55:29 +00:00

postfix-2.3.7-RC3

This commit is contained in:
Wietse Venema
2007-01-29 00:00:00 -05:00
committed by Viktor Dukhovni
parent 10d87f82d2
commit c6d2e6a37f
17 changed files with 209 additions and 81 deletions

1
postfix/.indent.pro vendored
View File

@@ -254,6 +254,7 @@
-TXSASL_SERVER -TXSASL_SERVER
-TXSASL_SERVER_IMPL -TXSASL_SERVER_IMPL
-TXSASL_SERVER_IMPL_INFO -TXSASL_SERVER_IMPL_INFO
-Tcipher_probe
-Tregex_t -Tregex_t
-Tregmatch_t -Tregmatch_t
-Tsasl_conn_t -Tsasl_conn_t

View File

@@ -12927,8 +12927,16 @@ Apologies for any names omitted.
Duchovni. Files: smtpd/smtpd_check.c. Duchovni. Files: smtpd/smtpd_check.c.
Workaround: don't insert header/body blank line separator Workaround: don't insert header/body blank line separator
in malformed attachments, to avoid breaking digital signatures. into malformed MIME attachments, to avoid breaking digital
Switch from header to body state, for robust MIME parsing. signatures. File: global/mime_state.c.
People concerned about MIME evasion can use a MIME normalizer
to corrupt their user's legitimate email. File: 20070118
global/mime_state.c.
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.

View File

@@ -20,8 +20,8 @@
* Patches change both the patchlevel and the release date. Snapshots have no * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20070113" #define MAIL_RELEASE_DATE "20070129"
#define MAIL_VERSION_NUMBER "2.3.7-RC2" #define MAIL_VERSION_NUMBER "2.3.7-RC3"
#ifdef SNAPSHOT #ifdef SNAPSHOT
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@@ -499,6 +499,7 @@ MIME_STATE *mime_state_alloc(int flags,
/* Volatile members. */ /* Volatile members. */
state->err_flags = 0; state->err_flags = 0;
state->body_offset = 0; /* XXX */
SET_MIME_STATE(state, MIME_STATE_PRIMARY, SET_MIME_STATE(state, MIME_STATE_PRIMARY,
MIME_CTYPE_TEXT, MIME_STYPE_PLAIN, MIME_CTYPE_TEXT, MIME_STYPE_PLAIN,
MIME_ENC_7BIT, MIME_ENC_7BIT); MIME_ENC_7BIT, MIME_ENC_7BIT);
@@ -938,6 +939,15 @@ int mime_state_update(MIME_STATE *state, int rec_type,
* messages. Otherwise, treat such headers as part of the "body". Set * messages. Otherwise, treat such headers as part of the "body". Set
* the proper encoding information for the multipart prolog. * the proper encoding information for the multipart prolog.
* *
* XXX We parse headers inside message/* content even when the encoding
* is invalid (encoding != domain). With base64 we won't recognize
* any headers, and with quoted-printable we won't recognize MIME
* boundary strings, but the MIME processor will still resynchronize
* when it runs into the higher-level boundary string at the end of
* the message/* content. Although we will treat some headers as body
* text, we will still do a better job than if we were treating the
* entire message/* content as body text.
*
* XXX This changes state to MIME_STATE_NESTED and then outputs a body * XXX This changes state to MIME_STATE_NESTED and then outputs a body
* line, so that the body offset is not properly reset. * line, so that the body offset is not properly reset.
* *
@@ -973,13 +983,14 @@ int mime_state_update(MIME_STATE *state, int rec_type,
* separator, nor does the Milter protocol pass it on to Milter * separator, nor does the Milter protocol pass it on to Milter
* applications. * applications.
* *
* XXX We don't insert a blank line separator with attachments, as * XXX We don't insert a blank line separator into attachments, to
* this breaks digital signatures. Postfix shall not do a worse * avoid breaking digital signatures. Postfix shall not do a
* mail delivery job than crappy MTAs that can't even parse MIME. * worse mail delivery job than MTAs that can't even parse MIME.
* But we switch to the body state anyway. * We switch to body state anyway, to avoid treating body text as
* header text, and mis-interpreting or truncating it. The code
* below for initial From_ lines is for educational purposes.
* *
* People who worry about MIME evasion can use a MIME normalizer, * Sites concerned about MIME evasion can use a MIME normalizer.
* and knowlingly corrupt legitimate email for their users.
* Postfix has a different mission. * Postfix has a different mission.
*/ */
else { else {
@@ -989,9 +1000,25 @@ int mime_state_update(MIME_STATE *state, int rec_type,
state->curr_state == MIME_STATE_PRIMARY ? "primary" : state->curr_state == MIME_STATE_PRIMARY ? "primary" :
state->curr_state == MIME_STATE_NESTED ? "nested" : state->curr_state == MIME_STATE_NESTED ? "nested" :
"other"); "other");
if (state->curr_state == MIME_STATE_PRIMARY) switch (state->curr_state) {
case MIME_STATE_PRIMARY:
BODY_OUT(state, REC_TYPE_NORM, "", 0); BODY_OUT(state, REC_TYPE_NORM, "", 0);
SET_CURR_STATE(state, MIME_STATE_BODY); SET_CURR_STATE(state, MIME_STATE_BODY);
break;
#if 0
case MIME_STATE_NESTED:
if (state->body_offset <= 1
&& rec_type == REC_TYPE_NORM
&& len > 7
&& (strncmp(text + (*text == '>'), "From ", 5) == 0
|| strncmp(text, "=46rom ", 7) == 0))
break;
/* FALLTHROUGH */
#endif
default:
SET_CURR_STATE(state, MIME_STATE_BODY);
break;
}
} }
} }

View File

@@ -77,8 +77,8 @@
/* and REC_FLAG_DEFAULT for normal use. /* and REC_FLAG_DEFAULT for normal use.
/* /*
/* rec_get() is a wrapper around rec_get_raw() that always /* rec_get() is a wrapper around rec_get_raw() that always
/* enables the REC_FLAG_FOLLOW_PTR and REC_FLAG_SKIP_DTXT /* enables the REC_FLAG_FOLLOW_PTR, REC_FLAG_SKIP_DTXT
/* features. /* and REC_FLAG_SEEK_END features.
/* /*
/* rec_put() stores the specified record and returns the record /* rec_put() stores the specified record and returns the record
/* type, or REC_TYPE_ERROR in case of problems. /* type, or REC_TYPE_ERROR in case of problems.

View File

@@ -210,6 +210,7 @@ smtp_chat.o: ../../include/dsn.h
smtp_chat.o: ../../include/dsn_buf.h smtp_chat.o: ../../include/dsn_buf.h
smtp_chat.o: ../../include/dsn_util.h smtp_chat.o: ../../include/dsn_util.h
smtp_chat.o: ../../include/htable.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/line_wrap.h
smtp_chat.o: ../../include/mail_addr.h smtp_chat.o: ../../include/mail_addr.h
smtp_chat.o: ../../include/mail_error.h smtp_chat.o: ../../include/mail_error.h

View File

@@ -716,6 +716,7 @@ int smtp_ext_prop_mask;
* OpenSSL client state. * OpenSSL client state.
*/ */
SSL_CTX *smtp_tls_ctx; SSL_CTX *smtp_tls_ctx;
int smtp_tls_mand_level;
#endif #endif
@@ -879,6 +880,18 @@ static void pre_init(char *unused_name, char **unused_argv)
props.CAfile = var_smtp_tls_CAfile; props.CAfile = var_smtp_tls_CAfile;
props.CApath = var_smtp_tls_CApath; 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_ctx = tls_client_init(&props);
smtp_tls_list_init(); smtp_tls_list_init();
#else #else

View File

@@ -168,6 +168,7 @@ extern int smtp_ext_prop_mask; /* address externsion propagation */
#ifdef USE_TLS #ifdef USE_TLS
extern SSL_CTX *smtp_tls_ctx; /* client-side TLS engine */ extern SSL_CTX *smtp_tls_ctx; /* client-side TLS engine */
extern int smtp_tls_mand_level; /* TLS_CIPHER_EXPORT, ... */
#endif #endif

View File

@@ -355,7 +355,7 @@ static void set_cipherlist(SMTP_SESSION *session, int cipher_level, int lmtp)
case TLS_LEV_ENCRYPT: case TLS_LEV_ENCRYPT:
also_exclude = "eNULL"; also_exclude = "eNULL";
if (cipher_level == TLS_CIPHER_NONE) if (cipher_level == TLS_CIPHER_NONE)
cipher_level = tls_cipher_level(var_smtp_tls_mand_ciph); cipher_level = smtp_tls_mand_level;
mand_exclude = var_smtp_tls_mand_excl; mand_exclude = var_smtp_tls_mand_excl;
break; break;
@@ -363,22 +363,14 @@ static void set_cipherlist(SMTP_SESSION *session, int cipher_level, int lmtp)
case TLS_LEV_SECURE: case TLS_LEV_SECURE:
also_exclude = "aNULL"; also_exclude = "aNULL";
if (cipher_level == TLS_CIPHER_NONE) if (cipher_level == TLS_CIPHER_NONE)
cipher_level = tls_cipher_level(var_smtp_tls_mand_ciph); cipher_level = smtp_tls_mand_level;
mand_exclude = var_smtp_tls_mand_excl; mand_exclude = var_smtp_tls_mand_excl;
break; break;
} }
cipherlist = tls_cipher_list(cipher_level, exclude, mand_exclude, cipherlist = tls_cipher_list(cipher_level, TLS_CIPH_EXCL_LIST,
also_exclude, TLS_END_EXCLUDE); exclude, mand_exclude, also_exclude,
if (cipherlist == 0) { TLS_CIPH_EXCL_END);
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); session->tls_cipherlist = mystrdup(cipherlist);
} }

View File

@@ -4226,6 +4226,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
if (use_tls) { if (use_tls) {
#ifdef USE_TLS #ifdef USE_TLS
tls_server_props props; tls_server_props props;
ARGV *cipher_exclusions;
int havecert; int havecert;
int oknocert; int oknocert;
int wantcert; int wantcert;
@@ -4271,32 +4272,44 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
if (!enforce_tls && var_smtpd_tls_req_ccert) if (!enforce_tls && var_smtpd_tls_req_ccert)
msg_warn("Can't require client certs unless TLS is required"); msg_warn("Can't require client certs unless TLS is required");
props.cipherlist = if (havecert || oknocert) {
tls_cipher_list(enforce_tls ? cipher_exclusions = argv_alloc(3);
tls_cipher_level(var_smtpd_tls_mand_ciph) : argv_add(cipher_exclusions, var_smtpd_tls_excl_ciph, ARGV_END);
TLS_CIPHER_EXPORT, if (wantcert)
var_smtpd_tls_excl_ciph, argv_add(cipher_exclusions, "aNULL", ARGV_END);
havecert ? "" : "aRSA aDSS",
wantcert ? "aNULL" : "",
enforce_tls ? var_smtpd_tls_mand_excl :
TLS_END_EXCLUDE,
TLS_END_EXCLUDE);
if (props.cipherlist == 0) { /*
msg_warn("unknown '%s' value '%s' ignored, using 'export'", * Detect problem configurations early, a certificate-less
VAR_SMTPD_TLS_MAND_CIPH, var_smtpd_tls_mand_ciph); * handshake can't use ciphers that need server certificates,
props.cipherlist = * so we want to fail now while setting up the cipherlist,
tls_cipher_list(TLS_CIPHER_EXPORT, * not later. Also this detects any conflict between wantcert
var_smtpd_tls_excl_ciph, * and !havecert.
havecert ? "" : "aRSA aDSS", */
wantcert ? "aNULL" : "", if (!havecert)
enforce_tls ? var_smtpd_tls_mand_excl : argv_add(cipher_exclusions, "aRSA", "aDSS", ARGV_END);
TLS_END_EXCLUDE, if (enforce_tls) {
TLS_END_EXCLUDE); 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);
} }
if (havecert || oknocert) } else
props.cipher_level = TLS_CIPHER_EXPORT;
props.cipher_exclusions = cipher_exclusions->argv;
smtpd_tls_ctx = tls_server_init(&props); smtpd_tls_ctx = tls_server_init(&props);
else if (enforce_tls) argv_free(cipher_exclusions);
} else if (enforce_tls)
msg_fatal("No server certs available. TLS can't be enabled"); msg_fatal("No server certs available. TLS can't be enabled");
else else
msg_warn("No server certs available. TLS won't be enabled"); msg_warn("No server certs available. TLS won't be enabled");

View File

@@ -107,8 +107,8 @@ OK
>>> mail sname@sdomain >>> mail sname@sdomain
OK OK
>>> rcpt rname@rdomain >>> rcpt rname@rdomain
./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld> ./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain
>>> # >>> #
>>> # Check MX access >>> # Check MX access
>>> # >>> #

View File

@@ -89,6 +89,7 @@ depend: $(MAKES)
@$(EXPORT) make -f Makefile.in Makefile 1>&2 @$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend' # 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/iostuff.h
tls_bio_ops.o: ../../include/msg.h tls_bio_ops.o: ../../include/msg.h
tls_bio_ops.o: ../../include/name_code.h tls_bio_ops.o: ../../include/name_code.h
@@ -99,6 +100,7 @@ tls_bio_ops.o: ../../include/vstream.h
tls_bio_ops.o: ../../include/vstring.h tls_bio_ops.o: ../../include/vstring.h
tls_bio_ops.o: tls.h tls_bio_ops.o: tls.h
tls_bio_ops.o: tls_bio_ops.c tls_bio_ops.o: tls_bio_ops.c
tls_certkey.o: ../../include/argv.h
tls_certkey.o: ../../include/msg.h tls_certkey.o: ../../include/msg.h
tls_certkey.o: ../../include/name_code.h tls_certkey.o: ../../include/name_code.h
tls_certkey.o: ../../include/name_mask.h tls_certkey.o: ../../include/name_mask.h
@@ -122,6 +124,7 @@ tls_client.o: ../../include/vstring.h
tls_client.o: tls.h tls_client.o: tls.h
tls_client.o: tls_client.c tls_client.o: tls_client.c
tls_client.o: tls_mgr.h tls_client.o: tls_mgr.h
tls_dh.o: ../../include/argv.h
tls_dh.o: ../../include/msg.h tls_dh.o: ../../include/msg.h
tls_dh.o: ../../include/name_code.h tls_dh.o: ../../include/name_code.h
tls_dh.o: ../../include/name_mask.h tls_dh.o: ../../include/name_mask.h
@@ -131,6 +134,7 @@ tls_dh.o: ../../include/vstream.h
tls_dh.o: ../../include/vstring.h tls_dh.o: ../../include/vstring.h
tls_dh.o: tls.h tls_dh.o: tls.h
tls_dh.o: tls_dh.c tls_dh.o: tls_dh.c
tls_level.o: ../../include/argv.h
tls_level.o: ../../include/name_code.h tls_level.o: ../../include/name_code.h
tls_level.o: ../../include/name_mask.h tls_level.o: ../../include/name_mask.h
tls_level.o: ../../include/sys_defs.h tls_level.o: ../../include/sys_defs.h
@@ -151,6 +155,7 @@ tls_mgr.o: ../../include/vstream.h
tls_mgr.o: ../../include/vstring.h tls_mgr.o: ../../include/vstring.h
tls_mgr.o: tls_mgr.c tls_mgr.o: tls_mgr.c
tls_mgr.o: tls_mgr.h tls_mgr.o: tls_mgr.h
tls_misc.o: ../../include/argv.h
tls_misc.o: ../../include/msg.h tls_misc.o: ../../include/msg.h
tls_misc.o: ../../include/mymalloc.h tls_misc.o: ../../include/mymalloc.h
tls_misc.o: ../../include/name_code.h tls_misc.o: ../../include/name_code.h
@@ -190,6 +195,7 @@ tls_prng_file.o: ../../include/mymalloc.h
tls_prng_file.o: ../../include/sys_defs.h tls_prng_file.o: ../../include/sys_defs.h
tls_prng_file.o: tls_prng.h tls_prng_file.o: tls_prng.h
tls_prng_file.o: tls_prng_file.c 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_code.h
tls_rsa.o: ../../include/name_mask.h tls_rsa.o: ../../include/name_mask.h
tls_rsa.o: ../../include/sys_defs.h tls_rsa.o: ../../include/sys_defs.h
@@ -211,6 +217,7 @@ tls_scache.o: ../../include/vstream.h
tls_scache.o: ../../include/vstring.h tls_scache.o: ../../include/vstring.h
tls_scache.o: tls_scache.c tls_scache.o: tls_scache.c
tls_scache.o: tls_scache.h tls_scache.o: tls_scache.h
tls_seed.o: ../../include/argv.h
tls_seed.o: ../../include/msg.h tls_seed.o: ../../include/msg.h
tls_seed.o: ../../include/name_code.h tls_seed.o: ../../include/name_code.h
tls_seed.o: ../../include/name_mask.h tls_seed.o: ../../include/name_mask.h
@@ -237,6 +244,7 @@ tls_server.o: ../../include/vstring.h
tls_server.o: tls.h tls_server.o: tls.h
tls_server.o: tls_mgr.h tls_server.o: tls_mgr.h
tls_server.o: tls_server.c tls_server.o: tls_server.c
tls_session.o: ../../include/argv.h
tls_session.o: ../../include/msg.h tls_session.o: ../../include/msg.h
tls_session.o: ../../include/mymalloc.h tls_session.o: ../../include/mymalloc.h
tls_session.o: ../../include/name_code.h tls_session.o: ../../include/name_code.h
@@ -247,6 +255,7 @@ tls_session.o: ../../include/vstream.h
tls_session.o: ../../include/vstring.h tls_session.o: ../../include/vstring.h
tls_session.o: tls.h tls_session.o: tls.h
tls_session.o: tls_session.c tls_session.o: tls_session.c
tls_stream.o: ../../include/argv.h
tls_stream.o: ../../include/iostuff.h tls_stream.o: ../../include/iostuff.h
tls_stream.o: ../../include/msg.h tls_stream.o: ../../include/msg.h
tls_stream.o: ../../include/name_code.h tls_stream.o: ../../include/name_code.h
@@ -257,6 +266,7 @@ tls_stream.o: ../../include/vstream.h
tls_stream.o: ../../include/vstring.h tls_stream.o: ../../include/vstring.h
tls_stream.o: tls.h tls_stream.o: tls.h
tls_stream.o: tls_stream.c tls_stream.o: tls_stream.c
tls_verify.o: ../../include/argv.h
tls_verify.o: ../../include/msg.h tls_verify.o: ../../include/msg.h
tls_verify.o: ../../include/mymalloc.h tls_verify.o: ../../include/mymalloc.h
tls_verify.o: ../../include/name_code.h tls_verify.o: ../../include/name_code.h

View File

@@ -56,6 +56,7 @@ extern NAME_CODE tls_level_table[];
#include <vstream.h> #include <vstream.h>
#include <name_mask.h> #include <name_mask.h>
#include <name_code.h> #include <name_code.h>
#include <argv.h>
#define TLS_BIO_BUFSIZE 8192 #define TLS_BIO_BUFSIZE 8192
@@ -128,8 +129,10 @@ extern NAME_CODE tls_cipher_level_table[];
#define tls_cipher_level(str) \ #define tls_cipher_level(str) \
name_code(tls_cipher_level_table, NAME_CODE_FLAG_NONE, (str)) name_code(tls_cipher_level_table, NAME_CODE_FLAG_NONE, (str))
#define TLS_END_EXCLUDE ((char *)0) #define TLS_CIPH_EXCL_ARRAY 1
extern const char *tls_cipher_list(int,...); #define TLS_CIPH_EXCL_LIST 2
#define TLS_CIPH_EXCL_END ((char *) 0)
extern const char *tls_cipher_list(int, int,...);
/* /*
* tls_client.c * tls_client.c
@@ -181,7 +184,8 @@ typedef struct {
const char *dkey_file; const char *dkey_file;
const char *CAfile; const char *CAfile;
const char *CApath; const char *CApath;
const char *cipherlist; int cipher_level; /* TLS_CIPHER_EXPORT, ... */
char **cipher_exclusions;
int protocols; /* protocols, 0 => all */ int protocols; /* protocols, 0 => all */
const char *dh1024_param_file; const char *dh1024_param_file;
const char *dh512_param_file; const char *dh512_param_file;

View File

@@ -718,7 +718,6 @@ TLScontext_t *tls_client_start(const tls_client_start_props *props)
* the caller to salt the session lookup key with the cipher list, so * the caller to salt the session lookup key with the cipher list, so
* that sessions found in the cache are always acceptable. * that sessions found in the cache are always acceptable.
*/ */
if (props->cipherlist != 0)
if (SSL_set_cipher_list(TLScontext->con, props->cipherlist) == 0) { if (SSL_set_cipher_list(TLScontext->con, props->cipherlist) == 0) {
msg_warn("Could not set cipherlist: %s", props->cipherlist); msg_warn("Could not set cipherlist: %s", props->cipherlist);
tls_print_errors(); tls_print_errors();

View File

@@ -18,8 +18,9 @@
/* /*
/* long tls_bug_bits() /* long tls_bug_bits()
/* /*
/* const char *tls_cipher_list(cipher_level, ...) /* const char *tls_cipher_list(cipher_level, options, ...)
/* int cipher_level; /* int cipher_level;
/* int options;
/* /*
/* void tls_print_errors() /* void tls_print_errors()
/* /*
@@ -56,7 +57,10 @@
/* tls_cipher_list() generates a cipher list from the specified /* tls_cipher_list() generates a cipher list from the specified
/* grade, minus any ciphers specified via a null-terminated /* grade, minus any ciphers specified via a null-terminated
/* list of string-valued exclusions. The result is overwritten /* list of string-valued exclusions. The result is overwritten
/* upon each call. /* 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).
/* /*
/* tls_print_errors() queries the OpenSSL error stack, /* tls_print_errors() queries the OpenSSL error stack,
/* logs the error messages, and clears the error stack. /* logs the error messages, and clears the error stack.
@@ -151,6 +155,41 @@ NAME_CODE tls_cipher_level_table[] = {
0, TLS_CIPHER_NONE, 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. * Parsed OpenSSL version number.
*/ */
@@ -164,15 +203,19 @@ typedef struct {
/* tls_cipher_list - Cipherlist for given grade, less exclusions */ /* tls_cipher_list - Cipherlist for given grade, less exclusions */
const char *tls_cipher_list(int cipher_level,...) const char *tls_cipher_list(int cipher_level, int options,...)
{ {
const char *myname = "tls_cipher_list"; const char *myname = "tls_cipher_list";
static VSTRING *buf; static VSTRING *buf;
static ARGV *exclude_unavailable;
cipher_probe *probe;
int i;
va_list ap; va_list ap;
const char *exclude; const char *exclude;
char *tok; char *tok;
char *save; char *save;
char *cp; char *cp;
char **ex_array = 0;
buf = buf ? buf : vstring_alloc(10); buf = buf ? buf : vstring_alloc(10);
VSTRING_RESET(buf); VSTRING_RESET(buf);
@@ -193,17 +236,30 @@ const char *tls_cipher_list(int cipher_level,...)
case TLS_CIPHER_NULL: case TLS_CIPHER_NULL:
vstring_strcpy(buf, var_tls_null_clist); vstring_strcpy(buf, var_tls_null_clist);
break; break;
case TLS_CIPHER_NONE:
return 0;
default: default:
msg_panic("%s: invalid cipher grade: %d", myname, cipher_level); msg_panic("%s: invalid cipher grade: %d", myname, cipher_level);
} }
if (VSTRING_LEN(buf) == 0) if (VSTRING_LEN(buf) == 0)
msg_panic("%s: empty cipherlist", myname); msg_panic("%s: empty cipherlist", myname);
va_start(ap, cipher_level); /*
while ((exclude = va_arg(ap, char *)) != 0) { * 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) {
if (*exclude == '\0') if (*exclude == '\0')
continue; continue;
save = cp = mystrdup(exclude); save = cp = mystrdup(exclude);

View File

@@ -249,6 +249,7 @@ SSL_CTX *tls_server_init(const tls_server_props *props)
int verify_flags = SSL_VERIFY_NONE; int verify_flags = SSL_VERIFY_NONE;
SSL_CTX *server_ctx; SSL_CTX *server_ctx;
int cachable; int cachable;
const char *cipher_list;
/* See skeleton at OpenSSL apps/s_server.c. */ /* See skeleton at OpenSSL apps/s_server.c. */
@@ -328,9 +329,11 @@ SSL_CTX *tls_server_init(const tls_server_props *props)
/* /*
* Override the default cipher list with our own list. * Override the default cipher list with our own list.
*/ */
if (*props->cipherlist != 0) cipher_list = tls_cipher_list(props->cipher_level, TLS_CIPH_EXCL_ARRAY,
if (SSL_CTX_set_cipher_list(server_ctx, props->cipherlist) == 0) { props->cipher_exclusions);
if (SSL_CTX_set_cipher_list(server_ctx, cipher_list) == 0) {
tls_print_errors(); tls_print_errors();
msg_warn("Invalid cipherlist: %s", cipher_list);
SSL_CTX_free(server_ctx); /* 200411 */ SSL_CTX_free(server_ctx); /* 200411 */
return (0); return (0);
} }

View File

@@ -96,7 +96,7 @@ struct MATCH_LIST {
}; };
#define MATCH_DICTIONARY(pattern) \ #define MATCH_DICTIONARY(pattern) \
((pattern)[0] != '[' && strchr((pattern), ':') != 0) ((pattern + strspn(pattern, "!"))[0] != '[' && strchr((pattern), ':') != 0)
/* match_list_parse - parse buffer, destroy buffer */ /* match_list_parse - parse buffer, destroy buffer */