[exim-cvs] Guards for older releases of GnuTLS.

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Guards for older releases of GnuTLS.
Gitweb: http://git.exim.org/exim.git/commitdiff/af3498d60d7cae92d50e56353ae19f304b84e6ca
Commit:     af3498d60d7cae92d50e56353ae19f304b84e6ca
Parent:     eae0036b2dfac1547351908f77a6154b898c45d6
Author:     Phil Pennock <pdp@???>
AuthorDate: Thu May 17 01:32:13 2012 -0400
Committer:  Phil Pennock <pdp@???>
CommitDate: Thu May 17 01:32:13 2012 -0400


    Guards for older releases of GnuTLS.


    gnutls_sec_param_to_pk_bits() and gnutls_rnd() are both new as of
    GnuTLS 2.12.x.  Guard their usage on 2.12.0+ at compile time.


    In older versions, the vaguely_random_number() function just immediately
    calls the fallback, so it's the same as before this change (just one
    extra indirection in the code-path).


    Define a constant of 1024 for dh-bits for use in those old releases
    where GnuTLS won't tell us how many we should use.


    Change the on-disk filename for generated D-H params again, replacing
    the -normal with -<bitcount>, so that it's 1024 or whatever, and as
    the value changes, Exim will automatically start using the new value.
---
 doc/doc-docbook/spec.xfpt |   25 ++++++++++++++------
 doc/doc-txt/ChangeLog     |    1 +
 doc/doc-txt/NewStuff      |    3 ++
 src/src/tls-gnu.c         |   53 +++++++++++++++++++++++++++++++++++++-------
 4 files changed, 65 insertions(+), 17 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 22b805c..6d1802b 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -9772,7 +9772,8 @@ supplied number and is at least 0. The quality of this randomness depends
on how Exim was built; the values are not suitable for keying material.
If Exim is linked against OpenSSL then RAND_pseudo_bytes() is used.
.new
-if Exim is linked against GnuTLS then gnutls_rnd(GNUTLS_RND_NONCE) is used.
+If Exim is linked against GnuTLS then gnutls_rnd(GNUTLS_RND_NONCE) is used,
+for versions of GnuTLS with that function.
.wen
Otherwise, the implementation may be arc4random(), random() seeded by
srandomdev() or srandom(), or a custom implementation even weaker than
@@ -24964,7 +24965,8 @@ implementation, then patches are welcome.
GnuTLS uses D-H parameters that may take a substantial amount of time
to compute. It is unreasonable to re-compute them for every TLS session.
Therefore, Exim keeps this data in a file in its spool directory, called
-&_gnutls-params-normal_&.
+&_gnutls-params-NNNN_& for some value of NNNN, corresponding to the number
+of bits requested.
The file is owned by the Exim user and is readable only by
its owner. Every Exim process that start up GnuTLS reads the D-H
parameters from this file. If the file does not exist, the first Exim process
@@ -24983,7 +24985,7 @@ until enough randomness (entropy) is available. This may cause Exim to hang for
a substantial amount of time, causing timeouts on incoming connections.

The solution is to generate the parameters externally to Exim. They are stored
-in &_gnutls-params-normal_& in PEM format, which means that they can be
+in &_gnutls-params-N_& in PEM format, which means that they can be
generated externally using the &(certtool)& command that is part of GnuTLS.

To replace the parameters with new ones, instead of deleting the file
@@ -24991,20 +24993,27 @@ and letting Exim re-create it, you can generate new parameters using
&(certtool)& and, when this has been done, replace Exim's cache file by
renaming. The relevant commands are something like this:
.code
+# ls
+[ look for file; assume gnutls-params-1024 is the most recent ]
# rm -f new-params
# touch new-params
# chown exim:exim new-params
# chmod 0600 new-params
-# certtool --generate-dh-params >>new-params
+# certtool --generate-dh-params --bits 1024 >>new-params
# chmod 0400 new-params
-# mv new-params gnutls-params-normal
+# mv new-params gnutls-params-1024
.endd
If Exim never has to generate the parameters itself, the possibility of
stalling is removed.

-The filename changed in Exim 4.78, to gain the -normal suffix, corresponding
-to the GnuTLS constant &`GNUTLS_SEC_PARAM_NORMAL`&, defining the number of
-bits to include. At time of writing, NORMAL corresponds to 2432 bits for D-H.
+The filename changed in Exim 4.78, to gain the -bits suffix. The value which
+Exim will choose depends upon the version of GnuTLS in use. For older GnuTLS,
+the value remains hard-coded in Exim as 1024. As of GnuTLS 2.12.x, there is
+a way for Exim to ask for the "normal" number of bits for D-H public-key usage,
+and Exim does so. Exim thus removes itself from the policy decision, and the
+filename and bits used change as the GnuTLS maintainers change the value for
+their parameter &`GNUTLS_SEC_PARAM_NORMAL`&. At the time of writing, this
+gives 2432 bits.
.wen


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index ff463b1..a93041e 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -106,6 +106,7 @@ PP/25 Revamped GnuTLS support, passing tls_require_ciphers to
       gnutls_priority_init, ignoring Exim options gnutls_require_kx,
       gnutls_require_mac & gnutls_require_protocols (no longer supported).
       Added SNI support via GnuTLS too.
