/[mailutils]/mailutils/mailbox/imap/folder.c
ViewVC logotype

Diff of /mailutils/mailbox/imap/folder.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.61 by gray, Wed Sep 10 10:03:03 2003 UTC revision 1.62 by gray, Wed Sep 10 14:06:52 2003 UTC
# Line 98  static int  folder_imap_subscribe   __P Line 98  static int  folder_imap_subscribe   __P
98  static int  folder_imap_unsubscribe __P ((folder_t, const char *));  static int  folder_imap_unsubscribe __P ((folder_t, const char *));
99  static int  folder_imap_get_authority __P ((folder_t, authority_t *));  static int  folder_imap_get_authority __P ((folder_t, authority_t *));
100    
 static int  authenticate_imap_login __P ((authority_t));  
 static int  authenticate_imap_sasl_anon __P ((authority_t));  
   
101  /* FETCH  */  /* FETCH  */
102  static int  imap_fetch              __P ((f_imap_t));  static int  imap_fetch              __P ((f_imap_t));
103  static int  imap_rfc822             __P ((f_imap_t, char **));  static int  imap_rfc822             __P ((f_imap_t, char **));
# Line 127  static int  imap_mailbox_name_match __P Line 124  static int  imap_mailbox_name_match __P
124    
125  static int  imap_token              __P ((char *, size_t, char **));  static int  imap_token              __P ((char *, size_t, char **));
126    
127  /* Initialize the concrete IMAP mailbox: overload the folder functions  */  /* Capability */
128  int  static int  parse_capa              __P ((f_imap_t f_imap, char *str));
129  _folder_imap_init (folder_t folder)  static int  read_capa               __P ((f_imap_t f_imap, int force));
130  {  static int  check_capa              __P ((f_imap_t f_imap, char *capa));
   int status;  
   f_imap_t f_imap;  
   
   /* Set the authority early:  
      (1) so we can check for errors.  
      (2) allow the client to get the authority for setting the ticket  
      before the open.  */  
   status = folder_imap_get_authority (folder, NULL);  
   if (status != 0)  
     return status;  
   
   f_imap = folder->data = calloc (1, sizeof (*f_imap));  
   if (f_imap == NULL)  
     return ENOMEM;  
   
   f_imap->folder = folder;  
   f_imap->state = IMAP_NO_STATE;  
   
   folder->_destroy = folder_imap_destroy;  
   
   folder->_open = folder_imap_open;  
   folder->_close = folder_imap_close;  
   
   folder->_list = folder_imap_list;  
   folder->_lsub = folder_imap_lsub;  
   folder->_subscribe = folder_imap_subscribe;  
   folder->_unsubscribe = folder_imap_unsubscribe;  
   folder->_delete = folder_imap_delete;  
   folder->_rename = folder_imap_rename;  
   
   return 0;  
 }  
   
 /* Destroy the folder resources.  */  
 static void  
 folder_imap_destroy (folder_t folder)  
 {  
   if (folder->data)  
     {  
       f_imap_t f_imap = folder->data;  
       if (f_imap->buffer)  
         free (f_imap->buffer);  
       if (f_imap->capav)  
         argcv_free (f_imap->capac, f_imap->capav);  
       free (f_imap);  
       folder->data = NULL;  
     }  
 }  
   
 static int  
 folder_imap_get_authority (folder_t folder, authority_t *pauth)  
 {  
   int status = 0;  
   if (folder->authority == NULL)  
     {  
       /* assert (folder->url); */  
       if (folder->url == NULL)  
         return EINVAL;  
   
       if (folder->url->auth == NULL  
           || strcasecmp (folder->url->auth, "*") == 0)  
         {  
           status = authority_create (&folder->authority, NULL, folder);  
           authority_set_authenticate (folder->authority,  
                                       authenticate_imap_login, folder);  
         }  
       else if (strcasecmp (folder->url->auth, "anon") == 0)  
         {  
           status = authority_create (&folder->authority, NULL, folder);  
           authority_set_authenticate (folder->authority,  
                                       authenticate_imap_sasl_anon, folder);  
         }  
       else  
         {  
           /* Not a supported authentication mechanism. */  
           status = ENOSYS;  
         }  
     }  
   if (pauth)  
     *pauth = folder->authority;  
   return status;  
 }  
   
 static int  
 parse_capa (f_imap_t f_imap, char *str)  
 {  
   if (f_imap->capav)  
     argcv_free (f_imap->capac, f_imap->capav);  
   return argcv_get (str, "", NULL, &f_imap->capac, &f_imap->capav);  
 }  
   
 static int  
 read_capa (f_imap_t f_imap, int force)  
 {  
   int status = 0;  
     
   if (force)  
     {  
       argcv_free (f_imap->capac, f_imap->capav);  
       f_imap->capac = 0;  
       f_imap->capav = NULL;  
     }  
     
   if (!f_imap->capav)  
     {  
       status = imap_writeline (f_imap, "g%u CAPABILITY\r\n",  
                                f_imap->seq++);  
       status = imap_send (f_imap);  
       status = imap_parse (f_imap);  
     }  
   return status;  
 }  
   
 static int  
 check_capa (f_imap_t f_imap, char *capa)  
 {  
   int i;  
131    
132    read_capa (f_imap, 0);  
133    for (i = 0; i < f_imap->capac; i++)  /* Authentication methods */
     if (strcasecmp (f_imap->capav[i], capa) == 0)  
       return 0;  
   return 1;  
 }  
   
 static int  
 tls (folder_t folder)  
 {  
 #ifdef WITH_TLS  
   int status;  
   f_imap_t f_imap = folder->data;  
134    
135    if (!mu_tls_enable || check_capa (f_imap, "STARTTLS"))  typedef int (*auth_method_t) __P((authority_t));
     return -1;  
     
   FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "g%u STARTTLS\n", f_imap->seq);  
   status = imap_writeline (f_imap, "g%u STARTTLS\r\n",  
                            f_imap->seq++, f_imap->user, f_imap->passwd);  
   CHECK_ERROR (f_imap, status);  
   status = imap_send (f_imap);  
   CHECK_ERROR (f_imap, status);  
   status = imap_parse (f_imap);  
   if (status == 0)  
     {  
       stream_t str;  
       status = tls_stream_create_client_from_tcp (&str, folder->stream, 0);  
       CHECK_ERROR (f_imap, status);  
       status = stream_open (str);  
       if (status == 0)  
         folder->stream = str;  
       FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "TLS negotiation %s\n",  
                      status == 0 ? "succeeded" : "failed");  
       read_capa (f_imap, 1);  
     }  
   return status;  
 #else  
   return -1;  
 #endif  
 }  
