]> granicus.if.org Git - mutt/commitdiff
The attached patch adds two variables: $pop_authenticators and
authorThomas Roessler <roessler@does-not-exist.org>
Mon, 18 Jun 2001 15:56:46 +0000 (15:56 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Mon, 18 Jun 2001 15:56:46 +0000 (15:56 +0000)
$pop_auth_try_all.

From Vsevolod Volkov.

globals.h
init.h
mutt.h
pop.h
pop_auth.c

index f8b9a65b1d9d405f5d44e6d8f6957ae91e0bcaec..afac9e75d218815e134d464fde3f799ce2e1577b 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -79,6 +79,7 @@ WHERE char *Pager;
 WHERE char *PagerFmt;
 WHERE char *PipeSep;
 #ifdef USE_POP
+WHERE char *PopAuthenticators INITVAL (NULL);
 WHERE short PopCheckTimeout;
 WHERE char *PopHost;
 WHERE char *PopPass INITVAL (NULL);
diff --git a/init.h b/init.h
index 41291401ee32e2a53ec287a1f703bb7a3479560c..b34a9429fe2108dbe41ec1b53200004071740fc1 100644 (file)
--- a/init.h
+++ b/init.h
@@ -1440,6 +1440,27 @@ struct option_t MuttVars[] = {
   ** messages to an external Unix command.
   */
 #ifdef USE_POP
+  { "pop_authenticators", DT_STR, R_NONE, UL &PopAuthenticators, UL 0 },
+  /*
+  ** .pp
+  ** This is a colon-delimited list of authentication methods mutt may
+  ** attempt to use to log in to an POP server, in the order mutt should
+  ** try them.  Authentication methods are either 'user', 'apop' or any
+  ** SASL mechanism, eg 'digest-md5', 'gssapi' or 'cram-md5'.
+  ** This parameter is case-insensitive. If this parameter is unset
+  ** (the default) mutt will try all available methods, in order from
+  ** most-secure to least-secure.
+  ** .pp
+  ** Example: set pop_authenticators="digest-md5:apop:user"
+  */
+  { "pop_auth_try_all",        DT_BOOL, R_NONE, OPTPOPAUTHTRYALL, 1 },
+  /*
+  ** .pp
+  ** If set, Mutt will try all available methods. When unset, Mutt will
+  ** only fall back to other authentication methods if the previous
+  ** methods are unavailable. If a method is available but authentication
+  ** fails, Mutt will not connect to the POP server.
+  */
   { "pop_checkinterval", DT_NUM, R_NONE, UL &PopCheckTimeout, 60 },
   /*
   ** .pp
diff --git a/mutt.h b/mutt.h
index 6d11a4aa0bf397e4fa9d268833f7aa0eeb70e2bf..2406546f6d31a2b0df5f99734cba24aeb5d8125d 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -263,8 +263,10 @@ enum
   OPT_MIMEFWD,
   OPT_MOVE,
   OPT_COPY,
+#ifdef USE_POP
   OPT_POPDELETE,
   OPT_POPRECONNECT,
+#endif
   OPT_POSTPONE,
   OPT_QUIT,
   OPT_REPLYTO,
@@ -355,7 +357,10 @@ enum
   OPTPAGERSTOP,
   OPTPIPEDECODE,
   OPTPIPESPLIT,
+#ifdef USE_POP
+  OPTPOPAUTHTRYALL,
   OPTPOPLAST,
+#endif
   OPTPRINTDECODE,
   OPTPRINTSPLIT,
   OPTPROMPTAFTER,
diff --git a/pop.h b/pop.h
index 878a3120b5bd0161f530840d899cb418069a738a..b8abc43b79e7be8729f9e184a6c63e4b56c18b8a 100644 (file)
--- a/pop.h
+++ b/pop.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000 Vsevolod Volkov <vvv@mutt.org.ua>
+ * Copyright (C) 2000-2001 Vsevolod Volkov <vvv@mutt.org.ua>
  * 
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
@@ -45,7 +45,6 @@ typedef enum
   POP_A_SUCCESS = 0,
   POP_A_SOCKET,
   POP_A_FAILURE,
-  POP_A_SKIP,
   POP_A_UNAVAIL
 } pop_auth_res_t;
 
@@ -67,7 +66,6 @@ typedef struct
   unsigned int resp_codes : 1; /* server supports extended response codes */
   unsigned int expire : 1;     /* expire is greater than 0 */
   unsigned int clear_cache : 1;
-  unsigned int authenticator;
   size_t size;
   time_t check_time;
   time_t login_delay;          /* minimal login delay  capability */
@@ -77,7 +75,14 @@ typedef struct
   POP_CACHE cache[POP_CACHE_LEN];
 } POP_DATA;
 
-typedef pop_auth_res_t (*pop_auth_t)(POP_DATA *);
+typedef struct
+{
+  /* do authentication, using named method or any available if method is NULL */
+  pop_auth_res_t (*authenticate) (POP_DATA *, const char *);
+  /* name of authentication method supported, NULL means variable. If this
+   * is not null, authenticate may ignore the second parameter. */
+  const char* method;
+} pop_auth_t;
 
 /* pop_auth.c */
 int pop_authenticate (POP_DATA *);
index fa62400530e21efb0e939387d4233cb62850e472..a4b38f23210b5be9013acd5e92f074d2927912e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000 Vsevolod Volkov <vvv@mutt.org.ua>
+ * Copyright (C) 2000-2001 Vsevolod Volkov <vvv@mutt.org.ua>
  * 
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
@@ -151,10 +151,7 @@ bail:
   mutt_error _("SASL authentication failed.");
   mutt_sleep (2);
 
-  if (rc == SASL_OK)
-    return POP_A_FAILURE;
-
-  return POP_A_SKIP;
+  return POP_A_FAILURE;
 }
 #endif
 
