From: Phil Pennock Date: Mon, 3 Oct 2011 11:36:12 +0000 (-0400) Subject: Merge branch 'list_safety' X-Git-Tag: exim-4_77_RC1~2 X-Git-Url: https://git.exim.org/users/jgh/exim.git/commitdiff_plain/d6cc7c78f624e505bb889c8ccd2879706d6dc9e1?hp=82c6910a112610ac5c121ff5321365c5dc7e8eb2 Merge branch 'list_safety' (gnutls fixes had updated some text docs) --- diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 128329ef2..81f69afab 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -24619,8 +24619,14 @@ DHE_DSS). The default list contains RSA, DHE_DSS, DHE_RSA. For &%gnutls_require_mac%&, the recognized names are SHA (synonym SHA1), and MD5. The default list contains SHA, MD5. -For &%gnutls_require_protocols%&, the recognized names are TLS1 and SSL3. -The default list contains TLS1, SSL3. +.new +For &%gnutls_require_protocols%&, the recognized names are TLS1.2, TLS1.1, +TLS1.0, (TLS1) and SSL3. +The default list contains TLS1.2, TLS1.1, TLS1.0, SSL3. +TLS1 is an alias for TLS1.0, for backwards compatibility. +For sufficiently old versions of the GnuTLS library, TLS1.2 or TLS1.1 might +not be supported and will not be recognised by Exim. +.wen In a server, the order of items in these lists is unimportant. The server advertises the availability of all the relevant cipher suites. However, in a diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index e2e95c548..a911d80a1 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -112,7 +112,12 @@ PP/08 Handle ${run} returning more data than OS pipe buffer size. PP/09 Handle IPv6 addresses with SPF. Bugzilla 860. Patch from Wolfgang Breyha. -PP/10 match_* no longer expand right-hand-side by default. +PP/10 GnuTLS: support TLS 1.2 & 1.1. + Bugzilla 1156. + Use gnutls_certificate_verify_peers2() [patch from Andreas Metzler]. + Bugzilla 1095. + +PP/11 match_* no longer expand right-hand-side by default. New compile-time build option, EXPAND_LISTMATCH_RHS. New expansion conditions, "inlist", "inlisti". diff --git a/src/README.UPDATING b/src/README.UPDATING index 20313b2cb..8a0533b10 100644 --- a/src/README.UPDATING +++ b/src/README.UPDATING @@ -29,6 +29,12 @@ that might affect a running system. Exim version 4.77 ----------------- + * GnuTLS will now attempt to use TLS 1.2 and TLS 1.1 before TLS 1.0 and SSL3, + if supported by your GnuTLS library. Use the existing + "gnutls_require_protocols" option to downgrade this if that will be a + problem. Prior to this release, supported values were "TLS1" and "SSL3", + so you should be able to update configuration prior to update. + * The match_{string1}{string2} expansion conditions no longer subject string2 to string expansion, unless Exim was built with the new "EXPAND_LISTMATCH_RHS" option. Too many people have inadvertently created diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index bf10526e9..f77768fb8 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -12,6 +12,13 @@ is based on a patch that was contributed by Nikos Mavroyanopoulos. No cryptographic code is included in Exim. All this module does is to call functions from the GnuTLS library. */ +/* Note: This appears to be using an old API from compat.h; it is likely that +someone familiary with GnuTLS programming could rework a lot of this to a +modern API and perhaps remove the explicit knowledge of crypto algorithms from +Exim. Such a re-work would be most welcome and we'd sacrifice support for +older GnuTLS releases without too many qualms -- maturity and experience +in crypto libraries tends to improve their robustness against attack. +Frankly, if you maintain it, you decide what's supported and what isn't. */ /* Heading stuff for GnuTLS */ @@ -46,6 +53,13 @@ static int verify_requirement; and space into which it can be copied and altered. */ static const int default_proto_priority[16] = { + /* These are gnutls_protocol_t enum values */ +#if GNUTLS_VERSION_MAJOR > 1 || GNUTLS_VERSION_MINOR >= 7 + GNUTLS_TLS1_2, +#endif +#if GNUTLS_VERSION_MAJOR > 1 || GNUTLS_VERSION_MINOR >= 2 + GNUTLS_TLS1_1, +#endif GNUTLS_TLS1, GNUTLS_SSL3, 0 }; @@ -89,11 +103,27 @@ typedef struct pri_item { } pri_item; -static int tls1_codes[] = { GNUTLS_TLS1, 0 }; +#if GNUTLS_VERSION_MAJOR > 1 || GNUTLS_VERSION_MINOR >= 7 +static int tls1_2_codes[] = { GNUTLS_TLS1_2, 0 }; +#endif +#if GNUTLS_VERSION_MAJOR > 1 || GNUTLS_VERSION_MINOR >= 2 +static int tls1_1_codes[] = { GNUTLS_TLS1_1, 0 }; +#endif +/* more recent libraries define this as an equivalent value to the +canonical GNUTLS_TLS1_0; since they're the same, we stick to the +older name. */ +static int tls1_0_codes[] = { GNUTLS_TLS1, 0 }; static int ssl3_codes[] = { GNUTLS_SSL3, 0 }; static pri_item proto_index[] = { - { US"TLS1", tls1_codes }, +#if GNUTLS_VERSION_MAJOR > 1 || GNUTLS_VERSION_MINOR >= 7 + { US"TLS1.2", tls1_2_codes }, +#endif +#if GNUTLS_VERSION_MAJOR > 1 || GNUTLS_VERSION_MINOR >= 2 + { US"TLS1.1", tls1_1_codes }, +#endif + { US"TLS1.0", tls1_0_codes }, + { US"TLS1", tls1_0_codes }, { US"SSL3", ssl3_codes } }; @@ -205,10 +235,10 @@ Returns: TRUE/FALSE static BOOL verify_certificate(gnutls_session session, const char **error) { -int verify; +int rc = -1; uschar *dn_string = US""; const gnutls_datum *cert; -unsigned int cert_size = 0; +unsigned int verify, cert_size = 0; *error = NULL; @@ -232,7 +262,7 @@ if (cert != NULL) dn_string = string_copy_malloc(buff); } - verify = gnutls_certificate_verify_peers(session); + rc = gnutls_certificate_verify_peers2(session, &verify); } else { @@ -244,7 +274,7 @@ else /* Handle the result of verification. INVALID seems to be set as well as REVOKED, but leave the test for both. */ -if ((verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0) +if ((rc < 0) || (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0) { tls_certificate_verified = FALSE; if (*error == NULL) *error = ((verify & GNUTLS_CERT_REVOKED) != 0)?