]> granicus.if.org Git - mutt/commitdiff
Brendan's latest patches.
authorThomas Roessler <roessler@does-not-exist.org>
Tue, 1 Aug 2000 08:23:48 +0000 (08:23 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Tue, 1 Aug 2000 08:23:48 +0000 (08:23 +0000)
imap/auth.c
imap/auth_gss.c
imap/auth_sasl.c
imap/message.c

index 26f2feff22bc64dd3dbd012354b241b3e4ff5536..fa485bfe955793fe703de48592c3f8020d783c40 100644 (file)
 #include "auth.h"
 
 static imap_auth_t imap_authenticators[] = {
-  imap_auth_anon,
 #ifdef USE_SASL
   imap_auth_sasl,
+#else
+  imap_auth_anon,
 #endif
 #ifdef USE_GSS
   imap_auth_gss,
index 73e3f8b8158b8b848fbafd60d84d1dadf3d31acf..96f79b56363d3cc141dd18a3d0be30a909d0d950 100644 (file)
@@ -29,6 +29,7 @@
 
 #ifdef HAVE_HEIMDAL
 #  include <gssapi.h>
+#  define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
 #else
 #  include <gssapi/gssapi.h>
 #  include <gssapi/gssapi_generic.h>
@@ -57,8 +58,6 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata)
   if (!mutt_bit_isset (idata->capabilities, AGSSAPI))
     return IMAP_AUTH_UNAVAIL;
 
-  mutt_message _("Authenticating (GSS)...");
-
   if (mutt_account_getuser (&idata->conn->account))
     return IMAP_AUTH_FAILURE;
   
@@ -71,7 +70,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata)
   if (maj_stat != GSS_S_COMPLETE)
   {
     dprint (2, (debugfile, "Couldn't get service name for [%s]\n", buf1));
-    goto bail;
+    return IMAP_AUTH_UNAVAIL;
   }
 #ifdef DEBUG   
   else if (debuglevel >= 2)
@@ -248,7 +247,7 @@ imap_auth_res_t imap_auth_gss (IMAP_DATA* idata)
   }
 
  bail:
-  mutt_error _("GSS authentication failed.");
+  mutt_error _("GSSAPI authentication failed.");
   sleep (2);
   return IMAP_AUTH_FAILURE;
 }
index ae77a17ba5926d7c10f889f7b8dc990f5a70d264..215c128b644a9fb801fbccc2b71e03af54f5ba15 100644 (file)
@@ -34,7 +34,8 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
   char buf[LONG_STRING];
   const char* mech;
   char* pc;
-  unsigned int len;
+  unsigned int len, olen;
+  unsigned char client_start;
 
   if (mutt_sasl_start () != SASL_OK)
     return IMAP_AUTH_FAILURE;
@@ -50,8 +51,26 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
     return IMAP_AUTH_FAILURE;
   }
 
-  rc = sasl_client_start (saslconn, idata->capstr, NULL, NULL, &pc, &len,
-    &mech);
+  /* hack for SASL ANONYMOUS support:
+   * 1. Fetch username. If it's "" or "anonymous" then
+   * 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability
+   * 3. if sasl_client_start fails, fall through... */
+  rc = SASL_FAIL;
+
+  if (mutt_account_getuser (&idata->conn->account))
+    return IMAP_AUTH_FAILURE;
+
+  if (mutt_bit_isset (idata->capabilities, AUTH_ANON) &&
+      (!idata->conn->account.user[0] ||
+       !mutt_strncmp (idata->conn->account.user, "anonymous", 9)))
+    rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, NULL, &pc, &olen,
+      &mech);
+
+  if (rc != SASL_OK && rc != SASL_CONTINUE)
+    rc = sasl_client_start (saslconn, idata->capstr, NULL, NULL, &pc, &olen,
+      &mech);
+
+  client_start = (pc != NULL);
 
   if (rc != SASL_OK && rc != SASL_CONTINUE)
   {
@@ -66,14 +85,7 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
   snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech);
   imap_cmd_start (idata, buf);
 
-  /* I believe IMAP requires a server response (even if empty) before the
-   * client can send data, so len should always be zero at this point */
-  if (len != 0)
-  {
-    dprint (1, (debugfile, "imap_auth_sasl: SASL produced invalid exchange!\n"));
-    goto bail;
-  }
-
+  /* looping protocol */
   while (rc == SASL_CONTINUE)
   {
     if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0)
@@ -86,20 +98,22 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
        goto bail;
       }
 
-    rc = sasl_client_step (saslconn, buf, len, NULL, &pc, &len);
-
-    if (rc != SASL_CONTINUE)
-      break;
+    if (!client_start)
+      rc = sasl_client_step (saslconn, buf, len, NULL, &pc, &olen);
+    client_start = 0;
 
