changeset 14729:0de6b238d6eb

Added libdovecot-ssl for creating SSL servers more easily using lib-ssl-iostream.
author Timo Sirainen <tss@iki.fi>
date Sat, 28 Jul 2012 17:55:46 +0300
parents 983c6ff12cc9
children 73ce16df6b16
files Makefile.am configure.in dovecot-config.in.in dovecot.m4 src/Makefile.am src/lib-dovecot/Makefile.am src/lib-master/Makefile.am src/lib-master/master-service-ssl.c src/lib-master/master-service-ssl.h
diffstat 9 files changed, 182 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Sat Jul 28 17:54:19 2012 +0300
+++ b/Makefile.am	Sat Jul 28 17:55:46 2012 +0300
@@ -65,6 +65,7 @@
 	-e "s|^\(LIBDOVECOT\)=.*$$|\1='-L$(pkglibdir) -ldovecot'|" \
 	-e "s|^\(LIBDOVECOT_LOGIN\)=.*$$|\1=-ldovecot-login|" \
 	-e "s|^\(LIBDOVECOT_SQL\)=.*$$|\1=-ldovecot-sql|" \
+	-e "s|^\(LIBDOVECOT_SSL\)=.*$$|\1=-ldovecot-ssl|" \
 	-e "s|^\(LIBDOVECOT_LDA\)=.*$$|\1=-ldovecot-lda|" \
 	-e "s|^\(LIBDOVECOT_STORAGE\)=.*$$|\1=-ldovecot-storage|" \
 	-e "s|^\(LIBDOVECOT_INCLUDE\)=.*$$|\1=-I$(pkgincludedir)|" \
--- a/configure.in	Sat Jul 28 17:54:19 2012 +0300
+++ b/configure.in	Sat Jul 28 17:55:46 2012 +0300
@@ -2514,6 +2514,7 @@
   LIBDOVECOT="$LIBDOVECOT_DEPS"
   LIBDOVECOT_STORAGE_DEPS='$(top_builddir)/src/lib-storage/libdovecot-storage.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la'
   LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/libdovecot-login.la'
+  LIBDOVECOT_SSL='$(top_builddir)/src/lib-master/libmaster_ssl.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la'
   LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/libdovecot-lda.la'
 else
   LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib/liblib.la'
@@ -2522,6 +2523,7 @@
   LIBDOVECOT_STORAGE_FIRST='$(top_builddir)/src/lib-storage/libstorage_service.la $(top_builddir)/src/lib-storage/register/libstorage_register.la'
   LIBDOVECOT_STORAGE_DEPS="$LIBDOVECOT_STORAGE_FIRST $LINKED_STORAGE_LIBS $LIBDOVECOT_STORAGE_LAST"
   LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/liblogin.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la'
+  LIBDOVECOT_SSL='$(top_builddir)/src/lib-master/libmaster_ssl.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la'
   LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/liblda.la'
 fi
 LIBDOVECOT_STORAGE="$LIBDOVECOT_STORAGE_DEPS $LINKED_STORAGE_LDADD"
@@ -2532,6 +2534,7 @@
 AC_SUBST(LIBDOVECOT_STORAGE_DEPS)
 AC_SUBST(LIBDOVECOT_LOGIN)
 AC_SUBST(LIBDOVECOT_SQL)
+AC_SUBST(LIBDOVECOT_SSL)
 AC_SUBST(LIBDOVECOT_LDA)
 
 dnl **
--- a/dovecot-config.in.in	Sat Jul 28 17:54:19 2012 +0300
+++ b/dovecot-config.in.in	Sat Jul 28 17:55:46 2012 +0300
@@ -6,16 +6,18 @@
 LIBDOVECOT="@LIBDOVECOT@ @MODULE_LIBS@"
 LIBDOVECOT_LOGIN="@LIBDOVECOT_LOGIN@ @SSL_LIBS@"
 LIBDOVECOT_SQL="@LIBDOVECOT_SQL@"
+LIBDOVECOT_SSL="@LIBDOVECOT_SSL@"
 LIBDOVECOT_LDA="@LIBDOVECOT_LDA@"
 LIBDOVECOT_STORAGE="@LIBDOVECOT_STORAGE@"
 
 LIBDOVECOT_DEPS="@LIBDOVECOT_DEPS@"
 LIBDOVECOT_LOGIN_DEPS="@LIBDOVECOT_LOGIN@"
 LIBDOVECOT_SQL_DEPS="@LIBDOVECOT_SQL@"
