Example #1
0
static gboolean
e_soup_ssl_trust_accept_certificate_cb (GTlsConnection *conn,
					GTlsCertificate *peer_cert,
					GTlsCertificateFlags errors,
					gpointer user_data)
{
	ESoupSslTrustData *handler = user_data;
	ETrustPromptResponse response;
	SoupURI *soup_uri;
	const gchar *host;
	gchar *auth_host = NULL;

	soup_uri = soup_message_get_uri (handler->soup_message);
	if (!soup_uri || !soup_uri_get_host (soup_uri))
		return FALSE;

	host = soup_uri_get_host (soup_uri);

	if (e_source_has_extension (handler->source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
		ESourceAuthentication *extension_authentication;

		extension_authentication = e_source_get_extension (handler->source, E_SOURCE_EXTENSION_AUTHENTICATION);
		auth_host = e_source_authentication_dup_host (extension_authentication);

		if (auth_host && *auth_host) {
			/* Use the 'host' from the Authentication extension, because
			   it's the one used when storing the trust prompt result.
			   The SoupMessage can be redirected, thus it would not ever match. */
			host = auth_host;
		} else {
			g_free (auth_host);
			auth_host = NULL;
		}
	}

	response = e_source_webdav_verify_ssl_trust (
		e_source_get_extension (handler->source, E_SOURCE_EXTENSION_WEBDAV_BACKEND),
		host, peer_cert, errors);

	g_free (auth_host);

	return (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
	        response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY);
}
Example #2
0
/**
 * e_trust_prompt_run_for_source:
 * @parent: A #GtkWindow to use as a parent for the trust prompt dialog
 * @source: an #ESource, with %E_SOURCE_EXTENSION_AUTHENTICATION
 * @certificate_pem: a PEM-encoded certificate for which to show the trust prompt
 * @certificate_errors: errors of the @certificate_pem
 * @error_text: (allow-none): an optional error text to show in the dialog; can be %NULL
 * @allow_source_save: whether can also save any @source changes
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @callback: a callback to call, when the prompt (an @source save) is done
 * @user_data: user data passed into @callback
 *
 * Similar to e_trust_prompt_run_modal(), except it also manages all the necessary things
 * around the @source<!-- -->'s SSL/TLS trust properties when it also contains %E_SOURCE_EXTENSION_WEBDAV,
 * thus the SSL/TLS trust on the WebDAV @source is properly updated based on the user's choice.
 * The call is finished with e_trust_prompt_run_for_source_finish(),
 * which also returns the user's choice. The finish happens in the @callback.
 * This is necessary, because the @source can be also saved.
 *
 * The function fails, if the @source doesn't contain the %E_SOURCE_EXTENSION_AUTHENTICATION.
 *
 * Note: The dialog is not shown when the stored certificate trust in the WebDAV @source
 *    matches the @certificate_pem and the stored result is #E_TRUST_PROMPT_RESPONSE_REJECT.
 *
 * Since: 3.16
 **/
void
e_trust_prompt_run_for_source (GtkWindow *parent,
			       ESource *source,
			       const gchar *certificate_pem,
			       GTlsCertificateFlags certificate_errors,
			       const gchar *error_text,
			       gboolean allow_source_save,
			       GCancellable *cancellable,
			       GAsyncReadyCallback callback,
			       gpointer user_data)
{
	ESourceAuthentication *extension_authentication = NULL;
	ESourceWebdav *extension_webdav = NULL;
	SaveSourceData *save_data;
	GTlsCertificate *certificate;
	gchar *host;
	GTask *task;

	if (parent)
		g_return_if_fail (GTK_IS_WINDOW (parent));
	g_return_if_fail (E_IS_SOURCE (source));
	g_return_if_fail (certificate_pem != NULL);

	if (e_source_has_extension (source, E_SOURCE_EXTENSION_GOA) ||
	    e_source_has_extension (source, E_SOURCE_EXTENSION_UOA)) {
		/* Make sure that GOA/UOA collection sources contain these extensions too */
		g_warn_if_fail (e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION));
		g_warn_if_fail (e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND));
	}

	if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION))
		extension_authentication = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
	if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND))
		extension_webdav = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);

	save_data = g_new0 (SaveSourceData, 1);
	save_data->response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
	save_data->call_save = FALSE;

	/* Lookup used host name */
	if (extension_authentication)
		host = e_source_authentication_dup_host (extension_authentication);
	else
		host = NULL;

	if (!host || !*host) {
		g_free (host);
		host = NULL;

		if (e_source_has_extension (source, E_SOURCE_EXTENSION_GOA)) {
			ESourceGoa *goa_extension;
			gchar *url;

			goa_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_GOA);

			url = e_source_goa_dup_calendar_url (goa_extension);
			host = trust_prompt_get_host_from_url (url);
			g_free (url);

			if (!host) {
				url = e_source_goa_dup_contacts_url (goa_extension);
				host = trust_prompt_get_host_from_url (url);
				g_free (url);
			}
		}
	}

	certificate = g_tls_certificate_new_from_pem (certificate_pem, -1, &save_data->error);
	if (certificate) {
		if (extension_webdav && host)
			save_data->response = e_source_webdav_verify_ssl_trust (extension_webdav, host, certificate, 0);
		else
			save_data->response = E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;

		if (save_data->response != E_TRUST_PROMPT_RESPONSE_REJECT) {
			const gchar *source_extension = NULL;

			if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
				source_extension = E_SOURCE_EXTENSION_ADDRESS_BOOK;

			if (e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR)) {
				if (!source_extension)
					source_extension = E_SOURCE_EXTENSION_CALENDAR;
				else
					source_extension = E_SOURCE_EXTENSION_COLLECTION;
			}

			if (e_source_has_extension (source, E_SOURCE_EXTENSION_MEMO_LIST)) {
				if (!source_extension)
					source_extension = E_SOURCE_EXTENSION_MEMO_LIST;
				else
					source_extension = E_SOURCE_EXTENSION_COLLECTION;
			}

			if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST)) {
				if (!source_extension)
					source_extension = E_SOURCE_EXTENSION_TASK_LIST;
				else
					source_extension = E_SOURCE_EXTENSION_COLLECTION;
			}

			if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_ACCOUNT)) {
				if (!source_extension)
					source_extension = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
				else
					source_extension = E_SOURCE_EXTENSION_COLLECTION;
			}

			if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_TRANSPORT)) {
				if (!source_extension)
					source_extension = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
				else
					source_extension = E_SOURCE_EXTENSION_COLLECTION;
			}

			save_data->response = e_trust_prompt_run_with_dialog_ready_callback (parent,
				source_extension, e_source_get_display_name (source), host,
				certificate_pem, certificate_errors, error_text,
				trust_prompt_listen_for_source_changes_cb, source);
		}
	}

	g_signal_handlers_disconnect_matched (source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
		source_connection_status_changed_cb, NULL);

	if (save_data->response != E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
		if (certificate && extension_webdav) {
			e_source_webdav_update_ssl_trust (extension_webdav, host, certificate, save_data->response);
			save_data->call_save = allow_source_save;
		}
	}

	g_clear_object (&certificate);
	g_free (host);

	task = g_task_new (source, cancellable, callback, user_data);
	g_task_set_source_tag (task, e_trust_prompt_run_for_source);
	g_task_set_task_data (task, save_data, save_source_data_free);

	g_task_run_in_thread (task, save_source_thread);

	g_object_unref (task);
}