Skip to content

Commit

Permalink
tls: clear data after a starttls acknowledgement
Browse files Browse the repository at this point in the history
After a starttls acknowledgement message, clear the buffers of any
incoming data / commands.  This will ensure that all future data is
handled securely.

Co-authored-by: Pietro Cerutti <gahr@gahr.ch>
  • Loading branch information
flatcap and gahr committed Jun 19, 2020
1 parent 523664a commit fb013ec
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 1 deletion.
20 changes: 20 additions & 0 deletions conn/socket.c
Expand Up @@ -301,3 +301,23 @@ struct Connection *mutt_socket_new(enum ConnectionType type)

return conn;
}

/**
* mutt_socket_empty - Clear out any queued data
*
* The internal buffer is emptied and any data that has already arrived at this
* machine (in kernel buffers) is read and dropped.
*/
void mutt_socket_empty(struct Connection *conn)
{
if (!conn)
return;

char buf[1024];
int bytes;

while ((bytes = mutt_socket_poll(conn, 0)) > 0)
{
mutt_socket_read(conn, buf, MIN(bytes, sizeof(buf)));
}
}
1 change: 1 addition & 0 deletions conn/socket.h
Expand Up @@ -39,6 +39,7 @@ enum ConnectionType
};

int mutt_socket_close (struct Connection *conn);
void mutt_socket_empty (struct Connection *conn);
struct Connection *mutt_socket_new (enum ConnectionType type);
int mutt_socket_open (struct Connection *conn);
int mutt_socket_poll (struct Connection *conn, time_t wait_secs);
Expand Down
10 changes: 10 additions & 0 deletions imap/command.c
Expand Up @@ -1250,6 +1250,13 @@ int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags fl
{
int rc;

if (flags & IMAP_CMD_SINGLE)
{
// Process any existing commands
if (adata->nextcmd != adata->lastcmd)
imap_exec(adata, NULL, IMAP_CMD_POLL);
}

rc = cmd_start(adata, cmdstr, flags);
if (rc < 0)
{
Expand All @@ -1273,6 +1280,9 @@ int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags fl
do
{
rc = imap_cmd_step(adata);
// The queue is empty, so the single command has been processed
if ((flags & IMAP_CMD_SINGLE) && (adata->nextcmd == adata->lastcmd))
break;
} while (rc == IMAP_RES_CONTINUE);
mutt_sig_allow_interrupt(false);

Expand Down
5 changes: 4 additions & 1 deletion imap/imap.c
Expand Up @@ -739,7 +739,10 @@ int imap_open_connection(struct ImapAccountData *adata)
}
if (ans == MUTT_YES)
{
enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_NO_FLAGS);
enum ImapExecResult rc = imap_exec(adata, "STARTTLS", IMAP_CMD_SINGLE);
// Clear any data after the STARTTLS acknowledgement
mutt_socket_empty(adata->conn);

if (rc == IMAP_EXEC_FATAL)
goto bail;
if (rc != IMAP_EXEC_ERROR)
Expand Down
1 change: 1 addition & 0 deletions imap/private.h
Expand Up @@ -73,6 +73,7 @@ typedef uint8_t ImapCmdFlags; ///< Flags for imap_exec(), e.g. #IMAP_CM
#define IMAP_CMD_PASS (1 << 0) ///< Command contains a password. Suppress logging
#define IMAP_CMD_QUEUE (1 << 1) ///< Queue a command, do not execute
#define IMAP_CMD_POLL (1 << 2) ///< Poll the tcp connection before running the imap command
#define IMAP_CMD_SINGLE (1 << 3) ///< Run a single command

/**
* enum ImapExecResult - imap_exec return code
Expand Down
2 changes: 2 additions & 0 deletions nntp/nntp.c
Expand Up @@ -1899,6 +1899,8 @@ int nntp_open_connection(struct NntpAccountData *adata)
{
return nntp_connect_error(adata);
}
// Clear any data after the STARTTLS acknowledgement
mutt_socket_empty(conn);
if (!mutt_str_startswith(buf, "382", CASE_MATCH))
{
adata->use_tls = 0;
Expand Down
2 changes: 2 additions & 0 deletions pop/pop_lib.c
Expand Up @@ -358,6 +358,8 @@ int pop_open_connection(struct PopAccountData *adata)
{
mutt_str_strfcpy(buf, "STLS\r\n", sizeof(buf));
rc = pop_query(adata, buf, sizeof(buf));
// Clear any data after the STLS acknowledgement
mutt_socket_empty(adata->conn);
if (rc == -1)
goto err_conn;
if (rc != 0)
Expand Down
2 changes: 2 additions & 0 deletions smtp.c
Expand Up @@ -719,6 +719,8 @@ static int smtp_open(struct Connection *conn, bool esmtp)
if (mutt_socket_send(conn, "STARTTLS\r\n") < 0)
return SMTP_ERR_WRITE;
rc = smtp_get_resp(conn);
// Clear any data after the STARTTLS acknowledgement
mutt_socket_empty(conn);
if (rc != 0)
return rc;

Expand Down

0 comments on commit fb013ec

Please sign in to comment.