** 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
/*
- * 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
POP_A_SUCCESS = 0,
POP_A_SOCKET,
POP_A_FAILURE,
- POP_A_SKIP,
POP_A_UNAVAIL
} pop_auth_res_t;
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 */
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 *);
/*
- * 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
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
mutt_error _("APOP authentication failed.");
mutt_sleep (2);
- return POP_A_SKIP;
+ return POP_A_FAILURE;
}
/* USER authenticator */
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 }
};
/*
{
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)
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;