]> Pileus Git - ~andy/fetchmail/blobdiff - imap.c
-vv multidrop: Also report non-Delivered-To: envelope parsing.
[~andy/fetchmail] / imap.c
diff --git a/imap.c b/imap.c
index 35b3bd07941000f961d5934a24bcdd09823a2b64..b1c510433cfd2b9023aaaaf6ffa444274be0b855 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -8,6 +8,7 @@
 #include  "config.h"
 #include  <stdio.h>
 #include  <string.h>
+#include  <strings.h>
 #include  <ctype.h>
 #if defined(STDC_HEADERS)
 #include  <stdlib.h>
@@ -289,57 +290,13 @@ static int imap_ok(int sock, char *argbuf)
 
 static int do_imap_ntlm(int sock, struct query *ctl)
 {
-    tSmbNtlmAuthRequest request;
-    tSmbNtlmAuthChallenge challenge;
-    tSmbNtlmAuthResponse response;
-
-    char msgbuf[2048];
-    int result,len;
+    int result;
 
     gen_send(sock, "AUTHENTICATE NTLM");
 
-    if ((result = gen_recv(sock, msgbuf, sizeof msgbuf)))
-       return result;
-  
-    if (msgbuf[0] != '+')
-       return PS_AUTHFAIL;
-  
-    buildSmbNtlmAuthRequest(&request,ctl->remotename,NULL);
-
-    if (outlevel >= O_DEBUG)
-       dumpSmbNtlmAuthRequest(stdout, &request);
-
-    memset(msgbuf,0,sizeof msgbuf);
-    to64frombits (msgbuf, &request, SmbLength(&request));
-  
-    if (outlevel >= O_MONITOR)
-       report(stdout, "IMAP> %s\n", msgbuf);
-  
-    strcat(msgbuf,"\r\n");
-    SockWrite (sock, msgbuf, strlen (msgbuf));
-
-    if ((gen_recv(sock, msgbuf, sizeof msgbuf)))
+    if ((result = ntlm_helper(sock, ctl, "IMAP")))
        return result;
-  
-    len = from64tobits (&challenge, msgbuf, sizeof(challenge));
-    
-    if (outlevel >= O_DEBUG)
-       dumpSmbNtlmAuthChallenge(stdout, &challenge);
-    
-    buildSmbNtlmAuthResponse(&challenge, &response,ctl->remotename,ctl->password);
-  
-    if (outlevel >= O_DEBUG)
-       dumpSmbNtlmAuthResponse(stdout, &response);
-  
-    memset(msgbuf,0,sizeof msgbuf);
-    to64frombits (msgbuf, &response, SmbLength(&response));
-
-    if (outlevel >= O_MONITOR)
-       report(stdout, "IMAP> %s\n", msgbuf);
-      
-    strcat(msgbuf,"\r\n");
-    SockWrite (sock, msgbuf, strlen (msgbuf));
-  
+
     result = imap_ok (sock, NULL);
     if (result == PS_SUCCESS)
        return PS_SUCCESS;
@@ -484,7 +441,7 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
             * (see below). */
            if (gen_transact(sock, "STARTTLS") == PS_SUCCESS
                    && SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
-                       ctl->sslcertpath, ctl->sslfingerprint, commonname,
+                       ctl->sslcertfile, ctl->sslcertpath, ctl->sslfingerprint, commonname,
                        ctl->server.pollname, &ctl->remotename) != -1)
            {
                /*
@@ -565,15 +522,13 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
     }
 
 #ifdef GSSAPI
-    if ((ctl->server.authenticate == A_ANY 
+    if (((ctl->server.authenticate == A_ANY && check_gss_creds("imap", ctl->server.truename) == PS_SUCCESS)
         || ctl->server.authenticate == A_GSSAPI)
        && strstr(capabilities, "AUTH=GSSAPI"))
     {
        if ((ok = do_gssauth(sock, "AUTHENTICATE", "imap",
                        ctl->server.truename, ctl->remotename)))
        {
-           /* SASL cancellation of authentication */
-           gen_send(sock, "*");
            if (ctl->server.authenticate != A_ANY)
                 return ok;
        } else  {
@@ -610,8 +565,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
     {
        if ((ok = do_cram_md5 (sock, "AUTHENTICATE", ctl, NULL)))
        {
-           /* SASL cancellation of authentication */
-           gen_send(sock, "*");
            if(ctl->server.authenticate != A_ANY)
                 return ok;
        }
@@ -647,8 +600,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
        && strstr (capabilities, "AUTH=NTLM")) {
        if ((ok = do_imap_ntlm(sock, ctl)))
        {
-           /* SASL cancellation of authentication */
-           gen_send(sock, "*");
            if(ctl->server.authenticate != A_ANY)
                 return ok;
        }
@@ -702,8 +653,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
        free(remotename);
        if (ok)
        {
-           /* SASL cancellation of authentication */
-           gen_send(sock, "*");
            if(ctl->server.authenticate != A_ANY)
                 return ok;
        }
@@ -917,6 +866,7 @@ fetchflags:
     while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
     {
        unsigned int num;
+       int consumed;
 
        /* expected response format:
         * IMAP< * 1 FETCH (FLAGS (\Seen))
@@ -926,7 +876,9 @@ fetchflags:
         * IMAP< * 5 FETCH (UID 10 FLAGS (\Recent))
         */
        if (unseen < count
-               && sscanf(buf, "* %u FETCH ", &num) == 1
+               && sscanf(buf, "* %u %n", &num, &consumed) == 1
+               && 0 == strncasecmp(buf+consumed, "FETCH", 5)
+               && isspace((unsigned char)buf[consumed+5])
                && num >= 1 && num <= (unsigned)count
                && strstr(buf, "FLAGS ")
                && !strstr(buf, "\\SEEN")
@@ -1126,16 +1078,19 @@ static int imap_getpartialsizes(int sock, int first, int last, int *sizes)
     {
        unsigned int size;
        int num;
+       int consumed;
+       char *ptr;
 
-       if (sscanf(buf, "* %d FETCH (RFC822.SIZE %u)", &num, &size) == 2
-       /* some servers (like mail.internode.on.net bld-mail04) return UID information here
-        *
+       /* expected response formats:
         * IMAP> A0005 FETCH 1 RFC822.SIZE
+        * IMAP< * 1 FETCH (RFC822.SIZE 1187)
         * IMAP< * 1 FETCH (UID 16 RFC822.SIZE 1447)
-        * IMAP< A0005 OK FETCH completed
-        *
         */
-               || sscanf(buf, "* %d FETCH (UID %*s RFC822.SIZE %u)", &num, &size) == 2)
+       if (sscanf(buf, "* %d %n", &num, &consumed) == 1
+           && 0 == strncasecmp(buf + consumed, "FETCH", 5)
+           && isspace((unsigned char)buf[consumed + 5])
+               && (ptr = strstr(buf, "RFC822.SIZE "))
+               && sscanf(ptr, "RFC822.SIZE %u", &size) == 1)
        {
            if (num >= first && num <= last)
                sizes[num - first] = size;
@@ -1178,6 +1133,7 @@ static int imap_is_old(int sock, struct query *ctl, int number)
     return(seen);
 }
 
+#if 0
 static char *skip_token(char *ptr)
 {
     while(isspace((unsigned char)*ptr)) ptr++;
@@ -1185,12 +1141,15 @@ static char *skip_token(char *ptr)
     while(isspace((unsigned char)*ptr)) ptr++;
     return(ptr);
 }
+#endif
 
 static int imap_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
 /* request headers of nth message */
 {
     char buf [MSGBUFSIZE+1];
     int        num;
+    int ok;
+    char *ptr;
 
     (void)ctl;
     /* expunges change the fetch numbers */
@@ -1203,47 +1162,49 @@ static int imap_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
     gen_send(sock, "FETCH %d RFC822.HEADER", number);
 
     /* looking for FETCH response */
-    for (;;) 
+    if ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
     {
-       int     ok;
-       char    *ptr;
-
-       if ((ok = gen_recv(sock, buf, sizeof(buf))))
-           return(ok);
-       ptr = skip_token(buf);  /* either "* " or "AXXXX " */
-       if (sscanf(ptr, "%d FETCH (RFC822.HEADER {%d}", &num, lenp) == 2
-       /* some servers (like mail.internode.on.net bld-mail04) return UID information here
-        *
+               int consumed;
+       /* expected response formats:
         * IMAP> A0006 FETCH 1 RFC822.HEADER
+        * IMAP< * 1 FETCH (RFC822.HEADER {1360}
         * IMAP< * 1 FETCH (UID 16 RFC822.HEADER {1360}
-        * ...
-        * IMAP< )
-        * IMAP< A0006 OK FETCH completed
-        *
+        * IMAP< * 1 FETCH (UID 16 RFC822.SIZE 4029 RFC822.HEADER {1360}
         */
-               || sscanf(ptr, "%d FETCH (UID %*s RFC822.HEADER {%d}", &num, lenp) == 2)
-           break;
-       /* try to recover from chronically fucked-up M$ Exchange servers */
-       else if (!strncmp(ptr, "NO", 2))
+       if (sscanf(buf, "* %d %n", &num, &consumed) == 1
+           && 0 == strncasecmp(buf + consumed, "FETCH", 5)
+           && isspace((unsigned char)buf[5+consumed])
+               && num == number
+               && (ptr = strstr(buf, "RFC822.HEADER"))
+               && sscanf(ptr, "RFC822.HEADER {%d}%n", lenp, &consumed) == 1
+               && ptr[consumed-1] == '}')
        {
-           /* wait for a tagged response */
-           if (strstr (buf, "* NO"))
-               imap_ok (sock, 0);
-           return(PS_TRANSIENT);
+           return(PS_SUCCESS);
        }
-       else if (!strncmp(ptr, "BAD", 3))
+
+       /* wait for a tagged response */
+       imap_ok (sock, 0);
+
+       /* try to recover for some responses */
+       if (!strncmp(buf, "* NO", 4) ||
+               !strncmp(buf, "* BAD", 5))
        {
-           /* wait for a tagged response */
-           if (strstr (buf, "* BAD"))
-               imap_ok (sock, 0);
-           return(PS_TRANSIENT);
+           return(PS_TRANSIENT);
        }
-    }
 
-    if (num != number)
+       /* a response which does not match any of the above */
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("Incorrect FETCH response: %s.\n"), buf);
        return(PS_ERROR);
-    else
-       return(PS_SUCCESS);
+    }
+    else if (ok == PS_SUCCESS)
+    {
+       /* an unexpected tagged response */
+       if (outlevel > O_SILENT)
+           report(stderr, GT_("Incorrect FETCH response: %s.\n"), buf);
+       return(PS_ERROR);
+    }
+    return(ok);
 }
 
 static int imap_fetch_body(int sock, struct query *ctl, int number, int *lenp)