[gnome-online-accounts] Implement SMTP AUTH LOGIN extension
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-online-accounts] Implement SMTP AUTH LOGIN extension
- Date: Fri, 20 Dec 2013 12:00:56 +0000 (UTC)
commit 969bad7038ca1979dc9c34f8da8fee28d9c2c334
Author: Debarshi Ray <debarshir gnome org>
Date: Wed Dec 11 17:50:18 2013 +0100
Implement SMTP AUTH LOGIN extension
Fixes: https://bugzilla.gnome.org/720262
src/goabackend/goasmtpauthplain.c | 102 +++++++++++++++++++++++++++++--------
1 files changed, 81 insertions(+), 21 deletions(-)
---
diff --git a/src/goabackend/goasmtpauthplain.c b/src/goabackend/goasmtpauthplain.c
index 77324cf..47ed3b1 100644
--- a/src/goabackend/goasmtpauthplain.c
+++ b/src/goabackend/goasmtpauthplain.c
@@ -34,11 +34,12 @@
/**
* SECTION:goasmtpauthplain
* @title: GoaSmtpAuthPlain
- * @short_description: PLAIN authentication method for SMTP
+ * @short_description: Authentication mechanisms for SMTP
*
* #GoaSmtpAuthPlain implements the <ulink
- * url="http://tools.ietf.org/html/rfc4616">PLAIN</ulink>
- * SASL mechanism (e.g. using usernames / passwords) for SMTP.
+ * url="http://tools.ietf.org/html/rfc4616">PLAIN</ulink> and <ulink
+ * url="http://msdn.microsoft.com/en-us/library/cc433484(v=EXCHG.80).aspx">LOGIN</ulink>
+ * SASL mechanisms (e.g. using usernames / passwords) for SMTP.
*/
/**
@@ -96,7 +97,7 @@ smtp_auth_plain_check_not_220 (const gchar *response, GError **error)
g_set_error (error,
GOA_ERROR,
GOA_ERROR_FAILED, /* TODO: more specific */
- "Unexpected response `%s' while doing PLAIN authentication",
+ "Unexpected response `%s'",
response);
return TRUE;
}
@@ -127,7 +128,23 @@ smtp_auth_plain_check_not_250 (const gchar *response, GError **error)
g_set_error (error,
GOA_ERROR,
GOA_ERROR_FAILED, /* TODO: more specific */
- "Unexpected response `%s' while doing PLAIN authentication",
+ "Unexpected response `%s'",
+ response);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+smtp_auth_plain_check_not_334_login_password (const gchar *response, GError **error)
+{
+ if (!g_str_has_prefix (response, "334 UGFzc3dvcmQ6"))
+ {
+ g_set_error (error,
+ GOA_ERROR,
+ GOA_ERROR_FAILED, /* TODO: more specific */
+ "Unexpected response `%s'",
response);
return TRUE;
}
@@ -246,7 +263,7 @@ smtp_auth_plain_get_domain (GoaSmtpAuthPlain *auth,
g_set_error (error,
GOA_ERROR,
GOA_ERROR_FAILED, /* TODO: more specific */
- _("Cannot do SMTP PLAIN without a domain"));
+ _("Cannot do SMTP authentication without a domain"));
goto out;
}
@@ -276,7 +293,7 @@ smtp_auth_plain_get_password (GoaSmtpAuthPlain *auth,
error);
if (credentials == NULL)
{
- g_prefix_error (error, "Error looking up credentials for SMTP PLAIN in keyring: ");
+ g_prefix_error (error, "Error looking up credentials for SMTP in keyring: ");
goto out;
}
if (!g_variant_lookup (credentials, "smtp-password", "s", &password))
@@ -295,7 +312,7 @@ smtp_auth_plain_get_password (GoaSmtpAuthPlain *auth,
g_set_error (error,
GOA_ERROR,
GOA_ERROR_FAILED, /* TODO: more specific */
- _("Cannot do SMTP PLAIN without a password"));
+ _("Cannot do SMTP authentication without a password"));
goto out;
}
@@ -519,7 +536,7 @@ goa_smtp_auth_plain_class_init (GoaSmtpAuthPlainClass *klass)
* (see the #GoaSmtpAuthPlain:password property).
*
* Creates a new #GoaMailAuth to be used for username/password
- * authentication using PLAIN over SMTP.
+ * authentication using LOGIN or PLAIN over SMTP.
*
* Returns: (type GoaSmtpAuthPlain): A #GoaSmtpAuthPlain. Free with
* g_object_unref().
@@ -562,6 +579,7 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth,
GoaSmtpAuthPlain *auth = GOA_SMTP_AUTH_PLAIN (_auth);
GDataInputStream *input;
GDataOutputStream *output;
+ gboolean login_supported;
gboolean plain_supported;
gboolean ret;
gchar *auth_arg_base64;
@@ -572,6 +590,7 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth,
gchar *response;
gsize auth_arg_plain_len;
+ login_supported = FALSE;
plain_supported = FALSE;
auth_arg_base64 = NULL;
auth_arg_plain = NULL;
@@ -609,7 +628,7 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth,
goto out;
g_clear_pointer (&request, g_free);
- /* Check if PLAIN is supported or not */
+ /* Check which SASL mechanisms are supported */
ehlo_again:
response = g_data_input_stream_read_line (input, NULL, cancellable, error);
@@ -626,6 +645,8 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth,
auth->auth_supported = TRUE;
if (strstr (response, "PLAIN") != NULL)
plain_supported = TRUE;
+ else if (strstr (response, "LOGIN") != NULL)
+ login_supported = TRUE;
}
if (response[3] == '-')
@@ -638,27 +659,66 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth,
ret = TRUE;
goto out;
}
- else if (!plain_supported)
+ else if (!login_supported && !plain_supported)
{
g_set_error (error,
GOA_ERROR,
GOA_ERROR_NOT_SUPPORTED,
- _("Server does not support PLAIN"));
+ _("Unknown authentication mechanism"));
goto out;
}
g_clear_pointer (&response, g_free);
- /* Send AUTH PLAIN */
+ /* Try different SASL mechanisms */
- auth_arg_plain = g_strdup_printf ("%s%c%s%c%s", auth->username, '\0', auth->username, '\0', password);
- auth_arg_plain_len = 2 * strlen (auth->username) + 2 + strlen (password);
- auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len);
+ if (plain_supported)
+ {
+ /* AUTH PLAIN */
- request = g_strdup_printf ("AUTH PLAIN %s\r\n", auth_arg_base64);
- g_debug ("> AUTH PLAIN ********************");
- if (!g_data_output_stream_put_string (output, request, cancellable, error))
- goto out;
- g_clear_pointer (&request, g_free);
+ auth_arg_plain = g_strdup_printf ("%s%c%s%c%s", auth->username, '\0', auth->username, '\0', password);
+ auth_arg_plain_len = 2 * strlen (auth->username) + 2 + strlen (password);
+ auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len);
+
+ request = g_strdup_printf ("AUTH PLAIN %s\r\n", auth_arg_base64);
+ g_debug ("> AUTH PLAIN ********************");
+ if (!g_data_output_stream_put_string (output, request, cancellable, error))
+ goto out;
+ g_clear_pointer (&request, g_free);
+ }
+ else
+ {
+ /* AUTH LOGIN */
+
+ auth_arg_plain = g_strdup (auth->username);
+ auth_arg_plain_len = strlen (auth->username);
+ auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len);
+
+ request = g_strdup_printf ("AUTH LOGIN %s\r\n", auth_arg_base64);
+ g_debug ("> AUTH LOGIN ********************");
+ if (!g_data_output_stream_put_string (output, request, cancellable, error))
+ goto out;
+ g_clear_pointer (&request, g_free);
+
+ response = g_data_input_stream_read_line (input, NULL, cancellable, error);
+ if (response == NULL)
+ goto out;
+ g_debug ("< %s", response);
+ if (smtp_auth_plain_check_not_334_login_password (response, error))
+ goto out;
+
+ g_free (auth_arg_plain);
+ g_free (auth_arg_base64);
+
+ auth_arg_plain = g_strdup (password);
+ auth_arg_plain_len = strlen (password);
+ auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len);
+
+ request = g_strdup_printf ("%s\r\n", auth_arg_base64);
+ g_debug ("> ********************");
+ if (!g_data_output_stream_put_string (output, request, cancellable, error))
+ goto out;
+ g_clear_pointer (&request, g_free);
+ }
response = g_data_input_stream_read_line (input, NULL, cancellable, error);
if (response == NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]