]> Pileus Git - ~andy/fetchmail/commitdiff
Use more stringent check for untagged responses - we check that the start with "...
authorMatthias Andree <matthias.andree@gmx.de>
Thu, 17 Nov 2005 11:04:33 +0000 (11:04 -0000)
committerMatthias Andree <matthias.andree@gmx.de>
Thu, 17 Nov 2005 11:04:33 +0000 (11:04 -0000)
svn path=/trunk/; revision=4450

imap.c

diff --git a/imap.c b/imap.c
index b7dae1af6aefdc414989f76e5eda940c6891f685..1f62f696c5be76d5420c1392ff262bee34105d72 100644 (file)
--- 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)));