[gnome-online-accounts/gnome-3-8] imap-auth-login: Don't send any requests if a response is pending
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-online-accounts/gnome-3-8] imap-auth-login: Don't send any requests if a response is pending
- Date: Mon, 22 Apr 2013 14:02:08 +0000 (UTC)
commit fbc5e8040e55f5e66ce572f91ac87bf5151ee2fa
Author: Debarshi Ray <debarshir gnome org>
Date: Mon Apr 22 14:47:54 2013 +0200
imap-auth-login: Don't send any requests if a response is pending
Otherwise some IMAP servers (eg., Zimbra) cause the socket to time out
when used with gnutls3.
Fixes: https://bugzilla.gnome.org/698203
src/goabackend/goaimapauthlogin.c | 163 ++++++++++++++++++++++++++++++--------
1 file changed, 129 insertions(+), 34 deletions(-)
---
diff --git a/src/goabackend/goaimapauthlogin.c b/src/goabackend/goaimapauthlogin.c
index 471c6aa..5019480 100644
--- a/src/goabackend/goaimapauthlogin.c
+++ b/src/goabackend/goaimapauthlogin.c
@@ -54,6 +54,7 @@ struct _GoaImapAuthLogin
GoaProvider *provider;
GoaObject *object;
+ gboolean greeting_absent;
gchar *username;
gchar *password;
};
@@ -85,6 +86,86 @@ G_DEFINE_TYPE (GoaImapAuthLogin, goa_imap_auth_login, GOA_TYPE_MAIL_AUTH);
/* ---------------------------------------------------------------------------------------------------- */
+static const gchar *IMAP_TAG = "A001";
+
+static gboolean
+imap_auth_login_check_BYE (const gchar *response, GError **error)
+{
+ if (g_str_has_prefix (response, "* BYE"))
+ {
+ g_set_error (error,
+ GOA_ERROR,
+ GOA_ERROR_FAILED, /* TODO: more specific */
+ _("Service not available"));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+imap_auth_login_check_NO (const gchar *response, GError **error)
+{
+ gboolean ret;
+ gchar *str;
+
+ ret = FALSE;
+ str = g_strdup_printf ("%s NO", IMAP_TAG);
+
+ if (g_str_has_prefix (response, str))
+ {
+ g_set_error (error,
+ GOA_ERROR,
+ GOA_ERROR_FAILED, /* TODO: more specific */
+ _("Authentication failed"));
+ ret = TRUE;
+ }
+
+ g_free (str);
+ return ret;
+}
+
+static gboolean
+imap_auth_login_check_not_OK (const gchar *response, gboolean tagged, GError **error)
+{
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (tagged)
+ {
+ gchar *str;
+
+ str = g_strdup_printf ("%s OK", IMAP_TAG);
+ if (!g_str_has_prefix (response, str))
+ {
+ g_set_error (error,
+ GOA_ERROR,
+ GOA_ERROR_FAILED, /* TODO: more specific */
+ "Unexpected response `%s' while doing LOGIN authentication",
+ response);
+ ret = TRUE;
+ }
+ g_free (str);
+ }
+ else
+ {
+ if (!g_str_has_prefix (response, "* OK"))
+ {
+ g_set_error (error,
+ GOA_ERROR,
+ GOA_ERROR_FAILED, /* TODO: more specific */
+ "Unexpected response `%s' while doing LOGIN authentication",
+ response);
+ ret = TRUE;
+ }
+ }
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gchar *
imap_auth_escape_backslash (const gchar *str)
{
@@ -387,30 +468,38 @@ goa_imap_auth_login_run_sync (GoaMailAuth *_auth,
input = goa_mail_auth_get_input (_auth);
output = goa_mail_auth_get_output (_auth);
- request = g_strdup_printf ("A001 LOGIN \"%s\" \"%s\"\r\n", auth->username, password);
- g_debug ("> A001 LOGIN \"********************\" \"********************\"");
+ /* Check the greeting, if there is one */
+
+ if (!auth->greeting_absent)
+ {
+ response = g_data_input_stream_read_line (input, NULL, cancellable, error);
+ if (response == NULL)
+ goto out;
+ g_debug ("< %s", response);
+ if (imap_auth_login_check_BYE (response, error))
+ goto out;
+ if (imap_auth_login_check_not_OK (response, FALSE, error))
+ goto out;
+ g_clear_pointer (&response, g_free);
+ }
+
+ /* Send LOGIN */
+
+ request = g_strdup_printf ("%s LOGIN \"%s\" \"%s\"\r\n", IMAP_TAG, auth->username, password);
+ g_debug ("> %s LOGIN \"********************\" \"********************\"", IMAP_TAG);
if (!g_data_output_stream_put_string (output, request, cancellable, error))
goto out;
+ g_clear_pointer (&request, g_free);
- again:
response = g_data_input_stream_read_line (input, NULL, cancellable, error);
if (response == NULL)
goto out;
g_debug ("< %s", response);
- /* ignore untagged responses */
- if (g_str_has_prefix (response, "*"))
- {
- g_free (response);
- goto again;
- }
- if (!g_str_has_prefix (response, "A001 OK"))
- {
- g_set_error (error,
- GOA_ERROR,
- GOA_ERROR_FAILED,
- _("Authentication failed"));
- goto out;
- }
+ if (imap_auth_login_check_NO (response, error))
+ goto out;
+ if (imap_auth_login_check_not_OK (response, TRUE, error))
+ goto out;
+ g_clear_pointer (&response, g_free);
ret = TRUE;
@@ -428,6 +517,7 @@ goa_imap_auth_login_starttls_sync (GoaMailAuth *_auth,
GCancellable *cancellable,
GError **error)
{
+ GoaImapAuthLogin *auth = GOA_IMAP_AUTH_LOGIN (_auth);
GDataInputStream *input;
GDataOutputStream *output;
gchar *request;
@@ -442,31 +532,36 @@ goa_imap_auth_login_starttls_sync (GoaMailAuth *_auth,
input = goa_mail_auth_get_input (_auth);
output = goa_mail_auth_get_output (_auth);
- request = g_strdup ("A001 STARTTLS\r\n");
+ /* Check the greeting */
+
+ response = g_data_input_stream_read_line (input, NULL, cancellable, error);
+ if (response == NULL)
+ goto out;
+ g_debug ("< %s", response);
+ if (imap_auth_login_check_BYE (response, error))
+ goto out;
+ if (imap_auth_login_check_not_OK (response, FALSE, error))
+ goto out;
+ g_clear_pointer (&response, g_free);
+
+ /* Send STARTTLS */
+
+ request = g_strdup_printf ("%s STARTTLS\r\n", IMAP_TAG);
g_debug ("> %s", request);
if (!g_data_output_stream_put_string (output, request, cancellable, error))
goto out;
+ g_clear_pointer (&request, g_free);
- again:
response = g_data_input_stream_read_line (input, NULL, cancellable, error);
if (response == NULL)
goto out;
g_debug ("< %s", response);
- /* ignore untagged responses */
- if (g_str_has_prefix (response, "*"))
- {
- g_free (response);
- goto again;
- }
- if (!g_str_has_prefix (response, "A001 OK"))
- {
- g_set_error (error,
- GOA_ERROR,
- GOA_ERROR_FAILED,
- "Unexpected response `%s' while doing LOGIN authentication",
- response);
- goto out;
- }
+ if (imap_auth_login_check_not_OK (response, TRUE, error))
+ goto out;
+ g_clear_pointer (&response, g_free);
+
+ /* There won't be a greeting after this */
+ auth->greeting_absent = TRUE;
ret = TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]