From: Timo Sirainen Date: Wed, 29 Oct 2014 16:58:01 +0000 (-0700) Subject: lmtp: Added support for STARTTLS command. X-Git-Tag: 2.2.16.rc1~265 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4fbf59562594dbbbe037f8d4c480dbf88f3fc708;p=thirdparty%2Fdovecot%2Fcore.git lmtp: Added support for STARTTLS command. --- diff --git a/src/lmtp/Makefile.am b/src/lmtp/Makefile.am index 39d34b0ac3..9991aa0bbc 100644 --- a/src/lmtp/Makefile.am +++ b/src/lmtp/Makefile.am @@ -11,6 +11,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib-index \ -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-lda \ + -I$(top_srcdir)/src/lib-ssl-iostream \ -I$(top_srcdir)/src/lib-storage \ -I$(top_srcdir)/src/lib-storage/index \ -I$(top_srcdir)/src/lib-storage/index/raw diff --git a/src/lmtp/client.c b/src/lmtp/client.c index 8adae4b351..09e14857fd 100644 --- a/src/lmtp/client.c +++ b/src/lmtp/client.c @@ -12,7 +12,9 @@ #include "var-expand.h" #include "settings-parser.h" #include "master-service.h" +#include "master-service-ssl.h" #include "master-service-settings.h" +#include "iostream-ssl.h" #include "mail-namespace.h" #include "mail-storage.h" #include "mail-storage-service.h" @@ -69,6 +71,9 @@ static int client_input_line(struct client *client, const char *line) if (strcmp(cmd, "LHLO") == 0) return cmd_lhlo(client, args); + if (strcmp(cmd, "STARTTLS") == 0 && + master_service_ssl_is_enabled(master_service)) + return cmd_starttls(client); if (strcmp(cmd, "MAIL") == 0) return cmd_mail(client, args); if (strcmp(cmd, "RCPT") == 0) @@ -274,6 +279,8 @@ void client_destroy(struct client *client, const char *prefix, io_remove(&client->io); if (client->to_idle != NULL) timeout_remove(&client->to_idle); + if (client->ssl_iostream != NULL) + ssl_iostream_destroy(&client->ssl_iostream); i_stream_destroy(&client->input); o_stream_destroy(&client->output); @@ -290,6 +297,16 @@ void client_destroy(struct client *client, const char *prefix, static const char *client_get_disconnect_reason(struct client *client) { + const char *err; + + if (client->ssl_iostream != NULL && + !ssl_iostream_is_handshaked(client->ssl_iostream)) { + err = ssl_iostream_get_last_error(client->ssl_iostream); + if (err != NULL) { + return t_strdup_printf("TLS handshaking failed: %s", + err); + } + } errno = client->input->stream_errno != 0 ? client->input->stream_errno : client->output->stream_errno; diff --git a/src/lmtp/client.h b/src/lmtp/client.h index 18ef1f53da..094e5894dc 100644 --- a/src/lmtp/client.h +++ b/src/lmtp/client.h @@ -48,6 +48,7 @@ struct client { struct io *io; struct istream *input; struct ostream *output; + struct ssl_iostream *ssl_iostream; struct timeout *to_idle; time_t last_input; diff --git a/src/lmtp/commands.c b/src/lmtp/commands.c index 42556b9543..29c8d375bd 100644 --- a/src/lmtp/commands.c +++ b/src/lmtp/commands.c @@ -15,6 +15,8 @@ #include "restrict-access.h" #include "settings-parser.h" #include "master-service.h" +#include "master-service-ssl.h" +#include "iostream-ssl.h" #include "rfc822-parser.h" #include "message-date.h" #include "auth-master.h" @@ -70,6 +72,9 @@ int cmd_lhlo(struct client *client, const char *args) client_state_reset(client); client_send_line(client, "250-%s", client->my_domain); + if (master_service_ssl_is_enabled(master_service) && + client->ssl_iostream == NULL) + client_send_line(client, "250-STARTTLS"); if (client_is_trusted(client)) client_send_line(client, "250-XCLIENT ADDR PORT TTL TIMEOUT"); client_send_line(client, "250-8BITMIME"); @@ -82,6 +87,34 @@ int cmd_lhlo(struct client *client, const char *args) return 0; } +int cmd_starttls(struct client *client) +{ + struct ostream *plain_output = client->output; + const char *error; + + if (client->ssl_iostream != NULL) { + o_stream_nsend_str(client->output, + "443 5.5.1 TLS is already active.\r\n"); + return 0; + } + + if (master_service_ssl_init(master_service, + &client->input, &client->output, + &client->ssl_iostream, &error) < 0) { + i_error("TLS initialization failed: %s", error); + o_stream_nsend_str(client->output, + "454 4.7.0 Internal error, TLS not available.\r\n"); + return 0; + } + o_stream_nsend_str(plain_output, + "220 2.0.0 Begin TLS negotiation now.\r\n"); + if (ssl_iostream_handshake(client->ssl_iostream) < 0) { + client_destroy(client, NULL, NULL); + return -1; + } + return 0; +} + static int parse_address(const char *str, const char **address_r, const char **rest_r) { diff --git a/src/lmtp/commands.h b/src/lmtp/commands.h index 0ad064770b..56310e39fe 100644 --- a/src/lmtp/commands.h +++ b/src/lmtp/commands.h @@ -4,6 +4,7 @@ struct client; int cmd_lhlo(struct client *client, const char *args); +int cmd_starttls(struct client *client); int cmd_mail(struct client *client, const char *args); int cmd_rcpt(struct client *client, const char *args); int cmd_quit(struct client *client, const char *args); diff --git a/src/lmtp/main.c b/src/lmtp/main.c index e40432fdc2..de227d246f 100644 --- a/src/lmtp/main.c +++ b/src/lmtp/main.c @@ -78,7 +78,8 @@ int main(int argc, char *argv[]) &lmtp_setting_parser_info, NULL }; - enum master_service_flags service_flags = 0; + enum master_service_flags service_flags = + MASTER_SERVICE_FLAG_USE_SSL_SETTINGS; enum mail_storage_service_flags storage_service_flags = MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT | MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP | @@ -91,7 +92,7 @@ int main(int argc, char *argv[]) service_flags |= MASTER_SERVICE_FLAG_STANDALONE | MASTER_SERVICE_FLAG_STD_CLIENT; } else { - service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN; + service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN ; } master_service = master_service_init("lmtp", service_flags,