+LIBDOVECOT_SSL_DEPS="@LIBDOVECOT_SSL@"
 LIBDOVECOT_LDA_DEPS="@LIBDOVECOT_LDA@"
 LIBDOVECOT_STORAGE_DEPS="@LIBDOVECOT_STORAGE_DEPS@"
 
-LIBDOVECOT_INCLUDE="-I$(incdir) -I$(incdir)/src/lib -I$(incdir)/src/lib-dict -I$(incdir)/src/lib-dns -I$(incdir)/src/lib-mail -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-fs -I$(incdir)/src/lib-charset -I$(incdir)/src/lib-auth -I$(incdir)/src/lib-master -I$(incdir)/src/lib-settings"
+LIBDOVECOT_INCLUDE="-I$(incdir) -I$(incdir)/src/lib -I$(incdir)/src/lib-dict -I$(incdir)/src/lib-dns -I$(incdir)/src/lib-mail -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-fs -I$(incdir)/src/lib-charset -I$(incdir)/src/lib-auth -I$(incdir)/src/lib-master -I$(incdir)/src/lib-ssl-iostream -I$(incdir)/src/lib-settings"
 LIBDOVECOT_LDA_INCLUDE="-I$(incdir)/src/lib-lda -I$(incdir)/src/lda"
 LIBDOVECOT_STORAGE_INCLUDE="-I$(incdir)/src/lib-index -I$(incdir)/src/lib-storage -I$(incdir)/src/lib-storage/index -I$(incdir)/src/lib-storage/index/raw"
 LIBDOVECOT_LOGIN_INCLUDE="-I$(incdir)/src/login-common"
--- a/dovecot.m4	Sat Jul 28 17:54:19 2012 +0300
+++ b/dovecot.m4	Sat Jul 28 17:55:46 2012 +0300
@@ -60,8 +60,8 @@
 	eval `grep '^LIBDOVECOT[[A-Z_]]*=' "$dovecotdir"/dovecot-config`
 	AX_SUBST_L([dovecotdir], [dovecot_moduledir], [dovecot_pkgincludedir], [dovecot_pkglibexecdir], [dovecot_pkglibdir], [dovecot_docdir])
 	AX_SUBST_L([DOVECOT_CFLAGS], [DOVECOT_LIBS], [DOVECOT_SSL_LIBS], [DOVECOT_SQL_LIBS])
-	AX_SUBST_L([LIBDOVECOT], [LIBDOVECOT_LOGIN], [LIBDOVECOT_SQL], [LIBDOVECOT_LDA], [LIBDOVECOT_STORAGE])
-	AX_SUBST_L([LIBDOVECOT_DEPS], [LIBDOVECOT_LOGIN_DEPS], [LIBDOVECOT_SQL_DEPS], [LIBDOVECOT_LDA_DEPS], [LIBDOVECOT_STORAGE_DEPS])
+	AX_SUBST_L([LIBDOVECOT], [LIBDOVECOT_LOGIN], [LIBDOVECOT_SQL], [LIBDOVECOT_SSL], [LIBDOVECOT_LDA], [LIBDOVECOT_STORAGE])
+	AX_SUBST_L([LIBDOVECOT_DEPS], [LIBDOVECOT_LOGIN_DEPS], [LIBDOVECOT_SQL_DEPS], [LIBDOVECOT_SSL_DEPS], [LIBDOVECOT_LDA_DEPS], [LIBDOVECOT_STORAGE_DEPS])
 	AX_SUBST_L([LIBDOVECOT_INCLUDE], [LIBDOVECOT_LDA_INCLUDE], [LIBDOVECOT_SERVICE_INCLUDE], [LIBDOVECOT_STORAGE_INCLUDE], [LIBDOVECOT_LOGIN_INCLUDE], [LIBDOVECOT_CONFIG_INCLUDE])
 
 	DC_PLUGIN_DEPS
--- a/src/Makefile.am	Sat Jul 28 17:54:19 2012 +0300
+++ b/src/Makefile.am	Sat Jul 28 17:55:46 2012 +0300
@@ -9,12 +9,12 @@
 	lib-imap-storage \
 	lib-master \
 	lib-dict \
