Commit a4c1eb53 authored by Thomas Roessler's avatar Thomas Roessler

The attached patch adds two variables: $pop_authenticators and

$pop_auth_try_all.

From Vsevolod Volkov.
parent 0e3ddb8e
......@@ -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);
......
......@@ -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
......
......@@ -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,
......
/*
* 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 *);
......
/*
* 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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment