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.
Showing
8 changed files
with
30 additions
and
51 deletions
... | @@ -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. */ | ... | ... |
-
Please register or sign in to post a comment