aboutsummaryrefslogtreecommitdiffstats
path: root/imap.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap.c')
-rw-r--r--imap.c146
1 files changed, 77 insertions, 69 deletions
diff --git a/imap.c b/imap.c
index b7dae1af..1f62f696 100644
--- a/imap.c
+++ b/imap.c
@@ -65,82 +65,90 @@ static int imap_ok(int sock, char *argbuf)
if (islower((unsigned char)*cp))
*cp = toupper((unsigned char)*cp);
- /* interpret untagged status responses */
- if (strstr(buf, "* CAPABILITY"))
- {
- strlcpy(capabilities, buf + 12, sizeof(capabilities));
- }
- else if (strstr(buf, "EXISTS"))
- {
- count = atoi(buf+2);
- /*
- * Don't trust the message count passed by the server.
- * Without this check, it might be possible to do a
- * DNS-spoofing attack that would pass back a ridiculous
- * count, and allocate a malloc area that would overlap
- * a portion of the stack.
- */
- if (count > INT_MAX/sizeof(int))
- {
- report(stderr, GT_("bogus message count!"));
- return(PS_PROTOCOL);
+ /* interpret untagged status responses
+ * First check if we really have an untagged response, starting
+ * with "*" SPACE. Then, for each individual check, use a BLANK
+ * before the word to avoid confusion with the \Recent flag or
+ * similar */
+ if (buf[0] == '*' && buf[1] == ' ') {
+ if (strstr(buf, " CAPABILITY")) {
+ strlcpy(capabilities, buf + 12, sizeof(capabilities));
}
-
- /*
- * Nasty kluge to handle RFC2177 IDLE. If we know we're idling
- * we can't wait for the tag matching the IDLE; we have to tell the
- * server the IDLE is finished by shipping back a DONE when we
- * see an EXISTS. Only after that will a tagged response be
- * shipped. The idling flag also gets cleared on a timeout.
- */
- if (stage == STAGE_IDLE)
+ else if (strstr(buf, " EXISTS"))
{
- /* If IDLE isn't supported, we were only sending NOOPs anyway. */
- if (has_idle)
+ count = atoi(buf+2);
+ /*
+ * Don't trust the message count passed by the server.
+ * Without this check, it might be possible to do a
+ * DNS-spoofing attack that would pass back a ridiculous
+ * count, and allocate a malloc area that would overlap
+ * a portion of the stack.
+ */
+ if (count > INT_MAX/sizeof(int))
{
- /* we do our own write and report here to disable tagging */
- SockWrite(sock, "DONE\r\n", 6);
- if (outlevel >= O_MONITOR)
- report(stdout, "IMAP> DONE\n");
+ report(stderr, GT_("bogus message count!"));
+ return(PS_PROTOCOL);
}
- mytimeout = saved_timeout;
- stage = STAGE_FETCH;
+ /*
+ * Nasty kluge to handle RFC2177 IDLE. If we know we're idling
+ * we can't wait for the tag matching the IDLE; we have to tell the
+ * server the IDLE is finished by shipping back a DONE when we
+ * see an EXISTS. Only after that will a tagged response be
+ * shipped. The idling flag also gets cleared on a timeout.
+ */
+ if (stage == STAGE_IDLE)
+ {
+ /* If IDLE isn't supported, we were only sending NOOPs anyway. */
+ if (has_idle)
+ {
+ /* we do our own write and report here to disable tagging */
+ SockWrite(sock, "DONE\r\n", 6);
+ if (outlevel >= O_MONITOR)
+ report(stdout, "IMAP> DONE\n");
+ }
+
+ mytimeout = saved_timeout;
+ stage = STAGE_FETCH;
+ }
+ }
+ else if (strstr(buf, " RECENT"))
+ {
+ recentcount_ok = 1;
+ recentcount = atoi(buf+2);
+ }
+ else if (strstr(buf, " EXPUNGE"))
+ {
+ /* the response "* 10 EXPUNGE" means that the currently
+ * tenth (i.e. only one) message has been deleted */
+ if (atoi(buf+2) > 0)
+ count--;
+ if (count < 0)
+ count = 0;
+ }
+ else if (strstr(buf, " PREAUTH"))
+ {
+ preauth = TRUE;
+ }
+ /*
+ * The server may decide to make the mailbox read-only,
+ * which causes fetchmail to go into a endless loop
+ * fetching the same message over and over again.
+ *
+ * However, for check_only, we use EXAMINE which will
+ * mark the mailbox read-only as per the RFC.
+ *
+ * This checks for the condition and aborts if
+ * the mailbox is read-only.
+ *
+ * See RFC 2060 section 6.3.1 (SELECT).
+ * See RFC 2060 section 6.3.2 (EXAMINE).
+ */
+ else if (!check_only && strstr(buf, "[READ-ONLY]"))
+ {
+ return(PS_LOCKBUSY);
}
}
- /* a space is required to avoid confusion with the \Recent flag */
- else if (strstr(buf, " RECENT"))
- {
- recentcount_ok = 1;
- recentcount = atoi(buf+2);
- }
- else if (strstr(buf, "EXPUNGE") && !strstr(buf, "OK"))
- {
- /* the response "* 10 EXPUNGE" means that the currently
- * tenth (i.e. only one) message has been deleted */
- if (atoi(buf+2) > 0)
- count--;
- if (count < 0)
- count = 0;
- }
- else if (strstr(buf, "PREAUTH"))
- preauth = TRUE;
- /*
- * The server may decide to make the mailbox read-only,
- * which causes fetchmail to go into a endless loop
- * fetching the same message over and over again.
- *
- * However, for check_only, we use EXAMINE which will
- * mark the mailbox read-only as per the RFC.
- *
- * This checks for the condition and aborts if
- * the mailbox is read-only.
- *
- * See RFC 2060 section 6.3.1 (SELECT).
- * See RFC 2060 section 6.3.2 (EXAMINE).
- */
- else if (!check_only && strstr(buf, "[READ-ONLY]"))
- return(PS_LOCKBUSY);
} while
(tag[0] != '\0' && strncmp(buf, tag, strlen(tag)));