From 8db11a8a18bf025186ac9913c1c9ea79df0bc66e Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Wed, 15 Mar 2000 23:25:42 +0000 Subject: [PATCH] Fix entropy gathering in the IMAP SSL support. From Tommi Komulainen. --- README.SSL | 15 ++++++++ configure.in | 3 ++ imap/imap_ssl.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-- imap/imap_ssl.h | 8 ++-- imap/socket.c | 5 +-- init.h | 5 +++ 6 files changed, 123 insertions(+), 12 deletions(-) diff --git a/README.SSL b/README.SSL index 38367d80..1cdceab4 100644 --- a/README.SSL +++ b/README.SSL @@ -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 diff --git a/configure.in b/configure.in index d78e52fb..a1b929a7 100644 --- a/configure.in +++ b/configure.in @@ -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" diff --git a/imap/imap_ssl.c b/imap/imap_ssl.c index 9b73e854..0691702d 100644 --- a/imap/imap_ssl.c +++ b/imap/imap_ssl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999 Tommi Komulainen + * Copyright (C) 1999-2000 Tommi Komulainen * * 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 #include #include +#include #undef _ @@ -36,7 +37,22 @@ #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); diff --git a/imap/imap_ssl.h b/imap/imap_ssl.h index 03fc7850..2e9bed2d 100644 --- a/imap/imap_ssl.h +++ b/imap/imap_ssl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999 Tommi Komulainen + * Copyright (C) 1999-2000 Tommi Komulainen * * 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 @@ -20,10 +20,8 @@ #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 diff --git a/imap/socket.c b/imap/socket.c index 533fa1fc..d8151c95 100644 --- a/imap/socket.c +++ b/imap/socket.c @@ -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 37ed629a..d100aba2 100644 --- 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 -- 2.40.0