-	lib-settings
+	lib-settings \
+	lib-ssl-iostream
 
 SUBDIRS = \
 	lib-test \
 	$(LIBDOVECOT_SUBDIRS) \
-	lib-ssl-iostream \
 	lib-imap-client \
 	lib-dovecot \
 	lib-index \
--- a/src/lib-dovecot/Makefile.am	Sat Jul 28 17:54:19 2012 +0300
+++ b/src/lib-dovecot/Makefile.am	Sat Jul 28 17:55:46 2012 +0300
@@ -10,15 +10,26 @@
 	../lib-master/libmaster.la \
 	../lib/liblib.la
 
-pkglib_LTLIBRARIES = libdovecot.la
+ssl_libs = \
+	../lib-master/libmaster_ssl.la
+	../lib-ssl-iostream/libssl_iostream.la
+
+pkglib_LTLIBRARIES = libdovecot.la libdovecot-ssl.la
 
 libdovecot_la_SOURCES = 
+libdovecot_ssl_la_SOURCES = 
 
 libdovecot_la_LIBADD = \
 	$(libs) \
 	$(MODULE_LIBS) \
 	$(LTLIBICONV)
 
+libdovecot_ssl_la_LIBADD = \
+	$(ssl_libs) \
+	$(SSL_LIBS)
+
 libdovecot_la_DEPENDENCIES = $(libs)
+libdovecot_ssl_la_DEPENDENCIES = $(ssl_libs)
 
 libdovecot_la_LDFLAGS = -export-dynamic
+libdovecot_ssl_la_LDFLAGS = -export-dynamic
--- a/src/lib-master/Makefile.am	Sat Jul 28 17:54:19 2012 +0300
+++ b/src/lib-master/Makefile.am	Sat Jul 28 17:55:46 2012 +0300
@@ -1,10 +1,11 @@
 pkgsysconfdir = $(sysconfdir)/dovecot
 
-noinst_LTLIBRARIES = libmaster.la
+noinst_LTLIBRARIES = libmaster.la libmaster_ssl.la
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-settings \
+	-I$(top_srcdir)/src/lib-ssl-iostream \
 	-DPKG_RUNDIR=\""$(rundir)"\" \
 	-DPKG_STATEDIR=\""$(statedir)"\" \
 	-DSYSCONFDIR=\""$(pkgsysconfdir)"\" \
@@ -25,6 +26,9 @@
 	mountpoint-list.c \
 	syslog-util.c
 
+libmaster_ssl_la_SOURCES = \
+	master-service-ssl.c
+
 headers = \
 	anvil-client.h \
 	ipc-client.h \
@@ -38,6 +42,7 @@
 	master-service-private.h \
 	master-service-settings.h \
 	master-service-settings-cache.h \
+	master-service-ssl.h \
 	master-service-ssl-settings.h \
 	service-settings.h \
 	mountpoint-list.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-master/master-service-ssl.c	Sat Jul 28 17:55:46 2012 +0300
