[evolution-data-server] Prevent busy-loop opening Google calendar configured in GOA



commit 3b7ea118fdbfdde1eccc4a05f3d0389f89badb0c
Author: Milan Crha <mcrha redhat com>
Date:   Tue May 23 08:39:52 2017 +0200

    Prevent busy-loop opening Google calendar configured in GOA
    
    This is semi-new in master.
    
    The change in e-backend.c prevents constant ping-pong with source registry
    when trying multiple times in a row with empty credentials and the backend
    returning 'REQUIRED', which can misbehave with OAuth2 tokens.
    
    The change in e-soup-session.c fixes a new issue in master, which
    caused such busy loops due to requiring non-empty credentials for
    OAuth2 authentication, while it had been needed only for Google
    authentication method.

 src/libebackend/e-backend.c         |   14 ++++++++++++++
 src/libedataserver/e-soup-session.c |   21 ++++++++++++++++++---
 2 files changed, 32 insertions(+), 3 deletions(-)
---
diff --git a/src/libebackend/e-backend.c b/src/libebackend/e-backend.c
index 5c35f50..e6aa435 100644
--- a/src/libebackend/e-backend.c
+++ b/src/libebackend/e-backend.c
@@ -58,6 +58,7 @@ struct _EBackendPrivate {
        GMainContext *main_context;
        GSocketConnectable *connectable;
        gboolean online;
+       gboolean tried_with_empty_credentials;
 
        GNetworkMonitor *network_monitor;
        gulong network_changed_handler_id;
@@ -293,6 +294,7 @@ backend_source_authenticate_thread (gpointer user_data)
        AuthenticateThreadData *thread_data = user_data;
        gchar *certificate_pem = NULL;
        GTlsCertificateFlags certificate_errors = 0;
+       gboolean empty_crendetials;
        GError *local_error = NULL;
        ESource *source;
 
@@ -315,6 +317,17 @@ backend_source_authenticate_thread (gpointer user_data)
        auth_result = e_backend_authenticate_sync (thread_data->backend, thread_data->credentials,
                &certificate_pem, &certificate_errors, thread_data->cancellable, &local_error);
 
+       empty_crendetials = auth_result == E_SOURCE_AUTHENTICATION_REQUIRED &&
+               (!thread_data->credentials || !e_named_parameters_count (thread_data->credentials));
+
+       if (empty_crendetials && thread_data->backend->priv->tried_with_empty_credentials) {
+               /* When tried repeatedly with empty credentials and both resulted in 'REQUIRED',
+                  then change it to 'REJECTED' to avoid loop. */
+               auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
+       }
+
+       thread_data->backend->priv->tried_with_empty_credentials = empty_crendetials;
+
        if (!g_cancellable_is_cancelled (thread_data->cancellable)) {
                ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_ERROR;
 
@@ -731,6 +744,7 @@ e_backend_init (EBackend *backend)
        backend->priv = E_BACKEND_GET_PRIVATE (backend);
        backend->priv->prompter = e_user_prompter_new ();
        backend->priv->main_context = g_main_context_ref_thread_default ();
+       backend->priv->tried_with_empty_credentials = FALSE;
 
        g_mutex_init (&backend->priv->property_lock);
        g_mutex_init (&backend->priv->update_online_state_lock);
diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c
index a790a5b..4da245a 100644
--- a/src/libedataserver/e-soup-session.c
+++ b/src/libedataserver/e-soup-session.c
@@ -115,9 +115,24 @@ e_soup_session_setup_bearer_auth (ESoupSession *session,
        credentials = e_soup_session_dup_credentials (session);
 
        if (!credentials || !e_named_parameters_count (credentials)) {
-               e_named_parameters_free (credentials);
-               g_set_error_literal (error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED, _("Credentials 
required"));
-               return FALSE;
+               /* Google authentication requires prefilled data in 'credentials' */
+               gboolean is_google = FALSE;
+
+               if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
+                       ESourceAuthentication *extension;
+                       gchar *auth_method;
+
+                       extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+                       auth_method = e_source_authentication_dup_method (extension);
+                       is_google = g_strcmp0 (auth_method, "Google") == 0;
+                       g_free (auth_method);
+               }
+
+               if (is_google) {
+                       e_named_parameters_free (credentials);
+                       g_set_error_literal (error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED, _("Credentials 
required"));
+                       return FALSE;
+               }
        }
 
        success = e_util_get_source_oauth2_access_token_sync (source, credentials,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]