summaryrefslogtreecommitdiffstats
path: root/imap
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>2001-06-05 08:11:57 +0000
committerThomas Roessler <roessler@does-not-exist.org>2001-06-05 08:11:57 +0000
commitd43cbd140463dea549f33fae5792943b5964a018 (patch)
tree61059ca29584719529049c92d7e574081a778535 /imap
parentf7934bf66aa14d2cc753ba747e3f1b489d6e8638 (diff)
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.)
Diffstat (limited to 'imap')
-rw-r--r--imap/auth.c74
-rw-r--r--imap/auth.h24
-rw-r--r--imap/auth_anon.c2
-rw-r--r--imap/auth_cram.c2
-rw-r--r--imap/auth_gss.c2
-rw-r--r--imap/auth_login.c2
-rw-r--r--imap/auth_sasl.c38
-rw-r--r--imap/imap.c2
8 files changed, 108 insertions, 38 deletions
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 <brendan@kublai.com>
+ * Copyright (C) 2000-1 Brendan Cully <brendan@kublai.com>
*
* 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 <saslutil.h>
/* 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;
}