Skip to content

Commit

Permalink
lib-smtp: client: Make smtp_client_connection_commands_fail_reply() m…
Browse files Browse the repository at this point in the history
…ore reliable by copying the command lists.

Copy the current lists of queued and waiting commands and reference each command before calling smtp_client_command_fail_reply().
Failing one command can cause other dependent commands to be aborted (in a transaction or from submission service), which could have caused trouble in this function.
Problems would likely occur at connection disconnect.
  • Loading branch information
stephanbosch committed Dec 23, 2017
1 parent df95782 commit bd06411
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 17 deletions.
31 changes: 31 additions & 0 deletions src/lib-smtp/smtp-client-command.c
Expand Up @@ -313,6 +313,37 @@ void smtp_client_command_fail(struct smtp_client_command **_cmd,
smtp_client_command_fail_reply(_cmd, &reply);
}

void smtp_client_commands_list_fail_reply(
struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
const struct smtp_reply *reply)
{
struct smtp_client_command *cmd;
ARRAY(struct smtp_client_command *) cmds_arr;
struct smtp_client_command **cmds;
unsigned int count, i;

if (cmds_list == NULL)
return;
i_assert(cmds_list_count > 0);

/* copy the array and reference the commands to be robust against more
than one command disappearing from the list */
t_array_init(&cmds_arr, cmds_list_count);
for (cmd = cmds_list; cmd != NULL; cmd = cmd->next) {
smtp_client_command_ref(cmd);
array_append(&cmds_arr, &cmd, 1);
}

cmds = array_get_modifiable(&cmds_arr, &count);
for (i = 0; i < count; i++) {
cmd = cmds[i];
/* fail the reply */
smtp_client_command_fail_reply(&cmds[i], reply);
/* drop our reference */
smtp_client_command_unref(&cmd);
}
}

void smtp_client_command_set_abort_callback(struct smtp_client_command *cmd,
void (*callback)(void *context), void *context)
{
Expand Down
21 changes: 4 additions & 17 deletions src/lib-smtp/smtp-client-connection.c
Expand Up @@ -145,23 +145,10 @@ static void
smtp_client_connection_commands_fail_reply(struct smtp_client_connection *conn,
const struct smtp_reply *reply)
{
struct smtp_client_command *cmd, *cmd_next = NULL;

cmd = conn->cmd_wait_list_head;
while (cmd != NULL) {
i_assert(conn->cmd_wait_list_count > 0);
cmd_next = cmd->next;
smtp_client_command_fail_reply(&cmd, reply);
cmd = cmd_next;
}

cmd = conn->cmd_send_queue_head;
while (cmd != NULL) {
i_assert(conn->cmd_send_queue_count > 0);
cmd_next = cmd->next;
smtp_client_command_fail_reply(&cmd, reply);
cmd = cmd_next;
}
smtp_client_commands_list_fail_reply(conn->cmd_wait_list_head,
conn->cmd_wait_list_count, reply);
smtp_client_commands_list_fail_reply(conn->cmd_send_queue_head,
conn->cmd_send_queue_count, reply);
}

static void
Expand Down
4 changes: 4 additions & 0 deletions src/lib-smtp/smtp-client-private.h
Expand Up @@ -189,10 +189,14 @@ int smtp_client_command_send_more(struct smtp_client_connection *conn,
const char **error_r);
int smtp_client_command_input_reply(struct smtp_client_command *cmd,
const struct smtp_reply *reply);

void smtp_client_command_fail(struct smtp_client_command **_cmd,
unsigned int status, const char *error);
void smtp_client_command_fail_reply(struct smtp_client_command **_cmd,
const struct smtp_reply *reply);
void smtp_client_commands_list_fail_reply(
struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
const struct smtp_reply *reply);

/*
* Transaction
Expand Down

0 comments on commit bd06411

Please sign in to comment.