summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsegfault <segfault@riseup.net>2017-12-06 17:42:43 +0100
committerOndrej Holy <oholy@redhat.com>2018-07-13 07:47:51 +0000
commit029db95bb7e0e358cbed745f3499470b923ba3e7 (patch)
tree336120994269f00af1f57e992306b66e39e00445
parent5bc9cb7802b7e9e797ff73a53a04f41a8cf7682a (diff)
downloadgvfs-029db95bb7e0e358cbed745f3499470b923ba3e7.tar.gz
udisks2: Support TCRYPT devices
Add support for unlocking TrueCrypt and VeraCrypt compatible (TCRYPT) volumes. Add a new MountOpReply2 method to the dbus interface, which handles the parameters required to unlock TCRYPT volumes.
-rw-r--r--monitor/proxy/dbus-interfaces.xml13
-rw-r--r--monitor/proxy/gproxymountoperation.c130
-rw-r--r--monitor/proxy/gvfsproxyvolumemonitordaemon.c66
-rw-r--r--monitor/udisks2/gvfsudisks2volume.c58
-rw-r--r--monitor/udisks2/gvfsudisks2volumemonitor.c2
5 files changed, 210 insertions, 59 deletions
diff --git a/monitor/proxy/dbus-interfaces.xml b/monitor/proxy/dbus-interfaces.xml
index e9a9c29a..03c6caaa 100644
--- a/monitor/proxy/dbus-interfaces.xml
+++ b/monitor/proxy/dbus-interfaces.xml
@@ -178,6 +178,19 @@
<arg type='i' name='choice' direction='in'/>
<arg type='b' name='anonymous' direction='in'/>
</method>
+ <method name="MountOpReply2">
+ <arg type='s' name='mount_op_id' direction='in'/>
+ <arg type='i' name='result' direction='in'/>
+ <arg type='s' name='user_name' direction='in'/>
+ <arg type='s' name='domain' direction='in'/>
+ <arg type='s' name='encoded_password' direction='in'/>
+ <arg type='i' name='password_save' direction='in'/>
+ <arg type='i' name='choice' direction='in'/>
+ <arg type='b' name='anonymous' direction='in'/>
+ <arg type='b' name='hidden_volume' direction='in'/>
+ <arg type='b' name='system_volume' direction='in'/>
+ <arg type='u' name='pim' direction='in'/>
+ </method>
</interface>
</node>
diff --git a/monitor/proxy/gproxymountoperation.c b/monitor/proxy/gproxymountoperation.c
index ac61046e..fffd6e72 100644
--- a/monitor/proxy/gproxymountoperation.c
+++ b/monitor/proxy/gproxymountoperation.c
@@ -45,6 +45,21 @@ typedef struct
gulong reply_handler_id;
} ProxyMountOpData;
+typedef struct
+{
+ ProxyMountOpData *op_data;
+ GMountOperationResult result;
+ const gchar *user_name;
+ const gchar *domain;
+ gchar *encoded_password;
+ gint password_save;
+ gint choice;
+ gboolean anonymous;
+ gboolean hidden_volume;
+ gboolean system_volume;
+ guint pim;
+} MountOpReplyData;
+
static void
proxy_mount_op_data_free (ProxyMountOpData *data)
{
@@ -123,54 +138,99 @@ mount_op_reply_cb (GVfsRemoteVolumeMonitor *proxy,
}
static void
+mount_op_reply2_cb (GVfsRemoteVolumeMonitor *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ MountOpReplyData *data = user_data;
+ ProxyMountOpData *op_data = data->op_data;
+ GError *error = NULL;
+ gboolean ret;
+
+ ret = gvfs_remote_volume_monitor_call_mount_op_reply2_finish (proxy, res, &error);
+ if (!ret)
+ {
+ if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
+ {
+ /* The monitor doesn't implement MountOpReply2(), so we fall back to
+ * MountOpReply()
+ */
+ proxy = g_proxy_volume_monitor_get_dbus_proxy (op_data->monitor);
+ gvfs_remote_volume_monitor_call_mount_op_reply (proxy,
+ op_data->id,
+ data->result,
+ data->user_name,
+ data->domain,
+ data->encoded_password,
+ data->password_save,
+ data->choice,
+ data->anonymous,
+ NULL,
+ (GAsyncReadyCallback) mount_op_reply_cb,
+ op_data);
+ }
+ else
+ g_warning ("Error from MountOpReply2(): %s", error->message);
+
+ g_error_free (error);
+ }
+
+ g_free (data->encoded_password);
+ g_free (data);
+}
+
+static void
mount_operation_reply (GMountOperation *mount_operation,
GMountOperationResult result,
gpointer user_data)
{
- ProxyMountOpData *data = user_data;
+ ProxyMountOpData *op_data = user_data;
+ MountOpReplyData *data;
GVfsRemoteVolumeMonitor *proxy;
- const gchar *user_name;
- const gchar *domain;
const gchar *password;
- gchar *encoded_password;
- gint password_save;
- gint choice;
- gboolean anonymous;
-
- user_name = g_mount_operation_get_username (mount_operation);
- domain = g_mount_operation_get_domain (mount_operation);
- password = g_mount_operation_get_password (mount_operation);
- password_save = g_mount_operation_get_password_save (mount_operation);
- choice = g_mount_operation_get_choice (mount_operation);
- anonymous = g_mount_operation_get_anonymous (mount_operation);
-
- if (user_name == NULL)
- user_name = "";
- if (domain == NULL)
- domain = "";
+
+ data = g_new0 (MountOpReplyData, 1);
+ data->op_data = op_data;
+ data->result = result;
+ data->user_name = g_mount_operation_get_username (mount_operation);
+ data->domain = g_mount_operation_get_domain (mount_operation);
+ password = g_mount_operation_get_password (mount_operation);
+ data->password_save = g_mount_operation_get_password_save (mount_operation);
+ data->choice = g_mount_operation_get_choice (mount_operation);
+ data->anonymous = g_mount_operation_get_anonymous (mount_operation);
+ data->hidden_volume = g_mount_operation_get_is_tcrypt_hidden_volume (mount_operation);
+ data->system_volume = g_mount_operation_get_is_tcrypt_system_volume (mount_operation);
+ data->pim = g_mount_operation_get_pim (mount_operation);
+
+ if (data->user_name == NULL)
+ data->user_name = "";
+ if (data->domain == NULL)
+ data->domain = "";
if (password == NULL)
password = "";
/* NOTE: this is not to add "security", it's merely to prevent accidental exposure
* of passwords when running dbus-monitor
*/
- encoded_password = g_base64_encode ((const guchar *) password, (gsize) (strlen (password) + 1));
-
- proxy = g_proxy_volume_monitor_get_dbus_proxy (data->monitor);
- gvfs_remote_volume_monitor_call_mount_op_reply (proxy,
- data->id,
- result,
- user_name,
- domain,
- encoded_password,
- password_save,
- choice,
- anonymous,
- NULL,
- (GAsyncReadyCallback) mount_op_reply_cb,
- data);
+ data->encoded_password = g_base64_encode ((const guchar *) password, (gsize) (strlen (password) + 1));
+
+ proxy = g_proxy_volume_monitor_get_dbus_proxy (op_data->monitor);
+ gvfs_remote_volume_monitor_call_mount_op_reply2 (proxy,
+ op_data->id,
+ result,
+ data->user_name,
+ data->domain,
+ data->encoded_password,
+ data->password_save,
+ data->choice,
+ data->anonymous,
+ data->hidden_volume,
+ data->system_volume,
+ data->pim,
+ NULL,
+ (GAsyncReadyCallback) mount_op_reply2_cb,
+ data);
g_object_unref (proxy);
- g_free (encoded_password);
}
/* ---------------------------------------------------------------------------------------------------- */
diff --git a/monitor/proxy/gvfsproxyvolumemonitordaemon.c b/monitor/proxy/gvfsproxyvolumemonitordaemon.c
index 05750036..7a3d01bc 100644
--- a/monitor/proxy/gvfsproxyvolumemonitordaemon.c
+++ b/monitor/proxy/gvfsproxyvolumemonitordaemon.c
@@ -1079,17 +1079,20 @@ handle_mount_unmount (GVfsRemoteVolumeMonitor *object,
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
-handle_mount_op_reply (GVfsRemoteVolumeMonitor *object,
- GDBusMethodInvocation *invocation,
- const gchar *arg_mount_op_id,
- gint arg_result,
- const gchar *arg_user_name,
- const gchar *arg_domain,
- const gchar *arg_encoded_password,
- gint arg_password_save,
- gint arg_choice,
- gboolean arg_anonymous,
- gpointer user_data)
+handle_mount_op_reply2 (GVfsRemoteVolumeMonitor *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_mount_op_id,
+ gint arg_result,
+ const gchar *arg_user_name,
+ const gchar *arg_domain,
+ const gchar *arg_encoded_password,
+ gint arg_password_save,
+ gint arg_choice,
+ gboolean arg_anonymous,
+ gboolean arg_hidden_volume,
+ gboolean arg_system_volume,
+ guint arg_pim,
+ gpointer user_data)
{
char *decoded_password;
gsize decoded_password_len;
@@ -1097,7 +1100,7 @@ handle_mount_op_reply (GVfsRemoteVolumeMonitor *object,
GMountOperation *mount_operation;
const gchar *sender;
- print_debug ("in handle_mount_op_reply");
+ print_debug ("in handle_mount_op_reply2");
decoded_password = NULL;
sender = g_dbus_method_invocation_get_sender (invocation);
@@ -1137,16 +1140,52 @@ handle_mount_op_reply (GVfsRemoteVolumeMonitor *object,
g_mount_operation_set_password_save (mount_operation, arg_password_save);
g_mount_operation_set_choice (mount_operation, arg_choice);
g_mount_operation_set_anonymous (mount_operation, arg_anonymous);
+ g_mount_operation_set_is_tcrypt_hidden_volume (mount_operation, arg_hidden_volume);
+ g_mount_operation_set_is_tcrypt_system_volume (mount_operation, arg_system_volume);
+ g_mount_operation_set_pim (mount_operation, arg_pim);
g_mount_operation_reply (mount_operation, arg_result);
- gvfs_remote_volume_monitor_complete_mount_op_reply (object, invocation);
+ /* gvfs_remote_volume_monitor_complete_mount_op_reply2 should be
+ * identical to gvfs_remote_volume_monitor_complete_mount_op_reply,
+ * so it should be ok that we call this from handle_mount_op_reply too.
+ */
+ gvfs_remote_volume_monitor_complete_mount_op_reply2 (object, invocation);
out:
g_free (decoded_password);
return TRUE;
}
+static gboolean
+handle_mount_op_reply (GVfsRemoteVolumeMonitor *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_mount_op_id,
+ gint arg_result,
+ const gchar *arg_user_name,
+ const gchar *arg_domain,
+ const gchar *arg_encoded_password,
+ gint arg_password_save,
+ gint arg_choice,
+ gboolean arg_anonymous,
+ gpointer user_data)
+{
+ return handle_mount_op_reply2 (object,
+ invocation,
+ arg_mount_op_id,
+ arg_result,
+ arg_user_name,
+ arg_domain,
+ arg_encoded_password,
+ arg_password_save,
+ arg_choice,
+ arg_anonymous,
+ FALSE,
+ FALSE,
+ 0,
+ user_data);
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static void
@@ -1926,6 +1965,7 @@ bus_acquired_handler_cb (GDBusConnection *conn,
g_signal_connect (monitor_daemon, "handle-drive-start", G_CALLBACK (handle_drive_start), NULL);
g_signal_connect (monitor_daemon, "handle-drive-stop", G_CALLBACK (handle_drive_stop), NULL);
g_signal_connect (monitor_daemon, "handle-mount-op-reply", G_CALLBACK (handle_mount_op_reply), NULL);
+ g_signal_connect (monitor_daemon, "handle-mount-op-reply2", G_CALLBACK (handle_mount_op_reply2), NULL);
g_signal_connect (monitor_daemon, "handle-mount-unmount", G_CALLBACK (handle_mount_unmount), NULL);
g_signal_connect (monitor_daemon, "handle-volume-mount", G_CALLBACK (handle_volume_mount), NULL);
}
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index dc4351ce..642fa6ad 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -91,6 +91,9 @@ typedef struct MountData
GMountOperation *mount_operation;
gchar *passphrase;
+ gboolean hidden_volume;
+ gboolean system_volume;
+ guint pim;
gchar *passphrase_from_keyring;
GPasswordSave password_save;
@@ -290,7 +293,7 @@ update_volume (GVfsUDisks2Volume *volume)
{
volume->name = g_strdup (udisks_block_get_id_label (block));
}
- else if (g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0)
+ else if (g_strcmp0 (udisks_block_get_id_usage (block), "crypto") == 0)
{
s = udisks_client_get_size_for_display (udisks_client, udisks_block_get_size (volume->block), FALSE, FALSE);
/* Translators: This is used for encrypted volumes.
@@ -499,7 +502,7 @@ update_volume (GVfsUDisks2Volume *volume)
}
/* Add an emblem, depending on whether the encrypted volume is locked or unlocked */
- if (g_strcmp0 (udisks_block_get_id_type (volume->block), "crypto_LUKS") == 0)
+ if (g_strcmp0 (udisks_block_get_id_usage (volume->block), "crypto") == 0)
{
GEmblem *emblem;
GIcon *padlock;
@@ -666,8 +669,8 @@ gvfs_udisks2_volume_new (GVfsUDisks2VolumeMonitor *monitor,
update_volume (volume);
- /* For LUKS devices, we also need to listen for changes on any possible cleartext device */
- if (volume->block != NULL && g_strcmp0 (udisks_block_get_id_type (volume->block), "crypto_LUKS") == 0)
+ /* For encrypted devices, we also need to listen for changes on any possible cleartext device */
+ if (volume->block != NULL && g_strcmp0 (udisks_block_get_id_usage (volume->block), "crypto") == 0)
{
g_signal_connect (gvfs_udisks2_volume_monitor_get_udisks_client (volume->monitor),
"changed",
@@ -1313,6 +1316,9 @@ on_mount_operation_reply (GMountOperation *mount_operation,
data->passphrase = g_strdup (g_mount_operation_get_password (mount_operation));
data->password_save = g_mount_operation_get_password_save (mount_operation);
+ data->hidden_volume = g_mount_operation_get_is_tcrypt_hidden_volume (mount_operation);
+ data->system_volume = g_mount_operation_get_is_tcrypt_system_volume (mount_operation);
+ data->pim = g_mount_operation_get_pim (mount_operation);
/* Don't save password in keyring just yet - check if it works first */
@@ -1386,7 +1392,13 @@ static void
do_unlock (GTask *task)
{
MountData *data = g_task_get_task_data (task);
+ GVfsUDisks2Volume *volume = g_task_get_source_object (task);
GVariantBuilder builder;
+ gboolean handle_as_tcrypt;
+ const gchar *type = udisks_block_get_id_type (volume->block);
+
+ handle_as_tcrypt = (g_strcmp0 (type, "crypto_TCRYPT") == 0 ||
+ g_strcmp0 (type, "crypto_unknown") == 0);
if (data->passphrase == NULL)
{
@@ -1398,6 +1410,7 @@ do_unlock (GTask *task)
else
{
gchar *message;
+ GAskPasswordFlags pw_ask_flags;
#ifdef HAVE_KEYRING
/* check if the passphrase is in the user's keyring */
@@ -1428,10 +1441,22 @@ do_unlock (GTask *task)
"aborted",
G_CALLBACK (on_mount_operation_aborted),
task);
- /* Translators: This is the message shown to users */
- message = g_strdup_printf (_("Enter a passphrase to unlock the volume\n"
- "The passphrase is needed to access encrypted data on %s."),
- data->desc_of_encrypted_to_unlock);
+ if (g_strcmp0 (type, "crypto_unknown") == 0)
+ /* Translators: This is the message shown to users. %s is the
+ * description of the volume that is being unlocked */
+ message = g_strdup_printf (_("Enter a passphrase to unlock the volume\n"
+ "The volume %s might be a VeraCrypt volume as it contains random data."),
+ data->desc_of_encrypted_to_unlock);
+ else
+ /* Translators: This is the message shown to users. %s is the
+ * description of the volume that is being unlocked */
+ message = g_strdup_printf (_("Enter a passphrase to unlock the volume\n"
+ "The passphrase is needed to access encrypted data on %s."),
+ data->desc_of_encrypted_to_unlock);
+
+ pw_ask_flags = G_ASK_PASSWORD_NEED_PASSWORD | G_ASK_PASSWORD_SAVING_SUPPORTED;
+ if (handle_as_tcrypt)
+ pw_ask_flags |= G_ASK_PASSWORD_TCRYPT;
/* NOTE: We (currently) don't offer the user to save the
* passphrase in the keyring or /etc/crypttab - compared to
@@ -1453,8 +1478,7 @@ do_unlock (GTask *task)
message,
NULL,
NULL,
- G_ASK_PASSWORD_NEED_PASSWORD |
- G_ASK_PASSWORD_SAVING_SUPPORTED);
+ pw_ask_flags);
g_free (message);
goto out;
}
@@ -1467,6 +1491,20 @@ do_unlock (GTask *task)
"{sv}",
"auth.no_user_interaction", g_variant_new_boolean (TRUE));
}
+
+ if (handle_as_tcrypt)
+ {
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "hidden", g_variant_new_boolean (data->hidden_volume));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "system", g_variant_new_boolean (data->system_volume));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ "pim", g_variant_new_uint32 (data->pim));
+ }
+
udisks_encrypted_call_unlock (data->encrypted_to_unlock,
data->passphrase,
g_variant_builder_end (&builder),
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index e1d67fb8..b3f3ce65 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -866,7 +866,7 @@ should_include_volume (GVfsUDisks2VolumeMonitor *monitor,
}
/* show encrypted volumes... */
- if (g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0)
+ if (g_strcmp0 (udisks_block_get_id_usage (block), "crypto") == 0)
{
UDisksBlock *cleartext_block;
/* ... unless the volume is unlocked and we don't want to show the cleartext volume */