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; ...@@ -28,9 +28,9 @@ static Gsasl_session *sess_ctx;
28 static void auth_gsasl_capa_init (int disable); 28 static void auth_gsasl_capa_init (int disable);
29 29
30 static void 30 static void
31 finish_session (void) 31 finish_session (void *ptr)
32 { 32 {
33 gsasl_finish (sess_ctx); 33 gsasl_finish ((Gsasl_session *)ptr);
34 } 34 }
35 35
36 static int 36 static int
...@@ -171,7 +171,7 @@ auth_gsasl (struct imap4d_auth *ap) ...@@ -171,7 +171,7 @@ auth_gsasl (struct imap4d_auth *ap)
171 mu_stream_unref (newstream[0]); 171 mu_stream_unref (newstream[0]);
172 mu_stream_unref (newstream[1]); 172 mu_stream_unref (newstream[1]);
173 173
174 util_atexit (finish_session); 174 mu_onexit (finish_session, sess_ctx);
175 return imap4d_auth_ok; 175 return imap4d_auth_ok;
176 } 176 }
177 177
......
...@@ -443,7 +443,6 @@ int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp); ...@@ -443,7 +443,6 @@ int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp);
443 443
444 int util_is_master (void); 444 int util_is_master (void);
445 void util_bye (void); 445 void util_bye (void);
446 void util_atexit (void (*fp) (void));
447 void util_chdir (const char *homedir); 446 void util_chdir (const char *homedir);
448 int is_atom (const char *s); 447 int is_atom (const char *s);
449 int util_isdelim (const char *str); 448 int util_isdelim (const char *str);
......
...@@ -45,8 +45,6 @@ imap4d_starttls (struct imap4d_session *session, ...@@ -45,8 +45,6 @@ imap4d_starttls (struct imap4d_session *session,
45 if (imap4d_tokbuf_argc (tok) != 2) 45 if (imap4d_tokbuf_argc (tok) != 2)
46 return io_completion_response (command, RESP_BAD, "Invalid arguments"); 46 return io_completion_response (command, RESP_BAD, "Invalid arguments");
47 47
48 util_atexit (mu_deinit_tls_libs);
49
50 status = io_completion_response (command, RESP_OK, "Begin TLS negotiation"); 48 status = io_completion_response (command, RESP_OK, "Begin TLS negotiation");
51 io_flush (); 49 io_flush ();
52 50
...@@ -73,6 +71,7 @@ tls_encryption_on (struct imap4d_session *session) ...@@ -73,6 +71,7 @@ tls_encryption_on (struct imap4d_session *session)
73 71
74 session->tls_mode = tls_no; 72 session->tls_mode = tls_no;
75 imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED); 73 imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED);
74 mu_diag_output (MU_DIAG_INFO, _("TLS established"));
76 } 75 }
77 76
78 void 77 void
...@@ -80,8 +79,6 @@ starttls_init () ...@@ -80,8 +79,6 @@ starttls_init ()
80 { 79 {
81 tls_available = mu_check_tls_environment (); 80 tls_available = mu_check_tls_environment ();
82 if (tls_available) 81 if (tls_available)
83 tls_available = mu_init_tls_libs (1);
84 if (tls_available)
85 imap4d_capability_add (IMAP_CAPA_STARTTLS); 82 imap4d_capability_add (IMAP_CAPA_STARTTLS);
86 } 83 }
87 84
......
...@@ -273,29 +273,11 @@ util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp) ...@@ -273,29 +273,11 @@ util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp)
273 return mu_mailbox_uidvalidity (smbox, uidvp); 273 return mu_mailbox_uidvalidity (smbox, uidvp);
274 } 274 }
275 275
276 static mu_list_t atexit_list;
277
278 void
279 util_atexit (void (*fp) (void))
280 {
281 if (!atexit_list)
282 mu_list_create (&atexit_list);
283 mu_list_append (atexit_list, (void*)fp);
284 }
285
286 static int
287 atexit_run (void *item, void *data)
288 {
289 ((void (*) (void)) item) ();
290 return 0;
291 }
292
293 void 276 void
294 util_bye () 277 util_bye ()
295 { 278 {
296 mu_stream_close (iostream); 279 mu_stream_close (iostream);
297 mu_stream_destroy (&iostream); 280 mu_stream_destroy (&iostream);
298 mu_list_foreach (atexit_list, atexit_run, 0);
299 } 281 }
300 282
301 void 283 void
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
43 #include <mailutils/acl.h> 43 #include <mailutils/acl.h>
44 #include <mailutils/sockaddr.h> 44 #include <mailutils/sockaddr.h>
45 #include <mailutils/url.h> 45 #include <mailutils/url.h>
46 #include <mailutils/util.h>
46 47
47 typedef RETSIGTYPE (*mu_sig_handler_t) (int); 48 typedef RETSIGTYPE (*mu_sig_handler_t) (int);
48 49
...@@ -519,6 +520,7 @@ mu_m_server_begin (mu_m_server_t msrv) ...@@ -519,6 +520,7 @@ mu_m_server_begin (mu_m_server_t msrv)
519 mu_error (_("failed to become a daemon: %s"), mu_strerror (errno)); 520 mu_error (_("failed to become a daemon: %s"), mu_strerror (errno));
520 exit (EXIT_FAILURE); 521 exit (EXIT_FAILURE);
521 } 522 }
523 mu_onexit_reset ();
522 } 524 }
523 525
524 if (msrv->pidfile) 526 if (msrv->pidfile)
......
...@@ -54,9 +54,6 @@ mu_tls_module_init (enum mu_gocs_op op, void *data) ...@@ -54,9 +54,6 @@ mu_tls_module_init (enum mu_gocs_op op, void *data)
54 break; 54 break;
55 55
56 case mu_gocs_op_flush: 56 case mu_gocs_op_flush:
57 #ifdef WITH_TLS
58 mu_init_tls_libs (0);
59 #endif
60 break; 57 break;
61 } 58 }
62 return 0; 59 return 0;
...@@ -125,6 +122,24 @@ _mu_gtls_logger(int level, const char *text) ...@@ -125,6 +122,24 @@ _mu_gtls_logger(int level, const char *text)
125 } 122 }
126 #endif 123 #endif
127 124
125 void
126 mu_deinit_tls_libs (void)
127 {
128 if (mu_tls_enable)
129 {
130 if (x509_cred)
131 gnutls_certificate_free_credentials (x509_cred);
132 gnutls_global_deinit ();
133 }
134 mu_tls_enable = 0;
135 }
136
137 static void
138 _onexit_deinit (void *ptr MU_ARG_UNUSED)
139 {
140 mu_deinit_tls_libs ();
141 }
142
128 int 143 int
129 mu_init_tls_libs (int x509_setup) 144 mu_init_tls_libs (int x509_setup)
130 { 145 {
...@@ -138,6 +153,7 @@ mu_init_tls_libs (int x509_setup) ...@@ -138,6 +153,7 @@ mu_init_tls_libs (int x509_setup)
138 mu_error ("gnutls_global_init: %s", gnutls_strerror (rc)); 153 mu_error ("gnutls_global_init: %s", gnutls_strerror (rc));
139 return 0; 154 return 0;
140 } 155 }
156 mu_onexit (_onexit_deinit, NULL);
141 } 157 }
142 158
143 if (x509_setup && !x509_cred) 159 if (x509_setup && !x509_cred)
...@@ -161,18 +177,6 @@ mu_init_tls_libs (int x509_setup) ...@@ -161,18 +177,6 @@ mu_init_tls_libs (int x509_setup)
161 return mu_tls_enable; 177 return mu_tls_enable;
162 } 178 }
163 179
164 void
165 mu_deinit_tls_libs (void)
166 {
167 if (mu_tls_enable)
168 {
169 if (x509_cred)
170 gnutls_certificate_free_credentials (x509_cred);
171 gnutls_global_deinit ();
172 }
173 mu_tls_enable = 0;
174 }
175
176 static char default_priority_string[] = "NORMAL"; 180 static char default_priority_string[] = "NORMAL";
177 181
178 static gnutls_session_t 182 static gnutls_session_t
...@@ -408,7 +412,8 @@ _tls_server_open (mu_stream_t stream) ...@@ -408,7 +412,8 @@ _tls_server_open (mu_stream_t stream)
408 if (!stream || sp->state != state_init) 412 if (!stream || sp->state != state_init)
409 return EINVAL; 413 return EINVAL;
410 414
411 mu_init_tls_libs (1); 415 if (!mu_init_tls_libs (1))
416 return MU_ERR_FAILURE;
412 417
413 sp->session = initialize_tls_session (); 418 sp->session = initialize_tls_session ();
414 mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, transport); 419 mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, transport);
...@@ -481,7 +486,8 @@ _tls_client_open (mu_stream_t stream) ...@@ -481,7 +486,8 @@ _tls_client_open (mu_stream_t stream)
481 /* FALLTHROUGH */ 486 /* FALLTHROUGH */
482 487
483 case state_init: 488 case state_init:
484 mu_init_tls_libs (0); 489 if (!mu_init_tls_libs (0))
490 return MU_ERR_FAILURE;
485 prepare_client_session (stream); 491 prepare_client_session (stream);
486 rc = gnutls_handshake (sp->session); 492 rc = gnutls_handshake (sp->session);
487 if (rc < 0) 493 if (rc < 0)
......
...@@ -158,6 +158,7 @@ pop3d_setio (int ifd, int ofd, int tls) ...@@ -158,6 +158,7 @@ pop3d_setio (int ifd, int ofd, int tls)
158 pop3d_abquit (ERR_FILE); 158 pop3d_abquit (ERR_FILE);
159 } 159 }
160 tls_done = 1; 160 tls_done = 1;
161 mu_diag_output (MU_DIAG_INFO, _("TLS established"));
161 } 162 }
162 else 163 else
163 #endif 164 #endif
...@@ -238,10 +239,6 @@ pop3d_bye () ...@@ -238,10 +239,6 @@ pop3d_bye ()
238 { 239 {
239 mu_stream_close (iostream); 240 mu_stream_close (iostream);
240 mu_stream_destroy (&iostream); 241 mu_stream_destroy (&iostream);
241 #ifdef WITH_TLS
242 if (tls_available)
243 mu_deinit_tls_libs ();
244 #endif /* WITH_TLS */
245 } 242 }
246 243
247 void 244 void
......
...@@ -653,11 +653,7 @@ main (int argc, char **argv) ...@@ -653,11 +653,7 @@ main (int argc, char **argv)
653 #ifdef WITH_TLS 653 #ifdef WITH_TLS
654 tls_available = mu_check_tls_environment (); 654 tls_available = mu_check_tls_environment ();
655 if (tls_available) 655 if (tls_available)
656 {
657 tls_available = mu_init_tls_libs (1);
658 if (tls_available)
659 enable_stls (); 656 enable_stls ();
660 }
661 #endif /* WITH_TLS */ 657 #endif /* WITH_TLS */
662 658
663 /* Actually run the daemon. */ 659 /* Actually run the daemon. */
......