File cyrus-imapd-STARTTLS-plaintext-command-injection.dif of Package cyrus-imapd.import5133
From febfa4a5e2b20521e6176c787b0f05acc05d93e6 Mon Sep 17 00:00:00 2001
From: Ken Murchison <murch@andrew.cmu.edu>
Date: Fri, 25 Mar 2011 11:50:18 -0400
Subject: Fixed bug #3423 - STARTTLS plaintext command injection vulnerability
diff --git a/cyrus/imap/imapd.c b/cyrus/imap/imapd.c
index de67b46..a978338 100644
--- a/cyrus/imap/imapd.c
+++ b/cyrus/imap/imapd.c
@@ -1688,6 +1688,9 @@ void cmdloop()
if (c == '\r') c = prot_getc(imapd_in);
if (c != '\n') goto extraargs;
+ /* XXX discard any input pipelined after STARTTLS */
+ prot_flush(imapd_in);
+
/* if we've already done SASL fail */
if (imapd_userid != NULL) {
prot_printf(imapd_out,
diff --git a/cyrus/imap/lmtpengine.c b/cyrus/imap/lmtpengine.c
index eff3e50..16ccc54 100644
--- a/cyrus/imap/lmtpengine.c
+++ b/cyrus/imap/lmtpengine.c
@@ -1562,6 +1562,9 @@ void lmtpmode(struct lmtp_func *func,
sasl_ssf_t ssf;
char *auth_id;
+ /* XXX discard any input pipelined after STARTTLS */
+ prot_flush(pin);
+
/* SASL and openssl have different ideas
about whether ssf is signed */
layerp = (int *) &ssf;
diff --git a/cyrus/imap/mupdate.c b/cyrus/imap/mupdate.c
index b6cc1cb..a4f6509 100644
--- a/cyrus/imap/mupdate.c
+++ b/cyrus/imap/mupdate.c
@@ -927,6 +927,9 @@ mupdate_docmd_result_t docmd(struct conn *c)
if (!strcmp(c->cmd.s, "Starttls")) {
CHECKNEWLINE(c, ch);
+ /* XXX discard any input pipelined after STARTTLS */
+ prot_flush(c->pin);
+
if (!tls_enabled()) {
/* we don't support starttls */
goto badcmd;
diff --git a/cyrus/imap/nntpd.c b/cyrus/imap/nntpd.c
index 1c9dbb1..105fa4b 100644
--- a/cyrus/imap/nntpd.c
+++ b/cyrus/imap/nntpd.c
@@ -1428,6 +1428,9 @@ static void cmdloop(void)
if (c == '\r') c = prot_getc(nntp_in);
if (c != '\n') goto extraargs;
+ /* XXX discard any input pipelined after STARTTLS */
+ prot_flush(nntp_in);
+
cmd_starttls(0);
}
else if (!strcmp(cmd.s, "Stat")) {
diff --git a/cyrus/imap/pop3d.c b/cyrus/imap/pop3d.c
index b84ca2e..7303771 100644
--- a/cyrus/imap/pop3d.c
+++ b/cyrus/imap/pop3d.c
@@ -930,6 +930,9 @@ static void cmdloop(void)
if (arg) {
prot_printf(popd_out, "-ERR Unexpected extra argument\r\n");
} else {
+ /* XXX discard any input pipelined after STLS */
+ prot_flush(popd_in);
+
cmd_starttls(0);
}
}
diff --git a/cyrus/imap/sync_server.c b/cyrus/imap/sync_server.c
index b2f0a7b..b8b4263 100644
--- a/cyrus/imap/sync_server.c
+++ b/cyrus/imap/sync_server.c
@@ -904,6 +904,9 @@ static void cmdloop(void)
if (c == '\r') c = prot_getc(sync_in);
if (c != '\n') goto extraargs;
+ /* XXX discard any input pipelined after STARTTLS */
+ prot_flush(sync_in);
+
/* if we've already done SASL fail */
if (sync_userid != NULL) {
prot_printf(sync_out,
diff --git a/cyrus/lib/prot.c b/cyrus/lib/prot.c
index 4fef8e3..1f06fc4 100644
--- a/cyrus/lib/prot.c
+++ b/cyrus/lib/prot.c
@@ -728,10 +728,29 @@ int prot_fill(struct protstream *s)
}
/*
+ * If 's' is an input stream, discard any pending/buffered data. Otherwise,
* Write out any buffered data in the stream 's'
*/
int prot_flush(struct protstream *s)
{
+ if (!s->write) {
+ int c, save_dontblock = s->dontblock;
+
+ /* Set stream to nonblocking mode */
+ if (!save_dontblock) nonblock(s->fd, (s->dontblock = 1));
+
+ /* Ingest any pending input */
+ while ((c = prot_fill(s)) != EOF);
+
+ /* Reset stream to previous blocking mode */
+ if (!save_dontblock) nonblock(s->fd, (s->dontblock = 0));
+
+ /* Discard any buffered input */
+ s->cnt = 0;
+
+ return 0;
+ }
+
return prot_flush_internal(s, 1);
}
diff --git a/cyrus/timsieved/parser.c b/cyrus/timsieved/parser.c
index 49b2881..dc710c0 100644
--- a/cyrus/timsieved/parser.c
+++ b/cyrus/timsieved/parser.c
@@ -443,6 +443,9 @@ int parser(struct protstream *sieved_out, struct protstream *sieved_in)
goto error;
}
+ /* XXX discard any input pipelined after STARTTLS */
+ prot_flush(sieved_in);
+
if(referral_host)
goto do_referral;
--
1.7.3.4