Mercurial > dovecot > core-2.2
changeset 12617:7b7434fef6ff
imapc: Added initial support for SSL.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 31 Jan 2011 18:41:04 +0200 |
parents | bd23d4e10fa1 |
children | ac84693374ad |
files | configure.in src/lib-storage/index/imapc/Makefile.am src/lib-storage/index/imapc/imapc-client-private.h src/lib-storage/index/imapc/imapc-client.c src/lib-storage/index/imapc/imapc-client.h src/lib-storage/index/imapc/imapc-connection.c src/lib-storage/index/imapc/imapc-storage.c |
diffstat | 7 files changed, 120 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/configure.in Mon Jan 31 18:40:27 2011 +0200 +++ b/configure.in Mon Jan 31 18:41:04 2011 +0200 @@ -2429,7 +2429,7 @@ sdbox_libs='$(top_builddir)/src/lib-storage/index/dbox-single/libstorage_dbox_single.la' mdbox_libs='$(top_builddir)/src/lib-storage/index/dbox-multi/libstorage_dbox_multi.la' cydir_libs='$(top_builddir)/src/lib-storage/index/cydir/libstorage_cydir.la' -imapc_libs='$(top_builddir)/src/lib-storage/index/imapc/libstorage_imapc.la' +imapc_libs='$(top_builddir)/src/lib-storage/index/imapc/libstorage_imapc.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la' raw_libs='$(top_builddir)/src/lib-storage/index/raw/libstorage_raw.la' shared_libs='$(top_builddir)/src/lib-storage/index/shared/libstorage_shared.la'
--- a/src/lib-storage/index/imapc/Makefile.am Mon Jan 31 18:40:27 2011 +0200 +++ b/src/lib-storage/index/imapc/Makefile.am Mon Jan 31 18:41:04 2011 +0200 @@ -4,6 +4,7 @@ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-test \ -I$(top_srcdir)/src/lib-dns \ + -I$(top_srcdir)/src/lib-ssl-iostream \ -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/lib-imap \ -I$(top_srcdir)/src/lib-index \
--- a/src/lib-storage/index/imapc/imapc-client-private.h Mon Jan 31 18:40:27 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-client-private.h Mon Jan 31 18:41:04 2011 +0200 @@ -11,6 +11,7 @@ struct imapc_client { pool_t pool; struct imapc_client_settings set; + struct ssl_iostream_context *ssl_ctx; imapc_untagged_callback_t *untagged_callback; void *untagged_context;
--- a/src/lib-storage/index/imapc/imapc-client.c Mon Jan 31 18:40:27 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-client.c Mon Jan 31 18:41:04 2011 +0200 @@ -5,6 +5,7 @@ #include "str.h" #include "ioloop.h" #include "safe-mkstemp.h" +#include "iostream-ssl.h" #include "imapc-seqmap.h" #include "imapc-connection.h" #include "imapc-client-private.h" @@ -33,6 +34,8 @@ imapc_client_init(const struct imapc_client_settings *set) { struct imapc_client *client; + struct ssl_iostream_settings ssl_set; + const char *source; pool_t pool; pool = pool_alloconly_create("imapc client", 1024); @@ -48,6 +51,23 @@ p_strdup(pool, set->dns_client_socket_path); client->set.temp_path_prefix = p_strdup(pool, set->temp_path_prefix); + + if (set->ssl_mode != IMAPC_CLIENT_SSL_MODE_NONE) { + client->set.ssl_mode = set->ssl_mode; + client->set.ssl_ca_dir = p_strdup(pool, set->ssl_ca_dir); + + memset(&ssl_set, 0, sizeof(ssl_set)); + ssl_set.ca_dir = set->ssl_ca_dir; + ssl_set.verify_remote_cert = TRUE; + + source = t_strdup_printf("%s:%u", set->host, set->port); + if (ssl_iostream_context_init_client(source, &ssl_set, + &client->ssl_ctx) < 0) { + i_error("imapc(%s): Couldn't initialize SSL context", + source); + } + } + p_array_init(&client->conns, pool, 8); return client; } @@ -59,6 +79,8 @@ *_client = NULL; + if (client->ssl_ctx != NULL) + ssl_iostream_context_deinit(&client->ssl_ctx); array_foreach_modifiable(&client->conns, connp) imapc_connection_deinit(&(*connp)->conn); pool_unref(&client->pool);
--- a/src/lib-storage/index/imapc/imapc-client.h Mon Jan 31 18:40:27 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-client.h Mon Jan 31 18:41:04 2011 +0200 @@ -23,6 +23,12 @@ }; extern const struct imapc_capability_name imapc_capability_names[]; +enum imapc_client_ssl_mode { + IMAPC_CLIENT_SSL_MODE_NONE, + IMAPC_CLIENT_SSL_MODE_IMMEDIATE, + IMAPC_CLIENT_SSL_MODE_STARTTLS +}; + struct imapc_client_settings { const char *host; unsigned int port; @@ -33,6 +39,9 @@ const char *dns_client_socket_path; const char *temp_path_prefix; + + enum imapc_client_ssl_mode ssl_mode; + const char *ssl_ca_dir; }; struct imapc_command_reply {
--- a/src/lib-storage/index/imapc/imapc-connection.c Mon Jan 31 18:40:27 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-connection.c Mon Jan 31 18:41:04 2011 +0200 @@ -9,6 +9,7 @@ #include "write-full.h" #include "str.h" #include "dns-lookup.h" +#include "iostream-ssl.h" #include "imap-quote.h" #include "imap-util.h" #include "imap-parser.h" @@ -68,6 +69,8 @@ struct imap_parser *parser; struct timeout *to; + struct ssl_iostream *ssl_iostream; + int (*input_callback)(struct imapc_connection *conn); enum imapc_input_state input_state; unsigned int cur_tag; @@ -123,7 +126,8 @@ *_conn = NULL; imapc_connection_disconnect(conn); - p_strsplit_free(default_pool, conn->capabilities_list); + if (conn->capabilities_list != NULL) + p_strsplit_free(default_pool, conn->capabilities_list); array_free(&conn->cmd_send_queue); array_free(&conn->cmd_wait_list); array_free(&conn->literal_files); @@ -215,6 +219,8 @@ timeout_remove(&conn->to); imap_parser_destroy(&conn->parser); io_remove(&conn->io); + if (conn->ssl_iostream != NULL) + ssl_iostream_unref(&conn->ssl_iostream); i_stream_destroy(&conn->input); o_stream_destroy(&conn->output); net_disconnect(conn->fd); @@ -835,15 +841,73 @@ static void imapc_connection_input(struct imapc_connection *conn) { - if (i_stream_read(conn->input) == -1) { + ssize_t ret; + + if ((ret = i_stream_read(conn->input)) > 0) + imapc_connection_input_pending(conn); + else if (ret < 0) { /* disconnected */ - i_error("imapc(%s): Server disconnected unexpectedly", - conn->name); + if (conn->ssl_iostream == NULL) { + i_error("imapc(%s): Server disconnected unexpectedly", + conn->name); + } else { + i_error("imapc(%s): Server disconnected: %s", conn->name, + ssl_iostream_get_last_error(conn->ssl_iostream)); + } imapc_connection_disconnect(conn); return; } +} - imapc_connection_input_pending(conn); +static int imapc_connection_ssl_handshaked(void *context) +{ + struct imapc_connection *conn = context; + + if (ssl_iostream_has_valid_client_cert(conn->ssl_iostream)) + return 0; + + if (!ssl_iostream_has_broken_client_cert(conn->ssl_iostream)) { + i_error("imapc(%s): SSL certificate not received", conn->name); + } else { + i_error("imapc(%s): Received invalid SSL certificate", + conn->name); + } + i_stream_close(conn->input); + return -1; +} + +static int imapc_connection_ssl_init(struct imapc_connection *conn) +{ + struct ssl_iostream_settings ssl_set; + const char *source; + + if (conn->client->ssl_ctx == NULL) { + i_error("imapc(%s): No SSL context", conn->name); + return -1; + } + + memset(&ssl_set, 0, sizeof(ssl_set)); + ssl_set.verbose_invalid_cert = TRUE; + ssl_set.verify_remote_cert = TRUE; + ssl_set.require_valid_cert = TRUE; + + source = t_strdup_printf("imapc(%s): ", conn->name); + if (io_stream_create_ssl(conn->client->ssl_ctx, source, &ssl_set, + &conn->input, &conn->output, + &conn->ssl_iostream) < 0) { + i_error("imapc(%s): Couldn't initialize SSL client", + conn->name); + return -1; + } + ssl_iostream_set_handshake_callback(conn->ssl_iostream, + imapc_connection_ssl_handshaked, + conn); + if (ssl_iostream_handshake(conn->ssl_iostream) < 0) { + i_error("imapc(%s): SSL handshake failed", conn->name); + return -1; + } + imap_parser_set_streams(conn->parser, conn->input, NULL); + return 0; } static void imapc_connection_connected(struct imapc_connection *conn) @@ -861,6 +925,11 @@ } io_remove(&conn->io); conn->io = io_add(conn->fd, IO_READ, imapc_connection_input, conn); + + if (conn->client->set.ssl_mode == IMAPC_CLIENT_SSL_MODE_IMMEDIATE) { + if (imapc_connection_ssl_init(conn) < 0) + imapc_connection_disconnect(conn); + } } static void imapc_connection_timeout(struct imapc_connection *conn) @@ -956,7 +1025,7 @@ return; o_stream_cork(conn->output); - while (ret > 0 && !conn->client->stop_now) { + while (ret > 0 && !conn->client->stop_now && conn->input != NULL) { T_BEGIN { ret = imapc_connection_input_one(conn); } T_END;
--- a/src/lib-storage/index/imapc/imapc-storage.c Mon Jan 31 18:40:27 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-storage.c Mon Jan 31 18:41:04 2011 +0200 @@ -163,7 +163,7 @@ { struct imapc_storage *storage = (struct imapc_storage *)_storage; struct imapc_client_settings set; - const char *port; + const char *port, *value; string_t *str; memset(&set, 0, sizeof(set)); @@ -196,6 +196,16 @@ mail_user_set_get_temp_prefix(str, _storage->user->set); set.temp_path_prefix = str_c(str); + set.ssl_ca_dir = mail_user_plugin_getenv(_storage->user, + "imapc_ssl_ca_dir"); + if (set.ssl_ca_dir != NULL) { + value = mail_user_plugin_getenv(_storage->user, + "imapc_ssl_starttls"); + set.ssl_mode = value != NULL ? + IMAPC_CLIENT_SSL_MODE_STARTTLS : + IMAPC_CLIENT_SSL_MODE_IMMEDIATE; + } + storage->list = (struct imapc_mailbox_list *)ns->list; storage->list->storage = storage; storage->client = imapc_client_init(&set);