]> granicus.if.org Git - neomutt/commitdiff
Fix entropy gathering in the IMAP SSL support. From Tommi Komulainen.
authorThomas Roessler <roessler@does-not-exist.org>
Wed, 15 Mar 2000 23:25:42 +0000 (23:25 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Wed, 15 Mar 2000 23:25:42 +0000 (23:25 +0000)
README.SSL
configure.in
imap/imap_ssl.c
imap/imap_ssl.h
imap/socket.c
init.h

index 38367d80dc1ed31df3c62957e1296e5e5410a757..1cdceab4fecd5cae269291b7cfc38df12b637e75 100644 (file)
@@ -26,6 +26,21 @@ For example:
        mailboxes {localhost:994/ssl}inbox
 
 
+If you get errors about lack of entropy, it means that Mutt was unable
+to find a source of random data to initialize SSL library with. Should
+this happen, you need to generate the data yourself and save it in a
+file somewhere Mutt will find it. Mutt tries to use files
+$SslEntropyFile, $RANDFILE (if this environment variable is set) and
+~/.rnd in that order as source for random data.
+
+If your OpenSSL is version 0.9.5 or later, you should try EGD, Entropy
+Gathering Daemon, from http://www.lothar.com/tech/crypto/ . Mutt will
+try to find EGD sockets in the following places, $SslEntropyFile,
+$EGDSOCKET (if this environment variable is set), ~/.entropy and
+/tmp/entropy. If no socket is found, static files will be tried as
+described above.
+
+
 Each time a server is contacted, its certificate is checked against
 known valid certificates. When an unknown certificate is encountered,
 you are asked to verify it. If you reject the certificate, the
index d78e52fb9d84b3dd0e35d3d0bd952e1d846c778e..a1b929a733fb5dba2c9d71bcddc57da93a3a07b4 100644 (file)
@@ -506,6 +506,9 @@ AC_ARG_WITH(ssl, [    --with-ssl[=PFX]         Compile in SSL socket support for
 
          AC_CHECK_LIB(crypto, X509_new,, AC_MSG_ERROR([Unable to find SSL library]))
          AC_CHECK_LIB(ssl, SSL_new,, AC_MSG_ERROR([Unable to find SSL library]), -lcrypto)
+
+         AC_CHECK_FUNCS(RAND_status RAND_egd)
+
          AC_DEFINE(USE_SSL)
          LIBS="$saved_LIBS"
          MUTTLIBS="$MUTTLIBS -lssl -lcrypto"
index 9b73e854196e1fba2ddfe782a746b883a12faf1d..0691702d2ff422a5d7c5c2bee17bd9346a697862 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi>
+ * Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen@iki.fi>
  * 
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 #include <openssl/err.h>
+#include <openssl/rand.h>
 
 #undef _
 
 #define READ_X509_KEY(fp, key) PEM_read_X509(fp, key, NULL)
 #endif
 
+/* This is ugly, but as RAND_status came in on OpenSSL version 0.9.5
+ * and the code has to support older versions too, this is seemed to
+ * be cleaner way compared to having even uglier #ifdefs all around.
+ */
+#ifdef HAVE_RAND_STATUS
+#define HAVE_ENTROPY() (RAND_status() == 1)
+#define GOT_ENTROPY()  return 0;
+#else
+static int needentropy = 1;
+/* OpenSSL fills the entropy pool from /dev/urandom if it exists */
+#define HAVE_ENTROPY() (!access("/dev/urandom", R_OK) || !needentropy)
+#define GOT_ENTROPY()  do { needentropy = 1; return 0; } while (0)
+#endif
+
 char *SslCertFile = NULL;
+char *SslEntropyFile = NULL;
 
 typedef struct _sslsockdata
 {
@@ -46,9 +62,87 @@ typedef struct _sslsockdata
 }
 sslsockdata;
 
+/* 
+ * OpenSSL library needs to be fed with sufficient entropy. On systems
+ * with /dev/urandom, this is done transparently by the library itself,
+ * on other systems we need to fill the entropy pool ourselves.
+ *
+ * Even though only OpenSSL 0.9.5 and later will complain about the
+ * lack of entropy, we try to our best and fill the pool with older
+ * versions also. (That's the reason for the ugly #ifdefs and macros,
+ * otherwise I could have simply #ifdef'd the whole ssl_init funcion)
+ */
+int ssl_init (void)
+{
+  char path[_POSIX_PATH_MAX], *file;
+
+  if (HAVE_ENTROPY()) return 0;
+  
+  mutt_message (_("Filling entropy pool"));
+  
+  /* try egd */
+#ifdef HAVE_RAND_EGD
+  file = SslEntropyFile;
+  if (file && RAND_egd(file) != -1)
+    GOT_ENTROPY;
+  file = getenv("EGDSOCKET");
+  if (file && RAND_egd(file) != -1)
+    GOT_ENTROPY();
+  snprintf (path, sizeof(path), "%s/.entropy", NONULL(Homedir));
+  if (RAND_egd(path) != -1)
+    GOT_ENTROPY();
+  if (RAND_egd("/tmp/entropy") != -1)
+    GOT_ENTROPY();
+#endif
+
+  /* try some files */
+  file = SslEntropyFile;
+  if (!file || access(file, R_OK) == -1)
+    file = getenv("RANDFILE");
+  if (!file || access(file, R_OK) == -1) {
+    snprintf (path, sizeof(path), "%s/.rnd", NONULL(Homedir));
+    file = path;
+  }
+  if (access(file, R_OK) == 0) {
+    if (RAND_load_file(file, 10240) >= 16)
+      GOT_ENTROPY();
+  }
+
+  if (HAVE_ENTROPY()) return 0;
+
+  mutt_error (_("Failed to find enough entropy on your system"));
+  sleep (2);
+  return -1;
+}
+
+static int ssl_socket_open_err (CONNECTION *conn)
+{
+  mutt_error (_("SSL disabled due the lack of entropy"));
+  sleep (2);
+  return -1;
+}
 
 static int ssl_check_certificate (sslsockdata * data);
 
+static int ssl_socket_read (CONNECTION * conn);
+static int ssl_socket_write (CONNECTION * conn, const char *buf);
+static int ssl_socket_open (CONNECTION * conn);
+static int ssl_socket_close (CONNECTION * conn);
+
+int ssl_socket_setup (CONNECTION * conn)
+{
+  if (ssl_init() < 0) {
+    conn->open = ssl_socket_open_err;
+    return -1;
+  }
+
+  conn->open   = ssl_socket_open;
+  conn->read   = ssl_socket_read;
+  conn->write  = ssl_socket_write;
+  conn->close  = ssl_socket_close;
+
+  return 0;
+}
 
 int ssl_socket_read (CONNECTION * conn)
 {
@@ -74,7 +168,7 @@ int ssl_socket_open (CONNECTION * conn)
   data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata));
   conn->sockdata = data;
 
-  SSLeay_add_ssl_algorithms ();
+  SSL_library_init();
   data->ctx = SSL_CTX_new (SSLv23_client_method ());
 
   /* disable SSL protocols as needed */
@@ -82,7 +176,6 @@ int ssl_socket_open (CONNECTION * conn)
   {
     SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1);
   }
-
   if (!option(OPTSSLV2)) 
   {
     SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2);
index 03fc785018fd5cd5c457ee87bce6dfa1b38e8b7e..2e9bed2d1bbcc7d9ec147f55e43d084ba861f098 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi>
+ * Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen@iki.fi>
  * 
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
 #define _MUTT_SSL_H_ 1
 
 extern char *SslCertFile;
+extern char *SslEntropyFile;
 
-extern int ssl_socket_read (CONNECTION *conn);
-extern int ssl_socket_write (CONNECTION *conn, const char *buf);
-extern int ssl_socket_open (CONNECTION *conn);
-extern int ssl_socket_close (CONNECTION *conn);
+extern int ssl_socket_setup (CONNECTION *conn);
 
 #endif
index 533fa1fc1fe8918aee7cbadeb8274e5792255935..d8151c95b7e2bf0af5c279ada0940c1e8020be70 100644 (file)
@@ -139,10 +139,7 @@ CONNECTION *mutt_socket_select_connection (const IMAP_MBOX *mx, int newconn)
 #ifdef USE_SSL
   if (mx->socktype == M_NEW_SSL_SOCKET) 
   {
-      conn->read = ssl_socket_read;
-      conn->write = ssl_socket_write;
-      conn->open = ssl_socket_open;
-      conn->close = ssl_socket_close;
+    ssl_socket_setup (conn);
   }
   else
 #endif
diff --git a/init.h b/init.h
index 37ed629a86d355bff556a0914fecde1558ab765f..d100aba2023f0fba894db60352430cb2bce941c0 100644 (file)
--- a/init.h
+++ b/init.h
@@ -1334,6 +1334,11 @@ struct option_t MuttVars[] = {
   ** be saved in this file and further connections are automatically 
   ** accepted.
   */
+  { "entropy_file",    DT_PATH, R_NONE, UL &SslEntropyFile, 0 },
+  /* .pp
+  ** The file which includes random data that is used to initalize SSL
+  ** library functions.
+   */
   { "ssl_use_sslv2", DT_BOOL, R_NONE, OPTSSLV2, 1 },
   /*
   ** .pp