136    
137  /* Simple User/pass authentication for imap.  */  /* Simple User/pass authentication for imap.  */
138  static int  static int
# Line 344  authenticate_imap_login (authority_t aut Line 187  authenticate_imap_login (authority_t aut
187            {            {
188              CHECK_ERROR_CLOSE (folder, f_imap, MU_ERR_NOPASSWORD);              CHECK_ERROR_CLOSE (folder, f_imap, MU_ERR_NOPASSWORD);
189            }            }
190          status = imap_writeline (f_imap, "g%u LOGIN %s %s\r\n",          status = imap_writeline (f_imap, "g%u LOGIN %s \"%s\"\r\n",
191                                   f_imap->seq, f_imap->user, f_imap->passwd);                                   f_imap->seq, f_imap->user, f_imap->passwd);
192          CHECK_ERROR_CLOSE(folder, f_imap, status);          CHECK_ERROR_CLOSE(folder, f_imap, status);
193          FOLDER_DEBUG2 (folder, MU_DEBUG_PROT, "g%u LOGIN %s *\n",          FOLDER_DEBUG2 (folder, MU_DEBUG_PROT, "g%u LOGIN %s *\n",
# Line 433  authenticate_imap_sasl_anon (authority_t Line 276  authenticate_imap_sasl_anon (authority_t
276    
277    assert (f_imap->state == IMAP_AUTH);    assert (f_imap->state == IMAP_AUTH);
278    
279      if (check_capa (f_imap, "AUTH=ANONYMOUS"))
280        {
281          FOLDER_DEBUG0 (folder, MU_DEBUG_PROT,
282                         "ANONYMOUS capability not present disabled\n");
283          return ENOSYS;
284        }
285    
286    switch (f_imap->auth_state)    switch (f_imap->auth_state)
287      {      {
288      case IMAP_AUTH_ANON_REQ_WRITE:      case IMAP_AUTH_ANON_REQ_WRITE:
# Line 489  authenticate_imap_sasl_anon (authority_t Line 339  authenticate_imap_sasl_anon (authority_t
339    return 0;    return 0;
340  }  }
341    
342    struct auth_tab
343    {
344      char *name;
345      auth_method_t method;
346    };
347    
348    /* NOTE: The ordering of methods in this table is from most secure
349       to less secure. */
350    
351    static struct auth_tab auth_tab[] = {
352      { "login", authenticate_imap_login },
353      { "anon", authenticate_imap_sasl_anon },
354      { NULL }
355    };
356    
357    static auth_method_t
358    find_auth_method (const char *name)
359    {
360      struct auth_tab *p;
361    
362      for (p = auth_tab; p->name; p++)
363        if (strcasecmp (p->name, name) == 0)
364          return p->method;
365    
366      return NULL;
367    }
368    
369    static int
370    authenticate_imap_select (authority_t auth)
371    {
372      struct auth_tab *p;
373      int status;
374      
375      for (p = auth_tab; status && p->name; p++)
376        status = p->method (auth);
377    
378      return status;
379    }
380    
381    
382    
383    
384    /* Initialize the concrete IMAP mailbox: overload the folder functions  */
385    int
386    _folder_imap_init (folder_t folder)
387    {
388      int status;
389      f_imap_t f_imap;
390    
391      /* Set the authority early:
392         (1) so we can check for errors.
393         (2) allow the client to get the authority for setting the ticket
394         before the open.  */
395      status = folder_imap_get_authority (folder, NULL);
396      if (status != 0)
397        return status;
398    
399      f_imap = folder->data = calloc (1, sizeof (*f_imap));
400      if (f_imap == NULL)
401        return ENOMEM;
402    
403      f_imap->folder = folder;
404      f_imap->state = IMAP_NO_STATE;
405    
406      folder->_destroy = folder_imap_destroy;
407    
408      folder->_open = folder_imap_open;
409      folder->_close = folder_imap_close;
410    
411      folder->_list = folder_imap_list;
412      folder->_lsub = folder_imap_lsub;
413      folder->_subscribe = folder_imap_subscribe;
414      folder->_unsubscribe = folder_imap_unsubscribe;
415      folder->_delete = folder_imap_delete;
416      folder->_rename = folder_imap_rename;
417    
418      return 0;
419    }
420    
421    /* Destroy the folder resources.  */
422    static void
423    folder_imap_destroy (folder_t folder)
424    {
425      if (folder->data)
426        {
427          f_imap_t f_imap = folder->data;
428          if (f_imap->buffer)
429            free (f_imap->buffer);
430          if (f_imap->capav)
431            argcv_free (f_imap->capac, f_imap->capav);
432          free (f_imap);
433          folder->data = NULL;
434        }
435    }
436    
437    static int
438    folder_set_auth_method (folder_t folder, auth_method_t method)
439    {
440      if (!folder->authority)
441        {
442          int status = authority_create (&folder->authority, NULL, folder);
443          if (status)
444            return status;
445        }
446      return authority_set_authenticate (folder->authority, method, folder);
447    }
448    
449    static int
450    folder_imap_get_authority (folder_t folder, authority_t *pauth)
451    {
452      int status = 0;
453      if (folder->authority == NULL)
454        {
455          /* assert (folder->url); */
456          if (folder->url == NULL)
457            return EINVAL;
458    
459          if (folder->url->auth == NULL
460              || strcasecmp (folder->url->auth, "*") == 0)
461            {
462              status = folder_set_auth_method (folder, authenticate_imap_select);
463            }
464          else
465            {
466              char *p, *sp;
467    
468              for (p = strtok_r (folder->url->auth, ",", &sp);
469                   status == 0 && p;
470                   p = strtok_r (NULL, ",", &sp))
471                {
472                  auth_method_t method = find_auth_method (p);
473                  if (method)
474                    status = folder_set_auth_method (folder, method);
475                  else
476                    status = MU_ERR_BAD_AUTH_SCHEME;
477                }            
478            }
479        }
480    
481      if (status)
482        return status;
483      
484      if (pauth)
485        *pauth = folder->authority;
486      return status;
487    }
488    
489    
490    /* Capability handling */
491    static int
492    parse_capa (f_imap_t f_imap, char *str)
493    {
494      if (f_imap->capav)
495        argcv_free (f_imap->capac, f_imap->capav);
496      return argcv_get (str, "", NULL, &f_imap->capac, &f_imap->capav);
497    }
498    
499    static int
500    read_capa (f_imap_t f_imap, int force)
501    {
502      int status = 0;
503      
504      if (force)
505        {
506          argcv_free (f_imap->capac, f_imap->capav);
507          f_imap->capac = 0;
508          f_imap->capav = NULL;
509        }
510      
511      if (!f_imap->capav)
512        {
513          status = imap_writeline (f_imap, "g%u CAPABILITY\r\n",
514                                   f_imap->seq++);
515          status = imap_send (f_imap);
516          status = imap_parse (f_imap);
517        }
518      return status;
519    }
520    
521    static int
522    check_capa (f_imap_t f_imap, char *capa)
523    {
524      int i;
525    
526      read_capa (f_imap, 0);
527      for (i = 0; i < f_imap->capac; i++)
528        if (strcasecmp (f_imap->capav[i], capa) == 0)
529          return 0;
530      return 1;
531    }
532    
533    
534    static int
535    tls (folder_t folder)
536    {
537    #ifdef WITH_TLS
538      int status;
539      f_imap_t f_imap = folder->data;
540    
541      if (!mu_tls_enable || check_capa (f_imap, "STARTTLS"))
542        return -1;
543      
544      FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "g%u STARTTLS\n", f_imap->seq);
545      status = imap_writeline (f_imap, "g%u STARTTLS\r\n",
546                               f_imap->seq++, f_imap->user, f_imap->passwd);
547      CHECK_ERROR (f_imap, status);
548      status = imap_send (f_imap);
549      CHECK_ERROR (f_imap, status);
550      status = imap_parse (f_imap);
551      if (status == 0)
552        {
553          stream_t str;
554          status = tls_stream_create_client_from_tcp (&str, folder->stream, 0);
555          CHECK_ERROR (f_imap, status);
556          status = stream_open (str);
557          if (status == 0)
558            folder->stream = str;
559          FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "TLS negotiation %s\n",
560                         status == 0 ? "succeeded" : "failed");
561          read_capa (f_imap, 1);
562        }
563      return status;
564    #else
565      return -1;
566    #endif
567    }
568    
569  /* Create/Open the stream for IMAP.  */  /* Create/Open the stream for IMAP.  */
570  static int  static int
571  folder_imap_open (folder_t folder, int flags)  folder_imap_open (folder_t folder, int flags)

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.62

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26