From b314f6b74b24679a37333d74f49553b0a7577d11 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 12 May 2007 11:42:55 +0200 Subject: [PATCH] further unclutter. Signed-off-by: Pierre Habouzit --- imap/Makefile.am | 4 +- imap/auth.c | 187 +++++++++++++++++++++++++++++++++++++++++++++- imap/auth.h | 35 --------- imap/auth_login.c | 51 ------------- imap/auth_sasl.c | 155 -------------------------------------- 5 files changed, 188 insertions(+), 244 deletions(-) delete mode 100644 imap/auth.h delete mode 100644 imap/auth_login.c delete mode 100644 imap/auth_sasl.c diff --git a/imap/Makefile.am b/imap/Makefile.am index 9591604..6fafb2e 100644 --- a/imap/Makefile.am +++ b/imap/Makefile.am @@ -3,8 +3,8 @@ EXTRA_DIST = BUGS README TODO INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/intl noinst_LIBRARIES = libimap.a -noinst_HEADERS = auth.h imap_private.h message.h +noinst_HEADERS = imap_private.h message.h -libimap_a_SOURCES = auth.c auth_login.c browse.c command.c imap.c imap.h message.c utf7.c util.c auth_sasl.c +libimap_a_SOURCES = auth.c browse.c command.c imap.c imap.h message.c utf7.c util.c -include $(top_builddir)/tools/cflags.mk diff --git a/imap/auth.c b/imap/auth.c index 8b32807..301c27d 100644 --- a/imap/auth.c +++ b/imap/auth.c @@ -13,10 +13,195 @@ #include +#include +#include + #include "mutt.h" +#include "mutt_sasl.h" #include "imap_private.h" -#include "auth.h" +typedef enum { + IMAP_AUTH_SUCCESS = 0, + IMAP_AUTH_FAILURE, + IMAP_AUTH_UNAVAIL +} imap_auth_res_t; + +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; + +/* imap_auth_sasl: Default authenticator if available. */ +static imap_auth_res_t imap_auth_sasl (IMAP_DATA * idata, const char *method) +{ + sasl_conn_t *saslconn; + sasl_interact_t *interaction = NULL; + int rc, irc; + char buf[HUGE_STRING]; + const char *mech; + + const char *pc = NULL; + unsigned int len, olen; + unsigned char client_start; + + if (mutt_sasl_client_new (idata->conn, &saslconn) < 0) { + return IMAP_AUTH_FAILURE; + } + + rc = SASL_FAIL; + + /* 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_account_getuser (&idata->conn->account)) + return IMAP_AUTH_FAILURE; + + if (mutt_bit_isset (idata->capabilities, AUTH_ANON) && + (!idata->conn->account.user[0] || + !m_strncmp(idata->conn->account.user, "anonymous", 9))) + rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen, + &mech); + } + + if (rc != SASL_OK && rc != SASL_CONTINUE) + do { + rc = sasl_client_start (saslconn, method, &interaction, + &pc, &olen, &mech); + if (rc == SASL_INTERACT) + mutt_sasl_interact (interaction); + } + while (rc == SASL_INTERACT); + + client_start = (olen > 0); + + if (rc != SASL_OK && rc != SASL_CONTINUE) { + /* SASL doesn't support LOGIN, so fall back */ + return IMAP_AUTH_UNAVAIL; + } + + mutt_message (_("Authenticating (%s)..."), mech); + + snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech); + imap_cmd_start (idata, buf); + irc = IMAP_CMD_CONTINUE; + + /* looping protocol */ + while (rc == SASL_CONTINUE || olen > 0) { + do + irc = imap_cmd_step (idata); + while (irc == IMAP_CMD_CONTINUE); + + if (method && irc == IMAP_CMD_NO) { + sasl_dispose (&saslconn); + return IMAP_AUTH_UNAVAIL; + } + + if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO) + goto bail; + + if (irc == IMAP_CMD_RESPOND) { + if (sasl_decode64(idata->cmd.buf + 2, m_strlen(idata->cmd.buf + 2), buf, + LONG_STRING - 1, &len) != SASL_OK) { + goto bail; + } + } + + /* client-start is only available with the SASL-IR extension, but + * SASL 2.1 seems to want to use it regardless, at least for DIGEST + * fast reauth. Override if the server sent an initial continuation */ + if (!client_start || buf[0]) { + do { + rc = sasl_client_step (saslconn, buf, len, &interaction, &pc, &olen); + if (rc == SASL_INTERACT) + mutt_sasl_interact (interaction); + } + while (rc == SASL_INTERACT); + } + else + client_start = 0; + + /* send out response, or line break if none needed */ + if (olen) { + if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK) { + goto bail; + } + } + + if (irc == IMAP_CMD_RESPOND) { + m_strcpy(buf + olen, sizeof(buf) - olen, "\r\n"); + mutt_socket_write (idata->conn, buf); + } + + /* If SASL has errored out, send an abort string to the server */ + if (rc < 0) { + mutt_socket_write (idata->conn, "*\r\n"); + } + + olen = 0; + } + + while (irc != IMAP_CMD_OK) + if ((irc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) + break; + + if (rc != SASL_OK) + goto bail; + + if (imap_code (idata->cmd.buf)) { + mutt_sasl_setup_conn (idata->conn, saslconn); + return IMAP_AUTH_SUCCESS; + } + +bail: + mutt_error _("SASL authentication failed."); + mutt_sleep (2); + sasl_dispose (&saslconn); + + return IMAP_AUTH_FAILURE; +} +/* imap_auth_login: Plain LOGIN support */ +static imap_auth_res_t imap_auth_login(IMAP_DATA *idata, const char *method) +{ + char q_user[STRING], q_pass[STRING]; + char buf[STRING]; + int rc; + + if (mutt_bit_isset (idata->capabilities, LOGINDISABLED)) { + mutt_message _("LOGIN disabled on this server."); + + return IMAP_AUTH_UNAVAIL; + } + + if (mutt_account_getlogin (&idata->conn->account)) + return IMAP_AUTH_FAILURE; + if (mutt_account_getpass (&idata->conn->account)) + return IMAP_AUTH_FAILURE; + + mutt_message _("Logging in..."); + + imap_quote_string(q_user, sizeof(q_user), idata->conn->account.login); + imap_quote_string(q_pass, sizeof(q_pass), idata->conn->account.pass); + + snprintf(buf, sizeof(buf), "LOGIN %s %s", q_user, q_pass); + rc = imap_exec(idata, buf, IMAP_CMD_FAIL_OK | IMAP_CMD_PASS); + + if (!rc) + return IMAP_AUTH_SUCCESS; + + mutt_error _("Login failed."); + + mutt_sleep (2); + return IMAP_AUTH_FAILURE; +} static imap_auth_t imap_authenticators[] = { {imap_auth_sasl, NULL}, {imap_auth_login, "login"}, diff --git a/imap/auth.h b/imap/auth.h deleted file mode 100644 index 4dab11d..0000000 --- a/imap/auth.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 2000-1 Brendan Cully - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -/* common defs for authenticators. A good place to set up a generic callback - * system */ - -#ifndef _IMAP_AUTH_H -#define _IMAP_AUTH_H 1 - -typedef enum { - IMAP_AUTH_SUCCESS = 0, - IMAP_AUTH_FAILURE, - IMAP_AUTH_UNAVAIL -} imap_auth_res_t; - - -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_login (IMAP_DATA * idata, const char *method); -imap_auth_res_t imap_auth_sasl (IMAP_DATA * idata, const char *method); - -#endif /* _IMAP_AUTH_H */ diff --git a/imap/auth_login.c b/imap/auth_login.c deleted file mode 100644 index 023c654..0000000 --- a/imap/auth_login.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 1999-2001 Brendan Cully - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -/* plain LOGIN support */ - -#include - -#include "mutt.h" -#include "imap_private.h" -#include "auth.h" - -/* imap_auth_login: Plain LOGIN support */ -imap_auth_res_t imap_auth_login(IMAP_DATA *idata, const char *method __attribute__ ((unused))) -{ - char q_user[STRING], q_pass[STRING]; - char buf[STRING]; - int rc; - - if (mutt_bit_isset (idata->capabilities, LOGINDISABLED)) { - mutt_message _("LOGIN disabled on this server."); - - return IMAP_AUTH_UNAVAIL; - } - - if (mutt_account_getlogin (&idata->conn->account)) - return IMAP_AUTH_FAILURE; - if (mutt_account_getpass (&idata->conn->account)) - return IMAP_AUTH_FAILURE; - - mutt_message _("Logging in..."); - - imap_quote_string(q_user, sizeof(q_user), idata->conn->account.login); - imap_quote_string(q_pass, sizeof(q_pass), idata->conn->account.pass); - - snprintf(buf, sizeof(buf), "LOGIN %s %s", q_user, q_pass); - rc = imap_exec(idata, buf, IMAP_CMD_FAIL_OK | IMAP_CMD_PASS); - - if (!rc) - return IMAP_AUTH_SUCCESS; - - mutt_error _("Login failed."); - - mutt_sleep (2); - return IMAP_AUTH_FAILURE; -} diff --git a/imap/auth_sasl.c b/imap/auth_sasl.c deleted file mode 100644 index a387758..0000000 --- a/imap/auth_sasl.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 2000-3 Brendan Cully - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -/* SASL login/authentication code */ - -#include - -#include "mutt.h" -#include "mutt_sasl.h" -#include "imap_private.h" -#include "auth.h" - -#include -#include - -/* imap_auth_sasl: Default authenticator if available. */ -imap_auth_res_t imap_auth_sasl (IMAP_DATA * idata, const char *method) -{ - sasl_conn_t *saslconn; - sasl_interact_t *interaction = NULL; - int rc, irc; - char buf[HUGE_STRING]; - const char *mech; - - const char *pc = NULL; - unsigned int len, olen; - unsigned char client_start; - - if (mutt_sasl_client_new (idata->conn, &saslconn) < 0) { - return IMAP_AUTH_FAILURE; - } - - rc = SASL_FAIL; - - /* 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_account_getuser (&idata->conn->account)) - return IMAP_AUTH_FAILURE; - - if (mutt_bit_isset (idata->capabilities, AUTH_ANON) && - (!idata->conn->account.user[0] || - !m_strncmp(idata->conn->account.user, "anonymous", 9))) - rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen, - &mech); - } - - if (rc != SASL_OK && rc != SASL_CONTINUE) - do { - rc = sasl_client_start (saslconn, method, &interaction, - &pc, &olen, &mech); - if (rc == SASL_INTERACT) - mutt_sasl_interact (interaction); - } - while (rc == SASL_INTERACT); - - client_start = (olen > 0); - - if (rc != SASL_OK && rc != SASL_CONTINUE) { - /* SASL doesn't support LOGIN, so fall back */ - return IMAP_AUTH_UNAVAIL; - } - - mutt_message (_("Authenticating (%s)..."), mech); - - snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech); - imap_cmd_start (idata, buf); - irc = IMAP_CMD_CONTINUE; - - /* looping protocol */ - while (rc == SASL_CONTINUE || olen > 0) { - do - irc = imap_cmd_step (idata); - while (irc == IMAP_CMD_CONTINUE); - - if (method && irc == IMAP_CMD_NO) { - sasl_dispose (&saslconn); - return IMAP_AUTH_UNAVAIL; - } - - if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO) - goto bail; - - if (irc == IMAP_CMD_RESPOND) { - if (sasl_decode64(idata->cmd.buf + 2, m_strlen(idata->cmd.buf + 2), buf, - LONG_STRING - 1, &len) != SASL_OK) { - goto bail; - } - } - - /* client-start is only available with the SASL-IR extension, but - * SASL 2.1 seems to want to use it regardless, at least for DIGEST - * fast reauth. Override if the server sent an initial continuation */ - if (!client_start || buf[0]) { - do { - rc = sasl_client_step (saslconn, buf, len, &interaction, &pc, &olen); - if (rc == SASL_INTERACT) - mutt_sasl_interact (interaction); - } - while (rc == SASL_INTERACT); - } - else - client_start = 0; - - /* send out response, or line break if none needed */ - if (olen) { - if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK) { - goto bail; - } - } - - if (irc == IMAP_CMD_RESPOND) { - m_strcpy(buf + olen, sizeof(buf) - olen, "\r\n"); - mutt_socket_write (idata->conn, buf); - } - - /* If SASL has errored out, send an abort string to the server */ - if (rc < 0) { - mutt_socket_write (idata->conn, "*\r\n"); - } - - olen = 0; - } - - while (irc != IMAP_CMD_OK) - if ((irc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) - break; - - if (rc != SASL_OK) - goto bail; - - if (imap_code (idata->cmd.buf)) { - mutt_sasl_setup_conn (idata->conn, saslconn); - return IMAP_AUTH_SUCCESS; - } - -bail: - mutt_error _("SASL authentication failed."); - mutt_sleep (2); - sasl_dispose (&saslconn); - - return IMAP_AUTH_FAILURE; -} -- 2.20.1