From: Aki Tuomi Date: Sun, 13 Oct 2019 17:38:12 +0000 (+0300) Subject: doveadm: Add STARTTLS support X-Git-Tag: 2.3.9~100 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=923a01165a23d1c6d362cd62e8090f09f09c5157;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Add STARTTLS support --- diff --git a/src/doveadm/client-connection-tcp.c b/src/doveadm/client-connection-tcp.c index d7bb131ebb..dca9d48bd5 100644 --- a/src/doveadm/client-connection-tcp.c +++ b/src/doveadm/client-connection-tcp.c @@ -47,6 +47,8 @@ static void client_connection_tcp_send_auth_handshake(struct client_connection_tcp *conn); static void client_connection_tcp_destroy(struct client_connection_tcp **_conn); +static int +client_connection_tcp_init_ssl(struct client_connection_tcp *conn); static failure_callback_t *orig_error_callback, *orig_fatal_callback; static failure_callback_t *orig_info_callback, *orig_debug_callback = NULL; @@ -446,6 +448,14 @@ client_connection_tcp_authenticate(struct client_connection_tcp *conn) return -1; } + if (strcmp(line, "STARTTLS") == 0) { + io_remove(&conn->io); + if (client_connection_tcp_init_ssl(conn) < 0) + return -1; + conn->io = io_add_istream(conn->input, client_connection_tcp_input, conn); + return 0; + } + /* FIXME: some day we should probably let auth process do this and support all kinds of authentication */ if (!str_begins(line, "PLAIN\t")) { diff --git a/src/doveadm/doveadm-util.h b/src/doveadm/doveadm-util.h index 11ec9afc27..8aefd92f34 100644 --- a/src/doveadm/doveadm-util.h +++ b/src/doveadm/doveadm-util.h @@ -4,9 +4,9 @@ #include "net.h" #define DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR 1 -#define DOVEADM_SERVER_PROTOCOL_VERSION_MINOR 1 -#define DOVEADM_SERVER_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-server\t1\t1" -#define DOVEADM_CLIENT_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-client\t1\t1" +#define DOVEADM_SERVER_PROTOCOL_VERSION_MINOR 2 +#define DOVEADM_SERVER_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-server\t1\t2" +#define DOVEADM_CLIENT_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-client\t1\t2" extern bool doveadm_verbose, doveadm_debug, doveadm_server; diff --git a/src/doveadm/server-connection.c b/src/doveadm/server-connection.c index 51a4038037..c0928b10d6 100644 --- a/src/doveadm/server-connection.c +++ b/src/doveadm/server-connection.c @@ -63,6 +63,7 @@ struct server_connection { bool authenticate_sent:1; bool authenticated:1; bool streaming:1; + bool ssl_done:1; }; static struct server_connection *printing_conn = NULL; @@ -70,6 +71,8 @@ static ARRAY(struct doveadm_server *) print_pending_servers = ARRAY_INIT; static void server_connection_input(struct server_connection *conn); static bool server_connection_input_one(struct server_connection *conn); +static int server_connection_init_ssl(struct server_connection *conn, + const char **error_r); static void server_set_print_pending(struct doveadm_server *server) { @@ -341,6 +344,7 @@ static void server_connection_start_multiplex(struct server_connection *conn) static void server_connection_input(struct server_connection *conn) { const char *line; + const char *error; if (i_stream_read(conn->input) < 0) { /* disconnected */ @@ -383,6 +387,24 @@ static void server_connection_input(struct server_connection *conn) server_connection_destroy(&conn); return; } + if (!conn->ssl_done && + (conn->server->ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) { + io_remove(&conn->io); + if (conn->minor < 2) { + i_error("doveadm STARTTLS failed: Server does not support it"); + server_connection_destroy(&conn); + return; + } + /* send STARTTLS */ + o_stream_nsend_str(conn->output, "STARTTLS\n"); + if (server_connection_init_ssl(conn, &error) < 0) { + i_error("doveadm STARTTLS failed: %s", error); + server_connection_destroy(&conn); + return; + } + conn->ssl_done = TRUE; + conn->io = io_add_istream(conn->input, server_connection_input, conn); + } if (server_connection_authenticate(conn) < 0) { server_connection_destroy(&conn); return; @@ -553,7 +575,8 @@ int server_connection_create(struct doveadm_server *server, array_push_back(&conn->server->connections, &conn); if (server_connection_read_settings(conn, error_r) < 0 || - server_connection_init_ssl(conn, error_r) < 0) { + ((server->ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0 && + server_connection_init_ssl(conn, error_r) < 0)) { server_connection_destroy(&conn); return -1; }