diff options
-rw-r--r-- | NEWS | 20 | ||||
-rw-r--r-- | doc/texinfo/programs/pop3d.texi | 33 | ||||
-rw-r--r-- | pop3d/cmd.c | 98 | ||||
-rw-r--r-- | pop3d/pop3d.c | 31 | ||||
-rw-r--r-- | pop3d/pop3d.h | 2 |
5 files changed, 142 insertions, 42 deletions
@@ -1,4 +1,4 @@ -GNU mailutils NEWS -- history of user-visible changes. 2019-06-21 +GNU mailutils NEWS -- history of user-visible changes. 2019-08-29 Copyright (C) 2002-2019 Free Software Foundation, Inc. See the end of file for copying conditions. @@ -6,6 +6,24 @@ Please send mailutils bug reports to <bug-mailutils@gnu.org>. Version 3.7.90 (git) +* Use of TLS in pop3d run from inetd + +New global configuration statement "tls-mode" configures the TLS for +use in inetd mode. + +The certificate and key files are configured by the global "tls" +compound statement. + +Example configuration (pop3s server): + + mode inetd; + tls-mode connection; + tls { + ssl-key-file /etc/ssl/key.pem; + ssl-certificate-file /etc/ssl/cert.pem; + } + + Version 3.7 - 2019-06-21 * Support for the new mailbox format - dotmail diff --git a/doc/texinfo/programs/pop3d.texi b/doc/texinfo/programs/pop3d.texi index 93ace2fff..b508bf534 100644 --- a/doc/texinfo/programs/pop3d.texi +++ b/doc/texinfo/programs/pop3d.texi @@ -213,6 +213,34 @@ The following configuration file statements affect the behavior of @item tcp-wrappers @tab @xref{tcp-wrappers statement}. @end multitable +@deffn {Pop3d Conf} tls-mode @var{mode} +Configure the use of TLS encryption for inetd mode. + +In daemon mode, this statement sets the type of TLS encryption to +use in all server blocks that lack the @code{tls-mode} statement +(@pxref{Server Statement}). + +Allowed values for @var{mode} are: + +@table @asis +@item no +TLS is not used. The @command{STLS} command won't be available even if +the TLS configuration is otherwise complete. + +@item ondemand +TLS is initiated when the user issues the appropriate command. +This is the default when TLS is configured. + +@item required +Same as above, but the use of TLS is mandatory. The authentication +state is entered only after TLS negotiation has succeeded. + +@item connection +TLS is always forced when the connection is established (POP3S +protocol). +@end table +@end deffn + @deffn {Pop3d Conf} undelete @var{bool} On startup, clear deletion marks from all the messages. @end deffn @@ -227,11 +255,6 @@ Delete expired messages upon closing the mailbox. @xref{Auto-expire}, for a detailed description. @end deffn -@deffn {Pop3d Conf} tls-required @var{bool} -Always require @code{STLS} command before entering authentication -phase. -@end deffn - @deffn {Pop3d Conf} login-delay @var{duration} Set the minimal allowed delay between two successive logins. @xref{Login delay}, for more information. diff --git a/pop3d/cmd.c b/pop3d/cmd.c index 5ca7b7b86..1ed73c237 100644 --- a/pop3d/cmd.c +++ b/pop3d/cmd.c @@ -17,6 +17,8 @@ #include "pop3d.h" struct mu_tls_config global_tls_conf; +int global_tls_mode; +int global_conf_status = -1; static struct pop3d_command command_table[] = { { "STLS", pop3d_stls }, @@ -49,73 +51,96 @@ pop3d_find_command (const char *name) } int -stls_preflight (mu_m_server_t msrv) +stls_server_check (struct pop3d_srv_config *cfg, char const *srvid) { - mu_list_t srvlist; - mu_iterator_t itr; - int errors = 0; - int tls_ok = mu_init_tls_libs (); - int tls_requested = 0; - int global_conf_status = 0; + int result; - 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)) - { - mu_ip_server_t ipsrv; - struct pop3d_srv_config *cfg; - mu_iterator_current (itr, (void**) &ipsrv); - cfg = mu_ip_server_get_data (ipsrv); switch (cfg->tls_mode) { case tls_unspecified: - if (cfg->tls_conf.cert_file) - { + if (global_tls_mode != tls_unspecified) + cfg->tls_mode = global_tls_mode; + else if (cfg->tls_conf.cert_file) cfg->tls_mode = tls_ondemand; - break; - } else + { cfg->tls_mode = tls_no; - /* fall through */ + return MU_TLS_CONFIG_NULL; + } + break; + case tls_no: - continue; + return MU_TLS_CONFIG_NULL; default: break; } - switch (mu_tls_config_check (&cfg->tls_conf, 1)) + 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"), - mu_ip_server_addrstr (ipsrv)); - errors = 1; + mu_error (_("server %s: no certificate set"), srvid); + result = MU_TLS_CONFIG_FAIL; } break; case MU_TLS_CONFIG_NULL: + 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_NULL) { cfg->tls_conf = global_tls_conf; + result = MU_TLS_CONFIG_OK; } else { - mu_error (_("server %s: no certificate set"), - mu_ip_server_addrstr (ipsrv)); - errors = 1; + mu_error (_("server %s: no certificate set"), srvid); + result = MU_TLS_CONFIG_FAIL; } break; default: - mu_error (_("server %s: TLS configuration failed"), - mu_ip_server_addrstr (ipsrv)); + mu_error (_("server %s: TLS configuration failed"), srvid); + } + return result; +} + +int +stls_preflight (mu_m_server_t msrv) +{ + mu_list_t srvlist; + mu_iterator_t itr; + int errors = 0; + int tls_ok = mu_init_tls_libs (); + int tls_requested = 0; + + 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)) + { + mu_ip_server_t ipsrv; + struct pop3d_srv_config *cfg; + mu_iterator_current (itr, (void**) &ipsrv); + cfg = mu_ip_server_get_data (ipsrv); + + switch (stls_server_check (cfg, mu_ip_server_addrstr (ipsrv))) + { + case MU_TLS_CONFIG_NULL: + continue; + + case MU_TLS_CONFIG_OK: + break; + + default: errors = 1; } @@ -123,6 +148,9 @@ stls_preflight (mu_m_server_t msrv) } mu_iterator_destroy (&itr); + if (global_tls_mode == tls_unspecified) + global_tls_mode = tls_no; + if (tls_requested && !tls_ok) { mu_error (_("TLS is not configured, but requested in the " diff --git a/pop3d/pop3d.c b/pop3d/pop3d.c index a993b9dc2..f400f2b26 100644 --- a/pop3d/pop3d.c +++ b/pop3d/pop3d.c @@ -231,6 +231,12 @@ static struct mu_cfg_param pop3d_cfg_param[] = { N_("arg: list") }, { "tls", mu_cfg_section, &global_tls_conf }, + { "tls-mode", mu_cfg_callback, + &global_tls_mode, 0, cb_tls, + N_("Kind of TLS encryption to use for the inetd server" + " and all server blocks that lack the tls-mode statement."), + /* TRANSLATORS: words to the right of : are keywords - do not translate */ + N_("arg: false|true|ondemand|stls|requred|connection") }, #ifdef ENABLE_LOGIN_DELAY { "login-delay", mu_c_time, &login_delay, 0, NULL, @@ -530,7 +536,30 @@ main (int argc, char **argv) { struct pop3d_srv_config cfg; memset (&cfg, 0, sizeof cfg); - cfg.tls_mode = tls_no; + + switch (stls_server_check (&cfg, "<inetd>")) + { + case MU_TLS_CONFIG_OK: + if (mu_init_tls_libs ()) + status = EX_OK; + else + { + mu_error (_("TLS is not configured, but requested in the " + "configuration")); + exit (EX_CONFIG); + } + break; + + case MU_TLS_CONFIG_NULL: + break; + + case MU_TLS_CONFIG_UNSAFE: + exit (EX_CONFIG); + + default: + exit (EX_UNAVAILABLE); + } + /* Make sure we are in the root directory. */ chdir ("/"); status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, &cfg); diff --git a/pop3d/pop3d.h b/pop3d/pop3d.h index c040a02bd..efd115644 100644 --- a/pop3d/pop3d.h +++ b/pop3d/pop3d.h @@ -248,6 +248,7 @@ extern uid_t apop_database_owner; extern int apop_database_owner_set; extern struct mu_tls_config global_tls_conf; +extern int global_tls_mode; /* Safety checks for group-rw database files, such as stat and bulletin databases */ @@ -291,6 +292,7 @@ extern RETSIGTYPE pop3d_child_signal (int); extern int pop3d_stls (char *, struct pop3d_session *); int stls_preflight (mu_m_server_t msrv); +int stls_server_check (struct pop3d_srv_config *cfg, char const *srvid); extern void pop3d_outf (const char *fmt, ...) MU_PRINTFLIKE(1,2); |