]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lmtp: Added support for STARTTLS command.
authorTimo Sirainen <tss@iki.fi>
Wed, 29 Oct 2014 16:58:01 +0000 (09:58 -0700)
committerTimo Sirainen <tss@iki.fi>
Wed, 29 Oct 2014 16:58:01 +0000 (09:58 -0700)
src/lmtp/Makefile.am
src/lmtp/client.c
src/lmtp/client.h
src/lmtp/commands.c
src/lmtp/commands.h
src/lmtp/main.c

index 39d34b0ac370f94e034a46b70b828ba6bcdaf979..9991aa0bbc907ff831ef017d64899b56f64af209 100644 (file)
@@ -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
index 8adae4b3514093e401e53e4e263acf4898e1c0c1..09e14857fd43a744d6faec748867d54c4e220c27 100644 (file)
@@ -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;
index 18ef1f53dab562b8615e2e9825368776c89783c3..094e5894dcdff9377a99f5e3ccc932de768db9dc 100644 (file)
@@ -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;
index 42556b95437a9ab5c1980a66192472a5794193e3..29c8d375bd4e7a99bd35f582b61fb8a752e3f196 100644 (file)
@@ -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)
 {
index 0ad064770baee5cfdc85bf4c0a18b586b097d5e2..56310e39fe11271985e0e2e2d79a399269755a74 100644 (file)
@@ -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);
index e40432fdc2ad5b7d05478bd6d92ab674ed8d8b94..de227d246f1a7e8bc41e5d1481cd5fe380df247b 100644 (file)
@@ -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,