Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion data/org.freedesktop.UDisks2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2949,7 +2949,7 @@
<!--
Unlock:
@passphrase: The passphrase to use.
@options: Options - known options (in addition to <link linkend="udisks-std-options">standard options</link>) includes <parameter>keyfile_contents</parameter> (of type 'ay') which is preferred over @passphrase if specified and <parameter>read-only</parameter> (of type 'b').
@options: Options - known options (in addition to <link linkend="udisks-std-options">standard options</link>) includes <parameter>keyfile_contents</parameter> (of type 'ay') which is preferred over @passphrase if specified, <parameter>read-only</parameter> (of type 'b') and <parameter>discard</parameter> (of type 'b').
@cleartext_device: An object path to the unlocked object implementing the #org.freedesktop.UDisks2.Block interface.

Tries to unlock the encrypted device using @passphrase.
Expand All @@ -2958,6 +2958,8 @@
configuration file (such as the <filename>/etc/crypttab</filename> file),
then name, options and passphrase (if available) is used from that
file after requesting additional authorization.
Note that parameters specified in @options take precedence over options
specified in the <filename>/etc/crypttab</filename> file.

If an empty passphrase should be used to unlock the device, it has to be
passed using the @keyfile_contents parameter. Empty string passed as
Expand Down
35 changes: 34 additions & 1 deletion src/tests/dbus-tests/test_70_encrypted.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ def test_close_open(self):
luks_ro = self.get_property(luks_obj, '.Block', 'ReadOnly')
luks_ro.assertTrue()

def _is_ro(self, dm_name):
dm_path = os.path.realpath("/dev/mapper/%s" % dm_name)
dm_basename = os.path.basename(dm_path)
sysfs_path = "/sys/block/%s/ro" % dm_basename

with open(sysfs_path, "r") as f:
ro = f.read()
return ro.strip() == "1"

@udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
def test_open_crypttab(self):
# this test will change /etc/crypttab, we might want to revert the changes when it finishes
Expand All @@ -216,12 +225,13 @@ def test_open_crypttab(self):
disk.Lock(self.no_options, dbus_interface=self.iface_prefix + '.Encrypted')

# add new entry to the crypttab
new_crypttab = crypttab + '%s UUID=%s none\n' % (self.LUKS_NAME, disk_uuid)
new_crypttab = crypttab + '%s UUID=%s none discard,read-only\n' % (self.LUKS_NAME, disk_uuid)
self.write_file('/etc/crypttab', new_crypttab)

dbus_conf = disk.GetSecretConfiguration(self.no_options, dbus_interface=self.iface_prefix + '.Block')
self.assertIsNotNone(dbus_conf)
self.assertEqual(self.ay_to_str(dbus_conf[0][1]['name']), self.LUKS_NAME)
self.assertEqual(self.ay_to_str(dbus_conf[0][1]['options']), "discard,read-only")

