summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2016-03-24 12:07:43 +0100
committerOndrej Holy <oholy@redhat.com>2016-04-06 16:16:34 +0200
commitbeea21e124d95c2f7cc0130148084e5e86eb46e5 (patch)
tree4804da678468dd33b7ea7b5eebf01ad099ff922f
parentdd98c02ecde5cc081a2d0e3990780efe3d66edfa (diff)
downloadgvfs-beea21e124d95c2f7cc0130148084e5e86eb46e5.tar.gz
udisks2: Abort mount operation if volume is unlocked
Mount operation for encrypted volumes consists from two udisks2 calls (unlock and mount). Volume monitor is able to mount already unlocked volumes. However password prompt doesn't disappear if the volume is unlocked externally and any reaction causes mount operation failure. The volume may be unlocked externally by e.g. project Tang, see https://github.com/latchset/tang for more details. Abort mount operation and continue with mounting in such situations. https://bugzilla.gnome.org/show_bug.cgi?id=763890
-rw-r--r--monitor/udisks2/gvfsudisks2volume.c105
1 files changed, 80 insertions, 25 deletions
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index fac90e5c..8bb572d9 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -87,6 +87,30 @@ struct _GVfsUDisks2Volume
MountData *mount_pending_op;
};
+struct MountData
+{
+ GSimpleAsyncResult *simple;
+
+ GVfsUDisks2Volume *volume;
+ GCancellable *cancellable;
+
+ gulong mount_operation_reply_handler_id;
+ gulong mount_operation_aborted_handler_id;
+ GMountOperation *mount_operation;
+
+ gchar *passphrase;
+
+ gchar *passphrase_from_keyring;
+ GPasswordSave password_save;
+
+ gchar *uuid_of_encrypted_to_unlock;
+ gchar *desc_of_encrypted_to_unlock;
+ UDisksEncrypted *encrypted_to_unlock;
+ UDisksFilesystem *filesystem_to_mount;
+
+ gboolean checked_keyring;
+};
+
static void gvfs_udisks2_volume_volume_iface_init (GVolumeIface *iface);
static void on_block_changed (GObject *object,
@@ -584,7 +608,22 @@ on_udisks_client_changed (UDisksClient *client,
gpointer user_data)
{
GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (user_data);
+ MountData *data = volume->mount_pending_op;
+
update_volume_on_event (volume);
+
+ if (data && data->mount_operation_aborted_handler_id && data->encrypted_to_unlock)
+ {
+ UDisksBlock *cleartext_block;
+
+ cleartext_block = udisks_client_get_cleartext_block (client, volume->block);
+ if (cleartext_block != NULL)
+ {
+ g_object_set_data (G_OBJECT (data->mount_operation), "x-udisks2-is-unlocked", GINT_TO_POINTER (1));
+ g_signal_emit_by_name (data->mount_operation, "aborted");
+ g_object_unref (cleartext_block);
+ }
+ }
}
/* takes ownership of @mount_point if not NULL */
@@ -882,30 +921,6 @@ static SecretSchema luks_passphrase_schema =
};
#endif
-struct MountData
-{
- GSimpleAsyncResult *simple;
-
- GVfsUDisks2Volume *volume;
- GCancellable *cancellable;
-
- gulong mount_operation_reply_handler_id;
- gulong mount_operation_aborted_handler_id;
- GMountOperation *mount_operation;
-
- gchar *passphrase;
-
- gchar *passphrase_from_keyring;
- GPasswordSave password_save;
-
- gchar *uuid_of_encrypted_to_unlock;
- gchar *desc_of_encrypted_to_unlock;
- UDisksEncrypted *encrypted_to_unlock;
- UDisksFilesystem *filesystem_to_mount;
-
- gboolean checked_keyring;
-};
-
static void
mount_data_free (MountData *data)
{
@@ -1269,7 +1284,47 @@ on_mount_operation_reply (GMountOperation *mount_operation,
if (result != G_MOUNT_OPERATION_HANDLED)
{
- if (result == G_MOUNT_OPERATION_ABORTED)
+ if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data->mount_operation), "x-udisks2-is-unlocked")) == 1)
+ {
+ UDisksClient *client;
+ UDisksBlock *cleartext_block;
+
+ g_object_set_data (G_OBJECT (data->mount_operation), "x-udisks2-is-unlocked", GINT_TO_POINTER (0));
+
+ client = gvfs_udisks2_volume_monitor_get_udisks_client (data->volume->monitor);
+ cleartext_block = udisks_client_get_cleartext_block (client, data->volume->block);
+ if (cleartext_block != NULL)
+ {
+ UDisksObject *object;
+
+ object = g_dbus_interface_get_object (G_DBUS_INTERFACE (cleartext_block));
+ g_object_unref (cleartext_block);
+ if (object != NULL)
+ {
+ data->filesystem_to_mount = udisks_object_get_filesystem (object);
+ if (data->filesystem_to_mount != NULL)
+ {
+ do_mount (data);
+ goto out;
+ }
+ else
+ {
+ g_simple_async_result_set_error (data->simple,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "No filesystem interface on D-Bus object for cleartext device");
+ }
+ }
+ else
+ {
+ g_simple_async_result_set_error (data->simple,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "No object for D-Bus interface");
+ }
+ }
+ }
+ else if (result == G_MOUNT_OPERATION_ABORTED)
{
/* The user aborted the operation so consider it "handled" */
g_simple_async_result_set_error (data->simple,