[evolution-data-server] [CalDAV/CardDAV] Check for TLS/authentication errors on refresh



commit c823d109bc9b0364464e031011a42ec3e6bdc274
Author: Milan Crha <mcrha redhat com>
Date:   Mon Aug 28 19:30:29 2017 +0200

    [CalDAV/CardDAV] Check for TLS/authentication errors on refresh
    
    By checking for the TLS/authentication errors in refresh function
    the connected backend can recover when a password expires or
    when the server changes its connection certificate.

 .../backends/webdav/e-book-backend-webdav.c        |   59 ++++++++++++++++----
 .../backends/caldav/e-cal-backend-caldav.c         |   59 ++++++++++++++++----
 2 files changed, 94 insertions(+), 24 deletions(-)
---
diff --git a/src/addressbook/backends/webdav/e-book-backend-webdav.c 
b/src/addressbook/backends/webdav/e-book-backend-webdav.c
index 79593f2..b4a16fa 100644
--- a/src/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/src/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -554,6 +554,7 @@ ebb_webdav_get_changes_sync (EBookMetaBackend *meta_backend,
        GHashTableIter iter;
        gpointer key = NULL, value = NULL;
        gboolean success;
+       GError *local_error = NULL;
 
        g_return_val_if_fail (E_IS_BOOK_BACKEND_WEBDAV (meta_backend), FALSE);
        g_return_val_if_fail (out_new_sync_tag, FALSE);
@@ -594,7 +595,7 @@ ebb_webdav_get_changes_sync (EBookMetaBackend *meta_backend,
        known_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, e_book_meta_backend_info_free);
 
        success = e_webdav_session_propfind_sync (bbdav->priv->webdav, NULL, 
E_WEBDAV_DEPTH_THIS_AND_CHILDREN, xml,
-               ebb_webdav_get_contact_items_cb, known_items, cancellable, error);
+               ebb_webdav_get_contact_items_cb, known_items, cancellable, &local_error);
 
        g_object_unref (xml);
 
@@ -608,24 +609,21 @@ ebb_webdav_get_changes_sync (EBookMetaBackend *meta_backend,
 
                book_cache = e_book_meta_backend_ref_cache (meta_backend);
 
-               success = e_book_cache_search_with_callback (book_cache, NULL, ebb_webdav_search_changes_cb, 
&ccd, cancellable, error);
+               success = e_book_cache_search_with_callback (book_cache, NULL, ebb_webdav_search_changes_cb, 
&ccd, cancellable, &local_error);
 
                g_clear_object (&book_cache);
        }
 
-       if (!success) {
-               g_hash_table_destroy (known_items);
-               return FALSE;
-       }
-
-       g_hash_table_iter_init (&iter, known_items);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               *out_created_objects = g_slist_prepend (*out_created_objects, e_book_meta_backend_info_copy 
(value));
+       if (success) {
+               g_hash_table_iter_init (&iter, known_items);
+               while (g_hash_table_iter_next (&iter, &key, &value)) {
+                       *out_created_objects = g_slist_prepend (*out_created_objects, 
e_book_meta_backend_info_copy (value));
+               }
        }
 
        g_hash_table_destroy (known_items);
 
-       if (*out_created_objects || *out_modified_objects) {
+       if (success && (*out_created_objects || *out_modified_objects)) {
                GSList *link, *set2 = *out_modified_objects;
 
                if (*out_created_objects) {
@@ -636,10 +634,47 @@ ebb_webdav_get_changes_sync (EBookMetaBackend *meta_backend,
                }
 
                do {
-                       success = ebb_webdav_multiget_from_sets_sync (bbdav, &link, &set2, cancellable, 
error);
+                       success = ebb_webdav_multiget_from_sets_sync (bbdav, &link, &set2, cancellable, 
&local_error);
                } while (success && link);
        }
 
+       if (local_error && !g_cancellable_is_cancelled (cancellable)) {
+               ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_UNKNOWN;
+
+               if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+                       reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
+               } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
+                          g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN)) {
+                       reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
+               }
+
+               if (reason != E_SOURCE_CREDENTIALS_REASON_UNKNOWN) {
+                       GTlsCertificateFlags certificate_errors = 0;
+                       gchar *certificate_pem = NULL;
+                       GError *local_error2 = NULL;
+
+                       if (!e_soup_session_get_ssl_error_details (E_SOUP_SESSION (bbdav->priv->webdav), 
&certificate_pem, &certificate_errors)) {
+                               certificate_pem = NULL;
+                               certificate_errors = 0;
+                       }
+
+                       if (!e_backend_credentials_required_sync (E_BACKEND (bbdav), reason, certificate_pem, 
certificate_errors,
+                               local_error, cancellable, &local_error2)) {
+                               g_warning ("%s: Failed to call credentials required: %s", G_STRFUNC, 
local_error2 ? local_error2->message : "Unknown error");
+                       } else {
+                               /* Ignore the error when the caller had been notified through the 
credentials-required */
+                               g_clear_error (&local_error);
+                               success = TRUE;
+                       }
+
+                       g_clear_error (&local_error2);
+                       g_free (certificate_pem);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
        return success;
 }
 
