From d43cbd140463dea549f33fae5792943b5964a018 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Tue, 5 Jun 2001 08:11:57 +0000 Subject: The attached patch should be the last feature I want to get in before 1.4. It creates a new config variable $imap_authenticators, which is a comma-separated list of authentication methods for mutt to try to use to authenticate to an IMAP server. If it is unspecified you get the old behaviour - any method is tried, the first to succeed or fail ends the auth loop. (From Brendan Cully.) --- imap/auth.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--------- imap/auth.h | 24 ++++++++++++------ imap/auth_anon.c | 2 +- imap/auth_cram.c | 2 +- imap/auth_gss.c | 2 +- imap/auth_login.c | 2 +- imap/auth_sasl.c | 38 +++++++++++++++++----------- imap/imap.c | 2 +- 8 files changed, 108 insertions(+), 38 deletions(-) (limited to 'imap') diff --git a/imap/auth.c b/imap/auth.c index e7c3661d..c7037a3a 100644 --- a/imap/auth.c +++ b/imap/auth.c @@ -26,34 +26,84 @@ static imap_auth_t imap_authenticators[] = { #ifdef USE_SASL - imap_auth_sasl, + { imap_auth_sasl, NULL }, #else - imap_auth_anon, + { imap_auth_anon, "anonymous" }, #endif #ifdef USE_GSS - imap_auth_gss, + { imap_auth_gss, "gssapi" }, #endif /* SASL includes CRAM-MD5 (and GSSAPI, but that's not enabled by default) */ #ifndef USE_SASL - imap_auth_cram_md5, + { imap_auth_cram_md5, "cram-md5" }, #endif - imap_auth_login, + { imap_auth_login, "login" }, - NULL + { NULL } }; -/* imap_authenticate: oh how simple! loops through authenticators. */ +/* imap_authenticate: Attempt to authenticate using either user-specified + * authentication method if specified, or any. */ int imap_authenticate (IMAP_DATA* idata) { - imap_auth_t* authenticator = imap_authenticators; + imap_auth_t* authenticator; + char* methods; + char* comma; + char* method; int r = -1; - while (*authenticator) + if (ImapAuthenticators && *ImapAuthenticators) { - if ((r = (*authenticator)(idata)) != IMAP_AUTH_UNAVAIL) - return r; - authenticator++; + /* Try user-specified list of authentication methods */ + methods = safe_strdup (ImapAuthenticators); + method = methods; + + while (method) + { + comma = strchr (method, ','); + if (comma) + *comma++ = '\0'; + dprint (2, (debugfile, "imap_authenticate: Trying method %s\n", method)); + authenticator = imap_authenticators; + + while (authenticator->authenticate) + { + if (!authenticator->method || + !ascii_strcasecmp (authenticator->method, method)) + if ((r = authenticator->authenticate (idata, method)) != + IMAP_AUTH_UNAVAIL) + { + FREE (&methods); + return r; + } + + authenticator++; + } + + method = comma; + } + + FREE (&methods); } + else + { + /* Fall back to default: any authenticator */ + dprint (2, (debugfile, "imap_authenticate: Using any available method.\n")); + authenticator = imap_authenticators; + while (authenticator->authenticate) + { + if ((r = authenticator->authenticate (idata, NULL)) != IMAP_AUTH_UNAVAIL) + return r; + authenticator++; + } + } + + if (r == IMAP_AUTH_UNAVAIL) + { + mutt_error (_("No authenticators available")); + mutt_sleep (1); + } + return r; } diff --git a/imap/auth.h b/imap/auth.h index bf3f2c21..608efc26 100644 --- a/imap/auth.h +++ b/imap/auth.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Brendan Cully + * Copyright (C) 2000-1 Brendan Cully * * 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 @@ -29,17 +29,27 @@ typedef enum IMAP_AUTH_UNAVAIL } imap_auth_res_t; -typedef imap_auth_res_t (*imap_auth_t)(IMAP_DATA* idata); + +typedef struct +{ + /* do authentication, using named method or any available if method is NULL */ + imap_auth_res_t (*authenticate) (IMAP_DATA* idata, const char* method); + /* name of authentication method supported, NULL means variable. If this + * is not null, authenticate may ignore the second parameter. */ + const char* method; +} imap_auth_t; /* external authenticator prototypes */ -imap_auth_res_t imap_auth_anon (IMAP_DATA* idata); -imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata); -imap_auth_res_t imap_auth_login (IMAP_DATA* idata); +#ifndef USE_SASL +imap_auth_res_t imap_auth_anon (IMAP_DATA* idata, const char* method); +imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata, const char* method); +#endif +imap_auth_res_t imap_auth_login (IMAP_DATA* idata, const char* method); #ifdef USE_GSS -imap_auth_res_t imap_auth_gss (IMAP_DATA* idata); +imap_auth_res_t imap_auth_gss (IMAP_DATA* idata, const char* method); #endif #ifdef USE_SASL -imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata); +imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method); #endif #endif /* _IMAP_AUTH_H */ diff --git a/imap/auth_anon.c b/imap/auth_anon.c index 7d60e017..252a3d01 100644 --- a/imap/auth_anon.c +++ b/imap/auth_anon.c @@ -23,7 +23,7 @@ #include "auth.h" /* this is basically a stripped-down version of the cram-md5 method. */ -imap_auth_res_t imap_auth_anon (IMAP_DATA* idata) +imap_auth_res_t imap_auth_anon (IMAP_DATA* idata, const char* method) { int rc; diff --git a/imap/auth_cram.c b/imap/auth_cram.c index 741e26c6..3003f7aa 100644 --- a/imap/auth_cram.c +++ b/imap/auth_cram.c @@ -31,7 +31,7 @@ static void hmac_md5 (const char* password, char* challenge, unsigned char* response); /* imap_auth_cram_md5: AUTH=CRAM-MD5 support. */ -imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata) +imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata, const char* method) { char ibuf[LONG_STRING*2], obuf[LONG_STRING]; unsigned char hmac_response[MD5_DIGEST_LEN]; diff --git a/imap/auth_gss.c b/imap/auth_gss.c index cfd7d2ad..1a7491e8 100644 --- a/imap/auth_gss.c +++ b/imap/auth_gss.c @@ -42,7 +42,7 @@ #define GSS_AUTH_P_PRIVACY 4 /* imap_auth_gss: AUTH=GSSAPI support. */ -imap_auth_res_t imap_auth_gss (IMAP_DATA* idata) +imap_auth_res_t imap_auth_gss (IMAP_DATA* idata, const char* method) { gss_buffer_desc request_buf, send_token; gss_buffer_t sec_token; diff --git a/imap/auth_login.c b/imap/auth_login.c index 9bdbb9fe..7be391d6 100644 --- a/imap/auth_login.c +++ b/imap/auth_login.c @@ -23,7 +23,7 @@ #include "auth.h" /* imap_auth_login: Plain LOGIN support */ -imap_auth_res_t imap_auth_login (IMAP_DATA* idata) +imap_auth_res_t imap_auth_login (IMAP_DATA* idata, const char* method) { char q_user[SHORT_STRING], q_pass[SHORT_STRING]; char buf[STRING]; diff --git a/imap/auth_sasl.c b/imap/auth_sasl.c index 640e434f..818d37db 100644 --- a/imap/auth_sasl.c +++ b/imap/auth_sasl.c @@ -27,7 +27,7 @@ #include /* imap_auth_sasl: Default authenticator if available. */ -imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata) +imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method) { sasl_conn_t* saslconn; sasl_interact_t* interaction = NULL; @@ -48,25 +48,32 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata) return IMAP_AUTH_FAILURE; } - /* hack for SASL ANONYMOUS support: - * 1. Fetch username. If it's "" or "anonymous" then - * 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability - * 3. if sasl_client_start fails, fall through... */ rc = SASL_FAIL; - if (mutt_account_getuser (&idata->conn->account)) - return IMAP_AUTH_FAILURE; + /* If the user hasn't specified a method, use any available */ + if (!method) + { + method = idata->capstr; + + /* hack for SASL ANONYMOUS support: + * 1. Fetch username. If it's "" or "anonymous" then + * 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability + * 3. if sasl_client_start fails, fall through... */ - if (mutt_bit_isset (idata->capabilities, AUTH_ANON) && - (!idata->conn->account.user[0] || - !mutt_strncmp (idata->conn->account.user, "anonymous", 9))) - rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, NULL, &pc, &olen, - &mech); + if (mutt_account_getuser (&idata->conn->account)) + return IMAP_AUTH_FAILURE; + if (mutt_bit_isset (idata->capabilities, AUTH_ANON) && + (!idata->conn->account.user[0] || + !mutt_strncmp (idata->conn->account.user, "anonymous", 9))) + rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, NULL, &pc, &olen, + &mech); + } + if (rc != SASL_OK && rc != SASL_CONTINUE) do { - rc = sasl_client_start (saslconn, idata->capstr, NULL, &interaction, + rc = sasl_client_start (saslconn, method, NULL, &interaction, &pc, &olen, &mech); if (rc == SASL_INTERACT) mutt_sasl_interact (interaction); @@ -77,7 +84,10 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata) if (rc != SASL_OK && rc != SASL_CONTINUE) { - dprint (1, (debugfile, "imap_auth_sasl: Failure starting authentication exchange. No shared mechanisms?\n")); + if (method) + dprint (2, (debugfile, "imap_auth_sasl: %s unavailable\n", method)); + else + dprint (1, (debugfile, "imap_auth_sasl: Failure starting authentication exchange. No shared mechanisms?\n")); /* SASL doesn't support LOGIN, so fall back */ return IMAP_AUTH_UNAVAIL; diff --git a/imap/imap.c b/imap/imap.c index 3a8247e8..dc208ed4 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -386,7 +386,7 @@ int imap_open_connection (IMAP_DATA* idata) { if (mutt_ssl_starttls (idata->conn)) { - mutt_error ("Could not negotiate TLS connection"); + mutt_error (_("Could not negotiate TLS connection")); mutt_sleep (1); goto bail; } -- cgit v1.2.3