-    /* send out response, or line break if none needed */
-    if (sasl_encode64 (pc, len, buf, sizeof (buf), &len) != SASL_OK)
+    if (olen)
     {
-      dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
-      goto bail;
-    }
+      /* send out response, or line break if none needed */
+      if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK)
+      {
+       dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
+       goto bail;
+      }
       
-    strfcpy (buf + len, "\r\n", sizeof (buf) - len);
-    mutt_socket_write (idata->conn, buf);
+      strfcpy (buf + olen, "\r\n", sizeof (buf) - olen);
+      mutt_socket_write (idata->conn, buf);
+    }
   }
 
   if (rc != SASL_OK)
index 56736512e185703f2d62e55ae23801a85c53dbc0..3ea4b4cce0abdc3db6e22fc5d5a5c336f9479a86 100644 (file)
@@ -35,7 +35,6 @@ static void flush_buffer(char* buf, size_t* len, CONNECTION* conn);
 static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf,
   FILE* fp);
 static int msg_has_flag (LIST* flag_list, const char* flag);
-static IMAP_HEADER* msg_new_header (void);
 static int msg_parse_fetch (IMAP_HEADER* h, char* s);
 static char* msg_parse_flags (IMAP_HEADER* h, char* s);
 
@@ -51,7 +50,7 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
   FILE *fp;
   char tempfile[_POSIX_PATH_MAX];
   int msgno;
-  IMAP_HEADER* h;
+  IMAP_HEADER h;
   int rc;
   int fetchlast = 0;
   const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL";
@@ -108,67 +107,75 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
       fetchlast = msgend + 1;
     }
 
+    /* freshen fp, h */
+    rewind (fp);
+    memset (&h, 0, sizeof (h));
+    h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));
+
+    /* this DO loop does two things:
+     * 1. handles untagged messages, so we can try again on the same msg
+     * 2. fetches the tagged response at the end of the last message.
+     */
     do
     {
-      /* freshen fp, h */
-      rewind (fp);
-      h = msg_new_header ();
-      
+      rc = 0;
+
       if (mutt_socket_readln (buf, sizeof (buf), CTX_DATA->conn) < 0)
       {
-       imap_free_header_data ((void**) &(h->data));
-       safe_free ((void**) &h);
+       imap_free_header_data ((void**) &h.data);
        fclose (fp);
         return -1;
       }
 
       if (buf[0] == '*')
       {
-       rc = msg_fetch_header (ctx, h, buf, fp);
-       /* make sure we don't get remnants from older larger message headers */
-       fputs ("\n\n", fp);
-
-       if ((rc == -1 && imap_handle_untagged (CTX_DATA, buf)) || rc == -2)
+       if ((rc = msg_fetch_header (ctx, &h, buf, fp)))
        {
-         imap_free_header_data ((void**) &(h->data));
-         safe_free ((void**) &h);
-         fclose (fp);
-         return -1;
+         if (rc == -1 && !imap_handle_untagged (CTX_DATA, buf))
+           continue;
+         else
+         {
+           imap_free_header_data ((void**) h.data);
+           fclose (fp);
+           return -1;
+         }
        }
 
-       /* update context with message header */
+       /* make sure we don't get remnants from older larger message headers */
+       fputs ("\n\n", fp);
 
-       ctx->hdrs[ctx->msgcount] = mutt_new_header ();
-       ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
+       /* update context with message header */
+       ctx->hdrs[msgno] = mutt_new_header ();
+       ctx->hdrs[msgno]->index = ctx->msgcount;
 
        /* messages which have not been expunged are ACTIVE (borrowed from
         * mh folders) */
        ctx->hdrs[msgno]->active = 1;
-       ctx->hdrs[msgno]->read = h->read;
-       ctx->hdrs[msgno]->old = h->old;
-       ctx->hdrs[msgno]->deleted = h->deleted;
-       ctx->hdrs[msgno]->flagged = h->flagged;
-       ctx->hdrs[msgno]->replied = h->replied;
-       ctx->hdrs[msgno]->changed = h->changed;
-       ctx->hdrs[msgno]->received = h->received;
-       ctx->hdrs[msgno]->data = (void *) (h->data);
+       ctx->hdrs[msgno]->read = h.read;
+       ctx->hdrs[msgno]->old = h.old;
+       ctx->hdrs[msgno]->deleted = h.deleted;
+       ctx->hdrs[msgno]->flagged = h.flagged;
+       ctx->hdrs[msgno]->replied = h.replied;
+       ctx->hdrs[msgno]->changed = h.changed;
+       ctx->hdrs[msgno]->received = h.received;
+       ctx->hdrs[msgno]->data = (void *) (h.data);
 
        rewind (fp);
        /* NOTE: if Date: header is missing, mutt_read_rfc822_header depends
-        *   on h->received being set */
+        *   on h.received being set */
        ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno],
           0, 0);
        /* content built as a side-effect of mutt_read_rfc822_header */
