Commit 10adba52 10adba5274b12a3c27e1a96bb6d934e430ce5f13 by Sergey Poznyakoff

Fix TLS streams

Avoid calling gnutls_global_init (via mu_tls_module_init) prior
to forking.  gnutls_global_init opens at least one file descriptor
(/dev/urandom), and closing it will disrupt its operation.
Current stable libgnutls (3.3.15) is able to cope with it, but
there are plenty of systems running much older versions.

* libmailutils/server/msrv.c (mu_m_server_begin): Reset onexit list
after forking.
* libmu_auth/tls.c (mu_tls_module_init): Don't call mu_init_tls_libs.
(_tls_server_open, _tls_client_open): Check return value from
mu_init_tls_libs.
* imap4d/auth_gsasl.c (auth_gsasl): Use mu_onexit to
register onexit functions.
* imap4d/imap4d.h (util_atexit): Remove prototype.
* imap4d/starttls.c (imap4d_starttls): Don't register
mu_deinit_tls_libs: now done by tls library.
(starttls_init): Don't call mu_init_tls_libs.
* imap4d/util.c (util_atexit): Remove.
(util_bye): Update accordingly.
* pop3d/extra.c (pop3d_setio): Print informational message after
establishing TLS.
(pop3d_bye): Don't call mu_deinit_tls_libs: that's done by the library.
* pop3d/pop3d.c (main): Don't call mu_init_tls_libs.
1 parent e57318e7
......@@ -28,9 +28,9 @@ static Gsasl_session *sess_ctx;
static void auth_gsasl_capa_init (int disable);
static void
finish_session (void)
finish_session (void *ptr)
{
gsasl_finish (sess_ctx);
gsasl_finish ((Gsasl_session *)ptr);
}
static int
......@@ -171,7 +171,7 @@ auth_gsasl (struct imap4d_auth *ap)
mu_stream_unref (newstream[0]);
mu_stream_unref (newstream[1]);
util_atexit (finish_session);
mu_onexit (finish_session, sess_ctx);
return imap4d_auth_ok;
}
......
......@@ -443,7 +443,6 @@ int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp);
int util_is_master (void);
void util_bye (void);
void util_atexit (void (*fp) (void));
void util_chdir (const char *homedir);
int is_atom (const char *s);
int util_isdelim (const char *str);
......
......@@ -45,8 +45,6 @@ imap4d_starttls (struct imap4d_session *session,
if (imap4d_tokbuf_argc (tok) != 2)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
util_atexit (mu_deinit_tls_libs);
status = io_completion_response (command, RESP_OK, "Begin TLS negotiation");
io_flush ();
......@@ -73,6 +71,7 @@ tls_encryption_on (struct imap4d_session *session)
session->tls_mode = tls_no;
imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED);
mu_diag_output (MU_DIAG_INFO, _("TLS established"));
}
void
......@@ -80,8 +79,6 @@ starttls_init ()
{
tls_available = mu_check_tls_environment ();
if (tls_available)
tls_available = mu_init_tls_libs (1);
if (tls_available)
imap4d_capability_add (IMAP_CAPA_STARTTLS);
}
......
......@@ -273,29 +273,11 @@ util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp)
return mu_mailbox_uidvalidity (smbox, uidvp);
}
static mu_list_t atexit_list;
void
util_atexit (void (*fp) (void))
{
if (!atexit_list)
mu_list_create (&atexit_list);
mu_list_append (atexit_list, (void*)fp);
}
static int
atexit_run (void *item, void *data)
{
((void (*) (void)) item) ();
return 0;
}
void
util_bye ()
{
mu_stream_close (iostream);
mu_stream_destroy (&iostream);
mu_list_foreach (atexit_list, atexit_run, 0);
}
void
......
......@@ -43,6 +43,7 @@
#include <mailutils/acl.h>
#include <mailutils/sockaddr.h>
#include <mailutils/url.h>
#include <mailutils/util.h>
typedef RETSIGTYPE (*mu_sig_handler_t) (int);
......@@ -519,6 +520,7 @@ mu_m_server_begin (mu_m_server_t msrv)
mu_error (_("failed to become a daemon: %s"), mu_strerror (errno));
exit (EXIT_FAILURE);
}
mu_onexit_reset ();
}
if (msrv->pidfile)
......
......@@ -54,9 +54,6 @@ mu_tls_module_init (enum mu_gocs_op op, void *data)
break;
case mu_gocs_op_flush:
#ifdef WITH_TLS
mu_init_tls_libs (0);
#endif
break;
}
return 0;
......@@ -125,6 +122,24 @@ _mu_gtls_logger(int level, const char *text)
}
#endif
void
mu_deinit_tls_libs (void)
{
if (mu_tls_enable)
{
if (x509_cred)
gnutls_certificate_free_credentials (x509_cred);
gnutls_global_deinit ();
}
mu_tls_enable = 0;
}
static void
_onexit_deinit (void *ptr MU_ARG_UNUSED)
{
mu_deinit_tls_libs ();
}
int
mu_init_tls_libs (int x509_setup)
{
......@@ -138,6 +153,7 @@ mu_init_tls_libs (int x509_setup)
mu_error ("gnutls_global_init: %s", gnutls_strerror (rc));
return 0;
}
mu_onexit (_onexit_deinit, NULL);
}
if (x509_setup && !x509_cred)
......@@ -161,18 +177,6 @@ mu_init_tls_libs (int x509_setup)
return mu_tls_enable;
}
void
mu_deinit_tls_libs (void)
{
if (mu_tls_enable)
{
if (x509_cred)
gnutls_certificate_free_credentials (x509_cred);
gnutls_global_deinit ();
}
mu_tls_enable = 0;
}
static char default_priority_string[] = "NORMAL";
static gnutls_session_t
......@@ -408,7 +412,8 @@ _tls_server_open (mu_stream_t stream)
if (!stream || sp->state != state_init)
return EINVAL;
mu_init_tls_libs (1);
if (!mu_init_tls_libs (1))
return MU_ERR_FAILURE;
sp->session = initialize_tls_session ();
mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, transport);
......@@ -481,7 +486,8 @@ _tls_client_open (mu_stream_t stream)
/* FALLTHROUGH */
case state_init:
mu_init_tls_libs (0);
if (!mu_init_tls_libs (0))
return MU_ERR_FAILURE;
prepare_client_session (stream);
rc = gnutls_handshake (sp->session);
if (rc < 0)
......
......@@ -158,6 +158,7 @@ pop3d_setio (int ifd, int ofd, int tls)
pop3d_abquit (ERR_FILE);
}
tls_done = 1;
mu_diag_output (MU_DIAG_INFO, _("TLS established"));
}
else
#endif
......@@ -238,10 +239,6 @@ pop3d_bye ()
{
mu_stream_close (iostream);
mu_stream_destroy (&iostream);
#ifdef WITH_TLS
if (tls_available)
mu_deinit_tls_libs ();
#endif /* WITH_TLS */
}
void
......
......@@ -653,11 +653,7 @@ main (int argc, char **argv)
#ifdef WITH_TLS
tls_available = mu_check_tls_environment ();
if (tls_available)
{
tls_available = mu_init_tls_libs (1);
if (tls_available)
enable_stls ();
}
#endif /* WITH_TLS */
/* Actually run the daemon. */
......