Merge branch 'list_safety'
authorPhil Pennock <pdp@exim.org>
Mon, 3 Oct 2011 11:36:12 +0000 (07:36 -0400)
committerPhil Pennock <pdp@exim.org>
Mon, 3 Oct 2011 11:36:12 +0000 (07:36 -0400)
(gnutls fixes had updated some text docs)

doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/README.UPDATING
src/src/tls-gnu.c

index 128329ef2d792b35c36034f6e891e134070381a9..81f69afaba28dc76199f69f598ac64375a1d9527 100644 (file)
@@ -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
index e2e95c54827213f0aca9b2b2e0ae78f9f48718d3..a911d80a1f3e849a07ddca9f8336c0f8bbc46411 100644 (file)
@@ -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".
 
index 20313b2cbdd9e44bc85030dfb61ea816c9e82daa..8a0533b102137bccb9d14eb082e2eacbb60febe3 100644 (file)
@@ -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_<type>{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
index bf10526e97d03b501ef2e4814dff256bb3c8fc5a..f77768fb8bcad489fa18c1c2653fd66e0aa18102 100644 (file)
@@ -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)?