# unlock the device
luks = disk.Unlock(self.PASSPHRASE, self.no_options,
Expand All @@ -232,12 +242,35 @@ def test_open_crypttab(self):
dm_path = '/dev/mapper/%s' % self.LUKS_NAME
self.assertTrue(os.path.exists(dm_path))

# check that discard is enabled for the mapped device
_ret, out, = self.run_command("dmsetup table %s" % self.LUKS_NAME)
self.assertIn("allow_discards", out)

# check that the device is read-only
self.assertTrue(self._is_ro(self.LUKS_NAME))

# preferred 'device' should be /dev/mapper/name too
luks_obj = self.get_object(luks)
self.assertIsNotNone(luks_obj)
luks_path = self.get_property(luks_obj, '.Block', 'PreferredDevice')
luks_path.assertEqual(self.str_to_ay(dm_path))

# lock the device
disk.Lock(self.no_options, dbus_interface=self.iface_prefix + '.Encrypted')

# override crypttab options with extra options
options = dbus.Dictionary({'discard' : False, 'read-only': False}, signature=dbus.Signature('sv'))
luks = disk.Unlock(self.PASSPHRASE, options,
dbus_interface=self.iface_prefix + '.Encrypted')
self.assertIsNotNone(luks)

# check that discard is not enabled for the mapped device
_ret, out, = self.run_command("dmsetup table %s" % self.LUKS_NAME)
self.assertNotIn("allow_discards", out)

# check that the device is not read-only
self.assertFalse(self._is_ro(self.LUKS_NAME))

@udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
def test_open_crypttab_keyfile(self):
# this test will change /etc/crypttab, we might want to revert the changes when it finishes
Expand Down
13 changes: 11 additions & 2 deletions src/udiskslinuxencrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ handle_unlock (UDisksEncrypted *encrypted,
gboolean read_only = FALSE;
gboolean is_hidden = FALSE;
gboolean is_system = FALSE;
gboolean discard = FALSE;
guint32 pim = 0;
GString *effective_passphrase = NULL;
GVariant *keyfiles_variant = NULL;
Expand Down Expand Up @@ -570,11 +571,18 @@ handle_unlock (UDisksEncrypted *encrypted,

device = udisks_block_dup_device (block);

/* unlock as read-only if specified in @options or if the device itself is read-only */
/* unlock as read-only if specified in @options or crypttab or if the device itself is read-only */
if (is_in_crypttab && (has_option (crypttab_options, "read-only") || has_option (crypttab_options, "readonly")))
read_only = TRUE;
g_variant_lookup (options, "read-only", "b", &read_only);
if (udisks_block_get_read_only (block))
read_only = TRUE;

/* unlock with discard if specified in @options or crypttab */
if (is_in_crypttab && has_option (crypttab_options, "discard"))
discard = TRUE;
g_variant_lookup (options, "discard", "b", &discard);

data.device = device;
data.map_name = name;
data.passphrase = effective_passphrase;
Expand All @@ -583,6 +591,7 @@ handle_unlock (UDisksEncrypted *encrypted,
data.hidden = is_hidden;
data.system = is_system;
data.read_only = read_only;
data.discard = discard;

if (is_luks)
open_func = luks_open_job_func;
Expand Down Expand Up @@ -924,7 +933,7 @@ handle_change_passphrase (UDisksEncrypted *encrypted,
const gchar *action_id;
GError *error = NULL;
gchar *device = NULL;
CryptoJobData data = { NULL, NULL, NULL, NULL, NULL, 0, 0, FALSE, FALSE, FALSE, NULL };
CryptoJobData data = { NULL, NULL, NULL, NULL, NULL, 0, 0, FALSE, FALSE, FALSE, FALSE, NULL };

object = udisks_daemon_util_dup_object (encrypted, &error);
if (object == NULL)
Expand Down
30 changes: 24 additions & 6 deletions src/udiskslinuxencryptedhelpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,20 @@ gboolean luks_open_job_func (UDisksThreadedJob *job,
CryptoJobData *data = (CryptoJobData*) user_data;
BDCryptoKeyslotContext *context = NULL;
gboolean ret = FALSE;
BDCryptoOpenFlags flags = 0;

context = bd_crypto_keyslot_context_new_passphrase ((const guint8 *) data->passphrase->str,
data->passphrase->len, error);
if (!context)
return FALSE;

/* device, name, context, read_only, error */
ret = bd_crypto_luks_open (data->device, data->map_name, context, data->read_only, error);
if (data->read_only)
flags |= BD_CRYPTO_OPEN_READONLY;
if (data->discard)
flags |= BD_CRYPTO_OPEN_ALLOW_DISCARDS;

/* device, name, context, flags, error */
ret = bd_crypto_luks_open_flags (data->device, data->map_name, context, flags, error);
bd_crypto_keyslot_context_free (context);
return ret;
}
Expand Down Expand Up @@ -136,6 +142,7 @@ gboolean tcrypt_open_job_func (UDisksThreadedJob *job,
CryptoJobData *data = (CryptoJobData*) user_data;
BDCryptoKeyslotContext *context = NULL;
gboolean ret = FALSE;
BDCryptoOpenFlags flags = 0;

/* We always use the veracrypt option, because it can unlock both VeraCrypt and legacy TrueCrypt volumes */
gboolean veracrypt = TRUE;
Expand All @@ -149,9 +156,14 @@ gboolean tcrypt_open_job_func (UDisksThreadedJob *job,
return FALSE;
}

ret = bd_crypto_tc_open (data->device, data->map_name, context,
data->keyfiles, data->hidden, data->system, veracrypt, data->pim,
data->read_only, error);
if (data->read_only)
flags |= BD_CRYPTO_OPEN_READONLY;
if (data->discard)
flags |= BD_CRYPTO_OPEN_ALLOW_DISCARDS;

ret = bd_crypto_tc_open_flags (data->device, data->map_name, context,
data->keyfiles, data->hidden, data->system, veracrypt, data->pim,
flags, error);
bd_crypto_keyslot_context_free (context);
return ret;
}
Expand All @@ -173,13 +185,19 @@ gboolean bitlk_open_job_func (UDisksThreadedJob *job,
CryptoJobData *data = (CryptoJobData*) user_data;
BDCryptoKeyslotContext *context = NULL;
gboolean ret = FALSE;
BDCryptoOpenFlags flags = 0;

context = bd_crypto_keyslot_context_new_passphrase ((const guint8 *) data->passphrase->str,
data->passphrase->len, error);
if (!context)
return FALSE;

ret = bd_crypto_bitlk_open (data->device, data->map_name, context, data->read_only, error);
if (data->read_only)
flags |= BD_CRYPTO_OPEN_READONLY;
if (data->discard)
flags |= BD_CRYPTO_OPEN_ALLOW_DISCARDS;

ret = bd_crypto_bitlk_open_flags (data->device, data->map_name, context, flags, error);
bd_crypto_keyslot_context_free (context);
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions src/udiskslinuxencryptedhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef struct {
gboolean hidden;
gboolean system;
gboolean read_only;
gboolean discard;
const gchar *type;
const gchar *pbkdf;
guint32 memory;
Expand Down