-       ctx->hdrs[msgno]->content->length = h->content_length;
+       ctx->hdrs[msgno]->content->length = h.content_length;
 
        mx_update_context (ctx); /* increments ->msgcount */
 
-       /* h->data shouldn't be freed here, it is kept in ctx->headers */
-       safe_free ((void**) &h);
       }
     }
-    while ((msgno + 1) >= fetchlast && mutt_strncmp (CTX_DATA->seq, buf,
-      SEQLEN) != 0);
+    while ((rc == -1) || ((msgno + 1) >= fetchlast &&
+      !mutt_strncmp (CTX_DATA->seq, buf, SEQLEN) != 0));
+
+    /* h.data shouldn't be freed here, it is kept in ctx->headers */
 
     /* in case we get new mail while fetching the headers */
     if (CTX_DATA->status == IMAP_NEW_MAIL)
@@ -280,14 +287,15 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
           else if ((strncasecmp ("FLAGS", pc, 5) == 0) &&
             !ctx->hdrs[msgno]->changed)
           {
-           IMAP_HEADER* newh;
+           IMAP_HEADER newh;
             HEADER* h = ctx->hdrs[msgno];
            unsigned char readonly;
 
-            newh = msg_new_header ();
+           memset (&newh, 0, sizeof (newh));
+           newh.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));
 
             dprint (2, (debugfile, "imap_fetch_message: parsing FLAGS\n"));
-            if ((pc = msg_parse_flags (newh, pc)) == NULL)
+            if ((pc = msg_parse_flags (&newh, pc)) == NULL)
              goto bail;
              
            /* this is less efficient than the code which used to be here,
@@ -304,12 +312,12 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
            ctx->readonly = 0;
            
            mutt_set_flag (ctx, h, M_NEW, 
-                   !(newh->read || newh->old || h->read || h->old));
-           mutt_set_flag (ctx, h, M_OLD, newh->old);
-           mutt_set_flag (ctx, h, M_READ, h->read || newh->read);
-           mutt_set_flag (ctx, h, M_DELETE, h->deleted || newh->deleted);
-           mutt_set_flag (ctx, h, M_FLAG, h->flagged || newh->flagged);
-           mutt_set_flag (ctx, h, M_REPLIED, h->replied || newh->replied);
+                   !(newh.read || newh.old || h->read || h->old));
+           mutt_set_flag (ctx, h, M_OLD, newh.old);
+           mutt_set_flag (ctx, h, M_READ, h->read || newh.read);
+           mutt_set_flag (ctx, h, M_DELETE, h->deleted || newh.deleted);
+           mutt_set_flag (ctx, h, M_FLAG, h->flagged || newh.flagged);
+           mutt_set_flag (ctx, h, M_REPLIED, h->replied || newh.replied);
 
             /* this message is now definitively *not* changed (mutt_set_flag
              * marks things changed as a side-effect) */
@@ -318,8 +326,8 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
            ctx->readonly = readonly;
 
             mutt_free_list (&(HEADER_DATA(h)->keywords));
-            HEADER_DATA(h)->keywords = newh->data->keywords;
-            safe_free ((void**) &newh);
+            HEADER_DATA(h)->keywords = newh.data->keywords;
+           FREE(&newh.data);
           }
        }
       }
@@ -527,7 +535,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
   else
   {
     mutt_message (_("Copying message %d to %s..."), h->index+1, cmd);
-    snprintf (buf, sizeof (buf), "%d", h->index+1);
+    snprintf (buf, sizeof (buf), "%u", HEADER_DATA (h)->uid);
   }
 
   /* let's get it on */
@@ -674,27 +682,6 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp)
   return rc;
 }
 
-/* msg_new_header: allocate and initialise a new IMAP_HEADER structure */
-static IMAP_HEADER* msg_new_header (void)
-{
-  IMAP_HEADER* h;
-
-  h = (IMAP_HEADER*) safe_malloc (sizeof (IMAP_HEADER));
-  h->data = (IMAP_HEADER_DATA*) safe_malloc (sizeof (IMAP_HEADER_DATA));
-
-  /* lists aren't allocated unless they're used */
-  h->data->keywords = NULL;
-
-  h->deleted = 0;
-  h->flagged = 0;
-  h->replied = 0;
-  h->read = 0;
-  h->old = 0;
-  h->changed = 0;
-
-  return h;
-}
-
 /* msg_has_flag: do a caseless comparison of the flag against a flag list,
  *   return 1 if found or flag list has '\*', 0 otherwise */
 static int msg_has_flag (LIST* flag_list, const char* flag)