@@ -211,7 +208,7 @@ static pop_auth_res_t pop_auth_apop (POP_DATA *pop_data)
   mutt_error _("APOP authentication failed.");
   mutt_sleep (2);
 
-  return POP_A_SKIP;
+  return POP_A_FAILURE;
 }
 
 /* USER authenticator */
@@ -274,11 +271,11 @@ static pop_auth_res_t pop_auth_user (POP_DATA *pop_data)
 
 static pop_auth_t pop_authenticators[] = {
 #ifdef USE_SASL
-  pop_auth_sasl,
+  { pop_auth_sasl, NULL },
 #endif
-  pop_auth_apop,
-  pop_auth_user,
-  NULL
+  { pop_auth_apop, "apop" },
+  { pop_auth_user, "user" },
+  { NULL }
 };
 
 /*
@@ -292,54 +289,97 @@ int pop_authenticate (POP_DATA* pop_data)
 {
   ACCOUNT *acct = &pop_data->conn->account;
   pop_auth_t* authenticator;
-  int attempt = 0;
-  int auth = 0;
+  char* methods;
+  char* comma;
+  char* method;
+  int attempts = 0;
   int ret = POP_A_UNAVAIL;
 
   if (mutt_account_getuser (acct) || !acct->user[0] ||
       mutt_account_getpass (acct) || !acct->pass[0])
     return -3;
 
-  if (pop_data->authenticator)
+  if (PopAuthenticators && *PopAuthenticators)
   {
-    authenticator = &pop_authenticators[pop_data->authenticator - 1];
-    ret = (*authenticator)(pop_data);
-    attempt = 1;
+    /* Try user-specified list of authentication methods */
+    methods = safe_strdup (PopAuthenticators);
+    method = methods;
+
+    while (method)
+    {
+      comma = strchr (method, ':');
+      if (comma)
+       *comma++ = '\0';
+      dprint (2, (debugfile, "pop_authenticate: Trying method %s\n", method));
+      authenticator = pop_authenticators;
+
+      while (authenticator->authenticate)
+      {
+       if (!authenticator->method ||
+           !ascii_strcasecmp (authenticator->method, method))
+       {
+         ret = authenticator->authenticate (pop_data, method);
+         if (ret == POP_A_SOCKET)
+           switch (pop_connect (pop_data))
+           {
+             case 0:
+             {
+               ret = authenticator->authenticate (pop_data, method);
+               break;
+             }
+             case -2:
+               ret = POP_A_FAILURE;
+           }
+
+         if (ret != POP_A_UNAVAIL)
+           attempts++;
+         if (ret == POP_A_SUCCESS || ret == POP_A_SOCKET ||
+             (ret == POP_A_FAILURE && !option (OPTPOPAUTHTRYALL)))
+         {
+           comma = NULL;
+           break;
+         }
+       }
+       authenticator++;
+      }
+
+      method = comma;
+    }
+
+    FREE (&methods);
   }
   else
   {
+    /* Fall back to default: any authenticator */
+    dprint (2, (debugfile, "pop_authenticate: Using any available method.\n"));
     authenticator = pop_authenticators;
 
-    while (authenticator)
+    while (authenticator->authenticate)
     {
-      auth++;
-
-      ret = (*authenticator)(pop_data);
+      ret = authenticator->authenticate (pop_data, method);
       if (ret == POP_A_SOCKET)
        switch (pop_connect (pop_data))
        {
          case 0:
          {
-           ret = (*authenticator)(pop_data);
+           ret = authenticator->authenticate (pop_data, method);
            break;
          }
          case -2:
            ret = POP_A_FAILURE;
        }
 
-      if (ret == POP_A_SKIP)
-       attempt = 1;
-      else if (ret != POP_A_UNAVAIL)
+      if (ret != POP_A_UNAVAIL)
+       attempts++;
+      if (ret == POP_A_SUCCESS || ret == POP_A_SOCKET ||
+         (ret == POP_A_FAILURE && !option (OPTPOPAUTHTRYALL)))
+      {
+       comma = NULL;
        break;
+      }
 
       authenticator++;
     }
-
-    if (ret == POP_A_SUCCESS)
-    {
-      pop_data->authenticator = auth;
-      dprint (1, (debugfile, "pop_authenticate: Authenticator #%d.\n", auth));
-    }
   }
 
   switch (ret)
@@ -349,8 +389,8 @@ int pop_authenticate (POP_DATA* pop_data)
     case POP_A_SOCKET:
       return -1;
     case POP_A_UNAVAIL:
-      if (!attempt)
-       mutt_error _("Authentication method is unknown.");
+      if (!attempts)
+       mutt_error (_("No authenticators available"));
   }
 
   return -2;