]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: smtp-server-connection - Fix STARTTLS command injection vulnerability.
authorStephan Bosch <stephan.bosch@open-xchange.com>
Fri, 21 May 2021 22:16:38 +0000 (00:16 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Mon, 21 Jun 2021 13:24:30 +0000 (13:24 +0000)
The input handler kept reading more commands even though the input was locked by
the STARTTLS command, thereby causing it to read the command pipelined beyond
STARTTLS. This causes a STARTTLS command injection vulerability.

src/lib-smtp/smtp-server-cmd-starttls.c
src/lib-smtp/smtp-server-connection.c

index ed1687e6b875f8bfa8b6731bb5d96286c7c350c9..de53b39a3807ee56e8bb680568e72a2ec864667a 100644 (file)
@@ -37,6 +37,13 @@ static int cmd_starttls_start(struct smtp_server_connection *conn)
                return -1;
        }
 
+       /* The command queue must be empty at this point. If anything were to be
+          queued somehow, this connection is vulnerable to STARTTLS command
+          insertion.
+        */
+       i_assert(conn->command_queue_count == 0 &&
+                conn->command_queue_head == NULL);
+
        /* RFC 3207, Section 4.2:
 
           Upon completion of the TLS handshake, the SMTP protocol is reset to
@@ -107,6 +114,13 @@ cmd_starttls_next(struct smtp_server_cmd_ctx *cmd, void *context ATTR_UNUSED)
        const struct smtp_server_callbacks *callbacks = conn->callbacks;
        int ret;
 
+       /* The command queue can only contain the STARTTLS command at this
+          point. If anything beyond the STARTTLS were queued somehow, this
+          connection is vulnerable to STARTTLS command insertion.
+        */
+       i_assert(conn->command_queue_count == 1 &&
+                conn->command_queue_tail == command);
+
        smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_STARTTLS,
                                         NULL);
 
index 819dfb16124c1e8057c7d4754bd3cd0acd5f6311..4d523b8f833c5073418e2d6191e5c5df551d8ca5 100644 (file)
@@ -434,7 +434,7 @@ smtp_server_connection_handle_input(struct smtp_server_connection *conn)
 
        /* Parse commands */
        ret = 1;
-       while (!conn->closing && ret != 0) {
+       while (!conn->closing && !conn->input_locked && ret != 0) {
                while ((ret = smtp_command_parse_next(
                        conn->smtp_parser, &cmd_name, &cmd_params,
                        &error_code, &error)) > 0) {
@@ -458,6 +458,10 @@ smtp_server_connection_handle_input(struct smtp_server_connection *conn)
 
                        if (conn->disconnected)
                                return;
+                       /* Last command locked the input; stop trying to read
+                          more. */
+                       if (conn->input_locked)
+                               break;
                        /* Client indicated it will close after this command;
                           stop trying to read more. */
                        if (conn->closing)