diff -up evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.cve-2019-3890 evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c --- evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c.cve-2019-3890 2019-04-15 09:43:49.672771516 +0200 +++ evolution-ews-3.28.5/src/addressbook/e-book-backend-ews.c 2019-04-15 09:43:49.683771516 +0200 @@ -2901,7 +2901,8 @@ ebb_ews_connect_sync (EBookMetaBackend * bbews->priv->cnc, "proxy-resolver", G_BINDING_SYNC_CREATE); - *out_auth_result = e_ews_connection_try_credentials_sync (bbews->priv->cnc, credentials, cancellable, error); + *out_auth_result = e_ews_connection_try_credentials_sync (bbews->priv->cnc, credentials, NULL, + out_certificate_pem, out_certificate_errors, cancellable, error); if (*out_auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) { ESource *source = e_backend_get_source (E_BACKEND (bbews)); diff -up evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.cve-2019-3890 evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c --- evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c.cve-2019-3890 2019-04-15 09:43:49.676771516 +0200 +++ evolution-ews-3.28.5/src/calendar/e-cal-backend-ews.c 2019-04-15 09:43:49.684771516 +0200 @@ -1394,7 +1394,8 @@ ecb_ews_connect_sync (ECalMetaBackend *m cbews->priv->cnc, "proxy-resolver", G_BINDING_SYNC_CREATE); - *out_auth_result = e_ews_connection_try_credentials_sync (cbews->priv->cnc, credentials, cancellable, error); + *out_auth_result = e_ews_connection_try_credentials_sync (cbews->priv->cnc, credentials, NULL, + out_certificate_pem, out_certificate_errors, cancellable, error); if (*out_auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) { ESource *source = e_backend_get_source (E_BACKEND (cbews)); diff -up evolution-ews-3.28.5/src/camel/camel-ews-store.c.cve-2019-3890 evolution-ews-3.28.5/src/camel/camel-ews-store.c --- evolution-ews-3.28.5/src/camel/camel-ews-store.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/camel/camel-ews-store.c 2019-04-15 09:43:49.684771516 +0200 @@ -1831,6 +1831,8 @@ ews_authenticate_sync (CamelService *ser const gchar *password; gchar *hosturl; gchar *old_sync_state = NULL, *new_sync_state = NULL; + gchar *certificate_pem = NULL; + GTlsCertificateFlags certificate_errors = 0; GError *local_error = NULL; ews_store = CAMEL_EWS_STORE (service); @@ -1959,6 +1961,18 @@ ews_authenticate_sync (CamelService *ser g_slist_free_full (created_folder_ids, g_free); + if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) && + e_ews_connection_get_ssl_error_details (connection, &certificate_pem, &certificate_errors)) { + source = e_ews_connection_get_source (connection); + + if (source) { + e_source_emit_credentials_required (source, E_SOURCE_CREDENTIALS_REASON_SSL_FAILED, + certificate_pem, certificate_errors, local_error); + } + + g_free (certificate_pem); + } + if (local_error == NULL) { result = CAMEL_AUTHENTICATION_ACCEPTED; } else if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED)) { diff -up evolution-ews-3.28.5/src/collection/e-ews-backend.c.cve-2019-3890 evolution-ews-3.28.5/src/collection/e-ews-backend.c --- evolution-ews-3.28.5/src/collection/e-ews-backend.c.cve-2019-3890 2019-04-15 09:43:49.679771516 +0200 +++ evolution-ews-3.28.5/src/collection/e-ews-backend.c 2019-04-15 09:43:49.685771516 +0200 @@ -727,6 +727,15 @@ ews_backend_constructed (GObject *object /* Reset the connectable, it steals data from Authentication extension, where is written incorrect address */ e_backend_set_connectable (backend, NULL); + + /* Eventually unset temporary SSL trust, but only once, when the process started. + It might bee too often anywhere lease (like in the authenticate callback) */ + if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND)) { + ESourceWebdav *webdav_extension; + + webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); + e_source_webdav_unset_temporary_ssl_trust (webdav_extension); + } } static void @@ -930,7 +939,7 @@ ews_backend_create_resource_sync (EColle } if (!success) { - connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, cancellable, error); + connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, NULL, NULL, cancellable, error); if (connection == NULL) return FALSE; @@ -1037,7 +1046,7 @@ ews_backend_delete_resource_sync (EColle const gchar *extension_name; gboolean success = FALSE; - connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, cancellable, error); + connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (backend), NULL, NULL, NULL, cancellable, error); if (connection == NULL) return FALSE; @@ -1142,7 +1151,7 @@ ews_backend_authenticate_sync (EBackend ews_backend->priv->credentials = e_named_parameters_new_clone (credentials); g_mutex_unlock (&ews_backend->priv->connection_lock); - connection = e_ews_backend_ref_connection_sync (ews_backend, &result, cancellable, error); + connection = e_ews_backend_ref_connection_sync (ews_backend, &result, out_certificate_pem, out_certificate_errors, cancellable, error); g_clear_object (&connection); if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) { @@ -1223,7 +1232,7 @@ ews_backend_ref_connection_thread (GSimp EEwsConnection *connection; GError *error = NULL; - connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (object), NULL, cancellable, &error); + connection = e_ews_backend_ref_connection_sync (E_EWS_BACKEND (object), NULL, NULL, NULL, cancellable, &error); /* Sanity check. */ g_return_if_fail ( @@ -1241,6 +1250,8 @@ ews_backend_ref_connection_thread (GSimp EEwsConnection * e_ews_backend_ref_connection_sync (EEwsBackend *backend, ESourceAuthenticationResult *result, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error) { @@ -1272,7 +1283,8 @@ e_ews_backend_ref_connection_sync (EEwsB connection, "proxy-resolver", G_BINDING_SYNC_CREATE); - local_result = e_ews_connection_try_credentials_sync (connection, backend->priv->credentials, cancellable, error); + local_result = e_ews_connection_try_credentials_sync (connection, backend->priv->credentials, NULL, + out_certificate_pem, out_certificate_errors, cancellable, error); if (result) *result = local_result; @@ -1413,7 +1425,7 @@ e_ews_backend_sync_folders_sync (EEwsBac return TRUE; } - connection = e_ews_backend_ref_connection_sync (backend, NULL, cancellable, error); + connection = e_ews_backend_ref_connection_sync (backend, NULL, NULL, NULL, cancellable, error); if (connection == NULL) { backend->priv->need_update_folders = TRUE; diff -up evolution-ews-3.28.5/src/collection/e-ews-backend.h.cve-2019-3890 evolution-ews-3.28.5/src/collection/e-ews-backend.h --- evolution-ews-3.28.5/src/collection/e-ews-backend.h.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/collection/e-ews-backend.h 2019-04-15 09:43:49.685771516 +0200 @@ -63,6 +63,8 @@ EEwsConnection * e_ews_backend_ref_connection_sync (EEwsBackend *backend, ESourceAuthenticationResult *result, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error); void e_ews_backend_ref_connection (EEwsBackend *backend, diff -up evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c.cve-2019-3890 evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c --- evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/configuration/e-ews-config-lookup.c 2019-04-15 09:43:49.685771516 +0200 @@ -344,9 +344,54 @@ ews_config_lookup_worker_run (EConfigLoo if (password) { const gchar *servers; + gchar *certificate_host = NULL; + gchar *certificate_pem = NULL; + GTlsCertificateFlags certificate_errors = 0; + GError *local_error = NULL; + + if (e_named_parameters_exists (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_PEM) && + e_named_parameters_exists (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_TRUST) && + e_named_parameters_exists (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_HOST)) { + GTlsCertificate *certificate; + const gchar *param_certificate_pem; + + param_certificate_pem = e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_PEM); + certificate = g_tls_certificate_new_from_pem (param_certificate_pem, -1, NULL); + + if (certificate) { + ETrustPromptResponse trust_response; + + trust_response = e_config_lookup_decode_certificate_trust ( + e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_TRUST)); + + if (trust_response != E_TRUST_PROMPT_RESPONSE_UNKNOWN) { + ESourceWebdav *webdav_extension; + + webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); + e_source_webdav_update_ssl_trust (webdav_extension, + e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_HOST), + certificate, trust_response); + } + + g_object_unref (certificate); + } + } - if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, cancellable, NULL)) { + if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, &certificate_pem, &certificate_errors, cancellable, &local_error)) { ews_config_lookup_worker_result_from_settings (lookup_worker, config_lookup, email_address, ews_settings, params); + } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) { + const gchar *hosturl; + SoupURI *suri; + + hosturl = camel_ews_settings_get_hosturl (ews_settings); + suri = soup_uri_new (hosturl); + if (suri) { + certificate_host = g_strdup (soup_uri_get_host (suri)); + + soup_uri_free (suri); + } + } else { + g_clear_error (&local_error); } servers = e_named_parameters_get (params, E_CONFIG_LOOKUP_PARAM_SERVERS); @@ -357,7 +402,7 @@ ews_config_lookup_worker_run (EConfigLoo servers_strv = g_strsplit (servers, ";", 0); - for (ii = 0; servers_strv && servers_strv[ii] && !g_cancellable_is_cancelled (cancellable); ii++) { + for (ii = 0; servers_strv && servers_strv[ii] && !g_cancellable_is_cancelled (cancellable) && !local_error; ii++) { const gchar *server = servers_strv[ii]; gchar *tmp = NULL; @@ -368,8 +413,21 @@ ews_config_lookup_worker_run (EConfigLoo camel_ews_settings_set_hosturl (ews_settings, server); - if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, cancellable, NULL)) { + if (e_ews_autodiscover_ws_url_sync (source, ews_settings, email_address, password, &certificate_pem, &certificate_errors, cancellable, &local_error)) { ews_config_lookup_worker_result_from_settings (lookup_worker, config_lookup, email_address, ews_settings, params); + } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) { + const gchar *hosturl; + SoupURI *suri; + + hosturl = camel_ews_settings_get_hosturl (ews_settings); + suri = soup_uri_new (hosturl); + if (suri) { + certificate_host = g_strdup (soup_uri_get_host (suri)); + + soup_uri_free (suri); + } + } else { + g_clear_error (&local_error); } g_free (tmp); @@ -378,7 +436,31 @@ ews_config_lookup_worker_run (EConfigLoo g_strfreev (servers_strv); } - if (out_restart_params) + if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) && + certificate_pem && *certificate_pem && certificate_errors) { + gchar *description = e_trust_prompt_describe_certificate_errors (certificate_errors); + + if (description) { + g_set_error_literal (error, E_CONFIG_LOOKUP_WORKER_ERROR, + E_CONFIG_LOOKUP_WORKER_ERROR_CERTIFICATE, description); + + g_free (description); + + if (out_restart_params) { + if (!*out_restart_params) + *out_restart_params = e_named_parameters_new_clone (params); + + e_named_parameters_set (*out_restart_params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_PEM, certificate_pem); + e_named_parameters_set (*out_restart_params, E_CONFIG_LOOKUP_PARAM_CERTIFICATE_HOST, certificate_host); + } + } + } + + g_clear_error (&local_error); + g_free (certificate_host); + g_free (certificate_pem); + + if (out_restart_params && !*out_restart_params) *out_restart_params = e_named_parameters_new_clone (params); } diff -up evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c.cve-2019-3890 evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c --- evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/configuration/e-ews-config-utils.c 2019-04-15 09:43:49.686771516 +0200 @@ -317,7 +317,7 @@ ews_config_utils_try_credentials_sync (E if (data->try_credentials_func) auth_result = data->try_credentials_func (data->conn, credentials, data->user_data, cancellable, error); else - auth_result = e_ews_connection_try_credentials_sync (data->conn, credentials, cancellable, error); + auth_result = e_ews_connection_try_credentials_sync (data->conn, credentials, NULL, NULL, NULL, cancellable, error); if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) { *out_authenticated = TRUE; @@ -377,7 +377,7 @@ e_ews_config_utils_open_connection_for ( if (try_credentials_func) result = try_credentials_func (conn, NULL, user_data, cancellable, &local_error); else - result = e_ews_connection_try_credentials_sync (conn, NULL, cancellable, &local_error); + result = e_ews_connection_try_credentials_sync (conn, NULL, NULL, NULL, NULL, cancellable, &local_error); if (result != E_SOURCE_AUTHENTICATION_ACCEPTED) { g_clear_object (&conn); diff -up evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c.cve-2019-3890 evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c --- evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/configuration/e-mail-config-ews-autodiscover.c 2019-04-15 09:43:49.686771516 +0200 @@ -45,6 +45,8 @@ struct _AsyncContext { ESource *source; CamelEwsSettings *ews_settings; gchar *email_address; + gchar *certificate_pem; + GTlsCertificateFlags certificate_errors; }; enum { @@ -67,6 +69,7 @@ async_context_free (gpointer ptr) g_clear_object (&async_context->source); g_clear_object (&async_context->ews_settings); g_free (async_context->email_address); + g_free (async_context->certificate_pem); g_slice_free (AsyncContext, async_context); } @@ -87,6 +90,9 @@ mail_config_ews_autodiscover_finish (EMa } static void +mail_config_ews_autodiscover_run (EMailConfigEwsAutodiscover *autodiscover); + +static void mail_config_ews_autodiscover_run_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) @@ -111,17 +117,62 @@ mail_config_ews_autodiscover_run_cb (GOb g_object_thaw_notify (G_OBJECT (settings)); if (e_activity_handle_cancellation (async_context->activity, error)) { - g_error_free (error); + /* Do nothing, just free the error below */ + } else if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) && + async_context->certificate_pem && *async_context->certificate_pem && async_context->certificate_errors) { + ETrustPromptResponse response; + GtkWidget *parent; + const gchar *host; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (autodiscover)); + if (!GTK_IS_WINDOW (parent)) + parent = NULL; + + host = camel_network_settings_get_host (CAMEL_NETWORK_SETTINGS (settings)); + + response = e_trust_prompt_run_modal (parent ? GTK_WINDOW (parent) : NULL, + E_SOURCE_EXTENSION_COLLECTION, _("Exchange Web Services"), + host, async_context->certificate_pem, async_context->certificate_errors, + error->message); + + g_clear_error (&error); + + if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN) { + GTlsCertificate *certificate; + + certificate = g_tls_certificate_new_from_pem (async_context->certificate_pem, -1, &error); + if (certificate) { + ESourceWebdav *extension_webdav; + + extension_webdav = e_source_get_extension (async_context->source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); + + e_source_webdav_update_ssl_trust (extension_webdav, host, certificate, response); + + g_object_unref (certificate); + } + + if (error) { + e_alert_submit ( + alert_sink, + "ews:autodiscovery-error", + error->message, NULL); + } + } + if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT || + response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) { + mail_config_ews_autodiscover_run (autodiscover); + } } else if (error != NULL) { e_alert_submit ( alert_sink, "ews:autodiscovery-error", error->message, NULL); - g_error_free (error); } gtk_widget_set_sensitive (GTK_WIDGET (autodiscover), TRUE); + + g_clear_error (&error); } static gboolean @@ -141,6 +192,7 @@ mail_config_ews_autodiscover_sync (ECred async_context->ews_settings, async_context->email_address, credentials && e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD) ? e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD) : "", + &async_context->certificate_pem, &async_context->certificate_errors, cancellable, &local_error); if (local_error == NULL) { @@ -173,6 +225,7 @@ mail_config_ews_autodiscover_run_thread if (without_password) { success = e_ews_autodiscover_ws_url_sync (async_context->source, async_context->ews_settings, async_context->email_address, "", + &async_context->certificate_pem, &async_context->certificate_errors, cancellable, &local_error); } @@ -236,6 +289,8 @@ mail_config_ews_autodiscover_run (EMailC async_context->source = g_object_ref (source); async_context->ews_settings = g_object_ref (settings); async_context->email_address = g_strdup (e_mail_config_service_page_get_email_address (page)); + async_context->certificate_pem = NULL; + async_context->certificate_errors = 0; /* * The GTask will be run in a new thread, which will invoke diff -up evolution-ews-3.28.5/src/server/e-ews-connection.c.cve-2019-3890 evolution-ews-3.28.5/src/server/e-ews-connection.c --- evolution-ews-3.28.5/src/server/e-ews-connection.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/server/e-ews-connection.c 2019-04-15 09:43:49.689771516 +0200 @@ -111,6 +111,10 @@ struct _EEwsConnectionPrivate { /* Set to TRUE when this connection had been disconnected and cannot be used anymore */ gboolean disconnected_flag; + + gboolean ssl_info_set; + gchar *ssl_certificate_pem; + GTlsCertificateFlags ssl_certificate_errors; }; enum { @@ -836,6 +840,37 @@ ews_connection_credentials_failed (EEwsC return expired; } +static void +ews_connection_check_ssl_error (EEwsConnection *connection, + SoupMessage *message) +{ + g_return_if_fail (E_IS_EWS_CONNECTION (connection)); + g_return_if_fail (SOUP_IS_MESSAGE (message)); + + if (message->status_code == SOUP_STATUS_SSL_FAILED) { + GTlsCertificate *certificate = NULL; + + g_mutex_lock (&connection->priv->property_lock); + + g_clear_pointer (&connection->priv->ssl_certificate_pem, g_free); + connection->priv->ssl_info_set = FALSE; + + g_object_get (G_OBJECT (message), + "tls-certificate", &certificate, + "tls-errors", &connection->priv->ssl_certificate_errors, + NULL); + + if (certificate) { + g_object_get (certificate, "certificate-pem", &connection->priv->ssl_certificate_pem, NULL); + connection->priv->ssl_info_set = TRUE; + + g_object_unref (certificate); + } + + g_mutex_unlock (&connection->priv->property_lock); + } +} + /* Response callbacks */ static void @@ -852,8 +887,15 @@ ews_response_cb (SoupSession *session, if (g_cancellable_is_cancelled (enode->cancellable)) goto exit; + ews_connection_check_ssl_error (enode->cnc, msg); + if (ews_connection_credentials_failed (enode->cnc, msg, enode->simple)) { goto exit; + } else if (msg->status_code == SOUP_STATUS_SSL_FAILED) { + g_simple_async_result_set_error ( + enode->simple, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED, + "%s", msg->reason_phrase); + goto exit; } else if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { if (msg->response_headers) { const gchar *diagnostics; @@ -1855,6 +1897,9 @@ ews_connection_constructed (GObject *obj cnc->priv->soup_thread = g_thread_new (NULL, e_ews_soup_thread, cnc); cnc->priv->soup_session = soup_session_async_new_with_options ( + SOUP_SESSION_TIMEOUT, 90, + SOUP_SESSION_SSL_STRICT, TRUE, + SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE, SOUP_SESSION_ASYNC_CONTEXT, cnc->priv->soup_context, NULL); @@ -1971,6 +2016,7 @@ ews_connection_finalize (GObject *object g_free (priv->email); g_free (priv->hash_key); g_free (priv->impersonate_user); + g_free (priv->ssl_certificate_pem); g_clear_object (&priv->bearer_auth); @@ -2557,10 +2603,15 @@ e_ews_connection_update_credentials (EEw ESourceAuthenticationResult e_ews_connection_try_credentials_sync (EEwsConnection *cnc, const ENamedParameters *credentials, + ESource *use_source, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error) { ESourceAuthenticationResult result; + ESource *source; + gboolean de_set_source; EwsFolderId *fid = NULL; GSList *ids = NULL; GError *local_error = NULL; @@ -2574,14 +2625,31 @@ e_ews_connection_try_credentials_sync (E fid->is_distinguished_id = TRUE; ids = g_slist_append (ids, fid); + source = e_ews_connection_get_source (cnc); + if (use_source && use_source != source) { + cnc->priv->source = g_object_ref (use_source); + de_set_source = TRUE; + } else { + source = NULL; + de_set_source = FALSE; + } + e_ews_connection_get_folder_sync ( cnc, EWS_PRIORITY_MEDIUM, "Default", NULL, ids, NULL, cancellable, &local_error); + if (de_set_source) { + g_clear_object (&cnc->priv->source); + cnc->priv->source = source; + } + g_slist_free_full (ids, (GDestroyNotify) e_ews_folder_id_free); if (local_error == NULL) { result = E_SOURCE_AUTHENTICATION_ACCEPTED; + } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) && + e_ews_connection_get_ssl_error_details (cnc, out_certificate_pem, out_certificate_errors)) { + result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED; } else { gboolean auth_failed; @@ -2618,6 +2686,29 @@ e_ews_connection_get_source (EEwsConnect return cnc->priv->source; } +gboolean +e_ews_connection_get_ssl_error_details (EEwsConnection *cnc, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors) +{ + g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE); + g_return_val_if_fail (out_certificate_pem != NULL, FALSE); + g_return_val_if_fail (out_certificate_errors != NULL, FALSE); + + g_mutex_lock (&cnc->priv->property_lock); + if (!cnc->priv->ssl_info_set) { + g_mutex_unlock (&cnc->priv->property_lock); + return FALSE; + } + + *out_certificate_pem = g_strdup (cnc->priv->ssl_certificate_pem); + *out_certificate_errors = cnc->priv->ssl_certificate_errors; + + g_mutex_unlock (&cnc->priv->property_lock); + + return TRUE; +} + const gchar * e_ews_connection_get_uri (EEwsConnection *cnc) { @@ -2906,6 +2997,9 @@ autodiscover_response_cb (SoupSession *s g_set_error ( &error, SOUP_HTTP_ERROR, status, "%d %s", status, msg->reason_phrase); + + if (status == SOUP_STATUS_SSL_FAILED) + ews_connection_check_ssl_error (ad->cnc, msg); } g_free (service_url); @@ -3056,7 +3150,8 @@ static void post_restarted (SoupMessage } static SoupMessage * -e_ews_get_msg_for_url (CamelEwsSettings *settings, +e_ews_get_msg_for_url (EEwsConnection *cnc, + CamelEwsSettings *settings, const gchar *url, xmlOutputBuffer *buf, GError **error) @@ -3078,6 +3173,9 @@ e_ews_get_msg_for_url (CamelEwsSettings return NULL; } + if (cnc->priv->source) + e_soup_ssl_trust_connect (msg, cnc->priv->source); + e_ews_message_attach_chunk_allocator (msg); e_ews_message_set_user_agent_header (msg, settings); @@ -3107,6 +3205,8 @@ e_ews_autodiscover_ws_url_sync (ESource CamelEwsSettings *settings, const gchar *email_address, const gchar *password, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error) { @@ -3125,7 +3225,7 @@ e_ews_autodiscover_ws_url_sync (ESource result = e_async_closure_wait (closure); - success = e_ews_autodiscover_ws_url_finish (settings, result, error); + success = e_ews_autodiscover_ws_url_finish (settings, result, out_certificate_pem, out_certificate_errors, error); e_async_closure_free (closure); @@ -3236,11 +3336,11 @@ e_ews_autodiscover_ws_url (ESource *sour simple, ad, (GDestroyNotify) autodiscover_data_free); /* Passing a NULL URL string returns NULL. */ - ad->msgs[0] = e_ews_get_msg_for_url (settings, url1, buf, &error); - ad->msgs[1] = e_ews_get_msg_for_url (settings, url2, buf, NULL); - ad->msgs[2] = e_ews_get_msg_for_url (settings, url3, buf, NULL); - ad->msgs[3] = e_ews_get_msg_for_url (settings, url4, buf, NULL); - ad->msgs[4] = e_ews_get_msg_for_url (settings, url5, buf, NULL); + ad->msgs[0] = e_ews_get_msg_for_url (cnc, settings, url1, buf, &error); + ad->msgs[1] = e_ews_get_msg_for_url (cnc, settings, url2, buf, NULL); + ad->msgs[2] = e_ews_get_msg_for_url (cnc, settings, url3, buf, NULL); + ad->msgs[3] = e_ews_get_msg_for_url (cnc, settings, url4, buf, NULL); + ad->msgs[4] = e_ews_get_msg_for_url (cnc, settings, url5, buf, NULL); /* These have to be submitted only after they're both set in ad->msgs[] * or there will be races with fast completion */ @@ -3300,10 +3400,13 @@ has_suffix_icmp (const gchar *text, gboolean e_ews_autodiscover_ws_url_finish (CamelEwsSettings *settings, GAsyncResult *result, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GError **error) { GSimpleAsyncResult *simple; struct _autodiscover_data *ad; + GError *local_error = NULL; g_return_val_if_fail ( g_simple_async_result_is_valid ( @@ -3313,8 +3416,20 @@ e_ews_autodiscover_ws_url_finish (CamelE simple = G_SIMPLE_ASYNC_RESULT (result); ad = g_simple_async_result_get_op_res_gpointer (simple); - if (g_simple_async_result_propagate_error (simple, error)) + if (g_simple_async_result_propagate_error (simple, &local_error)) { + if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) { + if (!e_ews_connection_get_ssl_error_details (ad->cnc, out_certificate_pem, out_certificate_errors)) { + if (out_certificate_pem) + *out_certificate_pem = NULL; + if (out_certificate_errors) + *out_certificate_errors = 0; + } + } + + g_propagate_error (error, local_error); + return FALSE; + } g_warn_if_fail (ad->as_url != NULL); g_warn_if_fail (ad->oab_url != NULL); @@ -3473,6 +3588,8 @@ oal_response_cb (SoupSession *soup_sessi simple = G_SIMPLE_ASYNC_RESULT (user_data); data = g_simple_async_result_get_op_res_gpointer (simple); + ews_connection_check_ssl_error (data->cnc, soup_message); + if (ews_connection_credentials_failed (data->cnc, soup_message, simple)) { goto exit; } else if (soup_message->status_code != 200) { @@ -3618,7 +3735,7 @@ e_ews_connection_get_oal_list (EEwsConne g_return_if_fail (E_IS_EWS_CONNECTION (cnc)); - soup_message = e_ews_get_msg_for_url (cnc->priv->settings, cnc->priv->uri, NULL, &error); + soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error); simple = g_simple_async_result_new ( G_OBJECT (cnc), callback, user_data, @@ -3739,7 +3856,7 @@ e_ews_connection_get_oal_detail (EEwsCon g_return_if_fail (E_IS_EWS_CONNECTION (cnc)); - soup_message = e_ews_get_msg_for_url (cnc->priv->settings, cnc->priv->uri, NULL, &error); + soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error); simple = g_simple_async_result_new ( G_OBJECT (cnc), callback, user_data, @@ -3826,6 +3943,8 @@ oal_download_response_cb (SoupSession *s simple = G_SIMPLE_ASYNC_RESULT (user_data); data = g_simple_async_result_get_op_res_gpointer (simple); + ews_connection_check_ssl_error (data->cnc, soup_message); + if (ews_connection_credentials_failed (data->cnc, soup_message, simple)) { g_unlink (data->cache_filename); } else if (soup_message->status_code != 200) { @@ -3954,7 +4073,7 @@ e_ews_connection_download_oal_file (EEws g_return_if_fail (E_IS_EWS_CONNECTION (cnc)); - soup_message = e_ews_get_msg_for_url (cnc->priv->settings, cnc->priv->uri, NULL, &error); + soup_message = e_ews_get_msg_for_url (cnc, cnc->priv->settings, cnc->priv->uri, NULL, &error); simple = g_simple_async_result_new ( G_OBJECT (cnc), callback, user_data, diff -up evolution-ews-3.28.5/src/server/e-ews-connection.h.cve-2019-3890 evolution-ews-3.28.5/src/server/e-ews-connection.h --- evolution-ews-3.28.5/src/server/e-ews-connection.h.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/server/e-ews-connection.h 2019-04-15 09:43:49.689771516 +0200 @@ -426,9 +426,16 @@ ESourceAuthenticationResult e_ews_connection_try_credentials_sync (EEwsConnection *cnc, const ENamedParameters *credentials, + ESource *use_source, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error); ESource * e_ews_connection_get_source (EEwsConnection *cnc); +gboolean e_ews_connection_get_ssl_error_details + (EEwsConnection *cnc, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors); const gchar * e_ews_connection_get_uri (EEwsConnection *cnc); ESoupAuthBearer * e_ews_connection_ref_bearer_auth(EEwsConnection *cnc); @@ -469,6 +476,8 @@ gboolean e_ews_autodiscover_ws_url_sync CamelEwsSettings *settings, const gchar *email_address, const gchar *password, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error); void e_ews_autodiscover_ws_url (ESource *source, @@ -481,6 +490,8 @@ void e_ews_autodiscover_ws_url (ESource gboolean e_ews_autodiscover_ws_url_finish (CamelEwsSettings *settings, GAsyncResult *result, + gchar **out_certificate_pem, + GTlsCertificateFlags *out_certificate_errors, GError **error); const gchar * e_ews_connection_get_mailbox (EEwsConnection *cnc); void e_ews_connection_set_mailbox (EEwsConnection *cnc, diff -up evolution-ews-3.28.5/src/server/e-ews-connection-utils.c.cve-2019-3890 evolution-ews-3.28.5/src/server/e-ews-connection-utils.c --- evolution-ews-3.28.5/src/server/e-ews-connection-utils.c.cve-2019-3890 2018-07-30 16:01:00.000000000 +0200 +++ evolution-ews-3.28.5/src/server/e-ews-connection-utils.c 2019-04-15 09:43:49.690771516 +0200 @@ -522,8 +522,13 @@ e_ews_connection_utils_prepare_message ( GCancellable *cancellable) { ESoupAuthBearer *using_bearer_auth; + ESource *source; GError *local_error = NULL; + source = e_ews_connection_get_source (cnc); + if (source) + e_soup_ssl_trust_connect (message, source); + if (!ews_connection_utils_maybe_prepare_bearer_auth (cnc, message, cancellable)) return FALSE;