|
|
c506382 |
From 79f0ea7c0d5cb39cf1ab40afaea0e485aeb4bc49 Mon Sep 17 00:00:00 2001
|
|
|
c506382 |
From: David Zeuthen <davidz@redhat.com>
|
|
|
c506382 |
Date: Thu, 26 Apr 2012 14:35:37 -0400
|
|
|
c506382 |
Subject: [PATCH 7/9] udisks2: Support getting/storing LUKS encryption passphrase from keyring
|
|
|
c506382 |
|
|
|
c506382 |
Also use a nicer message when asking for the passphrase, e.g. use strings like
|
|
|
c506382 |
|
|
|
c506382 |
'SD04G (SD Card Reader)'
|
|
|
c506382 |
'WD 2500JB External (250 GB Hard Disk)'
|
|
|
c506382 |
|
|
|
c506382 |
instead of /dev/mmcblk0p1 or /dev/sdb1. If stored in the keyring, we
|
|
|
c506382 |
also use the following display name
|
|
|
c506382 |
|
|
|
c506382 |
'Encryption passphrase for $DRIVE'
|
|
|
c506382 |
|
|
|
c506382 |
where $DRIVE is of the above form. This makes it easy for the user to
|
|
|
c506382 |
manage (for example, delete) pass-phrases using seahorse(1).
|
|
|
c506382 |
|
|
|
c506382 |
This was discussed in bug 674161.
|
|
|
c506382 |
|
|
|
c506382 |
https://bugzilla.gnome.org/show_bug.cgi?id=674161
|
|
|
c506382 |
|
|
|
c506382 |
This commit adds/changes translatable strings but Tomas said he would
|
|
|
c506382 |
soon branch gvfs for gnome-3-at a point before this patch.
|
|
|
c506382 |
|
|
|
c506382 |
Signed-off-by: David Zeuthen <davidz@redhat.com>
|
|
|
c506382 |
---
|
|
|
c506382 |
monitor/udisks2/Makefile.am | 2 +
|
|
|
c506382 |
monitor/udisks2/gvfsudisks2volume.c | 225 ++++++++++++++++++++++++++++++++++-
|
|
|
c506382 |
2 files changed, 221 insertions(+), 6 deletions(-)
|
|
|
c506382 |
|
|
|
c506382 |
diff --git a/monitor/udisks2/Makefile.am b/monitor/udisks2/Makefile.am
|
|
|
c506382 |
index 776f670..c5ddd7c 100644
|
|
|
c506382 |
--- a/monitor/udisks2/Makefile.am
|
|
|
c506382 |
+++ b/monitor/udisks2/Makefile.am
|
|
|
c506382 |
@@ -20,6 +20,7 @@ gvfs_udisks2_volume_monitor_CFLAGS = \
|
|
|
c506382 |
$(UDISKS2_CFLAGS) \
|
|
|
c506382 |
$(GUDEV_CFLAGS) \
|
|
|
c506382 |
$(LIBSYSTEMD_LOGIN_CFLAGS) \
|
|
|
c506382 |
+ $(KEYRING_CFLAGS) \
|
|
|
c506382 |
-DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
|
|
|
c506382 |
-DGVFS_LOCALEDIR=\""$(localedir)"\" \
|
|
|
c506382 |
-DG_DISABLE_DEPRECATED \
|
|
|
c506382 |
@@ -34,6 +35,7 @@ gvfs_udisks2_volume_monitor_LDADD = \
|
|
|
c506382 |
$(UDISKS2_LIBS) \
|
|
|
c506382 |
$(GUDEV_LIBS) \
|
|
|
c506382 |
$(LIBSYSTEMD_LOGIN_LIBS) \
|
|
|
c506382 |
+ $(KEYRING_LIBS) \
|
|
|
c506382 |
$(top_builddir)/common/libgvfscommon.la \
|
|
|
c506382 |
$(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \
|
|
|
c506382 |
$(NULL)
|
|
|
c506382 |
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
|
|
|
c506382 |
index 3ef5895..bb5c687 100644
|
|
|
c506382 |
--- a/monitor/udisks2/gvfsudisks2volume.c
|
|
|
c506382 |
+++ b/monitor/udisks2/gvfsudisks2volume.c
|
|
|
c506382 |
@@ -31,6 +31,10 @@
|
|
|
c506382 |
#include <glib/gi18n-lib.h>
|
|
|
c506382 |
#include <gio/gio.h>
|
|
|
c506382 |
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+#include <gnome-keyring.h>
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
#include "gvfsudisks2drive.h"
|
|
|
c506382 |
#include "gvfsudisks2volume.h"
|
|
|
c506382 |
#include "gvfsudisks2mount.h"
|
|
|
c506382 |
@@ -756,6 +760,17 @@ gvfs_udisks2_volume_get_activation_root (GVolume *_volume)
|
|
|
c506382 |
|
|
|
c506382 |
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
c506382 |
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+static GnomeKeyringPasswordSchema luks_passphrase_schema =
|
|
|
c506382 |
+{
|
|
|
c506382 |
+ GNOME_KEYRING_ITEM_GENERIC_SECRET,
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ {"gvfs-luks-uuid", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING},
|
|
|
c506382 |
+ {NULL, 0}
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+};
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
struct MountData
|
|
|
c506382 |
{
|
|
|
c506382 |
GSimpleAsyncResult *simple;
|
|
|
c506382 |
@@ -769,9 +784,15 @@ struct MountData
|
|
|
c506382 |
|
|
|
c506382 |
gchar *passphrase;
|
|
|
c506382 |
|
|
|
c506382 |
+ gchar *passphrase_from_keyring;
|
|
|
c506382 |
+ GPasswordSave password_save;
|
|
|
c506382 |
+
|
|
|
c506382 |
+ gchar *uuid_of_encrypted_to_unlock;
|
|
|
c506382 |
+ gchar *desc_of_encrypted_to_unlock;
|
|
|
c506382 |
UDisksEncrypted *encrypted_to_unlock;
|
|
|
c506382 |
UDisksFilesystem *filesystem_to_mount;
|
|
|
c506382 |
|
|
|
c506382 |
+ gboolean checked_keyring;
|
|
|
c506382 |
};
|
|
|
c506382 |
|
|
|
c506382 |
static void
|
|
|
c506382 |
@@ -795,7 +816,10 @@ mount_data_free (MountData *data)
|
|
|
c506382 |
}
|
|
|
c506382 |
|
|
|
c506382 |
g_free (data->passphrase);
|
|
|
c506382 |
+ g_free (data->passphrase_from_keyring);
|
|
|
c506382 |
|
|
|
c506382 |
+ g_free (data->uuid_of_encrypted_to_unlock);
|
|
|
c506382 |
+ g_free (data->desc_of_encrypted_to_unlock);
|
|
|
c506382 |
g_clear_object (&data->encrypted_to_unlock);
|
|
|
c506382 |
g_clear_object (&data->filesystem_to_mount);
|
|
|
c506382 |
g_free (data);
|
|
|
c506382 |
@@ -912,6 +936,62 @@ do_mount (MountData *data)
|
|
|
c506382 |
|
|
|
c506382 |
/* ------------------------------ */
|
|
|
c506382 |
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+static void
|
|
|
c506382 |
+luks_store_passphrase_cb (GnomeKeyringResult result,
|
|
|
c506382 |
+ gpointer user_data)
|
|
|
c506382 |
+{
|
|
|
c506382 |
+ MountData *data = user_data;
|
|
|
c506382 |
+ if (result == GNOME_KEYRING_RESULT_OK)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ /* everything is good */
|
|
|
c506382 |
+ do_mount (data);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+ else
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ /* report failure */
|
|
|
c506382 |
+ g_simple_async_result_set_error (data->simple,
|
|
|
c506382 |
+ G_IO_ERROR,
|
|
|
c506382 |
+ G_IO_ERROR_FAILED,
|
|
|
c506382 |
+ _("Error storing passphrase in keyring (error code %d)"),
|
|
|
c506382 |
+ result);
|
|
|
c506382 |
+ g_simple_async_result_complete (data->simple);
|
|
|
c506382 |
+ mount_data_free (data);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+}
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
+
|
|
|
c506382 |
+static void do_unlock (MountData *data);
|
|
|
c506382 |
+
|
|
|
c506382 |
+
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+static void
|
|
|
c506382 |
+luks_delete_passphrase_cb (GnomeKeyringResult result,
|
|
|
c506382 |
+ gpointer user_data)
|
|
|
c506382 |
+{
|
|
|
c506382 |
+ MountData *data = user_data;
|
|
|
c506382 |
+ if (result == GNOME_KEYRING_RESULT_OK)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ /* with the bad passphrase out of the way, try again */
|
|
|
c506382 |
+ g_free (data->passphrase);
|
|
|
c506382 |
+ data->passphrase = NULL;
|
|
|
c506382 |
+ do_unlock (data);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+ else
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ /* report failure */
|
|
|
c506382 |
+ g_simple_async_result_set_error (data->simple,
|
|
|
c506382 |
+ G_IO_ERROR,
|
|
|
c506382 |
+ G_IO_ERROR_FAILED,
|
|
|
c506382 |
+ _("Error deleting invalid passphrase from keyring (error code %d)"),
|
|
|
c506382 |
+ result);
|
|
|
c506382 |
+ g_simple_async_result_complete (data->simple);
|
|
|
c506382 |
+ mount_data_free (data);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+}
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
static void
|
|
|
c506382 |
unlock_cb (GObject *source_object,
|
|
|
c506382 |
GAsyncResult *res,
|
|
|
c506382 |
@@ -927,6 +1007,26 @@ unlock_cb (GObject *source_object,
|
|
|
c506382 |
res,
|
|
|
c506382 |
&error))
|
|
|
c506382 |
{
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+ /* If this failed with a passphrase read from the keyring, try again
|
|
|
c506382 |
+ * this time prompting the user...
|
|
|
c506382 |
+ *
|
|
|
c506382 |
+ * TODO: ideally check against something like UDISKS_ERROR_PASSPHRASE_INVALID
|
|
|
c506382 |
+ * when such a thing is available in udisks
|
|
|
c506382 |
+ */
|
|
|
c506382 |
+ if (data->passphrase_from_keyring != NULL &&
|
|
|
c506382 |
+ g_strcmp0 (data->passphrase, data->passphrase_from_keyring) == 0)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ /* nuke the invalid passphrase from keyring... */
|
|
|
c506382 |
+ gnome_keyring_delete_password (&luks_passphrase_schema,
|
|
|
c506382 |
+ luks_delete_passphrase_cb,
|
|
|
c506382 |
+ data,
|
|
|
c506382 |
+ NULL, /* GDestroyNotify */
|
|
|
c506382 |
+ "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
|
|
|
c506382 |
+ NULL); /* sentinel */
|
|
|
c506382 |
+ goto out;
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
gvfs_udisks2_utils_udisks_error_to_gio_error (error);
|
|
|
c506382 |
g_simple_async_result_take_error (data->simple, error);
|
|
|
c506382 |
g_simple_async_result_complete (data->simple);
|
|
|
c506382 |
@@ -953,6 +1053,42 @@ unlock_cb (GObject *source_object,
|
|
|
c506382 |
goto out;
|
|
|
c506382 |
}
|
|
|
c506382 |
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+ /* passphrase worked - save it in the keyring if requested */
|
|
|
c506382 |
+ if (data->password_save != G_PASSWORD_SAVE_NEVER)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ const gchar *keyring;
|
|
|
c506382 |
+ gchar *display_name;
|
|
|
c506382 |
+
|
|
|
c506382 |
+ switch (data->password_save)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ case G_PASSWORD_SAVE_NEVER:
|
|
|
c506382 |
+ g_assert_not_reached ();
|
|
|
c506382 |
+ break;
|
|
|
c506382 |
+ case G_PASSWORD_SAVE_FOR_SESSION:
|
|
|
c506382 |
+ keyring = GNOME_KEYRING_SESSION;
|
|
|
c506382 |
+ break;
|
|
|
c506382 |
+ case G_PASSWORD_SAVE_PERMANENTLY:
|
|
|
c506382 |
+ keyring = GNOME_KEYRING_DEFAULT;
|
|
|
c506382 |
+ break;
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+
|
|
|
c506382 |
+ display_name = g_strdup_printf (_("Encryption passphrase for %s"),
|
|
|
c506382 |
+ data->desc_of_encrypted_to_unlock);
|
|
|
c506382 |
+
|
|
|
c506382 |
+ gnome_keyring_store_password (&luks_passphrase_schema,
|
|
|
c506382 |
+ keyring,
|
|
|
c506382 |
+ display_name,
|
|
|
c506382 |
+ data->passphrase,
|
|
|
c506382 |
+ luks_store_passphrase_cb,
|
|
|
c506382 |
+ data,
|
|
|
c506382 |
+ NULL, /* GDestroyNotify */
|
|
|
c506382 |
+ "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
|
|
|
c506382 |
+ NULL); /* sentinel */
|
|
|
c506382 |
+ goto out;
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
/* OK, ready to rock */
|
|
|
c506382 |
do_mount (data);
|
|
|
c506382 |
}
|
|
|
c506382 |
@@ -961,8 +1097,6 @@ unlock_cb (GObject *source_object,
|
|
|
c506382 |
g_free (cleartext_device);
|
|
|
c506382 |
}
|
|
|
c506382 |
|
|
|
c506382 |
-static void do_unlock (MountData *data);
|
|
|
c506382 |
-
|
|
|
c506382 |
static void
|
|
|
c506382 |
on_mount_operation_reply (GMountOperation *mount_operation,
|
|
|
c506382 |
GMountOperationResult result,
|
|
|
c506382 |
@@ -1005,6 +1139,9 @@ on_mount_operation_reply (GMountOperation *mount_operation,
|
|
|
c506382 |
}
|
|
|
c506382 |
|
|
|
c506382 |
data->passphrase = g_strdup (g_mount_operation_get_password (mount_operation));
|
|
|
c506382 |
+ data->password_save = g_mount_operation_get_password_save (mount_operation);
|
|
|
c506382 |
+
|
|
|
c506382 |
+ /* Don't save password in keyring just yet - check if it works first */
|
|
|
c506382 |
|
|
|
c506382 |
do_unlock (data);
|
|
|
c506382 |
|
|
|
c506382 |
@@ -1049,6 +1186,27 @@ has_crypttab_passphrase (MountData *data)
|
|
|
c506382 |
return ret;
|
|
|
c506382 |
}
|
|
|
c506382 |
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+static void
|
|
|
c506382 |
+luks_find_passphrase_cb (GnomeKeyringResult result,
|
|
|
c506382 |
+ const gchar *string,
|
|
|
c506382 |
+ gpointer user_data)
|
|
|
c506382 |
+{
|
|
|
c506382 |
+ MountData *data = user_data;
|
|
|
c506382 |
+
|
|
|
c506382 |
+ /* Don't fail if a keyring error occured - just continue and request
|
|
|
c506382 |
+ * the passphrase from the user...
|
|
|
c506382 |
+ */
|
|
|
c506382 |
+ if (result == GNOME_KEYRING_RESULT_OK)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ data->passphrase = g_strdup (string);
|
|
|
c506382 |
+ data->passphrase_from_keyring = g_strdup (string);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+ /* try again */
|
|
|
c506382 |
+ do_unlock (data);
|
|
|
c506382 |
+}
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
static void
|
|
|
c506382 |
do_unlock (MountData *data)
|
|
|
c506382 |
{
|
|
|
c506382 |
@@ -1065,6 +1223,21 @@ do_unlock (MountData *data)
|
|
|
c506382 |
{
|
|
|
c506382 |
gchar *message;
|
|
|
c506382 |
|
|
|
c506382 |
+#ifdef HAVE_KEYRING
|
|
|
c506382 |
+ /* check if the passphrase is in the user's keyring */
|
|
|
c506382 |
+ if (!data->checked_keyring)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ data->checked_keyring = TRUE;
|
|
|
c506382 |
+ gnome_keyring_find_password (&luks_passphrase_schema,
|
|
|
c506382 |
+ luks_find_passphrase_cb,
|
|
|
c506382 |
+ data,
|
|
|
c506382 |
+ NULL, /* GDestroyNotify */
|
|
|
c506382 |
+ "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
|
|
|
c506382 |
+ NULL); /* sentinel */
|
|
|
c506382 |
+ goto out;
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+#endif
|
|
|
c506382 |
+
|
|
|
c506382 |
if (data->mount_operation == NULL)
|
|
|
c506382 |
{
|
|
|
c506382 |
g_simple_async_result_set_error (data->simple,
|
|
|
c506382 |
@@ -1084,9 +1257,10 @@ do_unlock (MountData *data)
|
|
|
c506382 |
"aborted",
|
|
|
c506382 |
G_CALLBACK (on_mount_operation_aborted),
|
|
|
c506382 |
data);
|
|
|
c506382 |
- message = g_strdup_printf (_("Enter a password to unlock the volume\n"
|
|
|
c506382 |
- "The device %s contains encrypted data."),
|
|
|
c506382 |
- udisks_block_get_device (data->volume->block));
|
|
|
c506382 |
+ /* Translators: This is the message shown to users */
|
|
|
c506382 |
+ message = g_strdup_printf (_("Enter a passphrase to unlock the volume\n"
|
|
|
c506382 |
+ "The passphrase is needed to access encrypted data on %s."),
|
|
|
c506382 |
+ data->desc_of_encrypted_to_unlock);
|
|
|
c506382 |
|
|
|
c506382 |
/* NOTE: We (currently) don't offer the user to save the
|
|
|
c506382 |
* passphrase in the keyring or /etc/crypttab - compared to
|
|
|
c506382 |
@@ -1109,7 +1283,7 @@ do_unlock (MountData *data)
|
|
|
c506382 |
NULL,
|
|
|
c506382 |
NULL,
|
|
|
c506382 |
G_ASK_PASSWORD_NEED_PASSWORD |
|
|
|
c506382 |
- 0/*G_ASK_PASSWORD_SAVING_SUPPORTED*/);
|
|
|
c506382 |
+ G_ASK_PASSWORD_SAVING_SUPPORTED);
|
|
|
c506382 |
g_free (message);
|
|
|
c506382 |
goto out;
|
|
|
c506382 |
}
|
|
|
c506382 |
@@ -1209,6 +1383,45 @@ gvfs_udisks2_volume_mount (GVolume *_volume,
|
|
|
c506382 |
data->encrypted_to_unlock = udisks_object_get_encrypted (UDISKS_OBJECT (object));
|
|
|
c506382 |
if (data->encrypted_to_unlock != NULL)
|
|
|
c506382 |
{
|
|
|
c506382 |
+ UDisksDrive *udisks_drive;
|
|
|
c506382 |
+
|
|
|
c506382 |
+ /* This description is used in both the prompt and the display-name of
|
|
|
c506382 |
+ * the key stored in the user's keyring ...
|
|
|
c506382 |
+ *
|
|
|
c506382 |
+ * NOTE: we want a little bit more detail than what g_drive_get_name()
|
|
|
c506382 |
+ * gives us, since this is going to be used to refer to the device even
|
|
|
c506382 |
+ * when not plugged in
|
|
|
c506382 |
+ */
|
|
|
c506382 |
+ udisks_drive = udisks_client_get_drive_for_block (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
|
|
|
c506382 |
+ block);
|
|
|
c506382 |
+ if (udisks_drive != NULL)
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ gchar *drive_name;
|
|
|
c506382 |
+ gchar *drive_desc;
|
|
|
c506382 |
+ udisks_client_get_drive_info (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
|
|
|
c506382 |
+ udisks_drive,
|
|
|
c506382 |
+ &drive_name,
|
|
|
c506382 |
+ &drive_desc,
|
|
|
c506382 |
+ NULL, /* drive_icon */
|
|
|
c506382 |
+ NULL, /* media_desc */
|
|
|
c506382 |
+ NULL); /* media_icon */
|
|
|
c506382 |
+ /* Translators: this is used to describe the drive the encrypted media
|
|
|
c506382 |
+ * is on - the first %s is the name (such as 'WD 2500JB External'), the
|
|
|
c506382 |
+ * second %s is the description ('250 GB Hard Disk').
|
|
|
c506382 |
+ */
|
|
|
c506382 |
+ data->desc_of_encrypted_to_unlock = g_strdup_printf (_("%s (%s)"),
|
|
|
c506382 |
+ drive_name,
|
|
|
c506382 |
+ drive_desc);
|
|
|
c506382 |
+ g_free (drive_desc);
|
|
|
c506382 |
+ g_free (drive_name);
|
|
|
c506382 |
+ g_object_unref (udisks_drive);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+ else
|
|
|
c506382 |
+ {
|
|
|
c506382 |
+ data->desc_of_encrypted_to_unlock = udisks_block_dup_preferred_device (block);
|
|
|
c506382 |
+ }
|
|
|
c506382 |
+ data->uuid_of_encrypted_to_unlock = udisks_block_dup_id_uuid (block);
|
|
|
c506382 |
+
|
|
|
c506382 |
do_unlock (data);
|
|
|
c506382 |
goto out;
|
|
|
c506382 |
}
|
|
|
c506382 |
--
|
|
|
c506382 |
1.7.3.4
|
|
|
c506382 |
|