From: Thomas Roessler Date: Mon, 18 Jun 2001 15:56:46 +0000 (+0000) Subject: The attached patch adds two variables: $pop_authenticators and X-Git-Tag: mutt-1-3-20-rel~30 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a4c1eb53d2c6f4ec6f0ecb3062203cc17c9309cc;p=mutt The attached patch adds two variables: $pop_authenticators and $pop_auth_try_all. From Vsevolod Volkov. --- diff --git a/globals.h b/globals.h index f8b9a65b..afac9e75 100644 --- 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 41291401..b34a9429 100644 --- 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 6d11a4aa..2406546f 100644 --- 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 878a3120..b8abc43b 100644 --- a/pop.h +++ b/pop.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Vsevolod Volkov + * Copyright (C) 2000-2001 Vsevolod Volkov * * 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 *); diff --git a/pop_auth.c b/pop_auth.c index fa624005..a4b38f23 100644 --- a/pop_auth.c +++ b/pop_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Vsevolod Volkov + * Copyright (C) 2000-2001 Vsevolod Volkov * * 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;