summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mutt_socket.c30
-rw-r--r--mutt_socket.h2
-rw-r--r--mutt_ssl.c12
-rw-r--r--mutt_ssl_gnutls.c12
4 files changed, 56 insertions, 0 deletions
diff --git a/mutt_socket.c b/mutt_socket.c
index 83d8ddf7..5a2800b8 100644
--- a/mutt_socket.c
+++ b/mutt_socket.c
@@ -129,6 +129,36 @@ int mutt_socket_write_d (CONNECTION *conn, const char *buf, int len, int dbg)
return sent;
}
+/* Checks if the CONNECTION input buffer has unread data.
+ *
+ * NOTE: for general use, the function needs to expand to poll nested
+ * connections. It currently does not to make backporting a security
+ * fix easier.
+ *
+ * STARTTLS occurs before SASL and COMPRESS=DEFLATE processing, and
+ * mutt_tunnel() does not wrap the connection. So this and the next
+ * function are safe for current usage in mutt_ssl_starttls().
+ */
+int mutt_socket_has_buffered_input (CONNECTION *conn)
+{
+ return conn->bufpos < conn->available;
+}
+
+/* Clears buffered input from a connection.
+ *
+ * NOTE: for general use, the function needs to expand to call nested
+ * connections. It currently does not to make backporting a security
+ * fix easier.
+ *
+ * STARTTLS occurs before SASL and COMPRESS=DEFLATE processing, and
+ * mutt_tunnel() does not wrap the connection. So this and the previous
+ * function are safe for current usage in mutt_ssl_starttls().
+ */
+void mutt_socket_clear_buffered_input (CONNECTION *conn)
+{
+ conn->bufpos = conn->available = 0;
+}
+
/* poll whether reads would block.
* Returns: >0 if there is data to read,
* 0 if a read would block,
diff --git a/mutt_socket.h b/mutt_socket.h
index 68f158e0..b0b27ee8 100644
--- a/mutt_socket.h
+++ b/mutt_socket.h
@@ -53,6 +53,8 @@ typedef struct _connection
int mutt_socket_open (CONNECTION* conn);
int mutt_socket_close (CONNECTION* conn);
+int mutt_socket_has_buffered_input (CONNECTION *conn);
+void mutt_socket_clear_buffered_input (CONNECTION *conn);
int mutt_socket_poll (CONNECTION* conn, time_t wait_secs);
int mutt_socket_readchar (CONNECTION *conn, char *c);
#define mutt_socket_readln(A,B,C) mutt_socket_readln_d(A,B,C,MUTT_SOCK_LOG_CMD)
diff --git a/mutt_ssl.c b/mutt_ssl.c
index 6978e4e4..9c0e52b5 100644
--- a/mutt_ssl.c
+++ b/mutt_ssl.c
@@ -199,6 +199,18 @@ int mutt_ssl_starttls (CONNECTION* conn)
int maxbits;
long ssl_options = 0;
+ if (mutt_socket_has_buffered_input (conn))
+ {
+ /* L10N:
+ The server is not supposed to send data immediately after
+ confirming STARTTLS. This warns the user that something
+ weird is going on.
+ */
+ mutt_error _("Warning: clearing unexpected buffered data before STARTTLS");
+ mutt_sleep (0);
+ mutt_socket_clear_buffered_input (conn);
+ }
+
if (ssl_init())
goto bail;
diff --git a/mutt_ssl_gnutls.c b/mutt_ssl_gnutls.c
index 693311f9..3eb276d5 100644
--- a/mutt_ssl_gnutls.c
+++ b/mutt_ssl_gnutls.c
@@ -218,6 +218,18 @@ static int tls_socket_open (CONNECTION* conn)
int mutt_ssl_starttls (CONNECTION* conn)
{
+ if (mutt_socket_has_buffered_input (conn))
+ {
+ /* L10N:
+ The server is not supposed to send data immediately after
+ confirming STARTTLS. This warns the user that something
+ weird is going on.
+ */
+ mutt_error _("Warning: clearing unexpected buffered data before STARTTLS");
+ mutt_sleep (0);
+ mutt_socket_clear_buffered_input (conn);
+ }
+
if (tls_init() < 0)
return -1;