summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS73
-rw-r--r--configure.ac3
-rw-r--r--doc/texinfo/programs.texi92
-rw-r--r--imap4d/commands.c2
-rw-r--r--imap4d/imap4d.c95
-rw-r--r--imap4d/imap4d.h23
-rw-r--r--imap4d/io.c30
-rw-r--r--imap4d/starttls.c105
-rw-r--r--include/mailutils/cfg.h15
-rw-r--r--include/mailutils/server.h10
-rw-r--r--include/mailutils/sys/tls-stream.h8
-rw-r--r--include/mailutils/tls.h72
-rw-r--r--libmailutils/cfg/driver.c24
-rw-r--r--libmailutils/cfg/parser.y6
-rw-r--r--libmailutils/diag/debcat1
-rw-r--r--libmailutils/server/ipsrv.c6
-rw-r--r--libmailutils/server/msrv.c47
-rw-r--r--libmu_auth/Makefile.am11
-rw-r--r--libmu_auth/notls.c29
-rw-r--r--libmu_auth/tls.c843
-rw-r--r--libmu_auth/tlsconf.c140
-rw-r--r--libmu_auth/tlsiostr.c216
-rw-r--r--libmu_auth/tlsvar.c101
-rw-r--r--pop3d/capa.c17
-rw-r--r--pop3d/cmd.c173
-rw-r--r--pop3d/extra.c24
-rw-r--r--pop3d/pop3d.c96
-rw-r--r--pop3d/pop3d.h80
-rw-r--r--pop3d/stls.c14
29 files changed, 1426 insertions, 930 deletions
diff --git a/NEWS b/NEWS
index 76ab20bd6..fde44651a 100644
--- a/NEWS
+++ b/NEWS
@@ -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