[evolution-data-server] imap: Adapt to Camel's new authentication API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] imap: Adapt to Camel's new authentication API.
- Date: Sat, 15 Oct 2011 14:59:38 +0000 (UTC)
commit ed5e4c6f4d9b148128f0043b997cdfadd65b670d
Author: Matthew Barnes <mbarnes redhat com>
Date: Sat Oct 15 09:50:06 2011 -0400
imap: Adapt to Camel's new authentication API.
camel/providers/imap/camel-imap-store.c | 347 +++++++++++++------------------
1 files changed, 149 insertions(+), 198 deletions(-)
---
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 7838b1c..5deabf8 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -607,86 +607,19 @@ connect_to_server_wrapper (CamelService *service,
}
static gboolean
-try_auth (CamelImapStore *store,
- CamelSasl *sasl,
- GCancellable *cancellable,
- GError **error)
-{
- CamelService *service;
- CamelImapResponse *response;
- CamelURL *url;
- gchar *resp;
- gchar *sasl_resp;
-
- service = CAMEL_SERVICE (store);
- url = camel_service_get_camel_url (service);
-
- response = camel_imap_command (
- store, NULL, cancellable, error,
- "AUTHENTICATE %s", url->authmech);
- if (!response) {
- g_object_unref (sasl);
- return FALSE;
- }
-
- while (!camel_sasl_get_authenticated (sasl)) {
- resp = camel_imap_response_extract_continuation (store, response, error);
- if (!resp)
- goto lose;
-
- sasl_resp = camel_sasl_challenge_base64_sync (
- sasl, imap_next_word (resp), cancellable, error);
- g_free (resp);
- if (!sasl_resp)
- goto break_and_lose;
-
- response = camel_imap_command_continuation (store, sasl_resp, strlen (sasl_resp), cancellable, error);
- g_free (sasl_resp);
- if (!response)
- goto lose;
- }
-
- resp = camel_imap_response_extract_continuation (store, response, NULL);
- if (resp) {
- /* Oops. SASL claims we're done, but the IMAP server
- * doesn't think so...
- */
- g_free (resp);
- goto lose;
- }
-
- g_object_unref (sasl);
-
- return TRUE;
-
- break_and_lose:
- /* Get the server out of "waiting for continuation data" mode. */
- response = camel_imap_command_continuation (store, "*", 1, cancellable, NULL);
- if (response)
- camel_imap_response_free (store, response);
-
- lose:
- g_object_unref (sasl);
-
- return FALSE;
-}
-
-static gboolean
imap_auth_loop (CamelService *service,
GCancellable *cancellable,
GError **error)
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelSession *session = camel_service_get_session (service);
- CamelServiceAuthType *authtype = NULL;
- CamelImapResponse *response;
- CamelSasl *sasl = NULL;
+ CamelSession *session;
CamelURL *url;
- gchar *errbuf = NULL;
- gboolean authenticated = FALSE;
- guint32 prompt_flags = CAMEL_SESSION_PASSWORD_SECRET;
+ const gchar *mechanism;
+
+ session = camel_service_get_session (service);
url = camel_service_get_camel_url (service);
+ mechanism = url->authmech;
if (store->preauthed) {
if (camel_verbose_debug)
@@ -695,139 +628,19 @@ imap_auth_loop (CamelService *service,
return TRUE;
}
- if (url->authmech) {
- if (!g_hash_table_lookup (store->authtypes, url->authmech)) {
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- _("IMAP server %s does not support requested "
- "authentication type %s"),
- url->host, url->authmech);
- return FALSE;
- }
-
- authtype = camel_sasl_authtype (url->authmech);
- if (!authtype) {
+ if (mechanism != NULL) {
+ if (!g_hash_table_lookup (store->authtypes, mechanism)) {
g_set_error (
error, CAMEL_SERVICE_ERROR,
CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- _("No support for authentication type %s"),
- url->authmech);
- return FALSE;
- }
-
- sasl = camel_sasl_new (
- "imap", url->authmech, service);
- if (!sasl) {
- nosasl:
- g_set_error (
- error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
- _("Error creating SASL authentication object."));
+ _("IMAP server %s does not support %s "
+ "authentication"), url->host, mechanism);
return FALSE;
}
-
- if (!authtype->need_password ||
- camel_sasl_try_empty_password_sync (sasl, cancellable, error)) {
- authenticated = try_auth (store, sasl, cancellable, error);
- if (!authenticated && !authtype->need_password)
- return FALSE;
- sasl = NULL;
- }
- }
-
- while (!authenticated) {
- const gchar *password;
- GError *local_error = NULL;
-
- if (errbuf) {
- /* We need to un-cache the password before prompting again */
- prompt_flags |= CAMEL_SESSION_PASSWORD_REPROMPT;
- camel_service_set_password (service, NULL);
- }
-
- password = camel_service_get_password (service);
-
- if (password == NULL) {
- gchar *base_prompt;
- gchar *full_prompt;
- gchar *new_passwd;
-
- base_prompt = camel_session_build_password_prompt (
- "IMAP", url->user, url->host);
-
- if (errbuf != NULL)
- full_prompt = g_strconcat (errbuf, base_prompt, NULL);
- else
- full_prompt = g_strdup (base_prompt);
-
- /* XXX This is a tad awkward. Maybe define a
- * camel_service_ask_password() that calls
- * camel_session_get_password() and caches
- * the password itself? */
- new_passwd = camel_session_get_password (
- session, service, full_prompt,
- "password", prompt_flags, error);
- camel_service_set_password (service, new_passwd);
- password = camel_service_get_password (service);
- g_free (new_passwd);
-
- g_free (base_prompt);
- g_free (full_prompt);
- g_free (errbuf);
- errbuf = NULL;
-
- if (password == NULL) {
- g_set_error (
- error, G_IO_ERROR,
- G_IO_ERROR_CANCELLED,
- _("You did not enter a password."));
- if (sasl)
- g_object_unref (sasl);
- return FALSE;
- }
- }
-
- if (!store->connected) {
- /* Some servers (eg, courier) will disconnect on
- * a bad password. So reconnect here. */
- if (!connect_to_server_wrapper (
- service, cancellable, error))
- return FALSE;
- }
-
- if (authtype) {
- if (!sasl)
- sasl = camel_sasl_new (
- "imap", url->authmech, service);
- if (!sasl)
- goto nosasl;
- authenticated = try_auth (store, sasl, cancellable,
- &local_error);
- sasl = NULL;
- } else {
- response = camel_imap_command (
- store, NULL, cancellable, &local_error,
- "LOGIN %S %S", url->user, password);
- if (response) {
- camel_imap_response_free (store, response);
- authenticated = TRUE;
- }
- }
- if (local_error != NULL) {
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
- g_error_matches (local_error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE)) {
- g_propagate_error (error, local_error);
- return FALSE;
- }
-
- errbuf = g_markup_printf_escaped (
- _("Unable to authenticate to IMAP server.\n%s\n\n"),
- local_error->message);
- g_clear_error (&local_error);
- }
}
- return TRUE;
+ return camel_session_authenticate_sync (
+ session, service, mechanism, cancellable, error);
}
static gboolean
@@ -1142,6 +955,143 @@ imap_store_disconnect_sync (CamelService *service,
return TRUE;
}
+static CamelAuthenticationResult
+imap_store_authenticate_sync (CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelImapStore *store = CAMEL_IMAP_STORE (service);
+ CamelAuthenticationResult result;
+ CamelImapResponse *response;
+ CamelSasl *sasl = NULL;
+ gchar *sasl_resp;
+ gchar *resp;
+ GError *local_error = NULL;
+
+ /* If not using SASL, do a simple LOGIN here. */
+ if (mechanism == NULL) {
+ CamelURL *url;
+ const gchar *password;
+
+ url = camel_service_get_camel_url (service);
+ password = camel_service_get_password (service);
+
+ if (url->user == NULL) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("Cannot authenticate without a username"));
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ if (password == NULL) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("Authentication password not available"));
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ response = camel_imap_command (
+ store, NULL, cancellable, &local_error,
+ "LOGIN %S %S", url->user, password);
+
+ if (response != NULL)
+ camel_imap_response_free (store, response);
+
+ goto exit;
+ }
+
+ /* Henceforth we're using SASL. */
+
+ sasl = camel_sasl_new ("imap", mechanism, service);
+ if (sasl == NULL) {
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("No support for %s authentication"), mechanism);
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ response = camel_imap_command (
+ store, NULL, cancellable, &local_error,
+ "AUTHENTICATE %s", mechanism);
+ if (response == NULL)
+ goto exit;
+
+ while (!camel_sasl_get_authenticated (sasl)) {
+ resp = camel_imap_response_extract_continuation (
+ store, response, &local_error);
+
+ if (resp == NULL)
+ goto exit;
+
+ sasl_resp = camel_sasl_challenge_base64_sync (
+ sasl, imap_next_word (resp),
+ cancellable, &local_error);
+
+ g_free (resp);
+
+ if (sasl_resp == NULL)
+ goto break_and_exit;
+
+ response = camel_imap_command_continuation (
+ store, sasl_resp, strlen (sasl_resp),
+ cancellable, &local_error);
+
+ g_free (sasl_resp);
+
+ if (response == NULL)
+ goto exit;
+ }
+
+ resp = camel_imap_response_extract_continuation (store, response, NULL);
+ if (resp != NULL) {
+ /* Oops. SASL claims we're done, but the IMAP server
+ * doesn't think so... */
+ g_free (resp);
+ goto exit;
+ }
+
+ goto exit;
+
+break_and_exit:
+ /* Get the server out of "waiting for continuation data" mode. */
+ response = camel_imap_command_continuation (
+ store, "*", 1, cancellable, NULL);
+ if (response != NULL)
+ camel_imap_response_free (store, response);
+
+exit:
+ /* XXX Apparently the IMAP parser sets CAMEL_SERVICE_ERROR_INVALID
+ * for failed IMAP server responses, so I guess check for that
+ * to know if our authentication credentials were rejected. */
+ if (local_error == NULL) {
+ result = CAMEL_AUTHENTICATION_ACCEPTED;
+ } else if (g_error_matches (local_error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_INVALID)) {
+ g_clear_error (&local_error);
+ result = CAMEL_AUTHENTICATION_REJECTED;
+
+ /* Some servers (eg, courier) will disconnect
+ * on a bad password, so we reconnect here. */
+ if (!store->connected) {
+ if (!connect_to_server_wrapper (
+ service, cancellable, error))
+ result = CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ } else {
+ g_propagate_error (error, local_error);
+ result = CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ if (sasl != NULL)
+ g_object_unref (sasl);
+
+ return result;
+}
+
static GList *
imap_store_query_auth_types_sync (CamelService *service,
GCancellable *cancellable,
@@ -1465,6 +1415,7 @@ camel_imap_store_class_init (CamelImapStoreClass *class)
service_class->get_name = imap_store_get_name;
service_class->connect_sync = imap_store_connect_sync;
service_class->disconnect_sync = imap_store_disconnect_sync;
+ service_class->authenticate_sync = imap_store_authenticate_sync;
service_class->query_auth_types_sync = imap_store_query_auth_types_sync;
store_class = CAMEL_STORE_CLASS (class);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]