Commit e1233d55 e1233d5516f48cd7d786a69d4eebd40e73d95d45 by Sergey Poznyakoff

Implement pop3s and imap4s in respective servers.

* comsat/comsat.c (comsat_prefork,comsat_connection): Change signatures.
* imap4d/imap4d.c: Implement imaps.
* imap4d/imap4d.h (io_setio): Change signature.
(tls_encryption_on): New proto.
* imap4d/io.c (io_setio): Change signature.  Initialize TLS stream if
requested.
* imap4d/starttls.c (tls_encryption_on): New function.
* include/mailutils/server.h (mu_srv_config): New struct.
(mu_m_server_conn_fp, mu_m_server_prefork_fp): Remove typedefs.
(mu_m_server_handler_fp): New typedef.
(mu_m_server_set_conn): Change signature.
(mu_m_server_set_prefork): Change signature.
(mu_m_server_set_app_data_size)
(mu_m_server_set_config_size): New prototype.
(mu_m_server_cfg_init): Change signature.
* include/mailutils/tls.h (mu_init_tls_libs): Change signature.
* lib/tcpwrap.c: Include tcpwrap.h
(mu_tcp_wrapper_daemon): Fix declaration.
(mu_tcp_wrapper_prefork): Change signature.
* lib/tcpwrap.h (mu_tcp_wrapper_prefork): Change signature
* libmailutils/server/msrv.c (_mu_m_server) <conn,prefork>: Change
data type.  All uses updated.
<app_data_size>: New member.
(m_srv_config): Remove struct.  Replaced with mu_srv_config from tls.h
(mu_m_server_set_conn): Change signature.
(mu_m_server_set_prefork): Change signature.
(mu_m_server_set_app_data_size)
(mu_m_server_set_config_size): New functions.
(add_server): Allocate app_data_size additional bytes of data.
(mu_m_server_cfg_init): Take one argument.
* libmu_auth/tls.c (mu_tls_module_init): Update call to mu_init_tls_libs.
Don't call mu_file_safety_check with NULL argument.
(mu_init_tls_libs): Rewrite.  Prepare x509 here, instead of
doing it each time a TLS stream is created.
(mu_deinit_tls_libs): Free x509, if exists.
(_tls_server_open): Update call to mu_init_tls_libs.
Remove x509 initialization.
* libmu_cfg/tls.c (cb2_safety_checks): Fix typos.
* maidag/lmtp.c (lmtp_connection): Change signature.
* maidag/maidag.c (main): Update call to mu_m_server_cfg_init.
* maidag/maidag.h (lmtp_connection): Change signature.
* pop3d/extra.c (pop3d_setio): Initialize TLS stream, if requested.
* pop3d/pop3d.c: Implement pops.
* pop3d/pop3d.h (pop3d_setio): Change prototype.
1 parent bad3c6c3
......@@ -320,7 +320,8 @@ static unsigned overflow_count = 0; /* Number of overflows detected during
the current interval */
int
comsat_prefork (int fd, void *data, struct sockaddr *s, int size)
comsat_prefork (int fd, struct sockaddr *s, int size,
struct mu_srv_config *pconf, void *data)
{
int retval = 0;
time_t now;
......@@ -367,15 +368,14 @@ comsat_prefork (int fd, void *data, struct sockaddr *s, int size)
int
comsat_connection (int fd, struct sockaddr *sa, int salen,
void *data, mu_ip_server_t srv,
time_t to, int transcript)
struct mu_srv_config *pconf, void *data)
{
char *buffer;
size_t rdlen, size;
if (mu_udp_server_get_rdata (srv, &buffer, &rdlen))
if (mu_udp_server_get_rdata (pconf->tcpsrv, &buffer, &rdlen))
return 0;
if (transcript)
if (pconf->transcript)
{
char *p = mu_sockaddr_to_astr (sa, salen);
mu_diag_output (MU_DIAG_INFO,
......@@ -386,10 +386,10 @@ comsat_connection (int fd, struct sockaddr *sa, int salen,
mu_diag_output (MU_DIAG_INFO, "string: %s", buffer);
free (p);
}
mu_udp_server_get_bufsize (srv, &size);
mu_udp_server_get_bufsize (pconf->tcpsrv, &size);
if (size < rdlen + 1)
{
int rc = mu_udp_server_set_bufsize (srv, rdlen + 1);
int rc = mu_udp_server_set_bufsize (pconf->tcpsrv, rdlen + 1);
if (rc)
{
mu_error (_("cannot resize buffer: %s"), mu_strerror (rc));
......@@ -560,7 +560,7 @@ main (int argc, char **argv)
mu_argp_init (NULL, NULL);
comsat_init ();
mu_acl_cfg_init ();
mu_m_server_cfg_init ();
mu_m_server_cfg_init (NULL);
mu_m_server_create (&server, program_version);
mu_m_server_set_type (server, MU_IP_UDP);
mu_m_server_set_conn (server, comsat_connection);
......
......@@ -93,7 +93,7 @@ static const char *imap4d_capa[] = {
NULL
};
static int imap4d_mainloop (int, int);
static int imap4d_mainloop (int, int, int);
static error_t
imap4d_parse_opt (int key, char *arg, struct argp_state *state)
......@@ -242,6 +242,20 @@ cb_mailbox_mode (void *data, mu_config_value_t *val)
return 0;
}
struct imap4d_srv_config
{
struct mu_srv_config m_cfg;
int tls;
};
static struct mu_cfg_param imap4d_srv_param[] = {
{ "tls", mu_cfg_bool, NULL, mu_offsetof (struct imap4d_srv_config, tls),
NULL,
N_("Use TLS encryption for this server")
},
{ NULL }
};
static struct mu_cfg_param imap4d_cfg_param[] = {
{ "homedir", mu_cfg_string, &modify_homedir, 0, NULL,
N_("Modify home directory.") },
......@@ -396,7 +410,7 @@ imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo))
}
static int
imap4d_mainloop (int ifd, int ofd)
imap4d_mainloop (int ifd, int ofd, int tls)
{
imap4d_tokbuf_t tokp;
char *text;
......@@ -435,7 +449,7 @@ imap4d_mainloop (int ifd, int ofd)
imap4d_child_signal_setup (imap4d_child_signal);
}
io_setio (ifd, ofd);
io_setio (ifd, ofd, tls);
if (imap4d_preauth_setup (ifd) == 0)
{
......@@ -478,13 +492,14 @@ imap4d_mainloop (int ifd, int ofd)
}
int
imap4d_connection (int fd, struct sockaddr *sa, int salen, void *data,
mu_ip_server_t srv, time_t timeout, int transcript)
imap4d_connection (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf, void *data)
{
idle_timeout = timeout;
if (imap4d_transcript != transcript)
imap4d_transcript = transcript;
imap4d_mainloop (fd, fd);
struct imap4d_srv_config *cfg = (struct imap4d_srv_config *) pconf;
idle_timeout = pconf->timeout;
imap4d_transcript = pconf->transcript;
imap4d_mainloop (fd, fd, cfg->tls);
return 0;
}
......@@ -559,11 +574,12 @@ main (int argc, char **argv)
mu_tcpwrapper_cfg_init ();
manlock_cfg_init ();
mu_acl_cfg_init ();
mu_m_server_cfg_init ();
mu_m_server_cfg_init (imap4d_srv_param);
mu_argp_init (NULL, NULL);
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);
mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork);
mu_m_server_set_mode (server, MODE_INTERACTIVE);
......@@ -669,7 +685,7 @@ main (int argc, char **argv)
{
/* Make sure we are in the root directory. */
chdir ("/");
status = imap4d_mainloop (MU_STDIN_FD, MU_STDOUT_FD);
status = imap4d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, 0);
}
if (status)
......
......@@ -220,7 +220,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);
void io_setio (int, int, int);
void io_flush (void);
int io_wait_input (int);
......@@ -297,6 +297,7 @@ extern int imap4d_select_status (void);
#ifdef WITH_TLS
extern int imap4d_starttls (struct imap4d_command *, imap4d_tokbuf_t);
extern void starttls_init (void);
void tls_encryption_on (void);
#endif /* WITH_TLS */
extern int imap4d_status (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_store (struct imap4d_command *, imap4d_tokbuf_t);
......
......@@ -20,7 +20,7 @@
mu_stream_t iostream;
void
io_setio (int ifd, int ofd)
io_setio (int ifd, int ofd, int tls)
{
mu_stream_t str, istream, ostream;
......@@ -38,6 +38,21 @@ io_setio (int ifd, int ofd)
mu_stream_set_buffer (ostream, mu_buffer_line, 0);
/* Combine the two streams into an I/O one. */
#ifdef WITH_TLS
if (tls)
{
int rc = mu_tls_server_stream_create (&str, istream, ostream, 0);
if (rc)
{
mu_stream_unref (istream);
mu_stream_unref (ostream);
mu_error (_("failed to create TLS stream: %s"), mu_strerror (rc));
imap4d_bye (ERR_STREAM_CREATE);
}
tls_encryption_on ();
}
else
#endif
if (mu_iostream_create (&str, istream, ostream))
imap4d_bye (ERR_STREAM_CREATE);
......
......@@ -47,18 +47,9 @@ imap4d_starttls (struct imap4d_command *command, imap4d_tokbuf_t tok)
status = io_completion_response (command, RESP_OK, "Begin TLS negotiation");
io_flush ();
tls_done = imap4d_init_tls_server () == 0;
if (tls_done)
{
imap4d_capability_remove (IMAP_CAPA_STARTTLS);
login_disabled = 0;
imap4d_capability_remove (IMAP_CAPA_LOGINDISABLED);
tls_required = 0;
imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED);
}
if (imap4d_init_tls_server () == 0)
tls_encryption_on ();
else
{
mu_diag_output (MU_DIAG_ERROR, _("session terminated"));
......@@ -70,11 +61,24 @@ imap4d_starttls (struct imap4d_command *command, imap4d_tokbuf_t tok)
}
void
tls_encryption_on ()
{
tls_done = 1;
imap4d_capability_remove (IMAP_CAPA_STARTTLS);
login_disabled = 0;
imap4d_capability_remove (IMAP_CAPA_LOGINDISABLED);
tls_required = 0;
imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED);
}
void
starttls_init ()
{
tls_available = mu_check_tls_environment ();
if (tls_available)
tls_available = mu_init_tls_libs ();
tls_available = mu_init_tls_libs (1);
if (tls_available)
imap4d_capability_add (IMAP_CAPA_STARTTLS);
}
......
......@@ -80,20 +80,31 @@ int mu_udp_server_get_rdata (mu_ip_server_t srv, char **pbuf,
/* m-server */
struct mu_srv_config /* Configuration data for a single TCP server. */
{
mu_m_server_t msrv; /* Parent m-server. */
mu_ip_server_t tcpsrv; /* TCP server these data are for. */
mu_acl_t acl; /* Access control list for this server. */
int single_process; /* Should it run as a single process? */
int transcript; /* Enable session transcript. */
time_t timeout; /* Idle timeout for this server. */
/* Application-dependent data may follow */
};
typedef struct mu_m_server_connect_data mu_m_server_connect_data_t;
typedef int (*mu_m_server_conn_fp) (int fd, struct sockaddr *sa, int salen,
void *data, mu_ip_server_t srv,
time_t timeout, int transcript);
typedef int (*mu_m_server_prefork_fp) (int, void *,
struct sockaddr *s, int size);
typedef int (*mu_m_server_handler_fp) (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data);
void mu_m_server_create (mu_m_server_t *psrv, const char *ident);
void mu_m_server_destroy (mu_m_server_t *pmsrv);
void mu_m_server_set_mode (mu_m_server_t srv, int mode);
void mu_m_server_set_type (mu_m_server_t srv, int type);
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_conn_fp f);
void mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_prefork_fp fun);
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_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);
......@@ -103,6 +114,8 @@ void mu_m_server_set_timeout (mu_m_server_t srv, time_t t);
void mu_m_server_set_mode (mu_m_server_t srv, int mode);
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);
int mu_m_server_mode (mu_m_server_t srv);
int mu_m_server_foreground (mu_m_server_t srv);
......@@ -120,7 +133,8 @@ void mu_m_server_end (mu_m_server_t msrv);
void mu_m_server_stop (int code);
int mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen);
void mu_m_server_cfg_init (void);
struct mu_cfg_param;
void mu_m_server_cfg_init (struct mu_cfg_param *app_param);
#endif
......
......@@ -49,7 +49,7 @@ extern int mu_tls_client_stream_create (mu_stream_t *stream,
int flags);
extern int mu_check_tls_environment (void);
extern int mu_init_tls_libs (void);
extern int mu_init_tls_libs (int x509);
extern void mu_deinit_tls_libs (void);
extern int mu_tls_enable;
......
......@@ -27,9 +27,11 @@
#include <mailutils/cfg.h>
#include <mailutils/diag.h>
#include <mailutils/error.h>
#include <mailutils/server.h>
#include "tcpwrap.h"
int mu_tcp_wrapper_enable = 1;
char *mu_tcp_wrapper_daemon;
const char *mu_tcp_wrapper_daemon;
#ifdef WITH_LIBWRAP
# include <tcpd.h>
......@@ -93,7 +95,9 @@ mu_tcpwrapper_access (int fd)
#endif
int
mu_tcp_wrapper_prefork (int fd, void *data, struct sockaddr *sa, int salen)
mu_tcp_wrapper_prefork (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data)
{
if (mu_tcp_wrapper_enable
&& sa->sa_family == AF_INET
......
......@@ -21,8 +21,10 @@ extern int mu_tcp_wrapper_enable;
const char *mu_tcp_wrapper_daemon;
extern int mu_tcpwrapper_access (int fd);
extern void mu_tcpwrapper_cfg_init (void);
extern int mu_tcp_wrapper_prefork (int fd, void *data,
struct sockaddr *sa, int salen);
extern int mu_tcp_wrapper_prefork (int fd,
struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data);
#ifdef WITH_LIBWRAP
# define TCP_WRAPPERS_CONFIG { "tcp-wrappers", mu_cfg_section },
......
......@@ -195,7 +195,9 @@ mu_file_safety_check (const char *filename, int mode,
mu_list_t idlist)
{
struct file_check_buffer buf;
if (!filename)
return EFAULT;
memset (&buf, 0, sizeof (buf));
if (stat (filename, &buf.filst) == 0)
{
......
......@@ -76,9 +76,10 @@ struct _mu_m_server
objects. It is cleared after the objects
are opened and attached to the server. */
mu_m_server_conn_fp conn; /* Connection handler function. */
mu_m_server_prefork_fp prefork;/* Pre-fork function. */
mu_m_server_handler_fp conn; /* Connection handler function. */
mu_m_server_handler_fp prefork;/* Pre-fork function. */
void *data; /* User-supplied data for conn and prefork. */
size_t app_data_size;
int mode; /* Server mode: should be removed. */
......@@ -98,16 +99,6 @@ struct _mu_m_server
description. */
};
struct m_srv_config /* Configuration data for a single TCP server. */
{
mu_m_server_t msrv; /* Parent m-server. */
mu_ip_server_t tcpsrv; /* TCP server these data are for. */
mu_acl_t acl; /* Access control list for this server. */
int single_process; /* Should it run as a single process? */
int transcript; /* Enable session transcript. */
time_t timeout; /* Idle timeout for this server. */
};
static int need_cleanup = 0;
static int stop = 0; /* FIXME: Must be per-m-server */
......@@ -326,13 +317,13 @@ mu_m_server_set_mode (mu_m_server_t srv, int mode)
}
void
mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_conn_fp conn)
mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_handler_fp conn)
{
srv->conn = conn;
}
void
mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_prefork_fp fun)
mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_handler_fp fun)
{
srv->prefork = fun;
}
......@@ -433,9 +424,24 @@ mu_m_server_foreground (mu_m_server_t srv)
}
void
m_srv_config_free (void *data)
mu_m_server_set_app_data_size (mu_m_server_t srv, size_t size)
{
srv->app_data_size = size;
}
int
mu_m_server_set_config_size (mu_m_server_t srv, size_t size)
{
if (size < sizeof (struct mu_srv_config))
return EINVAL;
srv->app_data_size = size - sizeof (struct mu_srv_config);
return 0;
}
void
mu_srv_config_free (void *data)
{
struct m_srv_config *pconf = data;
struct mu_srv_config *pconf = data;
/* FIXME */
free (pconf);
}
......@@ -444,15 +450,15 @@ static int m_srv_conn (int fd, struct sockaddr *sa, int salen,
void *server_data, void *call_data,
mu_ip_server_t srv);
static struct m_srv_config *
static struct mu_srv_config *
add_server (mu_m_server_t msrv, struct mu_sockaddr *s, int type)
{
mu_ip_server_t tcpsrv;
struct m_srv_config *pconf;
struct mu_srv_config *pconf;
MU_ASSERT (mu_ip_server_create (&tcpsrv, s, type)); /* FIXME: type */
MU_ASSERT (mu_ip_server_set_conn (tcpsrv, m_srv_conn));
pconf = calloc (1, sizeof (*pconf));
pconf = calloc (1, sizeof (*pconf) + msrv->app_data_size);
if (!pconf)
{
mu_error ("%s", mu_strerror (ENOMEM));
......@@ -462,7 +468,7 @@ add_server (mu_m_server_t msrv, struct mu_sockaddr *s, int type)
pconf->tcpsrv = tcpsrv;
pconf->single_process = 0;
pconf->timeout = msrv->timeout;
MU_ASSERT (mu_ip_server_set_data (tcpsrv, pconf, m_srv_config_free));
MU_ASSERT (mu_ip_server_set_data (tcpsrv, pconf, mu_srv_config_free));
if (!msrv->srvlist)
MU_ASSERT (mu_list_create (&msrv->srvlist));
MU_ASSERT (mu_list_append (msrv->srvlist, tcpsrv));
......@@ -681,7 +687,7 @@ m_srv_conn (int fd, struct sockaddr *sa, int salen,
mu_ip_server_t srv)
{
int status;
struct m_srv_config *pconf = server_data;
struct mu_srv_config *pconf = server_data;
if (mu_m_server_check_acl (pconf->msrv, sa, salen))
return 0;
......@@ -701,7 +707,7 @@ m_srv_conn (int fd, struct sockaddr *sa, int salen,
return 0;
}
if (pconf->msrv->prefork
&& pconf->msrv->prefork (fd, pconf->msrv->data, sa, salen))
&& pconf->msrv->prefork (fd, sa, salen, pconf, pconf->msrv->data))
return 0;
pid = fork ();
......@@ -711,8 +717,8 @@ m_srv_conn (int fd, struct sockaddr *sa, int salen,
{
mu_ip_server_shutdown (srv); /* FIXME: does it harm for MU_IP_UDP? */
mu_m_server_restore_signals (pconf->msrv);
status = pconf->msrv->conn (fd, sa, salen, pconf->msrv->data, srv,
pconf->timeout, pconf->transcript);
status = pconf->msrv->conn (fd, sa, salen, pconf,
pconf->msrv->data);
closelog ();
exit (status);
}
......@@ -722,9 +728,9 @@ m_srv_conn (int fd, struct sockaddr *sa, int salen,
}
}
else if (!pconf->msrv->prefork
|| pconf->msrv->prefork (fd, pconf->msrv->data, sa, salen) == 0)
pconf->msrv->conn (fd, sa, salen, pconf->msrv->data, srv,
pconf->timeout, pconf->transcript);
|| pconf->msrv->prefork (fd, sa, salen, pconf,
pconf->msrv->data) == 0)
pconf->msrv->conn (fd, sa, salen, pconf, pconf->msrv->data);
return 0;
}
......@@ -802,7 +808,7 @@ server_section_parser (enum mu_cfg_section_stage stage,
case mu_cfg_section_end:
{
struct m_srv_config *pconf = *section_data;
struct mu_srv_config *pconf = *section_data;
if (pconf->acl)
mu_ip_server_set_acl (pconf->tcpsrv, pconf->acl);
}
......@@ -904,22 +910,22 @@ static struct mu_cfg_param dot_server_cfg_param[] = {
static struct mu_cfg_param server_cfg_param[] = {
{ "single-process", mu_cfg_bool,
NULL, mu_offsetof (struct m_srv_config, single_process), NULL,
NULL, mu_offsetof (struct mu_srv_config, single_process), NULL,
N_("Run this server in foreground.") },
{ "transcript", mu_cfg_bool,
NULL, mu_offsetof (struct m_srv_config, transcript), NULL,
NULL, mu_offsetof (struct mu_srv_config, transcript), NULL,
N_("Log the session transcript.") },
{ "timeout", mu_cfg_time,
NULL, mu_offsetof (struct m_srv_config, timeout), NULL,
NULL, mu_offsetof (struct mu_srv_config, timeout), NULL,
N_("Set idle timeout.") },
{ "acl", mu_cfg_section,
NULL, mu_offsetof (struct m_srv_config, acl), NULL,
NULL, mu_offsetof (struct mu_srv_config, acl), NULL,
N_("Global access control list.") },
{ NULL }
};
void
mu_m_server_cfg_init ()
mu_m_server_cfg_init (struct mu_cfg_param *app_param)
{
struct mu_cfg_section *section;
if (mu_create_canned_section ("server", &section) == 0)
......@@ -927,6 +933,8 @@ mu_m_server_cfg_init ()
section->parser = server_section_parser;
section->label = N_("ipaddr[:port]");
mu_cfg_section_add_params (section, server_cfg_param);
if (app_param)
mu_cfg_section_add_params (section, app_param);
}
if (mu_create_canned_section (".server", &section) == 0)
{
......
......@@ -55,7 +55,7 @@ mu_tls_module_init (enum mu_gocs_op op, void *data)
case mu_gocs_op_flush:
#ifdef WITH_TLS
mu_init_tls_libs ();
mu_init_tls_libs (0);
#endif
break;
}
......@@ -99,14 +99,17 @@ mu_check_tls_environment (void)
return 0;
}
rc = mu_file_safety_check (mu_tls_module_config.ssl_cafile,
mu_tls_module_config.ssl_cafile_safety_checks,
-1, NULL);
if (rc)
if (mu_tls_module_config.ssl_cafile)
{
mu_error ("%s: %s", mu_tls_module_config.ssl_cafile,
mu_strerror (rc));
return 0;
rc = mu_file_safety_check (mu_tls_module_config.ssl_cafile,
mu_tls_module_config.ssl_cafile_safety_checks,
-1, NULL);
if (rc)
{
mu_error ("%s: %s", mu_tls_module_config.ssl_cafile,
mu_strerror (rc));
return 0;
}
}
}
else
......@@ -126,10 +129,40 @@ _mu_gtls_logger(int level, const char *text)
#endif
int
mu_init_tls_libs (void)
mu_init_tls_libs (int x509_setup)
{
if (!mu_tls_enable)
mu_tls_enable = !gnutls_global_init (); /* Returns 1 on success */
{
int rc;
if ((rc = gnutls_global_init ()) == GNUTLS_E_SUCCESS)
mu_tls_enable = 1;
else
{
mu_error ("gnutls_global_init: %s", gnutls_strerror (rc));
return 0;
}
}
if (x509_setup && !x509_cred)
{
mu_diag_output (MU_DIAG_INFO, _("initializing X509..."));
gnutls_certificate_allocate_credentials (&x509_cred);
if (mu_tls_module_config.ssl_cafile)
gnutls_certificate_set_x509_trust_file (x509_cred,
mu_tls_module_config.ssl_cafile,
GNUTLS_X509_FMT_PEM);
gnutls_certificate_set_x509_key_file (x509_cred,
mu_tls_module_config.ssl_cert,
mu_tls_module_config.ssl_key,
GNUTLS_X509_FMT_PEM);
gnutls_dh_params_init (&dh_params);
gnutls_dh_params_generate2 (dh_params, DH_BITS);
gnutls_certificate_set_dh_params (x509_cred, dh_params);
mu_diag_output (MU_DIAG_INFO, _("finished initializing X509"));
}
#ifdef DEBUG_TLS
gnutls_global_set_log_function (_mu_gtls_logger);
gnutls_global_set_log_level (110);
......@@ -141,17 +174,14 @@ void
mu_deinit_tls_libs (void)
{
if (mu_tls_enable)
gnutls_global_deinit ();
{
if (x509_cred)
gnutls_certificate_free_credentials (x509_cred);
gnutls_global_deinit ();
}
mu_tls_enable = 0;
}
static void
generate_dh_params (void)
{
gnutls_dh_params_init (&dh_params);
gnutls_dh_params_generate2 (dh_params, DH_BITS);
}
static gnutls_session
initialize_tls_session (void)
{
......@@ -382,28 +412,8 @@ _tls_server_open (mu_stream_t stream)
if (!stream || sp->state != state_init)
return EINVAL;
mu_init_tls_libs ();
mu_init_tls_libs (1);
gnutls_certificate_allocate_credentials (&x509_cred);
if (mu_tls_module_config.ssl_cafile)
gnutls_certificate_set_x509_trust_file (x509_cred,
mu_tls_module_config.ssl_cafile,
GNUTLS_X509_FMT_PEM);
rc = gnutls_certificate_set_x509_key_file (x509_cred,
mu_tls_module_config.ssl_cert,
mu_tls_module_config.ssl_key,
GNUTLS_X509_FMT_PEM);
if (rc < 0)
{
sp->tls_err = rc;
return EIO;
}
generate_dh_params ();
gnutls_certificate_set_dh_params (x509_cred, dh_params);
sp->session = initialize_tls_session ();
mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, transport);
gnutls_transport_set_ptr2 (sp->session,
......@@ -478,13 +488,12 @@ _tls_client_open (mu_stream_t stream)
switch (sp->state)
{
case state_closed:
gnutls_certificate_free_credentials (x509_cred);
if (sp->session)
gnutls_deinit (sp->session);
/* FALLTHROUGH */
case state_init:
mu_init_tls_libs ();
mu_init_tls_libs (0);
prepare_client_session (stream);
rc = gnutls_handshake (sp->session);
if (rc < 0)
......@@ -630,8 +639,6 @@ _tls_done (struct _mu_stream *stream)
{
struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
if (x509_cred)
gnutls_certificate_free_credentials (x509_cred);
if (sp->session && sp->state == state_closed)
{
gnutls_deinit (sp->session);
......
......@@ -52,11 +52,11 @@ cb2_safety_checks (const char *name, void *data)
{
int defval;
if (data == &tls_settings.ssl_key)
if (data == &tls_settings.ssl_key_safety_checks)
defval = SSL_KEY_FILE_CHECKS;
else if (data == &tls_settings.ssl_cert)
else if (data == &tls_settings.ssl_cert_safety_checks)
defval = SSL_CERT_FILE_CHECKS;
else if (data == &tls_settings.ssl_cafile)
else if (data == &tls_settings.ssl_cafile_safety_checks)
defval = SSL_CA_FILE_CHECKS;
else
{
......
......@@ -574,8 +574,9 @@ typedef union
} all_addr_t;
int
lmtp_connection (int fd, struct sockaddr *sa, int salen, void *data,
mu_ip_server_t srv, time_t timeout, int transcript)
lmtp_connection (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data)
{
mu_stream_t str;
int rc;
......@@ -588,9 +589,9 @@ lmtp_connection (int fd, struct sockaddr *sa, int salen, void *data,
}
mu_stream_set_buffer (str, mu_buffer_line, 0);
if (transcript || maidag_transcript)
if (pconf->transcript || maidag_transcript)
str = lmtp_transcript (str);
lmtp_loop (str, timeout);
lmtp_loop (str, pconf->timeout);
mu_stream_destroy (&str);
return 0;
}
......
......@@ -525,7 +525,7 @@ main (int argc, char *argv[])
mu_tcpwrapper_cfg_init ();
mu_acl_cfg_init ();
mu_m_server_cfg_init ();
mu_m_server_cfg_init (NULL);
maidag_cfg_init ();
/* Parse command line */
......
......@@ -150,8 +150,9 @@ int deliver_to_user (mu_message_t msg, char *dest_id, char **errp);
int maidag_stdio_delivery (maidag_delivery_fn fun, int argc, char **argv);
int maidag_lmtp_server (void);
int lmtp_connection (int fd, struct sockaddr *sa, int salen, void *data,
mu_ip_server_t srv, time_t timeout, int transcript);
int lmtp_connection (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data);
void maidag_error (const char *fmt, ...) MU_PRINTFLIKE(1, 2);
void notify_biff (mu_mailbox_t mbox, char *name, size_t size);
......
......@@ -93,6 +93,10 @@ pop3d_abquit (int reason)
mu_diag_output (MU_DIAG_INFO, _("no socket to send to"));
break;
case ERR_FILE:
code = EX_IOERR;
break;
case ERR_PROTO:
code = EX_PROTOCOL;
mu_diag_output (MU_DIAG_INFO, _("remote protocol error"));
......@@ -125,7 +129,7 @@ pop3d_abquit (int reason)
}
void
pop3d_setio (int ifd, int ofd)
pop3d_setio (int ifd, int ofd, int tls)
{
mu_stream_t str, istream, ostream;
......@@ -137,11 +141,26 @@ pop3d_setio (int ifd, int ofd)
if (mu_stdio_stream_create (&istream, ifd, MU_STREAM_READ))
pop3d_abquit (ERR_NO_IFILE);
mu_stream_set_buffer (istream, mu_buffer_line, 0);
if (mu_stdio_stream_create (&ostream, ofd, MU_STREAM_WRITE))
pop3d_abquit (ERR_NO_OFILE);
/* Combine the two streams into an I/O one. */
#ifdef WITH_TLS
if (tls)
{
int rc = mu_tls_server_stream_create (&str, istream, ostream, 0);
if (rc)
{
mu_stream_unref (istream);
mu_stream_unref (ostream);
mu_error (_("failed to create TLS stream: %s"), mu_strerror (rc));
pop3d_abquit (ERR_FILE);
}
tls_done = 1;
}
else
#endif
if (mu_iostream_create (&str, istream, ostream))
pop3d_abquit (ERR_FILE);
......
......@@ -18,6 +18,7 @@
#include "pop3d.h"
#include "mailutils/pam.h"
#include "mailutils/libargp.h"
#include "mailutils/pop3.h"
#include "tcpwrap.h"
mu_mailbox_t mbox;
......@@ -107,6 +108,19 @@ cb_bulletin_db (void *data, mu_config_value_t *val)
}
#endif
struct pop3d_srv_config
{
struct mu_srv_config m_cfg;
int tls;
};
static struct mu_cfg_param pop3d_srv_param[] = {
{ "tls", mu_cfg_bool, NULL, mu_offsetof (struct pop3d_srv_config, tls), NULL,
N_("Use TLS encryption for this server")
},
{ NULL }
};
static struct mu_cfg_param pop3d_cfg_param[] = {
{ "undelete", mu_cfg_bool, &undelete_on_startup, 0, NULL,
N_("On startup, clear deletion marks from all the messages.") },
......@@ -247,9 +261,10 @@ pop3d_get_client_address (int fd, struct sockaddr_in *pcs)
executes the proper functions. Also handles the bulk of error reporting.
Arguments:
ifd -- input descriptor
ofd -- output descriptor */
ofd -- output descriptor
tls -- initiate encrypted connection */
int
pop3d_mainloop (int ifd, int ofd)
pop3d_mainloop (int ifd, int ofd, int tls)
{
int status = OK;
char buffer[512];
......@@ -258,7 +273,7 @@ pop3d_mainloop (int ifd, int ofd)
mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab));
pop3d_setio (ifd, ofd);
pop3d_setio (ifd, ofd, tls);
state = initial_state;
......@@ -324,13 +339,16 @@ pop3d_mainloop (int ifd, int ofd)
}
int
pop3d_connection (int fd, struct sockaddr *sa, int salen, void *data,
mu_ip_server_t srv, time_t timeout, int transcript)
pop3d_connection (int fd, struct sockaddr *sa, int salen,
struct mu_srv_config *pconf,
void *data)
{
idle_timeout = timeout;
if (pop3d_transcript != transcript)
pop3d_transcript = transcript;
pop3d_mainloop (fd, fd);
struct pop3d_srv_config *cfg = (struct pop3d_srv_config *) pconf;
idle_timeout = pconf->timeout;
pop3d_transcript = pconf->transcript;
pop3d_mainloop (fd, fd, cfg->tls);
return 0;
}
......@@ -370,11 +388,12 @@ main (int argc, char **argv)
mu_tcpwrapper_cfg_init ();
manlock_cfg_init ();
mu_acl_cfg_init ();
mu_m_server_cfg_init ();
mu_m_server_cfg_init (pop3d_srv_param);
mu_argp_init (NULL, NULL);
mu_m_server_create (&server, program_version);
mu_m_server_set_config_size (server, sizeof (struct pop3d_srv_config));
mu_m_server_set_conn (server, pop3d_connection);
mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork);
mu_m_server_set_mode (server, MODE_INTERACTIVE);
......@@ -451,7 +470,7 @@ main (int argc, char **argv)
tls_available = mu_check_tls_environment ();
if (tls_available)
{
tls_available = mu_init_tls_libs ();
tls_available = mu_init_tls_libs (1);
if (tls_available)
enable_stls ();
}
......@@ -469,7 +488,7 @@ main (int argc, char **argv)
{
/* Make sure we are in the root directory. */
chdir ("/");
status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD);
status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, 0);
}
if (status)
......
......@@ -236,7 +236,7 @@ extern void enable_stls (void);
#endif /* WITH_TLS */
extern void pop3d_outf (const char *fmt, ...) MU_PRINTFLIKE(1,2);
extern void pop3d_setio (int, int);
extern void pop3d_setio (int, int, int);
extern char *pop3d_readline (char *, size_t);
extern void pop3d_flush_output (void);
......