diff --git a/src/calendar/backends/caldav/e-cal-backend-caldav.c 
b/src/calendar/backends/caldav/e-cal-backend-caldav.c
index 0421143..94a0984 100644
--- a/src/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/src/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -589,6 +589,7 @@ ecb_caldav_get_changes_sync (ECalMetaBackend *meta_backend,
        GHashTableIter iter;
        gpointer key = NULL, value = NULL;
        gboolean success;
+       GError *local_error = NULL;
 
        g_return_val_if_fail (E_IS_CAL_BACKEND_CALDAV (meta_backend), FALSE);
        g_return_val_if_fail (out_repeat, FALSE);
@@ -683,7 +684,7 @@ ecb_caldav_get_changes_sync (ECalMetaBackend *meta_backend,
        known_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, e_cal_meta_backend_info_free);
 
        success = e_webdav_session_report_sync (cbdav->priv->webdav, NULL, E_WEBDAV_DEPTH_THIS_AND_CHILDREN, 
xml,
-               ecb_caldav_get_calendar_items_cb, known_items, NULL, NULL, cancellable, error);
+               ecb_caldav_get_calendar_items_cb, known_items, NULL, NULL, cancellable, &local_error);
 
        g_object_unref (xml);
 
@@ -698,24 +699,21 @@ ecb_caldav_get_changes_sync (ECalMetaBackend *meta_backend,
 
                cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
 
-               success = e_cal_cache_search_with_callback (cal_cache, NULL, ecb_caldav_search_changes_cb, 
&ccd, cancellable, error);
+               success = e_cal_cache_search_with_callback (cal_cache, NULL, ecb_caldav_search_changes_cb, 
&ccd, cancellable, &local_error);
 
                g_clear_object (&cal_cache);
        }
 
-       if (!success) {
-               g_hash_table_destroy (known_items);
-               return FALSE;
-       }
-
-       g_hash_table_iter_init (&iter, known_items);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               *out_created_objects = g_slist_prepend (*out_created_objects, e_cal_meta_backend_info_copy 
(value));
+       if (success) {
+               g_hash_table_iter_init (&iter, known_items);
+               while (g_hash_table_iter_next (&iter, &key, &value)) {
+                       *out_created_objects = g_slist_prepend (*out_created_objects, 
e_cal_meta_backend_info_copy (value));
+               }
        }
 
        g_hash_table_destroy (known_items);
 
-       if (*out_created_objects || *out_modified_objects) {
+       if (success && (*out_created_objects || *out_modified_objects)) {
                GSList *link, *set2 = *out_modified_objects;
 
                if (*out_created_objects) {
@@ -726,10 +724,47 @@ ecb_caldav_get_changes_sync (ECalMetaBackend *meta_backend,
                }
 
                do {
-                       success = ecb_caldav_multiget_from_sets_sync (cbdav, &link, &set2, cancellable, 
error);
+                       success = ecb_caldav_multiget_from_sets_sync (cbdav, &link, &set2, cancellable, 
&local_error);
                } while (success && link);
        }
 
+       if (local_error && !g_cancellable_is_cancelled (cancellable)) {
+               ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_UNKNOWN;
+
+               if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+                       reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
+               } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
+                          g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN)) {
+                       reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
+               }
+
+               if (reason != E_SOURCE_CREDENTIALS_REASON_UNKNOWN) {
+                       GTlsCertificateFlags certificate_errors = 0;
+                       gchar *certificate_pem = NULL;
+                       GError *local_error2 = NULL;
+
+                       if (!e_soup_session_get_ssl_error_details (E_SOUP_SESSION (cbdav->priv->webdav), 
&certificate_pem, &certificate_errors)) {
+                               certificate_pem = NULL;
+                               certificate_errors = 0;
+                       }
+
+                       if (!e_backend_credentials_required_sync (E_BACKEND (cbdav), reason, certificate_pem, 
certificate_errors,
+                               local_error, cancellable, &local_error2)) {
+                               g_warning ("%s: Failed to call credentials required: %s", G_STRFUNC, 
local_error2 ? local_error2->message : "Unknown error");
+                       } else {
+                               /* Ignore the error when the caller had been notified through the 
credentials-required */
+                               g_clear_error (&local_error);
+                               success = TRUE;
+                       }
+
+                       g_clear_error (&local_error2);
+                       g_free (certificate_pem);
+               }
+       }
+
+       if (local_error)
+               g_propagate_error (error, local_error);
+
        return success;
 }
 


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