diff options
author | segfault <segfault@riseup.net> | 2017-12-06 17:42:43 +0100 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2018-07-13 07:47:51 +0000 |
commit | 029db95bb7e0e358cbed745f3499470b923ba3e7 (patch) | |
tree | 336120994269f00af1f57e992306b66e39e00445 | |
parent | 5bc9cb7802b7e9e797ff73a53a04f41a8cf7682a (diff) | |
download | gvfs-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.xml | 13 | ||||
-rw-r--r-- | monitor/proxy/gproxymountoperation.c | 130 | ||||
-rw-r--r-- | monitor/proxy/gvfsproxyvolumemonitordaemon.c | 66 | ||||
-rw-r--r-- | monitor/udisks2/gvfsudisks2volume.c | 58 | ||||
-rw-r--r-- | monitor/udisks2/gvfsudisks2volumemonitor.c | 2 |
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 */ |