From 0fb18c84eeadf39fb0fdc19f72adc906b9367282 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Fri, 12 Aug 2011 13:47:57 -0400 Subject: [PATCH] Support /etc/crypttab for unlocking and locking LUKS devices Signed-off-by: David Zeuthen --- data/org.freedesktop.UDisks2.xml | 13 ++--- policy/org.freedesktop.udisks2.policy.in | 10 ++++ src/udiskslinuxencrypted.c | 89 +++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/data/org.freedesktop.UDisks2.xml b/data/org.freedesktop.UDisks2.xml index 012791a..005e223 100644 --- a/data/org.freedesktop.UDisks2.xml +++ b/data/org.freedesktop.UDisks2.xml @@ -669,9 +669,7 @@ small subset per filesystem type is allowed. If the device in question is referenced in a system-wide - configuration file (such as the - /etc/fstab5 - file) + configuration file (such as the /etc/fstab file) then the mount8 command is called directly as the calling user. @@ -702,9 +700,7 @@ option force is given. If the device in question is referenced in a system-wide - configuration file (such as the - /etc/fstab5 - file) + configuration file (such as the /etc/fstab file) then the umount8 command is called directly as the calling user. @@ -776,6 +772,11 @@ Tries to unlock the encrypted device using @passphrase. + If the device in question is referenced in a system-wide + configuration file (such as the /etc/crypttab file), + then name, options and passphrase (if available) is used from that + file after requesting additional authorization. + If the device is removed without being locked (e.g. the user yanking the device or pulling the media out) the cleartext device will be cleaned up. diff --git a/policy/org.freedesktop.udisks2.policy.in b/policy/org.freedesktop.udisks2.policy.in index a27b6b2..efa05f3 100644 --- a/policy/org.freedesktop.udisks2.policy.in +++ b/policy/org.freedesktop.udisks2.policy.in @@ -71,6 +71,16 @@ + + <_description>Unlock an encrypted device specified in the crypttab file + <_message>Authentication is required to unlock an encrypted device + + auth_admin + auth_admin + auth_admin_keep + + + <_description>Lock an encrypted device unlocked by another user <_message>Authentication is required to lock an encrypted device unlocked by another user diff --git a/src/udiskslinuxencrypted.c b/src/udiskslinuxencrypted.c index 1d2fed8..7dba4d3 100644 --- a/src/udiskslinuxencrypted.c +++ b/src/udiskslinuxencrypted.c @@ -122,6 +122,61 @@ wait_for_cleartext_object (UDisksDaemon *daemon, /* ---------------------------------------------------------------------------------------------------- */ +static gboolean +check_crypttab (UDisksBlockDevice *block, + gboolean load_passphrase, + gboolean *out_found, + gchar **out_name, + gchar **out_passphrase, + gchar **out_options, + GError **error) +{ + gboolean ret = FALSE; + GVariantIter iter; + const gchar *type; + GVariant *details; + + g_variant_iter_init (&iter, udisks_block_device_get_configuration (block)); + while (g_variant_iter_next (&iter, "(&s@a{sv})", &type, &details)) + { + if (g_strcmp0 (type, "crypttab") == 0) + { + const gchar *passphrase_path; + if (out_found != NULL) + *out_found = TRUE; + g_variant_lookup (details, "name", "^ay", out_name); + g_variant_lookup (details, "options", "^ay", out_options); + if (g_variant_lookup (details, "passphrase-path", "^&ay", &passphrase_path) && + strlen (passphrase_path) > 0 && + !g_str_has_prefix (passphrase_path, "/dev")) + { + if (load_passphrase) + { + if (!g_file_get_contents (passphrase_path, + out_passphrase, + NULL, + error)) + { + g_variant_unref (details); + goto out; + } + } + } + ret = TRUE; + g_variant_unref (details); + goto out; + } + g_variant_unref (details); + } + + ret = TRUE; + + out: + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + /* runs in thread dedicated to handling @invocation */ static gboolean handle_unlock (UDisksEncrypted *encrypted, @@ -142,6 +197,10 @@ handle_unlock (UDisksEncrypted *encrypted, GError *error; uid_t caller_uid; const gchar *action_id; + gboolean is_in_crypttab = FALSE; + gchar *crypttab_name = NULL; + gchar *crypttab_passphrase = NULL; + gchar *crypttab_options = NULL; object = NULL; error_message = NULL; @@ -201,12 +260,28 @@ handle_unlock (UDisksEncrypted *encrypted, goto out; } + /* check if in crypttab file */ + error = NULL; + if (!check_crypttab (block, + TRUE, + &is_in_crypttab, + &crypttab_name, + &crypttab_passphrase, + &crypttab_options, + &error)) + { + g_dbus_method_invocation_take_error (invocation, error); + goto out; + } + /* Now, check that the user is actually authorized to unlock the device. */ action_id = "org.freedesktop.udisks2.encrypted-unlock"; if (udisks_block_device_get_hint_system (block) && !(udisks_daemon_util_setup_by_user (daemon, object, caller_uid))) action_id = "org.freedesktop.udisks2.encrypted-unlock-system"; + if (is_in_crypttab) + action_id = "org.freedesktop.udisks2.encrypted-unlock-crypttab"; if (!udisks_daemon_util_check_authorization_sync (daemon, object, action_id, @@ -216,9 +291,18 @@ handle_unlock (UDisksEncrypted *encrypted, goto out; /* calculate the name to use */ - name = g_strdup_printf ("LUKS-udisks2-%s", udisks_block_device_get_id_uuid (block)); + if (is_in_crypttab && crypttab_name != NULL) + name = g_strdup (crypttab_name); + else + name = g_strdup_printf ("LUKS-udisks2-%s", udisks_block_device_get_id_uuid (block)); escaped_name = g_strescape (name, NULL); + /* if available, use and prefer the /etc/crypttab passphrase */ + if (is_in_crypttab && crypttab_passphrase != NULL && strlen (crypttab_passphrase) > 0) + { + passphrase = crypttab_passphrase; + } + /* TODO: support a 'readonly' option */ if (!udisks_daemon_launch_spawned_job_sync (daemon, NULL, /* GCancellable */ @@ -280,6 +364,9 @@ handle_unlock (UDisksEncrypted *encrypted, g_dbus_object_get_object_path (G_DBUS_OBJECT (cleartext_object))); out: + g_free (crypttab_name); + g_free (crypttab_passphrase); + g_free (crypttab_options); g_free (escaped_name); g_free (name); g_free (error_message); -- 2.7.4