a2b238
From bbc95d6716ac491489f059c68a6dd258e38aee79 Mon Sep 17 00:00:00 2001
a2b238
From: Ondrej Holy <oholy@redhat.com>
a2b238
Date: Mon, 25 Nov 2019 16:53:31 +0100
a2b238
Subject: [PATCH] goa: Add support for certificate prompts
a2b238
a2b238
Since commit f5ee590e, it is not possible to access Nextcloud/ownCloud
a2b238
shares with self-signed (or invalid) certificates. This is because
a2b238
the mount operation is handled by GOA volume monitor and the prompt
a2b238
to accept certificate is not shown. Let's update the volume monitor
a2b238
to handle just passwords and show the prompt to the client.
a2b238
a2b238
Fixes: https://gitlab.gnome.org/GNOME/gvfs/issues/251
a2b238
---
a2b238
 monitor/goa/goavolume.c | 98 ++++++++++++++++++++++++++++++++++++++++-
a2b238
 1 file changed, 96 insertions(+), 2 deletions(-)
a2b238
a2b238
diff --git a/monitor/goa/goavolume.c b/monitor/goa/goavolume.c
a2b238
index c077dd94..5e9097c6 100644
a2b238
--- a/monitor/goa/goavolume.c
a2b238
+++ b/monitor/goa/goavolume.c
a2b238
@@ -64,6 +64,7 @@ G_DEFINE_TYPE_EXTENDED (GVfsGoaVolume, g_vfs_goa_volume, G_TYPE_OBJECT, 0,
a2b238
 typedef struct
a2b238
 {
a2b238
   GMountOperation *mount_operation;
a2b238
+  GMountOperation *mount_operation_orig;
a2b238
   gchar *passwd;
a2b238
 } MountOp;
a2b238
 
a2b238
@@ -72,6 +73,13 @@ mount_op_free (MountOp *data)
a2b238
 {
a2b238
   g_clear_object (&data->mount_operation);
a2b238
   g_free (data->passwd);
a2b238
+
a2b238
+  if (data->mount_operation_orig != NULL)
a2b238
+    {
a2b238
+      g_signal_handlers_disconnect_by_data (data->mount_operation_orig, data);
a2b238
+      g_object_unref (data->mount_operation_orig);
a2b238
+    }
a2b238
+
a2b238
   g_slice_free (MountOp, data);
a2b238
 }
a2b238
 
a2b238
@@ -97,6 +105,88 @@ account_attention_needed_cb (GObject *_object, GParamSpec *pspec, gpointer user_
a2b238
 
a2b238
 /* ---------------------------------------------------------------------------------------------------- */
a2b238
 
a2b238
+GType g_vfs_goa_mount_operation_get_type (void) G_GNUC_CONST;
a2b238
+
a2b238
+typedef struct
a2b238
+{
a2b238
+  GMountOperation parent_instance;
a2b238
+} GVfsGoaMountOperation;
a2b238
+
a2b238
+typedef struct
a2b238
+{
a2b238
+  GMountOperationClass parent_class;
a2b238
+} GVfsGoaMountOperationClass;
a2b238
+
a2b238
+static GMountOperation *
a2b238
+g_vfs_goa_mount_operation_new (void)
a2b238
+{
a2b238
+  return G_MOUNT_OPERATION (g_object_new (g_vfs_goa_mount_operation_get_type (), NULL));
a2b238
+}
a2b238
+
a2b238
+G_DEFINE_TYPE (GVfsGoaMountOperation, g_vfs_goa_mount_operation, G_TYPE_MOUNT_OPERATION)
a2b238
+
a2b238
+static void
a2b238
+g_vfs_goa_mount_operation_init (GVfsGoaMountOperation *mount_operation)
a2b238
+{
a2b238
+}
a2b238
+
a2b238
+static void
a2b238
+g_vfs_goa_mount_operation_ask_question (GMountOperation *op,
a2b238
+                                        const char *message,
a2b238
+                                        const char *choices[])
a2b238
+{
a2b238
+  /* This is needed to prevent G_MOUNT_OPERATION_UNHANDLED reply in idle. */
a2b238
+}
a2b238
+
a2b238
+static void
a2b238
+g_vfs_goa_mount_operation_class_init (GVfsGoaMountOperationClass *klass)
a2b238
+{
a2b238
+  GMountOperationClass *mount_op_class;
a2b238
+
a2b238
+  mount_op_class = G_MOUNT_OPERATION_CLASS (klass);
a2b238
+  mount_op_class->ask_question  = g_vfs_goa_mount_operation_ask_question;
a2b238
+}
a2b238
+
a2b238
+/* ---------------------------------------------------------------------------------------------------- */
a2b238
+
a2b238
+static void
a2b238
+ask_question_reply_cb (GMountOperation      *op,
a2b238
+                       GMountOperationResult result,
a2b238
+                       gpointer              user_data)
a2b238
+{
a2b238
+  MountOp *data = g_task_get_task_data (user_data);
a2b238
+
a2b238
+  g_mount_operation_set_choice (data->mount_operation,
a2b238
+                                g_mount_operation_get_choice (op));
a2b238
+  g_mount_operation_reply (data->mount_operation, result);
a2b238
+}
a2b238
+
a2b238
+static void
a2b238
+mount_operation_ask_question_cb (GMountOperation *op,
a2b238
+                                 gchar           *message,
a2b238
+                                 GStrv            choices,
a2b238
+                                 gpointer         user_data)
a2b238
+{
a2b238
+  MountOp *data = g_task_get_task_data (user_data);
a2b238
+
a2b238
+  if (data->mount_operation_orig != NULL)
a2b238
+    {
a2b238
+      g_signal_connect (data->mount_operation_orig,
a2b238
+                        "reply",
a2b238
+                        G_CALLBACK (ask_question_reply_cb),
a2b238
+                        user_data);
a2b238
+      g_signal_emit_by_name (data->mount_operation_orig,
a2b238
+                             "ask-question",
a2b238
+                             message,
a2b238
+                             choices);
a2b238
+    }
a2b238
+  else
a2b238
+    {
a2b238
+      g_mount_operation_reply (data->mount_operation,
a2b238
+                               G_MOUNT_OPERATION_UNHANDLED);
a2b238
+    }
a2b238
+}
a2b238
+
a2b238
 static void
a2b238
 mount_operation_ask_password_cb (GMountOperation   *op,
a2b238
                                  gchar             *message,
a2b238
@@ -412,7 +502,7 @@ g_vfs_goa_volume_get_uuid (GVolume *_self)
a2b238
 static void
a2b238
 g_vfs_goa_volume_mount (GVolume             *_self,
a2b238
                         GMountMountFlags     flags,
a2b238
-                        GMountOperation     *mount_operation,
a2b238
+                        GMountOperation     *mount_operation_orig,
a2b238
                         GCancellable        *cancellable,
a2b238
                         GAsyncReadyCallback  callback,
a2b238
                         gpointer             user_data)
a2b238
@@ -423,6 +513,9 @@ g_vfs_goa_volume_mount (GVolume             *_self,
a2b238
   GoaAccount *account;
a2b238
 
a2b238
   data = g_slice_new0 (MountOp);
a2b238
+  if (mount_operation_orig != NULL)
a2b238
+    data->mount_operation_orig = g_object_ref (mount_operation_orig);
a2b238
+
a2b238
   task = g_task_new (self, cancellable, callback, user_data);
a2b238
   g_task_set_source_tag (task, g_vfs_goa_volume_mount);
a2b238
   g_task_set_task_data (task, data, (GDestroyNotify) mount_op_free);
a2b238
@@ -431,8 +524,9 @@ g_vfs_goa_volume_mount (GVolume             *_self,
a2b238
    * monitor because it is set up to emit MountOpAskPassword on
a2b238
    * ask-password.
a2b238
    */
a2b238
-  data->mount_operation = g_mount_operation_new ();
a2b238
+  data->mount_operation = g_vfs_goa_mount_operation_new ();
a2b238
   g_signal_connect (data->mount_operation, "ask-password", G_CALLBACK (mount_operation_ask_password_cb), task);
a2b238
+  g_signal_connect (data->mount_operation, "ask-question", G_CALLBACK (mount_operation_ask_question_cb), task);
a2b238
 
a2b238
   account = goa_object_peek_account (self->object);
a2b238
   goa_account_call_ensure_credentials (account, cancellable, ensure_credentials_cb, task);
a2b238
-- 
a2b238
2.28.0
a2b238