diff options
Diffstat (limited to 'imap4d/starttls.c')
-rw-r--r-- | imap4d/starttls.c | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/imap4d/starttls.c b/imap4d/starttls.c index 4c87bcd84..78be4509b 100644 --- a/imap4d/starttls.c +++ b/imap4d/starttls.c @@ -1,5 +1,5 @@ /* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 2003-2019 Free Software Foundation, Inc. + Copyright (C) 2003-2024 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,8 +15,11 @@ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ #include "imap4d.h" +#include <mailutils/sockaddr.h> -struct mu_tls_config global_tls_conf; +static int global_conf_status = -1; +int global_tls_mode; +struct mu_tls_config global_tls_conf = { .handshake_timeout = 10 }; /* 6.2.1. STARTTLS Command @@ -26,11 +29,11 @@ struct mu_tls_config global_tls_conf; Responses: no specific response for this command Result: OK - starttls completed, begin TLS negotiation - BAD - command unknown or arguments invalid + BAD - command unknown or arguments invalid */ int imap4d_starttls (struct imap4d_session *session, - struct imap4d_command *command, imap4d_tokbuf_t tok) + struct imap4d_command *command, imap4d_tokbuf_t tok) { int status; @@ -60,13 +63,94 @@ tls_encryption_on (struct imap4d_session *session) { session->tls_mode = tls_no; imap4d_capability_remove (IMAP_CAPA_STARTTLS); - + login_disabled = 0; imap4d_capability_remove (IMAP_CAPA_LOGINDISABLED); imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED); } +static int +global_tls_status (void) +{ + if (global_conf_status == -1) + { + if (global_tls_conf.cert_file) + global_conf_status = mu_tls_config_check (&global_tls_conf, 1); + else + global_conf_status = MU_TLS_CONFIG_NULL; + + if (global_conf_status != MU_TLS_CONFIG_OK) + global_tls_mode = tls_no; + } + return global_conf_status; +} + +int +starttls_server_check (struct imap4d_srv_config *cfg, char const *srvid) +{ + int result; + + switch (cfg->tls_mode) + { + case tls_unspecified: + { + if (cfg->tls_conf.cert_file || global_tls_status () == MU_TLS_CONFIG_OK) + { + struct mu_sockaddr *sa; + int port = -1; + + mu_ip_server_get_sockaddr (cfg->m_cfg.tcpsrv, &sa); + mu_sockaddr_get_port (sa, &port); + mu_sockaddr_free (sa); + + if (port == PORT_IMAP4S) + cfg->tls_mode = tls_connection; + else if (global_tls_mode != tls_unspecified) + cfg->tls_mode = global_tls_mode; + else + cfg->tls_mode = tls_ondemand; + break; + } + } + /* fall through */ + case tls_no: + return MU_TLS_CONFIG_NULL; + + default: + break; + } + + result = mu_tls_config_check (&cfg->tls_conf, 1); + switch (result) + { + case MU_TLS_CONFIG_OK: + if (!cfg->tls_conf.cert_file) + { + mu_error (_("server %s: no certificate set"), srvid); + result = MU_TLS_CONFIG_FAIL; + } + break; + + case MU_TLS_CONFIG_NULL: + if (global_tls_status () == MU_TLS_CONFIG_OK) + { + cfg->tls_conf = global_tls_conf; + result = MU_TLS_CONFIG_OK; + } + else + { + mu_error (_("server %s: no certificate set"), srvid); + result = MU_TLS_CONFIG_FAIL; + } + break; + + default: + mu_error (_("server %s: TLS configuration failed"), srvid); + } + return result; +} + int starttls_init (mu_m_server_t msrv) { @@ -75,13 +159,7 @@ starttls_init (mu_m_server_t msrv) int errors = 0; int tls_ok = mu_init_tls_libs (); int tls_requested = 0; - int global_conf_status = 0; - if (global_tls_conf.cert_file) - global_conf_status = mu_tls_config_check (&global_tls_conf, 1); - else - global_conf_status = MU_TLS_CONFIG_NULL; - mu_m_server_get_srvlist (msrv, &srvlist); mu_list_get_iterator (srvlist, &itr); for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) @@ -90,54 +168,18 @@ starttls_init (mu_m_server_t msrv) struct imap4d_srv_config *cfg; mu_iterator_current (itr, (void**) &ipsrv); cfg = mu_ip_server_get_data (ipsrv); - switch (cfg->tls_mode) + switch (starttls_server_check (cfg, mu_ip_server_addrstr (ipsrv))) { - case tls_unspecified: - if (cfg->tls_conf.cert_file) - { - cfg->tls_mode = tls_ondemand; - break; - } - else - cfg->tls_mode = tls_no; - /* fall through */ - case tls_no: + case MU_TLS_CONFIG_NULL: continue; - - default: - break; - } - switch (mu_tls_config_check (&cfg->tls_conf, 1)) - { case MU_TLS_CONFIG_OK: - if (!cfg->tls_conf.cert_file) - { - mu_error (_("server %s: no certificate set"), - mu_ip_server_addrstr (ipsrv)); - errors = 1; - } - break; - - case MU_TLS_CONFIG_NULL: - if (global_conf_status != MU_TLS_CONFIG_NULL) - { - cfg->tls_conf = global_tls_conf; - } - else - { - mu_error (_("server %s: no certificate set"), - mu_ip_server_addrstr (ipsrv)); - errors = 1; - } break; default: - mu_error (_("server %s: TLS configuration failed"), - mu_ip_server_addrstr (ipsrv)); errors = 1; } - + tls_requested = 1; } mu_iterator_destroy (&itr); @@ -148,7 +190,7 @@ starttls_init (mu_m_server_t msrv) "configuration")); errors = 1; } - + if (errors) return 1; |