diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c b/addressbook/backends/webdav/e-book-backend-webdav.c
index cb0a403..a3edb6b 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -141,9 +141,50 @@ get_closure (EDataBookView *book_view)
 	return g_object_get_data (G_OBJECT (book_view), WEBDAV_CLOSURE_NAME);
 }
 
+static guint
+send_and_handle_ssl (EBookBackendWebdav *webdav,
+		     SoupMessage *message,
+		     GCancellable *cancellable)
+{
+	guint status_code;
+
+	status_code = soup_session_send_message (webdav->priv->session, message);
+	if (status_code == SOUP_STATUS_SSL_FAILED) {
+		ESource *source;
+		ESourceWebdav *extension;
+		EBackend *backend;
+		ETrustPromptResponse response;
+		ENamedParameters *parameters;
+
+		backend = E_BACKEND (webdav);
+		source = e_backend_get_source (backend);
+		extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+		parameters = e_named_parameters_new ();
+
+		response = e_source_webdav_prepare_ssl_trust_prompt (extension, message, parameters);
+		if (response == E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
+			response = e_backend_trust_prompt_sync (backend, parameters, cancellable, NULL);
+			if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN)
+				e_source_webdav_store_ssl_trust_prompt (extension, message, response);
+		}
+
+		e_named_parameters_free (parameters);
+
+		if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
+		    response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+			g_object_set (webdav->priv->session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE, NULL);
+			status_code = soup_session_send_message (webdav->priv->session, message);
+		}
+	}
+
+	return status_code;
+}
+
 static EContact *
 download_contact (EBookBackendWebdav *webdav,
-                  const gchar *uri)
+                  const gchar *uri,
+		  GCancellable *cancellable)
 {
 	SoupMessage *message;
 	const gchar  *etag;
@@ -154,7 +195,7 @@ download_contact (EBookBackendWebdav *webdav,
 	soup_message_headers_append (message->request_headers, "User-Agent", USERAGENT);
 	soup_message_headers_append (message->request_headers, "Connection", "close");
 
-	status = soup_session_send_message (webdav->priv->session, message);
+	status = send_and_handle_ssl (webdav, message, cancellable);
 	if (status != 200) {
 		g_warning ("Couldn't load '%s' (http status %d)", uri, status);
 		g_object_unref (message);
@@ -194,7 +235,8 @@ download_contact (EBookBackendWebdav *webdav,
 static guint
 upload_contact (EBookBackendWebdav *webdav,
                 EContact *contact,
-                gchar **reason)
+                gchar **reason,
+		GCancellable *cancellable)
 {
 	ESource     *source;
 	ESourceWebdav *webdav_extension;
@@ -250,7 +292,7 @@ upload_contact (EBookBackendWebdav *webdav,
 		message, "text/vcard", SOUP_MEMORY_TEMPORARY,
 		request, strlen (request));
 
-	status   = soup_session_send_message (webdav->priv->session, message);
+	status   = send_and_handle_ssl (webdav, message, cancellable);
 	new_etag = soup_message_headers_get_list (message->response_headers, "ETag");
 
 	redir_uri = soup_message_headers_get_list (message->response_headers, "Location");
@@ -349,7 +391,7 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
 	/* kill revision field (might have been set by some other backend) */
 	e_contact_set (contact, E_CONTACT_REV, NULL);
 
-	status = upload_contact (webdav, contact, &status_reason);
+	status = upload_contact (webdav, contact, &status_reason, cancellable);
 	if (status != 201 && status != 204) {
 		g_object_unref (contact);
 		if (status == 401 || status == 407) {
@@ -377,7 +419,7 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
 
 		g_warning ("Server didn't return etag for new address resource");
 		new_uid = e_contact_get_const (contact, E_CONTACT_UID);
-		new_contact = download_contact (webdav, new_uid);
+		new_contact = download_contact (webdav, new_uid, cancellable);
 		g_object_unref (contact);
 
 		if (new_contact == NULL) {
@@ -403,7 +445,8 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
 
 static guint
 delete_contact (EBookBackendWebdav *webdav,
-                const gchar *uri)
+                const gchar *uri,
+		GCancellable *cancellable)
 {
 	SoupMessage *message;
 	guint        status;
@@ -412,7 +455,7 @@ delete_contact (EBookBackendWebdav *webdav,
 	soup_message_headers_append (message->request_headers, "User-Agent", USERAGENT);
 	soup_message_headers_append (message->request_headers, "Connection", "close");
 
-	status = soup_session_send_message (webdav->priv->session, message);
+	status = send_and_handle_ssl (webdav, message, cancellable);
 	g_object_unref (message);
 
 	return status;
@@ -449,7 +492,7 @@ e_book_backend_webdav_remove_contacts (EBookBackend *backend,
 		return;
 	}
 
-	status = delete_contact (webdav, uid);
+	status = delete_contact (webdav, uid, cancellable);
 	if (status != 204) {
 		if (status == 401 || status == 407) {
 			e_data_book_respond_remove_contacts (
@@ -512,7 +555,7 @@ e_book_backend_webdav_modify_contacts (EBookBackend *backend,
 
 	/* modify contact */
 	contact = e_contact_new_from_vcard (vcard);
-	status = upload_contact (webdav, contact, &status_reason);
+	status = upload_contact (webdav, contact, &status_reason, cancellable);
 	if (status != 201 && status != 204) {
 		g_object_unref (contact);
 		if (status == 401 || status == 407) {
@@ -555,7 +598,7 @@ e_book_backend_webdav_modify_contacts (EBookBackend *backend,
 		EContact *new_contact;
 
 		g_warning ("Server didn't return etag for modified address resource");
-		new_contact = download_contact (webdav, uid);
+		new_contact = download_contact (webdav, uid, cancellable);
 		if (new_contact != NULL) {
 			contact = new_contact;
 		}
@@ -586,7 +629,7 @@ e_book_backend_webdav_get_contact (EBookBackend *backend,
 		contact = e_book_backend_cache_get_contact (priv->cache, uid);
 		g_mutex_unlock (&priv->cache_lock);
 	} else {
-		contact = download_contact (webdav, uid);
+		contact = download_contact (webdav, uid, cancellable);
 		/* update cache as we possibly have changes */
 		if (contact != NULL) {
 			g_mutex_lock (&priv->cache_lock);
@@ -743,7 +786,8 @@ parse_propfind_response (xmlTextReaderPtr reader)
 }
 
 static SoupMessage *
-send_propfind (EBookBackendWebdav *webdav)
+send_propfind (EBookBackendWebdav *webdav,
+	       GCancellable *cancellable)
 {
 	SoupMessage               *message;
 	EBookBackendWebdavPrivate *priv    = webdav->priv;
@@ -759,7 +803,7 @@ send_propfind (EBookBackendWebdav *webdav)
 		message, "text/xml", SOUP_MEMORY_TEMPORARY,
 		(gchar *) request, strlen (request));
 
-	soup_session_send_message (priv->session, message);
+	send_and_handle_ssl (webdav, message, cancellable);
 
 	return message;
 }
@@ -835,7 +879,8 @@ xp_object_get_status (xmlXPathObjectPtr result)
 
 static gboolean
 check_addressbook_changed (EBookBackendWebdav *webdav,
-                           gchar **new_ctag)
+                           gchar **new_ctag,
+			   GCancellable *cancellable)
 {
 	gboolean res = TRUE;
 	const gchar *request = "<?xml version=\"1.0\" encoding=\"utf-8\"?><propfind xmlns=\"DAV:\"><prop><getctag/></prop></propfind>";
@@ -861,7 +906,7 @@ check_addressbook_changed (EBookBackendWebdav *webdav,
 	soup_message_headers_append (message->request_headers, "Connection", "close");
 	soup_message_headers_append (message->request_headers, "Depth", "0");
 	soup_message_set_request (message, "text/xml", SOUP_MEMORY_TEMPORARY, (gchar *) request, strlen (request));
-	soup_session_send_message (priv->session, message);
+	send_and_handle_ssl (webdav, message, cancellable);
 
 	if (message->status_code == 207 && message->response_body) {
 		xmlDocPtr xml;
@@ -916,7 +961,8 @@ check_addressbook_changed (EBookBackendWebdav *webdav,
 static GError *
 download_contacts (EBookBackendWebdav *webdav,
                    EFlag *running,
-                  EDataBookView *book_view)
+		   EDataBookView *book_view,
+		   GCancellable *cancellable)
 {
 	EBookBackendWebdavPrivate *priv = webdav->priv;
 	EBookBackend		  *book_backend;
@@ -932,7 +978,7 @@ download_contacts (EBookBackendWebdav *webdav,
 
 	g_mutex_lock (&priv->update_lock);
 
-	if (!check_addressbook_changed (webdav, &new_ctag)) {
+	if (!check_addressbook_changed (webdav, &new_ctag, cancellable)) {
 		g_free (new_ctag);
 		g_mutex_unlock (&priv->update_lock);
 		return EDB_ERROR (SUCCESS);
@@ -945,7 +991,7 @@ download_contacts (EBookBackendWebdav *webdav,
 				_("Loading Addressbook summary..."));
 	}
 
-	message = send_propfind (webdav);
+	message = send_propfind (webdav, cancellable);
 	status  = message->status_code;
 
 	if (status == 401 || status == 407) {
@@ -1047,7 +1093,7 @@ download_contacts (EBookBackendWebdav *webdav,
 		/* download contact if it is not cached or its ETag changed */
 		if (contact == NULL || etag == NULL ||
 		    strcmp (e_contact_get_const (contact, E_CONTACT_REV), etag) != 0) {
-			contact = download_contact (webdav, complete_uri);
+			contact = download_contact (webdav, complete_uri, cancellable);
 			if (contact != NULL) {
 				g_mutex_lock (&priv->cache_lock);
 				if (e_book_backend_cache_remove_contact (priv->cache, complete_uri))
@@ -1103,7 +1149,7 @@ book_view_thread (gpointer data)
 	 * it's stopped */
 	g_object_ref (book_view);
 
-	error = download_contacts (webdav, closure->running, book_view);
+	error = download_contacts (webdav, closure->running, book_view, NULL);
 
 	g_object_unref (book_view);
 
@@ -1191,7 +1237,7 @@ e_book_backend_webdav_get_contact_list (EBookBackend *backend,
 
 	if (e_backend_get_online (E_BACKEND (backend))) {
 		/* make sure the cache is up to date */
-		GError *error = download_contacts (webdav, NULL, NULL);
+		GError *error = download_contacts (webdav, NULL, NULL, cancellable);
 
 		if (error) {
 			e_data_book_respond_get_contact_list (book, opid, error, NULL);
@@ -1235,7 +1281,7 @@ e_book_backend_webdav_get_contact_list_uids (EBookBackend *backend,
 
 	if (e_backend_get_online (E_BACKEND (backend))) {
 		/* make sure the cache is up to date */
-		GError *error = download_contacts (webdav, NULL, NULL);
+		GError *error = download_contacts (webdav, NULL, NULL, cancellable);
 
 		if (error) {
 			e_data_book_respond_get_contact_list_uids (book, opid, error, NULL);
@@ -1372,13 +1418,12 @@ e_book_backend_webdav_open (EBookBackend *backend,
 	g_mutex_unlock (&priv->cache_lock);
 
 	session = soup_session_sync_new ();
-	g_object_set (session, SOUP_SESSION_TIMEOUT, 90, NULL);
+	g_object_set (session,
+		SOUP_SESSION_TIMEOUT, 90,
+		SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
+		NULL);
 
-	g_object_bind_property (
-		webdav_extension, "ignore-invalid-cert",
-		session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
-		G_BINDING_SYNC_CREATE |
-		G_BINDING_INVERT_BOOLEAN);
+	e_source_webdav_unset_temporary_ssl_trust (webdav_extension);
 
 	g_signal_connect (
 		session, "authenticate",
@@ -1514,7 +1559,7 @@ book_backend_webdav_try_password_sync (ESourceAuthenticator *authenticator,
 	webdav->priv->password = g_strdup (password->str);
 
 	/* Send a PROPFIND to test whether user/password is correct. */
-	message = send_propfind (webdav);
+	message = send_propfind (webdav, cancellable);
 
 	switch (message->status_code) {
 		case SOUP_STATUS_OK:
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index 66602dd..5828586 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -542,10 +542,6 @@ status_code_to_result (SoupMessage *message,
                        GError **perror)
 {
 	ECalBackendCalDAVPrivate *priv;
-	ESource *source;
-	ESourceWebdav *extension;
-	const gchar *extension_name;
-	gboolean ignore_invalid_cert;
 
 	g_return_val_if_fail (cbdav != NULL, FALSE);
 	g_return_val_if_fail (message != NULL, FALSE);
@@ -556,11 +552,8 @@ status_code_to_result (SoupMessage *message,
 		return TRUE;
 	}
 
-	source = e_backend_get_source (E_BACKEND (cbdav));
-
-	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
-	extension = e_source_get_extension (source, extension_name);
-	ignore_invalid_cert = e_source_webdav_get_ignore_invalid_cert (extension);
+	if (perror && *perror)
+		return FALSE;
 
 	switch (message->status_code) {
 	case SOUP_STATUS_CANT_CONNECT:
@@ -596,22 +589,12 @@ status_code_to_result (SoupMessage *message,
 		break;
 
 	case SOUP_STATUS_SSL_FAILED:
-		if (ignore_invalid_cert) {
-			g_propagate_error (
-				perror,
-				e_data_cal_create_error_fmt ( OtherError,
-				_("Failed to connect to a server using SSL: %s"),
-				message->reason_phrase && *message->reason_phrase ? message->reason_phrase :
-				(soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : _("Unknown error"))));
-		} else {
-			g_propagate_error (
-				perror, EDC_ERROR_EX (OtherError,
-				_("Failed to connect to a server using SSL. "
-				"One possible reason is an invalid certificate being used by the server. "
-				"If this is expected, like self-signed certificate being used on the server, "
-				"then disable certificate validity tests by selecting 'Ignore invalid SSL certificate' option "
-				"in Properties")));
-		}
+		g_propagate_error (
+			perror,
+			e_data_cal_create_error_fmt ( OtherError,
+			_("Failed to connect to a server using SSL: %s"),
+			message->reason_phrase && *message->reason_phrase ? message->reason_phrase :
+			(soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : _("Unknown error"))));
 		break;
 
 	default:
@@ -1046,21 +1029,53 @@ redirect_handler (SoupMessage *msg,
 }
 
 static void
-send_and_handle_redirection (SoupSession *soup_session,
+send_and_handle_redirection (ECalBackendCalDAV *cbdav,
                              SoupMessage *msg,
-                             gchar **new_location)
+                             gchar **new_location,
+			     GCancellable *cancellable,
+			     GError **error)
 {
 	gchar *old_uri = NULL;
 
+	g_return_if_fail (E_IS_CAL_BACKEND_CALDAV (cbdav));
 	g_return_if_fail (msg != NULL);
 
 	if (new_location)
 		old_uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
 
 	soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
-	soup_message_add_header_handler (msg, "got_body", "Location", G_CALLBACK (redirect_handler), soup_session);
+	soup_message_add_header_handler (msg, "got_body", "Location", G_CALLBACK (redirect_handler), cbdav->priv->session);
 	soup_message_headers_append (msg->request_headers, "Connection", "close");
-	soup_session_send_message (soup_session, msg);
+	soup_session_send_message (cbdav->priv->session, msg);
+
+	if (msg->status_code == SOUP_STATUS_SSL_FAILED) {
+		ESource *source;
+		ESourceWebdav *extension;
+		EBackend *backend;
+		ETrustPromptResponse response;
+		ENamedParameters *parameters;
+
+		backend = E_BACKEND (cbdav);
+		source = e_backend_get_source (backend);
+		extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+		parameters = e_named_parameters_new ();
+
+		response = e_source_webdav_prepare_ssl_trust_prompt (extension, msg, parameters);
+		if (response == E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
+			response = e_backend_trust_prompt_sync (backend, parameters, cancellable, error);
+			if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN)
+				e_source_webdav_store_ssl_trust_prompt (extension, msg, response);
+		}
+
+		e_named_parameters_free (parameters);
+
+		if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
+		    response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+			g_object_set (cbdav->priv->session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE, NULL);
+			soup_session_send_message (cbdav->priv->session, msg);
+		}
+	}
 
 	if (new_location) {
 		gchar *new_loc = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
@@ -1094,19 +1109,20 @@ caldav_generate_uri (ECalBackendCalDAV *cbdav,
 static gboolean
 caldav_server_open_calendar (ECalBackendCalDAV *cbdav,
                              gboolean *server_unreachable,
+			     GCancellable *cancellable,
                              GError **perror)
 {
-	SoupMessage               *message;
-	const gchar                *header;
-	gboolean                   calendar_access;
-	gboolean                   put_allowed;
-	gboolean                   delete_allowed;
+	SoupMessage *message;
+	const gchar *header;
+	gboolean calendar_access;
+	gboolean put_allowed;
+	gboolean delete_allowed;
+	ESource *source;
+	ESourceWebdav *webdav_extension;
 
 	g_return_val_if_fail (cbdav != NULL, FALSE);
 	g_return_val_if_fail (server_unreachable != NULL, FALSE);
 
-	/* FIXME: setup text_uri */
-
 	message = soup_message_new (SOUP_METHOD_OPTIONS, cbdav->priv->uri);
 	if (message == NULL) {
 		g_propagate_error (perror, EDC_ERROR (NoSuchCal));
@@ -1116,7 +1132,14 @@ caldav_server_open_calendar (ECalBackendCalDAV *cbdav,
 		message->request_headers,
 		"User-Agent", "Evolution/" VERSION);
 
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	/* re-check server's certificate trust, if needed */
+	g_object_set (cbdav->priv->session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE, NULL);
+
+	source = e_backend_get_source (E_BACKEND (cbdav));
+	webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+	e_source_webdav_unset_temporary_ssl_trust (webdav_extension);
+
+	send_and_handle_redirection (cbdav, message, NULL, cancellable, perror);
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
 		switch (message->status_code) {
@@ -1271,7 +1294,7 @@ check_calendar_changed_on_server (ECalBackendCalDAV *cbdav)
 		buf_content, buf_size);
 
 	/* Send the request now */
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, NULL, NULL);
 
 	/* Clean up the memory */
 	xmlOutputBufferClose (buf);
@@ -1424,7 +1447,7 @@ caldav_server_list_objects (ECalBackendCalDAV *cbdav,
 		buf_content, buf_size);
 
 	/* Send the request now */
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, NULL, NULL);
 
 	/* Clean up the memory */
 	xmlOutputBufferClose (buf);
@@ -1481,7 +1504,7 @@ caldav_server_download_attachment (ECalBackendCalDAV *cbdav,
 	}
 
 	soup_message_headers_append (message->request_headers, "User-Agent", "Evolution/" VERSION);
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, NULL, NULL);
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
 		status_code_to_result (message, cbdav, FALSE, error);
@@ -1504,6 +1527,7 @@ caldav_server_download_attachment (ECalBackendCalDAV *cbdav,
 static gboolean
 caldav_server_get_object (ECalBackendCalDAV *cbdav,
                           CalDAVObject *object,
+			  GCancellable *cancellable,
                           GError **perror)
 {
 	SoupMessage              *message;
@@ -1524,7 +1548,7 @@ caldav_server_get_object (ECalBackendCalDAV *cbdav,
 		message->request_headers,
 		"User-Agent", "Evolution/" VERSION);
 
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, cancellable, perror);
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
 		status_code_to_result (message, cbdav, FALSE, perror);
@@ -1570,6 +1594,7 @@ static void
 caldav_post_freebusy (ECalBackendCalDAV *cbdav,
                       const gchar *url,
                       gchar **post_fb,
+		      GCancellable *cancellable,
                       GError **error)
 {
 	SoupMessage *message;
@@ -1592,7 +1617,7 @@ caldav_post_freebusy (ECalBackendCalDAV *cbdav,
 		SOUP_MEMORY_COPY,
 		*post_fb, strlen (*post_fb));
 
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, cancellable, error);
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
 		status_code_to_result (message, cbdav, FALSE, error);
@@ -1651,6 +1676,7 @@ static gboolean
 caldav_server_put_object (ECalBackendCalDAV *cbdav,
                           CalDAVObject *object,
                           icalcomponent *icalcomp,
+			  GCancellable *cancellable,
                           GError **perror)
 {
 	SoupMessage              *message;
@@ -1693,7 +1719,7 @@ caldav_server_put_object (ECalBackendCalDAV *cbdav,
 		strlen (object->cdata));
 
 	uri = NULL;
-	send_and_handle_redirection (cbdav->priv->session, message, &uri);
+	send_and_handle_redirection (cbdav, message, &uri, cancellable, perror);
 
 	if (uri) {
 		gchar *file = strrchr (uri, '/');
@@ -1740,7 +1766,7 @@ caldav_server_put_object (ECalBackendCalDAV *cbdav,
 			}
 		}
 
-		if (!caldav_server_get_object (cbdav, object, &local_error)) {
+		if (!caldav_server_get_object (cbdav, object, cancellable, &local_error)) {
 			if (g_error_matches (local_error, E_DATA_CAL_ERROR, ObjectNotFound)) {
 				gchar *file;
 
@@ -1754,7 +1780,7 @@ caldav_server_put_object (ECalBackendCalDAV *cbdav,
 					g_free (object->href);
 					object->href = file;
 
-					if (!caldav_server_get_object (cbdav, object, &local_error)) {
+					if (!caldav_server_get_object (cbdav, object, cancellable, &local_error)) {
 						if (g_error_matches (local_error, E_DATA_CAL_ERROR, ObjectNotFound)) {
 							g_clear_error (&local_error);
 
@@ -1798,6 +1824,7 @@ caldav_server_put_object (ECalBackendCalDAV *cbdav,
 static void
 caldav_server_delete_object (ECalBackendCalDAV *cbdav,
                              CalDAVObject *object,
+			     GCancellable *cancellable,
                              GError **perror)
 {
 	SoupMessage              *message;
@@ -1823,7 +1850,7 @@ caldav_server_delete_object (ECalBackendCalDAV *cbdav,
 			"If-Match", object->etag);
 	}
 
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, cancellable, perror);
 
 	status_code_to_result (message, cbdav, FALSE, perror);
 
@@ -1834,7 +1861,9 @@ caldav_server_delete_object (ECalBackendCalDAV *cbdav,
 }
 
 static gboolean
-caldav_receive_schedule_outbox_url (ECalBackendCalDAV *cbdav)
+caldav_receive_schedule_outbox_url (ECalBackendCalDAV *cbdav,
+				    GCancellable *cancellable,
+				    GError **error)
 {
 	SoupMessage *message;
 	xmlOutputBufferPtr buf;
@@ -1876,7 +1905,7 @@ caldav_receive_schedule_outbox_url (ECalBackendCalDAV *cbdav)
 		buf_content, buf_size);
 
 	/* Send the request now */
-	send_and_handle_redirection (cbdav->priv->session, message, NULL);
+	send_and_handle_redirection (cbdav, message, NULL, cancellable, error);
 
 	/* Clean up the memory */
 	xmlOutputBufferClose (buf);
@@ -1927,7 +1956,7 @@ caldav_receive_schedule_outbox_url (ECalBackendCalDAV *cbdav)
 			buf_content, buf_size);
 
 		/* Send the request now */
-		send_and_handle_redirection (cbdav->priv->session, message, NULL);
+		send_and_handle_redirection (cbdav, message, NULL, cancellable, error);
 
 		if (message->status_code == 207 && parse_propfind_response (message, XPATH_SCHEDULE_OUTBOX_URL_STATUS, XPATH_SCHEDULE_OUTBOX_URL, &cbdav->priv->schedule_outbox_url)) {
 			if (!*cbdav->priv->schedule_outbox_url) {
@@ -2371,7 +2400,7 @@ caldav_synch_slave_loop (gpointer data)
 			GError *local_error = NULL;
 			gboolean online;
 
-			if (caldav_server_open_calendar (cbdav, &server_unreachable, &local_error)) {
+			if (caldav_server_open_calendar (cbdav, &server_unreachable, NULL, &local_error)) {
 				cbdav->priv->opened = TRUE;
 				update_slave_cmd (cbdav->priv, SLAVE_SHOULD_WORK);
 				g_cond_signal (&cbdav->priv->cond);
@@ -2726,6 +2755,7 @@ initialize_backend (ECalBackendCalDAV *cbdav,
 
 static gboolean
 open_calendar (ECalBackendCalDAV *cbdav,
+	       GCancellable *cancellable,
                GError **error)
 {
 	gboolean server_unreachable = FALSE;
@@ -2738,7 +2768,7 @@ open_calendar (ECalBackendCalDAV *cbdav,
 	proxy_settings_changed (cbdav->priv->proxy, cbdav->priv);
 
 	success = caldav_server_open_calendar (
-		cbdav, &server_unreachable, &local_error);
+		cbdav, &server_unreachable, cancellable, &local_error);
 
 	if (success) {
 		update_slave_cmd (cbdav->priv, SLAVE_SHOULD_WORK);
@@ -2801,7 +2831,7 @@ caldav_do_open (ECalBackendSync *backend,
 	if (online) {
 		GError *local_error = NULL;
 
-		opened = open_calendar (cbdav, &local_error);
+		opened = open_calendar (cbdav, cancellable, &local_error);
 
 		if (g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationRequired) || g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationFailed)) {
 			g_clear_error (&local_error);
@@ -3690,6 +3720,7 @@ do_create_objects (ECalBackendCalDAV *cbdav,
                    const GSList *in_calobjs,
                    GSList **uids,
                    GSList **new_components,
+		   GCancellable *cancellable,
                    GError **perror)
 {
 	ECalComponent            *comp;
@@ -3762,7 +3793,7 @@ do_create_objects (ECalBackendCalDAV *cbdav,
 		object.etag  = NULL;
 		object.cdata = pack_cobj (cbdav, icalcomp);
 
-		did_put = caldav_server_put_object (cbdav, &object, icalcomp, perror);
+		did_put = caldav_server_put_object (cbdav, &object, icalcomp, cancellable, perror);
 
 		caldav_object_free (&object, FALSE);
 	} else {
@@ -3788,6 +3819,7 @@ do_modify_objects (ECalBackendCalDAV *cbdav,
                    CalObjModType mod,
                    GSList **old_components,
                    GSList **new_components,
+		   GCancellable *cancellable,
                    GError **error)
 {
 	ECalComponent            *comp;
@@ -3927,7 +3959,7 @@ do_modify_objects (ECalBackendCalDAV *cbdav,
 		object.etag  = etag;
 		object.cdata = pack_cobj (cbdav, cache_comp);
 
-		did_put = caldav_server_put_object (cbdav, &object, cache_comp, error);
+		did_put = caldav_server_put_object (cbdav, &object, cache_comp, cancellable, error);
 
 		caldav_object_free (&object, FALSE);
 		href = NULL;
@@ -3958,6 +3990,7 @@ do_remove_objects (ECalBackendCalDAV *cbdav,
                    CalObjModType mod,
                    GSList **old_components,
                    GSList **new_components,
+		   GCancellable *cancellable,
                    GError **perror)
 {
 	icalcomponent            *cache_comp;
@@ -4040,9 +4073,9 @@ do_remove_objects (ECalBackendCalDAV *cbdav,
 		if (mod == CALOBJ_MOD_THIS && rid && *rid) {
 			caldav_object.cdata = pack_cobj (cbdav, cache_comp);
 
-			caldav_server_put_object (cbdav, &caldav_object, cache_comp, perror);
+			caldav_server_put_object (cbdav, &caldav_object, cache_comp, cancellable, perror);
 		} else
-			caldav_server_delete_object (cbdav, &caldav_object, perror);
+			caldav_server_delete_object (cbdav, &caldav_object, cancellable, perror);
 
 		caldav_object_free (&caldav_object, FALSE);
 		href = NULL;
@@ -4134,6 +4167,7 @@ process_object (ECalBackendCalDAV *cbdav,
                 ECalComponent *ecomp,
                 gboolean online,
                 icalproperty_method method,
+		GCancellable *cancellable,
                 GError **error)
 {
 	ESourceRegistry *registry;
@@ -4175,7 +4209,7 @@ process_object (ECalBackendCalDAV *cbdav,
 
 				new_obj_strs.data = new_obj_str;
 				do_modify_objects (cbdav, &new_obj_strs, mod,
-						  &old_components, &new_components, &err);
+						  &old_components, &new_components, cancellable, &err);
 				if (!err && new_components && new_components->data) {
 					if (!old_components || !old_components->data) {
 						e_cal_backend_notify_component_created (backend, new_components->data);
@@ -4191,7 +4225,7 @@ process_object (ECalBackendCalDAV *cbdav,
 				GSList ids = {0,};
 
 				ids.data = id;
-				do_remove_objects (cbdav, &ids, mod, &old_components, &new_components, &err);
+				do_remove_objects (cbdav, &ids, mod, &old_components, &new_components, cancellable, &err);
 				if (!err && old_components && old_components->data) {
 					if (new_components && new_components->data) {
 						e_cal_backend_notify_component_modified (backend, old_components->data, new_components->data);
@@ -4209,7 +4243,7 @@ process_object (ECalBackendCalDAV *cbdav,
 
 			new_objs.data = new_obj_str;
 
-			do_create_objects (cbdav, &new_objs, NULL, &new_components, &err);
+			do_create_objects (cbdav, &new_objs, NULL, &new_components, cancellable, &err);
 
 			if (!err) {
 				if (new_components && new_components->data)
@@ -4225,7 +4259,7 @@ process_object (ECalBackendCalDAV *cbdav,
 			GSList ids = {0,};
 
 			ids.data = id;
-			do_remove_objects (cbdav, &ids, CALOBJ_MOD_THIS, &old_components, &new_components, &err);
+			do_remove_objects (cbdav, &ids, CALOBJ_MOD_THIS, &old_components, &new_components, cancellable, &err);
 			if (!err && old_components && old_components->data) {
 				if (new_components && new_components->data) {
 					e_cal_backend_notify_component_modified (backend, old_components->data, new_components->data);
@@ -4311,7 +4345,7 @@ do_receive_objects (ECalBackendSync *backend,
 			method = tmethod;
 		}
 
-		process_object (cbdav, ecomp, online, method, &err);
+		process_object (cbdav, ecomp, online, method, cancellable, &err);
 		g_object_unref (ecomp);
 	}
 
@@ -4367,6 +4401,7 @@ caldav_busy_stub (
                   in_calobjs,
                   uids,
                   new_components,
+		  cancellable,
                   perror))
 
 caldav_busy_stub (
@@ -4385,6 +4420,7 @@ caldav_busy_stub (
                   mod,
                   old_components,
                   new_components,
+		  cancellable,
                   perror))
 
 caldav_busy_stub (
@@ -4403,6 +4439,7 @@ caldav_busy_stub (
                   mod,
                   old_components,
                   new_components,
+		  cancellable,
                   perror))
 
 caldav_busy_stub (
@@ -4636,10 +4673,11 @@ caldav_get_free_busy (ECalBackendSync *backend,
 	}
 
 	if (!cbdav->priv->schedule_outbox_url) {
-		caldav_receive_schedule_outbox_url (cbdav);
+		caldav_receive_schedule_outbox_url (cbdav, cancellable, error);
 		if (!cbdav->priv->schedule_outbox_url) {
 			cbdav->priv->calendar_schedule = FALSE;
-			g_propagate_error (error, EDC_ERROR_EX (OtherError, _("Schedule outbox url not found")));
+			if (error && !*error)
+				g_propagate_error (error, EDC_ERROR_EX (OtherError, _("Schedule outbox url not found")));
 			return;
 		}
 	}
@@ -4720,7 +4758,7 @@ caldav_get_free_busy (ECalBackendSync *backend,
 
 	e_return_data_cal_error_if_fail (str != NULL, OtherError);
 
-	caldav_post_freebusy (cbdav, cbdav->priv->schedule_outbox_url, &str, &err);
+	caldav_post_freebusy (cbdav, cbdav->priv->schedule_outbox_url, &str, cancellable, &err);
 
 	if (!err) {
 		/* parse returned xml */
@@ -4911,7 +4949,7 @@ caldav_try_password_sync (ESourceAuthenticator *authenticator,
 	g_free (cbdav->priv->password);
 	cbdav->priv->password = g_strdup (password->str);
 
-	open_calendar (cbdav, &local_error);
+	open_calendar (cbdav, cancellable, &local_error);
 
 	if (local_error == NULL) {
 		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
@@ -5017,23 +5055,6 @@ e_cal_backend_caldav_finalize (GObject *object)
 static void
 cal_backend_caldav_constructed (GObject *object)
 {
-	ESource *source;
-	ESourceWebdav *extension;
-	ECalBackendCalDAV *cbdav;
-	const gchar *extension_name;
-
-	cbdav = E_CAL_BACKEND_CALDAV (object);
-
-	source = e_backend_get_source (E_BACKEND (cbdav));
-	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
-	extension = e_source_get_extension (source, extension_name);
-
-	g_object_bind_property (
-		extension, "ignore-invalid-cert",
-		cbdav->priv->session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
-		G_BINDING_SYNC_CREATE |
-		G_BINDING_INVERT_BOOLEAN);
-
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (e_cal_backend_caldav_parent_class)->
 		constructed (object);
diff --git a/calendar/backends/http/e-cal-backend-http.c b/calendar/backends/http/e-cal-backend-http.c
index 30daea6..f07bdcc 100644
--- a/calendar/backends/http/e-cal-backend-http.c
+++ b/calendar/backends/http/e-cal-backend-http.c
@@ -160,31 +160,21 @@ e_cal_backend_http_finalize (GObject *object)
 static void
 e_cal_backend_http_constructed (GObject *object)
 {
-	ESource *source;
 	ECalBackendHttp *backend;
-	ESourceWebdav *extension;
 	SoupSession *soup_session;
-	const gchar *extension_name;
 
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (e_cal_backend_http_parent_class)->constructed (object);
 
 	soup_session = soup_session_sync_new ();
-	g_object_set (soup_session, SOUP_SESSION_TIMEOUT, 90, NULL);
+	g_object_set (soup_session,
+		SOUP_SESSION_TIMEOUT, 90,
+		SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
+		NULL);
 
 	backend = E_CAL_BACKEND_HTTP (object);
 	backend->priv->soup_session = soup_session;
 
-	source = e_backend_get_source (E_BACKEND (backend));
-	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
-	extension = e_source_get_extension (source, extension_name);
-
-	g_object_bind_property (
-		extension, "ignore-invalid-cert",
-		soup_session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
-		G_BINDING_SYNC_CREATE |
-		G_BINDING_INVERT_BOOLEAN);
-
 	g_signal_connect (
 		backend->priv->soup_session, "authenticate",
 		G_CALLBACK (soup_authenticate), backend);
@@ -495,6 +485,34 @@ cal_backend_http_load (ECalBackendHttp *backend,
 	}
 
 	status_code = soup_session_send_message (soup_session, soup_message);
+	if (status_code == SOUP_STATUS_SSL_FAILED) {
+		ESource *source;
+		ESourceWebdav *extension;
+		EBackend *ebackend;
+		ETrustPromptResponse response;
+		ENamedParameters *parameters;
+
+		ebackend = E_BACKEND (backend);
+		source = e_backend_get_source (ebackend);
+		extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+		parameters = e_named_parameters_new ();
+
+		response = e_source_webdav_prepare_ssl_trust_prompt (extension, soup_message, parameters);
+		if (response == E_TRUST_PROMPT_RESPONSE_UNKNOWN) {
+			response = e_backend_trust_prompt_sync (ebackend, parameters, cancellable, NULL);
+			if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN)
+				e_source_webdav_store_ssl_trust_prompt (extension, soup_message, response);
+		}
+
+		e_named_parameters_free (parameters);
+
+		if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT ||
+		    response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+			g_object_set (soup_session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE, NULL);
+			status_code = soup_session_send_message (soup_session, soup_message);
+		}
+	}
 
 	if (G_IS_CANCELLABLE (cancellable))
 		g_cancellable_disconnect (cancellable, cancel_id);
@@ -839,6 +857,7 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	ESource *source;
 	ESourceRegistry *registry;
 	ESourceAuthentication *auth_extension;
+	ESourceWebdav *webdav_extension;
 	const gchar *extension_name;
 	const gchar *cache_dir;
 	gboolean auth_required;
@@ -865,6 +884,12 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	auth_extension = e_source_get_extension (source, extension_name);
 	auth_required = e_source_authentication_required (auth_extension);
 
+	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+	webdav_extension = e_source_get_extension (source, extension_name);
+
+	g_object_set (cbhttp->priv->soup_session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE, NULL);
+	e_source_webdav_unset_temporary_ssl_trust (webdav_extension);
+
 	if (priv->source_changed_id == 0) {
 		priv->source_changed_id = g_signal_connect (
 			source, "changed",
diff --git a/libebackend/e-backend.c b/libebackend/e-backend.c
index d24ba37..fd7c556 100644
--- a/libebackend/e-backend.c
+++ b/libebackend/e-backend.c
@@ -31,13 +31,16 @@
  * All #EBackend instances are created by an #EBackendFactory.
  **/
 
-#include "e-backend.h"
-
 #include <config.h>
 #include <glib/gi18n-lib.h>
 
 #include <gio/gio.h>
 
+#include <libedataserver/libedataserver.h>
+
+#include "e-backend.h"
+#include "e-user-prompter.h"
+
 #define E_BACKEND_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), E_TYPE_BACKEND, EBackendPrivate))
@@ -46,6 +49,7 @@ typedef struct _AsyncContext AsyncContext;
 
 struct _EBackendPrivate {
 	ESource *source;
+	EUserPrompter *prompter;
 	gboolean online;
 };
 
@@ -56,7 +60,8 @@ struct _AsyncContext {
 enum {
 	PROP_0,
 	PROP_ONLINE,
-	PROP_SOURCE
+	PROP_SOURCE,
+	PROP_USER_PROMPTER
 };
 
 G_DEFINE_ABSTRACT_TYPE (EBackend, e_backend, G_TYPE_OBJECT)
@@ -121,6 +126,12 @@ backend_get_property (GObject *object,
 				value, e_backend_get_source (
 				E_BACKEND (object)));
 			return;
+
+		case PROP_USER_PROMPTER:
+			g_value_set_object (
+				value, e_backend_get_user_prompter (
+				E_BACKEND (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -138,6 +149,11 @@ backend_dispose (GObject *object)
 		priv->source = NULL;
 	}
 
+	if (priv->prompter) {
+		g_object_unref (priv->prompter);
+		priv->prompter = NULL;
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (e_backend_parent_class)->dispose (object);
 }
@@ -280,12 +296,24 @@ e_backend_class_init (EBackendClass *class)
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT_ONLY |
 			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_USER_PROMPTER,
+		g_param_spec_object (
+			"user-prompter",
+			"User Prompter",
+			"User prompter instance",
+			E_TYPE_USER_PROMPTER,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
 }
 
 static void
 e_backend_init (EBackend *backend)
 {
 	backend->priv = E_BACKEND_GET_PRIVATE (backend);
+	backend->priv->prompter = e_user_prompter_new ();
 }
 
 /**
@@ -461,3 +489,147 @@ e_backend_authenticate_finish (EBackend *backend,
 	return class->authenticate_finish (backend, result, error);
 }
 
+/**
+ * e_backend_get_user_prompter:
+ * @backend: an #EBackend
+ *
+ * Gets an instance of #EUserPrompter, associated with this @backend.
+ * The instance is owned by the @backend.
+ *
+ * Returns: (transfer-none): an #EUserPrompter instance
+ *
+ * Since: 3.8
+ **/
+EUserPrompter *
+e_backend_get_user_prompter (EBackend *backend)
+{
+	g_return_val_if_fail (E_IS_BACKEND (backend), NULL);
+
+	return backend->priv->prompter;
+}
+
+/**
+ * e_backend_trust_prompt_sync:
+ * @backend: an #EBackend
+ * @parameters: an #ENamedParameters with values for the trust prompt
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Asks a user a trust prompt with given @parameters, and returns what
+ * user responded. This blocks until the response is delivered.
+ *
+ * Returns: an #ETrustPromptResponse what user responded
+ *
+ * Note: The function can return also %E_TRUST_PROMPT_RESPONSE_UNKNOWN,
+ *    it's on error or if user closes the trust prompt dialog with other
+ *    than the offered buttons. Usual behaviour in such case is to treat
+ *    it as a temporary reject.
+ *
+ * Since: 3.8
+ **/
+ETrustPromptResponse
+e_backend_trust_prompt_sync (EBackend *backend,
+			     const ENamedParameters *parameters,
+			     GCancellable *cancellable,
+			     GError **error)
+{
+	EUserPrompter *prompter;
+	gint response;
+
+	g_return_val_if_fail (E_IS_BACKEND (backend), E_TRUST_PROMPT_RESPONSE_UNKNOWN);
+	g_return_val_if_fail (parameters != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
+
+	prompter = e_backend_get_user_prompter (backend);
+	g_return_val_if_fail (prompter != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
+
+	response = e_user_prompter_extension_prompt_sync (prompter, "ETrustPrompt::trust-prompt", parameters, NULL, cancellable, error);
+
+	if (response == 0)
+		return E_TRUST_PROMPT_RESPONSE_REJECT;
+	if (response == 1)
+		return E_TRUST_PROMPT_RESPONSE_ACCEPT;
+	if (response == 2)
+		return E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY;
+	if (response == -1)
+		return E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;
+
+	return E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+}
+
+/**
+ * e_backend_trust_prompt:
+ * @backend: an #EBackend
+ * @parameters: an #ENamedParameters with values for the trust prompt
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Initiates a user trust prompt with given @parameters.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_backend_trust_prompt_finish() to get the result of the operation.
+ *
+ * Since: 3.8
+ **/
+void
+e_backend_trust_prompt (EBackend *backend,
+			const ENamedParameters *parameters,
+			GCancellable *cancellable,
+			GAsyncReadyCallback callback,
+			gpointer user_data)
+{
+	EUserPrompter *prompter;
+
+	g_return_if_fail (E_IS_BACKEND (backend));
+	g_return_if_fail (parameters != NULL);
+
+	prompter = e_backend_get_user_prompter (backend);
+	g_return_if_fail (prompter != NULL);
+
+	e_user_prompter_extension_prompt (prompter, "ETrustPrompt::trust-prompt", parameters, cancellable, callback, user_data);
+}
+
+/**
+ * e_backend_trust_prompt_finish:
+ * @backend: an #EBackend
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_backend_trust_prompt().  If
+ * an error occurred, the function will set @error and return %E_TRUST_PROMPT_RESPONSE_UNKNOWN.
+ *
+ * Returns: an #ETrustPromptResponse what user responded
+ *
+ * Note: The function can return also %E_TRUST_PROMPT_RESPONSE_UNKNOWN,
+ *    it's on error or if user closes the trust prompt dialog with other
+ *    than the offered buttons. Usual behaviour in such case is to treat
+ *    it as a temporary reject.
+ *
+ * Since: 3.8
+ **/
+ETrustPromptResponse
+e_backend_trust_prompt_finish (EBackend *backend,
+			       GAsyncResult *result,
+			       GError **error)
+{
+	EUserPrompter *prompter;
+	gint response;
+
+	g_return_val_if_fail (E_IS_BACKEND (backend), E_TRUST_PROMPT_RESPONSE_UNKNOWN);
+
+	prompter = e_backend_get_user_prompter (backend);
+	g_return_val_if_fail (prompter != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
+
+	response = e_user_prompter_extension_prompt_finish (prompter, result, NULL, error);
+
+	if (response == 0)
+		return E_TRUST_PROMPT_RESPONSE_REJECT;
+	if (response == 1)
+		return E_TRUST_PROMPT_RESPONSE_ACCEPT;
+	if (response == 2)
+		return E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY;
+	if (response == -1)
+		return E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;
+
+	return E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+}
diff --git a/libebackend/e-backend.h b/libebackend/e-backend.h
index 30b697e..65b8e8b 100644
--- a/libebackend/e-backend.h
+++ b/libebackend/e-backend.h
@@ -46,6 +46,9 @@
 
 G_BEGIN_DECLS
 
+/* forward declaration */
+struct _EUserPrompter;
+
 typedef struct _EBackend EBackend;
 typedef struct _EBackendClass EBackendClass;
 typedef struct _EBackendPrivate EBackendPrivate;
@@ -100,6 +103,22 @@ void		e_backend_authenticate		(EBackend *backend,
 gboolean	e_backend_authenticate_finish	(EBackend *backend,
 						 GAsyncResult *result,
 						 GError **error);
+struct _EUserPrompter *
+		e_backend_get_user_prompter	(EBackend *backend);
+ETrustPromptResponse
+		e_backend_trust_prompt_sync	(EBackend *backend,
+						 const ENamedParameters *parameters,
+						 GCancellable *cancellable,
+						 GError **error);
+void		e_backend_trust_prompt		(EBackend *backend,
+						 const ENamedParameters *parameters,
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+ETrustPromptResponse
+		e_backend_trust_prompt_finish	(EBackend *backend,
+						 GAsyncResult *result,
+						 GError **error);
 
 G_END_DECLS
 
diff --git a/libedataserver/e-source-webdav.c b/libedataserver/e-source-webdav.c
index e0ae6ba..1d0cb8b 100644
--- a/libedataserver/e-source-webdav.c
+++ b/libedataserver/e-source-webdav.c
@@ -60,9 +60,9 @@ struct _ESourceWebdavPrivate {
 	gchar *email_address;
 	gchar *resource_path;
 	gchar *resource_query;
+	gchar *ssl_trust;
 	gboolean avoid_ifmatch;
 	gboolean calendar_auto_schedule;
-	gboolean ignore_invalid_cert;
 	SoupURI *soup_uri;
 };
 
@@ -72,7 +72,7 @@ enum {
 	PROP_CALENDAR_AUTO_SCHEDULE,
 	PROP_DISPLAY_NAME,
 	PROP_EMAIL_ADDRESS,
-	PROP_IGNORE_INVALID_CERT,
+	PROP_SSL_TRUST,
 	PROP_RESOURCE_PATH,
 	PROP_RESOURCE_QUERY,
 	PROP_SOUP_URI
@@ -256,12 +256,6 @@ source_webdav_set_property (GObject *object,
 				g_value_get_string (value));
 			return;
 
-		case PROP_IGNORE_INVALID_CERT:
-			e_source_webdav_set_ignore_invalid_cert (
-				E_SOURCE_WEBDAV (object),
-				g_value_get_boolean (value));
-			return;
-
 		case PROP_RESOURCE_PATH:
 			e_source_webdav_set_resource_path (
 				E_SOURCE_WEBDAV (object),
@@ -274,6 +268,12 @@ source_webdav_set_property (GObject *object,
 				g_value_get_string (value));
 			return;
 
+		case PROP_SSL_TRUST:
+			e_source_webdav_set_ssl_trust (
+				E_SOURCE_WEBDAV (object),
+				g_value_get_string (value));
+			return;
+
 		case PROP_SOUP_URI:
 			e_source_webdav_set_soup_uri (
 				E_SOURCE_WEBDAV (object),
@@ -319,13 +319,6 @@ source_webdav_get_property (GObject *object,
 				E_SOURCE_WEBDAV (object)));
 			return;
 
-		case PROP_IGNORE_INVALID_CERT:
-			g_value_set_boolean (
-				value,
-				e_source_webdav_get_ignore_invalid_cert (
-				E_SOURCE_WEBDAV (object)));
-			return;
-
 		case PROP_RESOURCE_PATH:
 			g_value_take_string (
 				value,
@@ -340,6 +333,13 @@ source_webdav_get_property (GObject *object,
 				E_SOURCE_WEBDAV (object)));
 			return;
 
+		case PROP_SSL_TRUST:
+			g_value_take_string (
+				value,
+				e_source_webdav_dup_ssl_trust (
+				E_SOURCE_WEBDAV (object)));
+			return;
+
 		case PROP_SOUP_URI:
 			g_value_take_boxed (
 				value,
@@ -364,6 +364,7 @@ source_webdav_finalize (GObject *object)
 	g_free (priv->email_address);
 	g_free (priv->resource_path);
 	g_free (priv->resource_query);
+	g_free (priv->ssl_trust);
 
 	soup_uri_free (priv->soup_uri);
 
@@ -500,18 +501,6 @@ e_source_webdav_class_init (ESourceWebdavClass *class)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_IGNORE_INVALID_CERT,
-		g_param_spec_boolean (
-			"ignore-invalid-cert",
-			"Ignore Invalid Cert",
-			"Ignore invalid SSL certificates",
-			FALSE,
-			G_PARAM_READWRITE |
-			G_PARAM_CONSTRUCT |
-			E_SOURCE_PARAM_SETTING));
-
-	g_object_class_install_property (
-		object_class,
 		PROP_RESOURCE_PATH,
 		g_param_spec_string (
 			"resource-path",
@@ -536,6 +525,18 @@ e_source_webdav_class_init (ESourceWebdavClass *class)
 
 	g_object_class_install_property (
 		object_class,
+		PROP_SSL_TRUST,
+		g_param_spec_string (
+			"ssl-trust",
+			"SSL Trust",
+			"SSL certificate trust setting, for invalid server certificates",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			E_SOURCE_PARAM_SETTING));
+
+	g_object_class_install_property (
+		object_class,
 		PROP_SOUP_URI,
 		g_param_spec_boxed (
 			"soup-uri",
@@ -832,53 +833,6 @@ e_source_webdav_set_email_address (ESourceWebdav *extension,
 }
 
 /**
- * e_source_webdav_get_ignore_invalid_cert:
- * @extension: an #ESourceWebdav
- *
- * Returns %TRUE if invalid SSL certificates should be ignored.
- *
- * This option allows SSL certificates to be accepted even if they have
- * signed by an unrecognized Certificate Authority.
- *
- * Returns: whether invalid SSL certificates should be ignored
- *
- * Since: 3.6
- **/
-gboolean
-e_source_webdav_get_ignore_invalid_cert (ESourceWebdav *extension)
-{
-	g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
-
-	return extension->priv->ignore_invalid_cert;
-}
-
-/**
- * e_source_webdav_set_ignore_invalid_cert:
- * @extension: an #ESourceWebdav
- * @ignore_invalid_cert: whether invalid SSL certificates should be ignored
- *
- * Sets whether invalid SSL certificates should be ignored.
- *
- * This option allows SSL certificates to be accepted even if they have
- * signed by an unrecognized Certificate Authority.
- *
- * Since: 3.6
- **/
-void
-e_source_webdav_set_ignore_invalid_cert (ESourceWebdav *extension,
-                                         gboolean ignore_invalid_cert)
-{
-	g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
-
-	if (extension->priv->ignore_invalid_cert == ignore_invalid_cert)
-		return;
-
-	extension->priv->ignore_invalid_cert = ignore_invalid_cert;
-
-	g_object_notify (G_OBJECT (extension), "ignore-invalid-cert");
-}
-
-/**
  * e_source_webdav_get_resource_path:
  * @extension: an #ESourceWebdav
  *
@@ -1057,6 +1011,93 @@ e_source_webdav_set_resource_query (ESourceWebdav *extension,
 }
 
 /**
+ * e_source_webdav_get_ssl_trust:
+ * @extension: an #ESourceWebdav
+ *
+ * Returns an SSL certificate trust for the @extension.
+ * The value encodes three parameters, divided by a pipe '|',
+ * the first is users preference, can be one of "reject", "accept",
+ * "temporary-reject" and "temporary-accept". The second is a host
+ * name for which the trust was set. Finally the last is a SHA1
+ * hash of the certificate. This is not meant to be changed by a caller,
+ * it is supposed to be manipulated with e_source_webdav_prepare_ssl_trust_prompt()
+ * and e_source_webdav_store_ssl_trust_prompt().
+ *
+ * Returns: an SSL certificate trust for the @extension
+ *
+ * Since: 3.8
+ **/
+const gchar *
+e_source_webdav_get_ssl_trust (ESourceWebdav *extension)
+{
+	g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+
+	return extension->priv->ssl_trust;
+}
+
+/**
+ * e_source_webdav_dup_ssl_trust:
+ * @extension: an #ESourceWebdav
+ *
+ * Thread-safe variation of e_source_webdav_get_ssl_trust().
+ * Use this function when accessing @extension from multiple threads.
+ *
+ * The returned string should be freed with g_free() when no longer needed.
+ *
+ * Returns: the newly-allocated copy of #ESourceWebdav:ssl-trust
+ *
+ * Since: 3.8
+ **/
+gchar *
+e_source_webdav_dup_ssl_trust (ESourceWebdav *extension)
+{
+	const gchar *protected;
+	gchar *duplicate;
+
+	g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+
+	g_mutex_lock (&extension->priv->property_lock);
+
+	protected = e_source_webdav_get_ssl_trust (extension);
+	duplicate = g_strdup (protected);
+
+	g_mutex_unlock (&extension->priv->property_lock);
+
+	return duplicate;
+}
+
+/**
+ * e_source_webdav_set_ssl_trust:
+ * @extension: an #ESourceWebdav
+ * @ssl_trust: (allow-none): the ssl_trust to store, or %NULL to unset
+ *
+ * Sets the SSL certificate trust. See e_source_webdav_get_ssl_trust()
+ * for more infomation about its content and how to use it.
+ *
+ * Since: 3.8
+ **/
+void
+e_source_webdav_set_ssl_trust (ESourceWebdav *extension,
+			       const gchar *ssl_trust)
+{
+	g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+
+	g_mutex_lock (&extension->priv->property_lock);
+
+	if (g_strcmp0 (extension->priv->ssl_trust, ssl_trust) == 0) {
+		g_mutex_unlock (&extension->priv->property_lock);
+		return;
+	}
+
+	g_free (extension->priv->ssl_trust);
+	extension->priv->ssl_trust = g_strdup (ssl_trust);
+
+	g_mutex_unlock (&extension->priv->property_lock);
+
+	g_object_notify (G_OBJECT (extension), "ssl-trust");
+}
+
+/**
  * e_source_webdav_dup_soup_uri:
  * @extension: an #ESourceWebdav
  *
@@ -1123,3 +1164,271 @@ e_source_webdav_set_soup_uri (ESourceWebdav *extension,
 	g_object_thaw_notify (G_OBJECT (extension));
 }
 
+static gboolean
+decode_ssl_trust (ESourceWebdav *extension,
+		  ETrustPromptResponse *response,
+		  gchar **host,
+		  gchar **hash)
+{
+	gchar *ssl_trust, **strv;
+
+	g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
+
+	ssl_trust = e_source_webdav_dup_ssl_trust (extension);
+	if (!ssl_trust || !*ssl_trust) {
+		g_free (ssl_trust);
+		return FALSE;
+	}
+
+	strv = g_strsplit (ssl_trust, "|", 3);
+	if (!strv || !strv[0] || !strv[1] || !strv[2] || strv[3]) {
+		g_free (ssl_trust);
+		g_strfreev (strv);
+		return FALSE;
+	}
+
+	if (response) {
+		const gchar *resp = strv[0];
+
+		if (g_strcmp0 (resp, "reject") == 0)
+			*response = E_TRUST_PROMPT_RESPONSE_REJECT;
+		else if (g_strcmp0 (resp, "accept") == 0)
+			*response = E_TRUST_PROMPT_RESPONSE_ACCEPT;
+		else if (g_strcmp0 (resp, "temporary-reject") == 0)
+			*response = E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;
+		else if (g_strcmp0 (resp, "temporary-accept") == 0)
+			*response = E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY;
+		else
+			*response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+	}
+
+	if (host)
+		*host = g_strdup (strv[1]);
+
+	if (hash)
+		*hash = g_strdup (strv[2]);
+
+	g_free (ssl_trust);
+	g_strfreev (strv);
+
+	return TRUE;
+}
+
+static void
+encode_ssl_trust (ESourceWebdav *extension,
+		  ETrustPromptResponse response,
+		  const gchar *host,
+		  const gchar *hash)
+{
+	gchar *ssl_trust;
+	const gchar *resp;
+
+	g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+
+	if (response == E_TRUST_PROMPT_RESPONSE_REJECT)
+		resp = "reject";
+	else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT)
+		resp = "accept";
+	else if (response == E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY)
+		resp = "temporary-reject";
+	else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY)
+		resp = "temporary-accept";
+	else
+		resp = "temporary-reject";
+
+	if (host && *host && hash && *hash) {
+		ssl_trust = g_strconcat (resp, "|", host, "|", hash, NULL);
+	} else {
+		ssl_trust = NULL;
+	}
+
+	e_source_webdav_set_ssl_trust (extension, ssl_trust);
+}
+
+/**
+ * e_source_webdav_prepare_ssl_trust_prompt:
+ * @extension: an #ESourceWebdav
+ * @message: a #SoupMessage with #SOUP_STATUS_SSL_FAILED status code
+ * @parameters: an #ENamedParameters to be populated
+ *
+ * Checks @messages<!-- -->'s certificate against currently stored trust
+ * response and either returns what to do immediately, or returns
+ * #E_TRUST_PROMPT_RESPONSE_UNKNOWN and populates @parameters with necessary
+ * values for a trust prompt.
+ *
+ * Returns: What to do with SSL connection, where #E_TRUST_PROMPT_RESPONSE_UNKNOWN
+ *   means 'ask a user, with populated parameters'.
+ *
+ * Note: The #E_TRUST_PROMPT_RESPONSE_REJECT is returned on any errors, like
+ *  the @message not being with the #SOUP_STATUS_SSL_FAILED status code,
+ *  no certificate being stored in the @message and so on.
+ *
+ * Since: 3.8
+ **/
+ETrustPromptResponse
+e_source_webdav_prepare_ssl_trust_prompt (ESourceWebdav *extension,
+					  SoupMessage *message,
+					  ENamedParameters *parameters)
+{
+	ETrustPromptResponse response;
+	GTlsCertificate *cert = NULL;
+	GTlsCertificateFlags cert_errors = 0;
+	GByteArray *bytes = NULL;
+	SoupURI *soup_uri;
+	const gchar *host;
+	gchar *base64, *old_host = NULL, *old_hash = NULL, *cert_errs_str;
+	gint issuer_count;
+
+	g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), E_TRUST_PROMPT_RESPONSE_REJECT);
+	g_return_val_if_fail (SOUP_IS_MESSAGE (message), E_TRUST_PROMPT_RESPONSE_REJECT);
+	g_return_val_if_fail (parameters != NULL, E_TRUST_PROMPT_RESPONSE_REJECT);
+
+	if (message->status_code != SOUP_STATUS_SSL_FAILED)
+		return E_TRUST_PROMPT_RESPONSE_REJECT;
+
+	if (!soup_message_get_https_status (message, &cert, &cert_errors) || !cert)
+		return E_TRUST_PROMPT_RESPONSE_REJECT;
+
+	soup_uri = soup_message_get_uri (message);
+	if (!soup_uri || !soup_uri_get_host (soup_uri))
+		return E_TRUST_PROMPT_RESPONSE_REJECT;
+
+	g_object_get (cert, "certificate", &bytes, NULL);
+	if (!bytes)
+		return E_TRUST_PROMPT_RESPONSE_REJECT;
+
+	host = soup_uri_get_host (soup_uri);
+
+	if (decode_ssl_trust (extension, &response, &old_host, &old_hash)) {
+		gchar *hash = g_compute_checksum_for_data (G_CHECKSUM_SHA1, bytes->data, bytes->len);
+
+		if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN &&
+		    g_strcmp0 (old_host, host) == 0 &&
+		    g_strcmp0 (old_hash, hash) == 0) {
+			g_free (old_host);
+			g_free (old_hash);
+			g_free (hash);
+
+			return response;
+		}
+
+		g_free (old_host);
+		g_free (old_hash);
+		g_free (hash);
+	}
+
+	base64 = g_base64_encode (bytes->data, bytes->len);
+	cert_errs_str = g_strdup_printf ("%x", cert_errors);
+
+	e_named_parameters_set (parameters, "host", host);
+	e_named_parameters_set (parameters, "certificate", base64);
+	e_named_parameters_set (parameters, "certificate-errors", cert_errs_str);
+
+	g_byte_array_unref (bytes);
+	g_free (cert_errs_str);
+
+	issuer_count = 0;
+	while (cert) {
+		cert = NULL;
+		g_object_get (cert, "issuer", &cert, NULL);
+
+		if (cert) {
+			bytes = NULL;
+			g_object_get (cert, "certificate", &bytes, NULL);
+
+			if (bytes) {
+				base64 = g_base64_encode (bytes->data, bytes->len);
+				if (issuer_count == 0) {
+					e_named_parameters_set (parameters, "issuer", base64);
+				} else {
+					gchar *name;
+
+					name = g_strdup_printf ("issuer-%d", issuer_count);
+					e_named_parameters_set (parameters, name, base64);
+					g_free (name);
+				}
+
+				g_free (base64);
+				g_byte_array_unref (bytes);
+			} else {
+				break;
+			}
+		}
+
+		issuer_count++;
+	}
+
+	return E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+}
+
+/**
+ * e_source_webdav_store_ssl_trust_prompt:
+ * @extension: an #ESourceWebdav
+ * @message: a #SoupMessage with #SOUP_STATUS_SSL_FAILED status code
+ * @response: user's response from a trust prompt
+ *
+ * Stores user's response from a trust prompt, thus it is re-used the next
+ * time it'll be needed. An #E_TRUST_PROMPT_RESPONSE_UNKNOWN is treated as
+ * a temporary reject, which means the user will be asked again.
+ *
+ * Since: 3.8
+ **/
+void
+e_source_webdav_store_ssl_trust_prompt (ESourceWebdav *extension,
+					SoupMessage *message,
+					ETrustPromptResponse response)
+{
+	GTlsCertificate *cert = NULL;
+	GByteArray *bytes = NULL;
+	SoupURI *soup_uri;
+	const gchar *host;
+	gchar *hash;
+
+	g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+	g_return_if_fail (SOUP_IS_MESSAGE (message));
+
+	if (message->status_code != SOUP_STATUS_SSL_FAILED)
+		return;
+
+	if (!soup_message_get_https_status (message, &cert, NULL) || !cert)
+		return;
+
+	soup_uri = soup_message_get_uri (message);
+	if (!soup_uri || !soup_uri_get_host (soup_uri))
+		return;
+
+	g_object_get (cert, "certificate", &bytes, NULL);
+	if (!bytes)
+		return;
+
+	host = soup_uri_get_host (soup_uri);
+	hash = g_compute_checksum_for_data (G_CHECKSUM_SHA1, bytes->data, bytes->len);
+
+	encode_ssl_trust (extension, response, host, hash);
+
+	g_byte_array_unref (bytes);
+	g_free (hash);
+}
+
+/**
+ * e_source_webdav_unset_temporary_ssl_trust:
+ * @extension: an #ESourceWebdav
+ *
+ * Unsets temporary trust set on this @extension, but keeps
+ * it as is for other values.
+ *
+ * Since: 3.8
+ **/
+void
+e_source_webdav_unset_temporary_ssl_trust (ESourceWebdav *extension)
+{
+	ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+
+	g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+
+	if (!decode_ssl_trust (extension, &response, NULL, NULL) ||
+	    response == E_TRUST_PROMPT_RESPONSE_UNKNOWN ||
+	    response == E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY ||
+	    response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY)
+		e_source_webdav_set_ssl_trust (extension, NULL);
+}
diff --git a/libedataserver/e-source-webdav.h b/libedataserver/e-source-webdav.h
index 797d238..c90648f 100644
--- a/libedataserver/e-source-webdav.h
+++ b/libedataserver/e-source-webdav.h
@@ -57,6 +57,9 @@
 
 G_BEGIN_DECLS
 
+/* forward declaration */
+struct _ENamedParameters;
+
 typedef struct _ESourceWebdav ESourceWebdav;
 typedef struct _ESourceWebdavClass ESourceWebdavClass;
 typedef struct _ESourceWebdavPrivate ESourceWebdavPrivate;
@@ -78,6 +81,14 @@ struct _ESourceWebdavClass {
 	ESourceExtensionClass parent_class;
 };
 
+typedef enum {
+	E_TRUST_PROMPT_RESPONSE_UNKNOWN			= -1,
+	E_TRUST_PROMPT_RESPONSE_REJECT			=  0,
+	E_TRUST_PROMPT_RESPONSE_ACCEPT			=  1,
+	E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY	=  2,
+	E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY	=  3
+} ETrustPromptResponse;
+
 GType		e_source_webdav_get_type	(void) G_GNUC_CONST;
 gboolean	e_source_webdav_get_avoid_ifmatch
 						(ESourceWebdav *extension);
@@ -103,11 +114,6 @@ gchar *		e_source_webdav_dup_email_address
 void		e_source_webdav_set_email_address
 						(ESourceWebdav *extension,
 						 const gchar *email_address);
-gboolean	e_source_webdav_get_ignore_invalid_cert
-						(ESourceWebdav *extension);
-void		e_source_webdav_set_ignore_invalid_cert
-						(ESourceWebdav *extension,
-						 gboolean ignore_invalid_cert);
 const gchar *	e_source_webdav_get_resource_path
 						(ESourceWebdav *extension);
 gchar *		e_source_webdav_dup_resource_path
@@ -122,9 +128,24 @@ gchar *		e_source_webdav_dup_resource_query
 void		e_source_webdav_set_resource_query
 						(ESourceWebdav *extension,
 						 const gchar *resource_query);
+const gchar *	e_source_webdav_get_ssl_trust	(ESourceWebdav *extension);
+gchar *		e_source_webdav_dup_ssl_trust	(ESourceWebdav *extension);
+void		e_source_webdav_set_ssl_trust	(ESourceWebdav *extension,
+						 const gchar *ssl_trust);
 SoupURI *	e_source_webdav_dup_soup_uri	(ESourceWebdav *extension);
 void		e_source_webdav_set_soup_uri	(ESourceWebdav *extension,
 						 SoupURI *soup_uri);
+ETrustPromptResponse
+		e_source_webdav_prepare_ssl_trust_prompt
+						(ESourceWebdav *extension,
+						 SoupMessage *message,
+						 struct _ENamedParameters *parameters);
+void		e_source_webdav_store_ssl_trust_prompt
+						(ESourceWebdav *extension,
+						 SoupMessage *message,
+						 ETrustPromptResponse response);
+void		e_source_webdav_unset_temporary_ssl_trust
+						(ESourceWebdav *extension);
 
 G_END_DECLS
 