+      Made ${randint:..} supplier available, if using not-too-old GnuTLS.


PP/26 Added EXPERIMENTAL_OCSP for OpenSSL.

diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 82eaeb7..7b3b5af 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -80,6 +80,9 @@ Version 4.78

     SNI support has been added to Exim's GnuTLS integration too.


+    For sufficiently recent GnuTLS libraries, ${randint:..} will now use
+    gnutls_rnd(), asking for GNUTLS_RND_NONCE level randomness.
+
 12. With OpenSSL, if built with EXPERIMENTAL_OCSP, a new option tls_ocsp_file
     is now available.  If the contents of the file are valid, then Exim will
     send that back in response to a TLS status request; this is OCSP Stapling.
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index f0e391f..6dd76cd 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -141,12 +141,6 @@ static BOOL exim_gnutls_base_init_done = FALSE;



/* ------------------------------------------------------------------------ */
-/* Callback declarations */
-
-static void exim_gnutls_logger_cb(int level, const char *message);
-static int exim_sni_handling_cb(gnutls_session_t session);
-
-/* ------------------------------------------------------------------------ */
/* macros */

#define MAX_HOST_LEN 255
@@ -158,6 +152,11 @@ callbacks. */

#define EXIM_CLIENT_DH_MIN_BITS 1024

+/* With GnuTLS 2.12.x+ we have gnutls_sec_param_to_pk_bits() with which we
+can ask for a bit-strength. Without that, we stick to the constant we had
+before, for now. */
+#define EXIM_SERVER_DH_BITS_PRE2_12 1024
+
#define exim_gnutls_err_check(Label) do { \
if (rc != GNUTLS_E_SUCCESS) { return tls_error((Label), gnutls_strerror(rc), host); } } while (0)

@@ -170,8 +169,25 @@ callbacks. */

#if GNUTLS_VERSION_NUMBER >= 0x020c00
#define HAVE_GNUTLS_SESSION_CHANNEL_BINDING
+#define HAVE_GNUTLS_SEC_PARAM_CONSTANTS
+#define HAVE_GNUTLS_RND
#endif

+
+
+
+/* ------------------------------------------------------------------------ */
+/* Callback declarations */
+
+#if EXIM_GNUTLS_LIBRARY_LOG_LEVEL >= 0
+static void exim_gnutls_logger_cb(int level, const char *message);
+#endif
+
+static int exim_sni_handling_cb(gnutls_session_t session);
+
+
+
+
/* ------------------------------------------------------------------------ */
/* Static functions */

@@ -380,21 +396,30 @@ gnutls_datum m;
uschar filename[PATH_MAX];
size_t sz;
host_item *host = NULL; /* dummy for macros */
-const char * const dh_param_fn_ext = "normal"; /* change as dh_bits changes */

DEBUG(D_tls) debug_printf("Initialising GnuTLS server params.\n");

rc = gnutls_dh_params_init(&dh_server_params);
exim_gnutls_err_check(US"gnutls_dh_params_init");

-/* If you change this, also change dh_param_fn_ext so that we can use a
+#ifdef HAVE_GNUTLS_SEC_PARAM_CONSTANTS
+/* If you change this constant, also change dh_param_fn_ext so that we can use a
 different filename and ensure we have sufficient bits. */
 dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_NORMAL);
 if (!dh_bits)
   return tls_error(US"gnutls_sec_param_to_pk_bits() failed", NULL, NULL);
+DEBUG(D_tls)
+  debug_printf("GnuTLS tells us that for D-H PL, NORMAL is %d bits.\n",
+      dh_bits);
+#else
+dh_bits = EXIM_SERVER_DH_BITS_PRE2_12;
+DEBUG(D_tls)
+  debug_printf("GnuTLS lacks gnutls_sec_param_to_pk_bits(), using %d bits.\n",
+      dh_bits);
+#endif


 if (!string_format(filename, sizeof(filename),
-      "%s/gnutls-params-%s", spool_directory, dh_param_fn_ext))
+      "%s/gnutls-params-%d", spool_directory, dh_bits))
   return tls_error(US"overlong filename", NULL, NULL);


/* Open the cache file for reading and if successful, read it and set up the
@@ -1095,11 +1120,13 @@ return TRUE;
* gnutls_global_set_log_function()
* gnutls_global_set_log_level() 0..9
*/
+#if EXIM_GNUTLS_LIBRARY_LOG_LEVEL >= 0
static void
exim_gnutls_logger_cb(int level, const char *message)
{
DEBUG(D_tls) debug_printf("GnuTLS<%d>: %s\n", level, message);
}
+#endif


 /* Called after client hello, should handle SNI work.
@@ -1667,6 +1694,7 @@ Arguments:
 Returns     a random number in range [0, max-1]
 */


+#ifdef HAVE_GNUTLS_RND
int
vaguely_random_number(int max)
{
@@ -1704,6 +1732,13 @@ for (p = smallbuf; needed_len; --needed_len, ++p)
* smooth distribution and cares enough then they should submit a patch then. */
return r % max;
}
+#else /* HAVE_GNUTLS_RND */
+int
+vaguely_random_number(int max)
+{
+ return vaguely_random_number_fallback(max);
+}
+#endif /* HAVE_GNUTLS_RND */