From eeca44f5b71b2a5649a3f8805478de3a1b1c08f2 Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Thu, 1 Nov 2018 00:12:03 +0100 Subject: [PATCH] lib-smtp: server: Make sure command object is not used after it is destroyed in hook. --- src/lib-smtp/smtp-server-command.c | 30 ++++++++++++++++++--------- src/lib-smtp/smtp-server-connection.c | 7 ++++--- src/lib-smtp/smtp-server-private.h | 5 +++-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/lib-smtp/smtp-server-command.c b/src/lib-smtp/smtp-server-command.c index a2ad0e040f..6b55468583 100644 --- a/src/lib-smtp/smtp-server-command.c +++ b/src/lib-smtp/smtp-server-command.c @@ -421,32 +421,41 @@ void smtp_server_command_ready_to_reply(struct smtp_server_command *cmd) smtp_server_connection_trigger_output(cmd->context.conn); } -void smtp_server_command_next_to_reply(struct smtp_server_command *cmd) +bool smtp_server_command_next_to_reply(struct smtp_server_command **_cmd) { + struct smtp_server_command *cmd = *_cmd; + smtp_server_command_debug(&cmd->context, "Next to reply"); - smtp_server_command_call_hooks(&cmd, SMTP_SERVER_COMMAND_HOOK_NEXT); + return smtp_server_command_call_hooks( + _cmd, SMTP_SERVER_COMMAND_HOOK_NEXT); } -static void -smtp_server_command_replied(struct smtp_server_command *cmd) +static bool +smtp_server_command_replied(struct smtp_server_command **_cmd) { + struct smtp_server_command *cmd = *_cmd; + if (cmd->replies_submitted < cmd->replies_expected) - return; + return TRUE; smtp_server_command_debug(&cmd->context, "Replied"); - smtp_server_command_call_hooks(&cmd, SMTP_SERVER_COMMAND_HOOK_REPLIED); + return smtp_server_command_call_hooks( + _cmd, SMTP_SERVER_COMMAND_HOOK_REPLIED); } -void smtp_server_command_completed(struct smtp_server_command *cmd) +bool smtp_server_command_completed(struct smtp_server_command **_cmd) { + struct smtp_server_command *cmd = *_cmd; + if (cmd->replies_submitted < cmd->replies_expected) - return; + return TRUE; smtp_server_command_debug(&cmd->context, "Completed"); - smtp_server_command_call_hooks(&cmd, SMTP_SERVER_COMMAND_HOOK_COMPLETED); + return smtp_server_command_call_hooks( + _cmd, SMTP_SERVER_COMMAND_HOOK_COMPLETED); } static bool @@ -456,7 +465,8 @@ smtp_server_command_handle_reply(struct smtp_server_command *cmd) smtp_server_connection_ref(conn); - smtp_server_command_replied(cmd); + if (!smtp_server_command_replied(&cmd)) + return smtp_server_connection_unref(&conn); /* submit reply */ switch (cmd->state) { diff --git a/src/lib-smtp/smtp-server-connection.c b/src/lib-smtp/smtp-server-connection.c index 7deafd7ed7..d26d0b0d4d 100644 --- a/src/lib-smtp/smtp-server-connection.c +++ b/src/lib-smtp/smtp-server-connection.c @@ -333,7 +333,7 @@ smtp_server_connection_handle_command(struct smtp_server_connection *conn, } if (cmd != NULL && conn->command_queue_head == cmd) - smtp_server_command_next_to_reply(cmd); + (void)smtp_server_command_next_to_reply(&cmd); smtp_server_connection_timeout_update(conn); return (cmd == NULL || !cmd->input_locked); @@ -668,14 +668,15 @@ smtp_server_connection_next_reply(struct smtp_server_connection *conn) } if (cmd->state < SMTP_SERVER_COMMAND_STATE_READY_TO_REPLY) { - smtp_server_command_next_to_reply(cmd); + (void)smtp_server_command_next_to_reply(&cmd); return FALSE; } i_assert(cmd->state == SMTP_SERVER_COMMAND_STATE_READY_TO_REPLY && array_is_created(&cmd->replies)); - smtp_server_command_completed(cmd); + if (!smtp_server_command_completed(&cmd)) + return TRUE; /* send command replies */ // FIXME: handle LMTP DATA command with enormous number of recipients; diff --git a/src/lib-smtp/smtp-server-private.h b/src/lib-smtp/smtp-server-private.h index 9b574ebb8d..cc75320d4e 100644 --- a/src/lib-smtp/smtp-server-private.h +++ b/src/lib-smtp/smtp-server-private.h @@ -265,10 +265,11 @@ void smtp_server_command_submit_reply(struct smtp_server_command *cmd); int smtp_server_connection_flush(struct smtp_server_connection *conn); void smtp_server_command_ready_to_reply(struct smtp_server_command *cmd); -void smtp_server_command_next_to_reply(struct smtp_server_command *cmd); -void smtp_server_command_completed(struct smtp_server_command *cmd); void smtp_server_command_finished(struct smtp_server_command *cmd); +bool smtp_server_command_next_to_reply(struct smtp_server_command **_cmd); +bool smtp_server_command_completed(struct smtp_server_command **_cmd); + static inline bool smtp_server_command_is_complete(struct smtp_server_command *cmd) {