@@ -0,0 +1,138 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "buffer.h"
+#include "iostream-ssl.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+#include "master-service-ssl-settings.h"
+#include "master-service-ssl.h"
+
+#include <unistd.h>
+
+/* Check every 30 minutes if parameters file has been updated */
+#define SSL_PARAMS_CHECK_INTERVAL (60*30)
+
+#define SSL_PARAMETERS_PATH "ssl-params"
+
+static int ssl_refresh_parameters(struct master_service *service)
+{
+#define BUF_APPEND_SIZE 1024
+	const char *path;
+	buffer_t *buf;
+	void *data;
+	ssize_t ret;
+	int fd;
+
+	if (ioloop_time == 0 ||
+	    service->ssl_params_last_refresh > ioloop_time - SSL_PARAMS_CHECK_INTERVAL)
+		return 0;
+	service->ssl_params_last_refresh = ioloop_time;
+
+	path = t_strdup_printf("%s/"SSL_PARAMETERS_PATH, service->set->base_dir);
+	fd = net_connect_unix(path);
+	if (fd == -1) {
+		i_error("connect(%s) failed: %m", path);
+		return -1;
+	}
+	net_set_nonblock(fd, FALSE);
+
+	buf = buffer_create_dynamic(default_pool, BUF_APPEND_SIZE*2);
+	for (;;) {
+		data = buffer_append_space_unsafe(buf, BUF_APPEND_SIZE);
+		ret = read(fd, data, BUF_APPEND_SIZE);
+		buffer_set_used_size(buf, buf->used - BUF_APPEND_SIZE +
+				     (ret < 0 ? 0 : ret));
+		if (ret <= 0)
+			break;
+	}
+	if (ret < 0)
+		i_error("read(%s) failed: %m", path);
+	else if (ssl_iostream_context_import_params(service->ssl_ctx, buf) < 0) {
+		i_error("Corrupted SSL parameters file: "
+			PKG_STATEDIR"/ssl-parameters.dat - disabling SSL %u", (int)buf->used);
+		ret = -1;
+	}
+	i_close_fd(&fd);
+	buffer_free(&buf);
+	return ret < 0 ? -1 : 0;
+}
+
+int master_service_ssl_init(struct master_service *service,
+			    struct istream **input, struct ostream **output,
+			    struct ssl_iostream **ssl_iostream_r)
+{
+	const struct master_service_ssl_settings *set;
+	struct ssl_iostream_settings ssl_set;
+
+	i_assert(service->ssl_ctx_initialized);
+
+	if (service->ssl_ctx == NULL)
+		return -1;
+
+	(void)ssl_refresh_parameters(service);
+
+	set = master_service_ssl_settings_get(service);
+
+	memset(&ssl_set, 0, sizeof(ssl_set));
+	ssl_set.verbose = set->verbose_ssl;
+	ssl_set.verify_remote_cert = set->ssl_verify_client_cert;
+
+	return io_stream_create_ssl(service->ssl_ctx, service->name, &ssl_set,
+				    input, output, ssl_iostream_r);
+}
+
+bool master_service_ssl_is_enabled(struct master_service *service)
+{
+	return service->ssl_ctx != NULL;
+}
+
+void master_service_ssl_ctx_init(struct master_service *service)
+{
+	const struct master_service_ssl_settings *set;
+	struct ssl_iostream_settings ssl_set;
+
+	if (service->ssl_ctx_initialized)
+		return;
+	service->ssl_ctx_initialized = TRUE;
+
+	/* must be called after master_service_init_finish() so that if
+	   initialization fails we can close the SSL listeners */
+	i_assert(service->listeners != NULL);
+
+	set = master_service_ssl_settings_get(service);
+
+	memset(&ssl_set, 0, sizeof(ssl_set));
+	ssl_set.protocols = set->ssl_protocols;
+	ssl_set.cipher_list = set->ssl_cipher_list;
+	ssl_set.ca = set->ssl_ca;
+	ssl_set.cert = set->ssl_cert;
+	ssl_set.key = set->ssl_key;
+	ssl_set.key_password = set->ssl_key_password;
+	ssl_set.cert_username_field = set->ssl_cert_username_field;
+	ssl_set.crypto_device = set->ssl_crypto_device;
+
+	ssl_set.verbose = set->verbose_ssl;
+	ssl_set.verify_remote_cert = set->ssl_verify_client_cert;
+
+	if (ssl_iostream_context_init_server(service->name, &ssl_set,
+					     &service->ssl_ctx) < 0) {
+		i_error("SSL context initialization failed, disabling SSL");
+		master_service_ssl_io_listeners_remove(service);
+		return;
+	}
+	if (ssl_refresh_parameters(service) < 0) {
+		i_error("Couldn't initialize SSL parameters, disabling SSL");
+		ssl_iostream_context_deinit(&service->ssl_ctx);
+		master_service_ssl_io_listeners_remove(service);
+		return;
+	}
+}
+
+void master_service_ssl_ctx_deinit(struct master_service *service)
+{
+	if (service->ssl_ctx != NULL)
+		ssl_iostream_context_deinit(&service->ssl_ctx);
+	service->ssl_ctx_initialized = FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-master/master-service-ssl.h	Sat Jul 28 17:55:46 2012 +0300
@@ -0,0 +1,15 @@
+#ifndef MASTER_SERVICE_SSL_H
+#define MASTER_SERVICE_SSL_H
+
+struct ssl_iostream;
+
+int master_service_ssl_init(struct master_service *service,
+			    struct istream **input, struct ostream **output,
+			    struct ssl_iostream **ssl_iostream_r);
+
+bool master_service_ssl_is_enabled(struct master_service *service);
+
+void master_service_ssl_ctx_init(struct master_service *service);
+void master_service_ssl_ctx_deinit(struct master_service *service);
+
+#endif