[evolution-data-server] I#168 - Camel: Can fail to connect when password contains non-ASCII letters
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] I#168 - Camel: Can fail to connect when password contains non-ASCII letters
- Date: Fri, 7 Feb 2020 07:52:37 +0000 (UTC)
commit 3b59c0c3fd990c14a265e18d570eda1d99744442
Author: Milan Crha <mcrha redhat com>
Date: Fri Feb 7 08:54:06 2020 +0100
I#168 - Camel: Can fail to connect when password contains non-ASCII letters
Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/168
src/camel/providers/imapx/camel-imapx-command.c | 9 +++-
src/camel/providers/imapx/camel-imapx-server.c | 47 +++++++++++++++++++-
src/camel/providers/smtp/camel-smtp-transport.c | 57 ++++++++++++++++++++++++-
3 files changed, 108 insertions(+), 5 deletions(-)
---
diff --git a/src/camel/providers/imapx/camel-imapx-command.c b/src/camel/providers/imapx/camel-imapx-command.c
index acd2b1084..90beaf70b 100644
--- a/src/camel/providers/imapx/camel-imapx-command.c
+++ b/src/camel/providers/imapx/camel-imapx-command.c
@@ -199,6 +199,7 @@ camel_imapx_command_addv (CamelIMAPXCommand *ic,
gchar *utf7_name = NULL;
const gchar *name;
gboolean use_utf8_string = FALSE;
+ guchar force_str_mask = 0;
g_return_if_fail (CAMEL_IS_IMAPX_COMMAND (ic));
@@ -264,13 +265,19 @@ camel_imapx_command_addv (CamelIMAPXCommand *ic,
s = va_arg (ap, gchar *);
g_string_append (buffer, s);
break;
+ case 'S': /* escaped and quoted string */
+ s = va_arg (ap, gchar *);
+ use_utf8_string = FALSE;
+ force_str_mask = IMAPX_TYPE_TEXT_CHAR;
+ c (camel_imapx_server_get_tagprefix (ic->is), "got string '%s'\n",
g_str_has_prefix (format, "LOGIN") ? "***" : s);
+ goto output_string;
case 's': /* simple string */
s = va_arg (ap, gchar *);
use_utf8_string = FALSE;
c (camel_imapx_server_get_tagprefix (ic->is), "got string '%s'\n",
g_str_has_prefix (format, "LOGIN") ? "***" : s);
output_string:
if (s && *s) {
- guchar mask = imapx_is_mask (s);
+ guchar mask = force_str_mask ? force_str_mask : imapx_is_mask (s);
if (use_utf8_string && !(mask & IMAPX_TYPE_ATOM_CHAR)) {
g_string_append_c (buffer, '"');
diff --git a/src/camel/providers/imapx/camel-imapx-server.c b/src/camel/providers/imapx/camel-imapx-server.c
index cf341a917..3c38fb1e9 100644
--- a/src/camel/providers/imapx/camel-imapx-server.c
+++ b/src/camel/providers/imapx/camel-imapx-server.c
@@ -3140,6 +3140,25 @@ camel_imapx_server_is_connected (CamelIMAPXServer *imapx_server)
return imapx_server->priv->state >= IMAPX_CONNECTED;
}
+static gboolean
+imapx_password_contains_nonascii (CamelService *service)
+{
+ const gchar *password;
+
+ g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
+
+ password = camel_service_get_password (service);
+
+ while (password && *password) {
+ if (*password < 0)
+ return TRUE;
+
+ password++;
+ }
+
+ return FALSE;
+}
+
CamelAuthenticationResult
camel_imapx_server_authenticate_sync (CamelIMAPXServer *is,
const gchar *mechanism,
@@ -3155,6 +3174,8 @@ camel_imapx_server_authenticate_sync (CamelIMAPXServer *is,
CamelSasl *sasl = NULL;
gchar *host;
gchar *user;
+ gboolean can_retry_login = FALSE;
+ gboolean success;
g_return_val_if_fail (
CAMEL_IS_IMAPX_SERVER (is),
@@ -3235,10 +3256,32 @@ camel_imapx_server_authenticate_sync (CamelIMAPXServer *is,
}
ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_LOGIN, "LOGIN %s %s", user, password);
+
+ can_retry_login = TRUE;
+ }
+
+ success = camel_imapx_server_process_command_sync (is, ic, _("Failed to authenticate"), cancellable,
error);
+ if (!success && can_retry_login && imapx_password_contains_nonascii (service)) {
+ const gchar *password;
+ gchar *password_latin1;
+
+ can_retry_login = -1;
+
+ password = camel_service_get_password (service);
+ password_latin1 = g_convert_with_fallback (password, -1, "ISO-8859-1", "UTF-8", "", NULL,
NULL, NULL);
+
+ if (password_latin1 && g_strcmp0 (password, password_latin1) != 0) {
+ camel_imapx_command_unref (ic);
+ ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_LOGIN, "LOGIN %S %S", user,
password_latin1);
+ g_free (password_latin1);
+
+ success = camel_imapx_server_process_command_sync (is, ic, _("Failed to
authenticate"), cancellable, NULL);
+ } else {
+ g_free (password_latin1);
+ }
}
- if (!camel_imapx_server_process_command_sync (is, ic, _("Failed to authenticate"), cancellable,
error) && (
- !ic->status || ic->status->result != IMAPX_NO))
+ if (!success && (!ic->status || ic->status->result != IMAPX_NO))
result = CAMEL_AUTHENTICATION_ERROR;
else if (ic->status->result == IMAPX_OK)
result = CAMEL_AUTHENTICATION_ACCEPTED;
diff --git a/src/camel/providers/smtp/camel-smtp-transport.c b/src/camel/providers/smtp/camel-smtp-transport.c
index b459b14fa..035baf367 100644
--- a/src/camel/providers/smtp/camel-smtp-transport.c
+++ b/src/camel/providers/smtp/camel-smtp-transport.c
@@ -643,6 +643,25 @@ smtp_transport_disconnect_sync (CamelService *service,
return TRUE;
}
+static gboolean
+smtp_password_contains_nonascii (CamelService *service)
+{
+ const gchar *password;
+
+ g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
+
+ password = camel_service_get_password (service);
+
+ while (password && *password) {
+ if (*password < 0)
+ return TRUE;
+
+ password++;
+ }
+
+ return FALSE;
+}
+
static CamelAuthenticationResult
smtp_transport_authenticate_sync (CamelService *service,
const gchar *mechanism,
@@ -654,8 +673,8 @@ smtp_transport_authenticate_sync (CamelService *service,
CamelSasl *sasl;
CamelStreamBuffer *istream;
CamelStream *ostream;
- gchar *cmdbuf, *respbuf = NULL, *challenge;
- gboolean auth_challenge = FALSE;
+ gchar *cmdbuf, *respbuf = NULL, *challenge, *restore_password = NULL;
+ gboolean auth_challenge = FALSE, can_try_again = TRUE;
GError *local_error = NULL;
if (mechanism == NULL) {
@@ -666,6 +685,7 @@ smtp_transport_authenticate_sync (CamelService *service,
return CAMEL_AUTHENTICATION_ERROR;
}
+ try_again:
sasl = camel_sasl_new ("smtp", mechanism, service);
if (sasl == NULL) {
g_set_error (
@@ -796,6 +816,34 @@ smtp_transport_authenticate_sync (CamelService *service,
respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
}
+
+ if (can_try_again) {
+ can_try_again = FALSE;
+
+ if (smtp_password_contains_nonascii (service)) {
+ const gchar *password;
+ gchar *password_latin1;
+
+ password = camel_service_get_password (service);
+ password_latin1 = g_convert_with_fallback (password, -1, "ISO-8859-1",
"UTF-8", "", NULL, NULL, NULL);
+
+ if (password_latin1 && g_strcmp0 (password, password_latin1) != 0) {
+ restore_password = g_strdup (password);
+
+ camel_service_set_password (service, password_latin1);
+
+ g_clear_object (&istream);
+ g_clear_object (&ostream);
+ g_object_unref (sasl);
+ g_free (password_latin1);
+ g_free (respbuf);
+
+ goto try_again;
+ } else {
+ g_free (password_latin1);
+ }
+ }
+ }
} else if (strncmp (respbuf, "235", 3) == 0)
result = CAMEL_AUTHENTICATION_ACCEPTED;
/* Catch any other errors. */
@@ -820,6 +868,11 @@ lose:
result = CAMEL_AUTHENTICATION_ERROR;
exit:
+ if (restore_password) {
+ camel_service_set_password (service, restore_password);
+ g_free (restore_password);
+ }
+
g_clear_object (&istream);
g_clear_object (&ostream);
g_object_unref (sasl);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]