diff options
-rw-r--r-- | NEWS | 73 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | doc/texinfo/programs.texi | 92 | ||||
-rw-r--r-- | imap4d/commands.c | 2 | ||||
-rw-r--r-- | imap4d/imap4d.c | 95 | ||||
-rw-r--r-- | imap4d/imap4d.h | 23 | ||||
-rw-r--r-- | imap4d/io.c | 30 | ||||
-rw-r--r-- | imap4d/starttls.c | 105 | ||||
-rw-r--r-- | include/mailutils/cfg.h | 15 | ||||
-rw-r--r-- | include/mailutils/server.h | 10 | ||||
-rw-r--r-- | include/mailutils/sys/tls-stream.h | 8 | ||||
-rw-r--r-- | include/mailutils/tls.h | 72 | ||||
-rw-r--r-- | libmailutils/cfg/driver.c | 24 | ||||
-rw-r--r-- | libmailutils/cfg/parser.y | 6 | ||||
-rw-r--r-- | libmailutils/diag/debcat | 1 | ||||
-rw-r--r-- | libmailutils/server/ipsrv.c | 6 | ||||
-rw-r--r-- | libmailutils/server/msrv.c | 47 | ||||
-rw-r--r-- | libmu_auth/Makefile.am | 11 | ||||
-rw-r--r-- | libmu_auth/notls.c | 29 | ||||
-rw-r--r-- | libmu_auth/tls.c | 843 | ||||
-rw-r--r-- | libmu_auth/tlsconf.c | 140 | ||||
-rw-r--r-- | libmu_auth/tlsiostr.c | 216 | ||||
-rw-r--r-- | libmu_auth/tlsvar.c | 101 | ||||
-rw-r--r-- | pop3d/capa.c | 17 | ||||
-rw-r--r-- | pop3d/cmd.c | 173 | ||||
-rw-r--r-- | pop3d/extra.c | 24 | ||||
-rw-r--r-- | pop3d/pop3d.c | 96 | ||||
-rw-r--r-- | pop3d/pop3d.h | 80 | ||||
-rw-r--r-- | pop3d/stls.c | 14 |
29 files changed, 1426 insertions, 930 deletions
@@ -1,10 +1,81 @@ -GNU mailutils NEWS -- history of user-visible changes. 2017-03-11 +GNU mailutils NEWS -- history of user-visible changes. 2017-03-18 Copyright (C) 2002-2017 Free Software Foundation, Inc. See the end of file for copying conditions. Please send mailutils bug reports to <bug-mailutils@gnu.org>. +Version 3.2.90 (Git) + +* TLS configuration + +Note the following changes to the TLS configuration: + +** global tls section + +The following statements have been renamed: + + ssl-cafile renamed to ssl-ca-file + ssl-cert renamed to ssl-certificate-file + ssl-key renamed to ssl-key-file + +The following statements have been removed: + + enable + key-file-safety-checks + cert-file-safety-checks + ca-file-safety-checks + +The functionality of the latter three is now moved to the +tls-file-checks section. + +Example of a valid global tls section: + + tls { + ssl-certificate-file /etc/ssl/cert/imap.pem; + ssl-key-file /etc/ssl/private/imap.key; + } + +** global tls-file-checks statement + +The tls-file-checks statement configures safety checks for SSL +certificate and key files. It is a global section. Its syntax is +as follows: + + tls-file-checks { + key-file <arg: list>; + cert-file <arg: list>; + ca-file <arg: list>; + } + +The <arg> list is a list or sequence of check names optionally +prefixed with '+' to enable or '-' to disable the corresponding check. +Valid check names are the same as in previous versions. + +Use this statement instead of the deprecated cert-file-safety-checks, +key-file-safety-checks, and ca-file-safety-checks. + +* Per-server TLS support + +It is now possible to configure per-server SSL certificates in POP3 +and IMAP4 servers. To do so, place a "tls" subsection within the +corresponding "server" section. The syntax of the "tls" subsection +is the same as for the global section described above, e.g.: + + server imap.example.com:143 { + tls-mode required; + tls { + ssl-certificate-file /etc/ssl/cert/imap.pem; + ssl-key-file /etc/ssl/private/imap.key; + } + } + +If the "tls" section is absent, but "tls-mode" is specified and it's +value is anything but "no", the settings from the global "tls" section +will be used. Im this case, it is an error if the global "tls" +section is not defined. + + Version 3.2 - 2017-03-11 * configuration syntax diff --git a/configure.ac b/configure.ac index 3c62385e6..fb3322f6d 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. AC_PREREQ(2.63) -AC_INIT([GNU Mailutils], [3.2], [bug-mailutils@gnu.org], [mailutils], +AC_INIT([GNU Mailutils], [3.2.90], [bug-mailutils@gnu.org], [mailutils], [http://mailutils.org]) AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c]) AC_CONFIG_AUX_DIR([build-aux]) @@ -306,6 +306,7 @@ MU_CHECK_GNUTLS([1.2.1],[ ],[ status_gnutls=no ]) +AM_CONDITIONAL([MU_COND_GNUTLS], [test "$status_gnutls" = yes]) AC_SUBST(SITE_MAIL_RC) AC_ARG_WITH([mail-rc], diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi index 58f81848c..e479944dc 100644 --- a/doc/texinfo/programs.texi +++ b/doc/texinfo/programs.texi @@ -417,6 +417,7 @@ configuration files. * sql statement:: * ldap statement:: * tls statement:: +* tls-file-checks statement:: * gsasl statement:: @end menu @@ -1700,8 +1701,19 @@ server @var{ipaddr}[:@var{port}] @{ backlog <number: callback>; # @r{Kind of TLS encryption to use for this server.} - tls @samp{no}|@samp{ondemand}|@samp{required}|@samp{connection}; - + tls-mode @samp{no}|@samp{ondemand}|@samp{required}|@samp{connection}; + + tls @{ + # @r{Specify SSL certificate file.} + ssl-certificate-file @var{string}; + # @r{Specify SSL certificate key file.} + ssl-key-file @var{file}; + # @r{Specify trusted CAs file.} + ssl-ca-file @var{file}; + # @r{Set the priorities to use on the ciphers, methods, etc.} + ssl-priorities @var{string}; + @} + # @r{Set server specific ACLs.} acl @{ /* @xref{ACL Statement}. */ @}; @} @@ -1756,7 +1768,7 @@ settings (@pxref{General Server Configuration, timeout}). Configures the size of the queue of pending connections @end deffn -@deffn {Configuration} tls @var{mode}; +@deffn {Configuration} tls-mode @var{mode}; Configure the use of TLS encryption. The @var{mode} argument is one of the following: @@ -1781,6 +1793,20 @@ TLS is always forced when the connection is established. For @end table @end deffn +@deffn {Configuration} tls @{ ... @} +The @code{tls} statement configures SSL certificate and key files, as +well as other SSL settings for use in this server. It is used when +@code{tls-mode} is set to any of the following values: +@code{ondemand}, @code{required}, @code{connection}. + +If @code{tls-mode} is set to any of the values above and @code{tls} +section is absent, settings from the global @code{tls} section will +be used. In this case, it is an error if the global @code{tls} +section is not defined. + +@xref{tls statement}, for a discussion of its syntax. +@end deffn + @deffn {Configuration} acl This statement defines a per-server Access Control List. Its syntax is as described in @ref{ACL Statement}. Per-server ACLs complement, @@ -2483,39 +2509,32 @@ default filter is: @subheading Syntax @example tls @{ - # @r{Enable TLS support.} - enable @var{bool}; # @r{Specify SSL certificate file.} - ssl-cert @var{string}; + ssl-certificate-file @var{string}; # @r{Specify SSL certificate key file.} - ssl-key @var{file}; + ssl-key-file @var{file}; # @r{Specify trusted CAs file.} - ssl-cafile @var{file}; + ssl-ca-file @var{file}; # @r{Set the priorities to use on the ciphers, methods, etc.} ssl-priorities @var{string}; - # @r{Configure safety checks for SSL key file.} - key-file-safety-checks @var{list}; - # @r{Configure safety checks for SSL certificate.} - cert-file-safety-checks @var{list}; - # @r{Configure safety checks for SSL CA file.} - ca-file-safety-checks @var{list}; @} @end example @subheading Description -@deffn {Configuration} enable @var{bool} -Enable TLS support. If absent, @samp{enable On} is assumed. -@end deffn +The @samp{tls} statement configures TLS parameters to be used by +servers. It can appear both in the global scope and in server +scope. Global tls settings are applied for servers that are declared +as supporting TLS encryption, but lack the @samp{tls} substatement. -@deffn {Configuration} ssl-cert @var{string} +@deffn {Configuration} ssl-certificate-file @var{string} Specify SSL certificate file. @end deffn -@deffn {Configuration} ssl-key @var{file} +@deffn {Configuration} ssl-key-file @var{file} Specify SSL certificate key file. @end deffn -@deffn {Configuration} ssl-cafile @var{file} +@deffn {Configuration} ssl-ca-file @var{file} Specify the trusted certificate authorities file. @end deffn @@ -2524,7 +2543,27 @@ Set the priorities to use on the ciphers, key exchange methods, MACs and compression methods. @end deffn -@deffn {Configuration} key-file-safety-checks @var{list} +@node tls-file-checks statement +@subsection The @code{tls-file-checks} Statement +@kwindex tls-file-checks +@subheading Syntax +@example +tls-file-checks @{ + # @r{Configure safety checks for SSL key file.} + key-file @var{list}; + # @r{Configure safety checks for SSL certificate.} + cert-file @var{list}; + # @r{Configure safety checks for SSL CA file.} + ca-file @var{list}; +@} +@end example + +@subheading Description + +This section configures security checks applied to the particular SSL +configuration files in order to decide whether it is safe to use them. + +@deffn {Configuration} key-file @var{list} Configure safety checks for SSL key file. Elements of the @var{list} are names of individual checks, optionally prefixed with @samp{+} to enable or @samp{-} to disable the corresponding check. Valid check names are: @@ -2551,16 +2590,17 @@ Forbid files in world writable directories, @end table @end deffn -@deffn {Configuration} cert-file-safety-checks @var{list} +@deffn {Configuration} cert-file @var{list} Configure safety checks for SSL certificate. See -@code{key-file-safety-checks} for a description of @var{list}. +@code{key-file} for a description of @var{list}. @end deffn -@deffn {Configuration} ca-file-safety-checks @var{list} +@deffn {Configuration} ca-file @var{list} Configure safety checks for SSL CA file. See -@code{key-file-safety-checks} for a description of @var{list}. +@code{key-file} for a description of @var{list}. @end deffn + @node gsasl statement @subsection The @code{gsasl} Statement @anchor{GSASL Statement} @@ -7494,6 +7534,7 @@ The following configuration file statements affect the behavior of @headitem Statement @tab Reference @item debug @tab @xref{debug statement}. @item tls @tab @xref{tls statement}. +@item tls-file-checks @tab @xref{tls-file-checks statement}. @item mailbox @tab @xref{mailbox statement}. @item locking @tab @xref{locking statement}. @item logging @tab @xref{logging statement}. @@ -7804,6 +7845,7 @@ configuration statements: @headitem Statement @tab Reference @item debug @tab @xref{debug statement}. @item tls @tab @xref{tls statement}. +@item tls-file-checks @tab @xref{tls-file-checks statement}. @item mailbox @tab @xref{mailbox statement}. @item locking @tab @xref{locking statement}. @item logging @tab @xref{logging statement}. diff --git a/imap4d/commands.c b/imap4d/commands.c index 697741396..cba5c41b9 100644 --- a/imap4d/commands.c +++ b/imap4d/commands.c @@ -47,8 +47,6 @@ struct imap4d_command imap4d_command_table [] = { "NAMESPACE", imap4d_namespace, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, { "ID", imap4d_id, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, { "IDLE", imap4d_idle, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, -#ifdef WITH_TLS { "STARTTLS", imap4d_starttls, STATE_NONAUTH, STATE_NONE, STATE_NONE, NULL }, -#endif /* WITH_TLS */ { NULL, 0, 0, 0, 0, NULL } }; diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c index 670624b8b..5fa579c40 100644 --- a/imap4d/imap4d.c +++ b/imap4d/imap4d.c @@ -30,7 +30,6 @@ char *real_homedir; /* Homedir as returned by user database */ int state = STATE_NONAUTH; /* Current IMAP4 state */ struct mu_auth_data *auth_data; -enum tls_mode tls_mode; int login_disabled; /* Disable LOGIN command */ int create_home_dir; /* Create home directory if it does not exist */ @@ -258,13 +257,6 @@ cb_group (void *data, mu_config_value_t *arg) } -struct imap4d_srv_config -{ - struct mu_srv_config m_cfg; - enum tls_mode tls_mode; -}; - -#ifdef WITH_TLS static int cb_tls (void *data, mu_config_value_t *val) { @@ -293,33 +285,6 @@ cb_tls (void *data, mu_config_value_t *val) mu_error (_("not a valid tls keyword: %s"), val->v.string); return 0; } -#endif - -#ifdef WITH_TLS -static int -cb_tls_required (void *data, mu_config_value_t *val) -{ - int bv; - - if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) - return 1; - if (mu_str_to_c (val->v.string, mu_c_bool, &bv, NULL)) - mu_error (_("Not a boolean value")); - else if (bv) - { - tls_mode = tls_required; - mu_diag_output (MU_DIAG_WARNING, - "the \"tls-required\" statement is deprecated, " - "use \"tls required\" instead"); - } - else - mu_diag_output (MU_DIAG_WARNING, - "the \"tls-required\" statement is deprecated, " - "use \"tls\" instead"); - - return 0; -} -#endif static mu_list_t auth_deny_user_list, auth_allow_user_list; static mu_list_t auth_deny_group_list, auth_allow_group_list; @@ -532,13 +497,13 @@ namespace_cfg_init (void) } static struct mu_cfg_param imap4d_srv_param[] = { -#ifdef WITH_TLS - { "tls", mu_cfg_callback, + { "tls-mode", mu_cfg_callback, NULL, mu_offsetof (struct imap4d_srv_config, tls_mode), cb_tls, N_("Kind of TLS encryption to use for this server"), /* TRANSLATORS: translate only arg:, the rest are keywords */ N_("arg: false|true|ondemand|stls|requred|connection") }, -#endif + { "tls", mu_cfg_section, + NULL, mu_offsetof (struct imap4d_srv_config, tls_conf) }, { NULL } }; @@ -568,16 +533,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = { { "retain-groups", mu_cfg_callback, &user_retain_groups, 0, cb_group, N_("Retain these supplementary groups when switching to user privileges"), N_("groups: list of string") }, -#ifdef WITH_TLS - { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls, - N_("Kind of TLS encryption to use"), - /* TRANSLATORS: translate only arg:, the rest are keywords */ - N_("arg: false|true|ondemand|stls|requred|connection") }, - { "tls-required", mu_cfg_callback, &tls_mode, 0, cb_tls_required, - N_("Always require STLS before entering authentication phase.\n" - "Deprecated, use \"tls required\" instead."), - N_("arg: bool") }, -#endif + { "tls", mu_cfg_section, &global_tls_conf }, { "preauth", mu_cfg_callback, NULL, 0, cb_preauth, N_("Configure PREAUTH mode. <value> is one of:\n" " prog:///<full-program-name: string>\n" @@ -836,7 +792,7 @@ imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo)) } static int -imap4d_mainloop (int ifd, int ofd, enum tls_mode tls) +imap4d_mainloop (int ifd, int ofd, struct imap4d_srv_config *cfg) { imap4d_tokbuf_t tokp; char *text; @@ -877,33 +833,27 @@ imap4d_mainloop (int ifd, int ofd, enum tls_mode tls) /* Set child-specific signal handlers */ imap4d_child_signal_setup (imap4d_child_signal); } - - if (tls == tls_unspecified) - tls = tls_available ? tls_ondemand : tls_no; - else if (tls != tls_no && !tls_available) - { - mu_error (_("TLS is not configured, but requested in the " - "configuration")); - tls = tls_no; - } - switch (tls) + switch (cfg->tls_mode) { case tls_required: imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED); + imap4d_capability_add (IMAP_CAPA_STARTTLS); break; - case tls_no: - imap4d_capability_remove (IMAP_CAPA_STARTTLS); - tls_available = 0; + + case tls_ondemand: + imap4d_capability_add (IMAP_CAPA_STARTTLS); break; + default: break; } - session.tls_mode = tls; + session.tls_mode = cfg->tls_mode; + session.tls_conf = &cfg->tls_conf; - io_setio (ifd, ofd, tls == tls_connection); - if (tls == tls_connection) + io_setio (ifd, ofd, cfg->tls_mode == tls_connection ? &cfg->tls_conf : NULL); + if (cfg->tls_mode == tls_connection) tls_encryption_on (&session); if (imap4d_preauth_setup (ifd) == 0) @@ -961,8 +911,7 @@ imap4d_connection (int fd, struct sockaddr *sa, int salen, else rc = 1; - imap4d_mainloop (fd, fd, - cfg->tls_mode == tls_unspecified ? tls_mode : cfg->tls_mode); + imap4d_mainloop (fd, fd, cfg); if (rc == 0) clr_strerr_flt (); @@ -1040,8 +989,9 @@ main (int argc, char **argv) mu_tcpwrapper_cfg_init (); manlock_cfg_init (); mu_acl_cfg_init (); + mu_tls_cfg_init (); namespace_cfg_init (); - + mu_m_server_create (&server, program_version); mu_m_server_set_config_size (server, sizeof (struct imap4d_srv_config)); mu_m_server_set_conn (server, imap4d_connection); @@ -1141,9 +1091,7 @@ main (int argc, char **argv) umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ /* Check TLS environment, i.e. cert and key files */ -#ifdef WITH_TLS - starttls_init (); -#endif /* WITH_TLS */ + mu_m_server_set_preflight (server, starttls_init); /* Actually run the daemon. */ if (mu_m_server_mode (server) == MODE_DAEMON) @@ -1155,9 +1103,12 @@ main (int argc, char **argv) } else { + struct imap4d_srv_config cfg; + memset (&cfg, 0, sizeof cfg); + cfg.tls_mode = tls_no; /* Make sure we are in the root directory. */ chdir ("/"); - status = imap4d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, tls_mode); + status = imap4d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, &cfg); } if (status) diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h index 51cac08e9..76deaaec4 100644 --- a/imap4d/imap4d.h +++ b/imap4d/imap4d.h @@ -193,6 +193,14 @@ enum tls_mode struct imap4d_session { enum tls_mode tls_mode; + struct mu_tls_config *tls_conf; +}; + +struct imap4d_srv_config +{ + struct mu_srv_config m_cfg; + enum tls_mode tls_mode; + struct mu_tls_config tls_conf; }; extern struct imap4d_command imap4d_command_table[]; @@ -217,7 +225,8 @@ extern mu_list_t imap4d_id_list; extern int imap4d_argc; extern char **imap4d_argv; extern jmp_buf child_jmp; - +extern struct mu_tls_config global_tls_conf; + extern int test_mode; extern int silent_expunge; @@ -240,7 +249,7 @@ extern int io_stream_completion_response (mu_stream_t str, const char *format, ...) MU_PRINTFLIKE(4,5); void io_getline (char **pbuf, size_t *psize, size_t *pnbytes); -void io_setio (int, int, int); +void io_setio (int, int, struct mu_tls_config *); void io_flush (void); int io_wait_input (int); @@ -333,14 +342,10 @@ extern int imap4d_select (struct imap4d_session *, struct imap4d_command *, imap4d_tokbuf_t); extern int imap4d_select0 (struct imap4d_command *, const char *, int); extern int imap4d_select_status (void); -#ifdef WITH_TLS extern int imap4d_starttls (struct imap4d_session *, struct imap4d_command *, imap4d_tokbuf_t); -extern void starttls_init (void); +int starttls_init (mu_m_server_t msrv); void tls_encryption_on (struct imap4d_session *); -#else -# define tls_encryption_on(s) -#endif /* WITH_TLS */ extern int imap4d_status (struct imap4d_session *, struct imap4d_command *, imap4d_tokbuf_t); extern int imap4d_store (struct imap4d_session *, @@ -466,9 +471,7 @@ int util_trim_nl (char *s, size_t len); int set_xscript_level (int xlev); -#ifdef WITH_TLS -int imap4d_init_tls_server (void); -#endif /* WITH_TLS */ +int imap4d_init_tls_server (struct mu_tls_config *); struct imap4d_auth { diff --git a/imap4d/io.c b/imap4d/io.c index 1d6ae7f8f..b1c1d7d04 100644 --- a/imap4d/io.c +++ b/imap4d/io.c @@ -50,7 +50,7 @@ log_cipher (mu_stream_t stream) } void -io_setio (int ifd, int ofd, int tls) +io_setio (int ifd, int ofd, struct mu_tls_config *tls_conf) { mu_stream_t str, istream, ostream; @@ -68,10 +68,12 @@ io_setio (int ifd, int ofd, int tls) mu_stream_set_buffer (ostream, mu_buffer_line, 0); /* Combine the two streams into an I/O one. */ -#ifdef WITH_TLS - if (tls) + if (tls_conf) { - int rc = mu_tls_server_stream_create (&str, istream, ostream, 0); + int rc = mu_tls_stream_create (&str, istream, ostream, + tls_conf, + MU_TLS_SERVER, + 0); if (rc) { mu_stream_unref (istream); @@ -81,9 +83,7 @@ io_setio (int ifd, int ofd, int tls) } log_cipher (str); } - else -#endif - if (mu_iostream_create (&str, istream, ostream)) + else if (mu_iostream_create (&str, istream, ostream)) imap4d_bye (ERR_STREAM_CREATE); /* Convert all writes to CRLF form. @@ -120,9 +120,8 @@ io_setio (int ifd, int ofd, int tls) } } -#ifdef WITH_TLS int -imap4d_init_tls_server () +imap4d_init_tls_server (struct mu_tls_config *tls_conf) { mu_stream_t tlsstream, stream[2]; int rc; @@ -135,7 +134,12 @@ imap4d_init_tls_server () return 1; } - rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0); + rc = mu_tls_stream_create (&tlsstream, stream[0], stream[1], + tls_conf, + MU_TLS_SERVER, + 0); + mu_stream_unref (stream[0]); + mu_stream_unref (stream[1]); if (rc) { mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), @@ -145,8 +149,6 @@ imap4d_init_tls_server () log_cipher (tlsstream); - mu_stream_unref (stream[0]); - mu_stream_unref (stream[1]); stream[0] = stream[1] = tlsstream; rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, stream); @@ -158,11 +160,9 @@ imap4d_init_tls_server () } mu_stream_unref (stream[0]); mu_stream_unref (stream[1]); - + return 0; } -#endif - /* Status Code to String. */ static const char * diff --git a/imap4d/starttls.c b/imap4d/starttls.c index 6894255a1..f22012305 100644 --- a/imap4d/starttls.c +++ b/imap4d/starttls.c @@ -17,11 +17,7 @@ #include "imap4d.h" -int tls_available; - -#ifdef WITH_TLS - -static int tls_done; +struct mu_tls_config global_tls_conf; /* 6.2.1. STARTTLS Command @@ -39,7 +35,7 @@ imap4d_starttls (struct imap4d_session *session, { int status; - if (!tls_available || tls_done) + if (session->tls_mode == tls_no) return io_completion_response (command, RESP_BAD, "Invalid command"); if (imap4d_tokbuf_argc (tok) != 2) @@ -48,7 +44,7 @@ imap4d_starttls (struct imap4d_session *session, status = io_completion_response (command, RESP_OK, "Begin TLS negotiation"); io_flush (); - if (imap4d_init_tls_server () == 0) + if (imap4d_init_tls_server (session->tls_conf) == 0) tls_encryption_on (session); else { @@ -63,24 +59,101 @@ imap4d_starttls (struct imap4d_session *session, void tls_encryption_on (struct imap4d_session *session) { - tls_done = 1; + session->tls_mode = tls_no; imap4d_capability_remove (IMAP_CAPA_STARTTLS); login_disabled = 0; imap4d_capability_remove (IMAP_CAPA_LOGINDISABLED); - session->tls_mode = tls_no; imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED); } -void -starttls_init () +int +starttls_init (mu_m_server_t msrv) { - tls_available = mu_check_tls_environment (); - if (tls_available) - imap4d_capability_add (IMAP_CAPA_STARTTLS); -} + 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; + + 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 imap4d_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) + { + cfg->tls_mode = tls_ondemand; + break; + } + else + cfg->tls_mode = tls_no; + /* fall through */ + case tls_no: + 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); -#endif /* WITH_TLS */ + if (tls_requested && !tls_ok) + { + mu_error (_("TLS is not configured, but requested in the " + "configuration")); + errors = 1; + } + + if (errors) + return 1; + + return 0; +} /* EOF */ diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h index 03d319f5f..8ccd7f4eb 100644 --- a/include/mailutils/cfg.h +++ b/include/mailutils/cfg.h @@ -180,13 +180,16 @@ typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage, struct mu_cfg_section { - const char *ident; - char *label; - mu_cfg_section_fp parser; - void *target; - size_t offset; + const char *ident; /* Section identifier */ + char *label; /* Label description */ + mu_cfg_section_fp parser; /* Parser function */ + void *data; /* Data pointer */ + size_t offset; /* Offset within target (see below) */ mu_list_t /* of mu_cfg_cont */ children; - char *docstring; + char *docstring; /* Documentation string */ + void *target; /* Actual pointer to the data. It is + recomputed each time the section is + reduced. */ }; enum mu_cfg_cont_type diff --git a/include/mailutils/server.h b/include/mailutils/server.h index d34978bc6..1354feba1 100644 --- a/include/mailutils/server.h +++ b/include/mailutils/server.h @@ -28,7 +28,7 @@ typedef int (*mu_conn_loop_fp) (int fd, void *conn_data, void *server_data); typedef void (*mu_conn_free_fp) (void *conn_data, void *server_data); typedef int (*mu_server_idle_fp) (void *server_data); typedef void (*mu_server_free_fp) (void *server_data); - + #define MU_SERVER_SUCCESS 0 #define MU_SERVER_CLOSE_CONN 1 #define MU_SERVER_SHUTDOWN 2 @@ -40,7 +40,8 @@ int mu_server_set_idle (mu_server_t srv, mu_server_idle_fp fp); int mu_server_set_data (mu_server_t srv, void *data, mu_server_free_fp fp); int mu_server_add_connection (mu_server_t srv, int fd, void *data, - mu_conn_loop_fp loop, mu_conn_free_fp free); + mu_conn_loop_fp loop, + mu_conn_free_fp free); struct timeval; int mu_server_set_timeout (mu_server_t srv, struct timeval *to); int mu_server_count (mu_server_t srv, size_t *pcount); @@ -100,6 +101,7 @@ typedef struct mu_m_server_connect_data mu_m_server_connect_data_t; typedef int (*mu_m_server_handler_fp) (int fd, struct sockaddr *sa, int salen, struct mu_srv_config *pconf, void *data); +typedef int (*mu_m_server_preflight_fp) (mu_m_server_t); void mu_m_server_create (mu_m_server_t *psrv, const char *ident); void mu_m_server_destroy (mu_m_server_t *pmsrv); @@ -109,6 +111,7 @@ void mu_m_server_get_type (mu_m_server_t srv, int *ptype); void mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_handler_fp f); void mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_handler_fp fun); void mu_m_server_set_data (mu_m_server_t srv, void *data); +void *mu_ip_server_get_data (mu_ip_server_t tcpsrv); void mu_m_server_set_max_children (mu_m_server_t srv, size_t num); int mu_m_server_set_pidfile (mu_m_server_t srv, const char *pidfile); int mu_m_server_set_foreground (mu_m_server_t srv, int enable); @@ -119,6 +122,8 @@ void mu_m_server_set_sigset (mu_m_server_t srv, sigset_t *sigset); void mu_m_server_set_strexit (mu_m_server_t srv, const char *(*fun) (int)); void mu_m_server_set_app_data_size (mu_m_server_t srv, size_t size); int mu_m_server_set_config_size (mu_m_server_t srv, size_t size); +void mu_m_server_set_preflight (mu_m_server_t srv, + mu_m_server_preflight_fp fun); struct mu_srv_config *mu_m_server_listen (mu_m_server_t msrv, struct mu_sockaddr *s, int type); @@ -144,5 +149,4 @@ int mu_m_server_check_acl (mu_m_server |