From 2a53140af4747cfe9346e82b6ac20ab287ea9dda Mon Sep 17 00:00:00 2001 From: Brendan Cully Date: Wed, 16 Jul 2003 11:18:12 +0000 Subject: [PATCH] I noticed that my mutt hung when I tried SASL DIGEST-MD5 authentication (I'm not sure when this started). I believe this patch should solve that problem in a reliable way. This patch also attempts to reuse connections even when authentication fails, instead of just throwing away a perfectly good socket. --- account.c | 7 ++++- account.h | 3 ++- imap/auth_sasl.c | 8 +++--- imap/imap.c | 67 +++++++++++++++++++++++++++++++----------------- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/account.c b/account.c index 3fda792b..4f0ed881 100644 --- a/account.c +++ b/account.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Brendan Cully + * Copyright (C) 2000-3 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 @@ -180,3 +180,8 @@ int mutt_account_getpass (ACCOUNT* account) return 0; } + +void mutt_account_unsetpass (ACCOUNT* account) +{ + account->flags &= !M_ACCT_PASS; +} diff --git a/account.h b/account.h index a6850a6c..145e5145 100644 --- a/account.h +++ b/account.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Brendan Cully + * Copyright (C) 2000-3 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 @@ -52,5 +52,6 @@ int mutt_account_fromurl (ACCOUNT* account, ciss_url_t* url); void mutt_account_tourl (ACCOUNT* account, ciss_url_t* url); int mutt_account_getuser (ACCOUNT* account); int mutt_account_getpass (ACCOUNT* account); +void mutt_account_unsetpass (ACCOUNT* account); #endif /* _MUTT_ACCOUNT_H_ */ diff --git a/imap/auth_sasl.c b/imap/auth_sasl.c index 4a929c97..57404357 100644 --- a/imap/auth_sasl.c +++ b/imap/auth_sasl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2 Brendan Cully + * Copyright (C) 2000-3 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 @@ -109,7 +109,7 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method) return IMAP_AUTH_UNAVAIL; } - mutt_message _("Authenticating (SASL)..."); + mutt_message (_("Authenticating (%s)..."), mech); snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech); imap_cmd_start (idata, buf); @@ -153,7 +153,7 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method) client_start = 0; /* send out response, or line break if none needed */ - if (pc) + if (olen) { if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK) { @@ -168,7 +168,7 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method) #endif } - if (olen || rc == SASL_CONTINUE) + if (irc == IMAP_CMD_RESPOND) { strfcpy (buf + olen, "\r\n", sizeof (buf) - olen); mutt_socket_write (idata->conn, buf); diff --git a/imap/imap.c b/imap/imap.c index a70d2232..f10ae281 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -340,30 +340,48 @@ IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags) /* don't open a new connection if one isn't wanted */ if (flags & M_IMAP_CONN_NONEW) - if (!idata || idata->state == IMAP_DISCONNECTED) - goto err_conn; + { + if (!idata) + { + mutt_socket_free (conn); + return NULL; + } + if (idata->state < IMAP_AUTHENTICATED) + return NULL; + } if (!idata) { /* The current connection is a new connection */ if (! (idata = imap_new_idata ())) - goto err_conn; + { + mutt_socket_free (conn); + return NULL; + } conn->data = idata; idata->conn = conn; } + if (idata->state == IMAP_DISCONNECTED) - if (imap_open_connection (idata) != 0) - goto err_idata; + imap_open_connection (idata); + if (idata->state == IMAP_CONNECTED) + { + if (!imap_authenticate (idata)) + { + idata->state = IMAP_AUTHENTICATED; + if (idata->conn->ssf) + dprint (2, (debugfile, "Communication encrypted at %d bits\n", + idata->conn->ssf)); + imap_get_delim (idata); + } + else + mutt_account_unsetpass (&idata->conn->account); + + FREE (&idata->capstr); + } return idata; - - err_idata: - imap_free_idata (&idata); - err_conn: - mutt_socket_free (conn); - - return NULL; } int imap_open_connection (IMAP_DATA* idata) @@ -375,8 +393,14 @@ int imap_open_connection (IMAP_DATA* idata) idata->state = IMAP_CONNECTED; - if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE) - goto bail; + if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE) { + mutt_error (_("Unexpected response received from server: %s"), idata->cmd.buf); + mutt_sleep (1); + + mutt_socket_close (idata->conn); + idata->state = IMAP_DISCONNECTED; + return -1; + } if (ascii_strncasecmp ("* OK", idata->cmd.buf, 4) == 0) { @@ -413,16 +437,13 @@ int imap_open_connection (IMAP_DATA* idata) } } #endif - if (imap_authenticate (idata)) - goto bail; - if (idata->conn->ssf) - dprint (2, (debugfile, "Communication encrypted at %d bits\n", - idata->conn->ssf)); } else if (ascii_strncasecmp ("* PREAUTH", idata->cmd.buf, 9) == 0) { + idata->state = IMAP_AUTHENTICATED; if (imap_check_capabilities (idata) != 0) goto bail; + FREE (&idata->capstr); } else { @@ -430,17 +451,12 @@ int imap_open_connection (IMAP_DATA* idata) goto bail; } - FREE (&idata->capstr); - idata->state = IMAP_AUTHENTICATED; - - imap_get_delim (idata); return 0; err_close_conn: mutt_socket_close (idata->conn); bail: FREE (&idata->capstr); - idata->state = IMAP_DISCONNECTED; return -1; } @@ -520,6 +536,9 @@ int imap_open_mailbox (CONTEXT* ctx) /* we require a connection which isn't currently in IMAP_SELECTED state */ if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NOSELECT))) goto fail_noidata; + if (idata->state < IMAP_AUTHENTICATED) + goto fail; + conn = idata->conn; /* once again the context is new */ -- 2.50.1