Skip to content

Commit

Permalink
Merge pull request #1270 from xyakimo1/master
Browse files Browse the repository at this point in the history
core: Add Encrypted.Convert method
  • Loading branch information
vojtechtrefny committed Jul 15, 2024
2 parents 6739cd8 + 7e14d30 commit da84236
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 0 deletions.
17 changes: 17 additions & 0 deletions data/org.freedesktop.UDisks2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2975,6 +2975,21 @@
<arg name="options" direction="in" type="a{sv}"/>
</method>


<!--
Convert:
@target_version: The LUKS version to convert to. Either 'luks1' or 'luks2'.
@options: Options (currently unused except for <link linkend="udisks-std-options">standard options</link>).
@since: 2.11.0
Converts the encrypted device to a different version of LUKS. Other encryption formats are not supported.
The device must be locked.
-->
<method name="Convert">
<arg name="target_version" direction="in" type="s"/>
<arg name="options" direction="in" type="a{sv}"/>
</method>

</interface>

<!-- ********************************************************************** -->
Expand Down Expand Up @@ -3396,6 +3411,8 @@
<listitem><para>Modifying encrypted device.</para></listitem></varlistentry>
<varlistentry><term>encrypted-resize</term>
<listitem><para>Resizing encrypted device.</para></listitem></varlistentry>
<varlistentry><term>encrypted-convert</term>
<listitem><para>Converting encrypted device.</para></listitem></varlistentry>
<varlistentry><term>swapspace-start</term>
<listitem><para>Starting swapspace.</para></listitem></varlistentry>
<varlistentry><term>swapspace-stop</term>
Expand Down
4 changes: 4 additions & 0 deletions doc/udisks2-sections.txt.in.in
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,10 @@ udisks_encrypted_call_resize
udisks_encrypted_call_resize_finish
udisks_encrypted_call_resize_sync
udisks_encrypted_complete_resize
udisks_encrypted_call_convert
udisks_encrypted_call_convert_finish
udisks_encrypted_call_convert_sync
udisks_encrypted_complete_convert
UDisksEncryptedProxy
UDisksEncryptedProxyClass
udisks_encrypted_proxy_new
Expand Down
50 changes: 50 additions & 0 deletions src/tests/dbus-tests/test_70_encrypted.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ def _get_blkid_version():
raise RuntimeError('Failed to determine blkid version from: %s' % out)
return Version(m.groups()[0])

def _get_luks_version(disk):
ret, out = udiskstestcase.UdisksTestCase.run_command("cryptsetup luksDump %s" % disk)
m = re.search(r'Version:\s*([1-2])', out)
if not m or len(m.groups()) != 1:
raise RuntimeError('Failed to determine LUKS version of device: %s.' % disk)
return int(m.groups()[0])


class UdisksEncryptedTest(udiskstestcase.UdisksTestCase):
'''This is an encrypted device test suite'''
Expand Down Expand Up @@ -449,6 +456,24 @@ def _get_metadata_size_from_dump(self, disk):
# offset value is in 512B blocks; we need to multiply to get the real metadata size
return int(m.group(1)) * 512

def test_convert(self):
disk = self.vdevs[0]
device = self.get_device(disk)
self._create_luks(device, self.PASSPHRASE)
self.assertEqual(1, _get_luks_version(disk))

self.addCleanup(self._remove_luks, device)
self.udev_settle()
device.Lock(self.no_options, dbus_interface=self.iface_prefix + '.Encrypted')

device.Convert("luks2", self.no_options,
dbus_interface=self.iface_prefix + '.Encrypted')
self.assertEqual(2, _get_luks_version(disk))

device.Convert("luks1", self.no_options,
dbus_interface=self.iface_prefix + '.Encrypted')
self.assertEqual(1, _get_luks_version(disk))

class UdisksEncryptedTestLUKS2(UdisksEncryptedTest):
'''This is a LUKS2 encrypted device test suite'''

Expand Down Expand Up @@ -559,6 +584,31 @@ def test_resize(self):
clear_size3 = self.get_block_size(clear_dev)
self.assertEqual(clear_size3, clear_size)

def test_convert_xfail(self):
disk = self.vdevs[0]
device = self.get_device(disk)
self._create_luks(device, self.PASSPHRASE)
self.assertEqual(2, _get_luks_version(disk))

self.addCleanup(self._remove_luks, device)
self.udev_settle()
device.Lock(self.no_options, dbus_interface=self.iface_prefix + '.Encrypted')

# check that the device is not LUKS1 compatible
ret, out = udiskstestcase.UdisksTestCase.run_command("cryptsetup luksDump %s" % disk)
m = re.search(r'PBKDF:\s*(.*)', out)
if not m or len(m.groups()) != 1:
raise RuntimeError('Failed to determine PBKDF of LUKS device: %s.' % disk)
self.assertEqual("argon2id", m.groups()[0])

# check that conversion fails
msg = 'org.freedesktop.UDisks2.Error.Failed: Error converting encrypted device /dev/.+: Conversion failed: Invalid argument'
with self.assertRaisesRegex(dbus.exceptions.DBusException, msg):
device.Convert("luks1", self.no_options,
dbus_interface=self.iface_prefix + '.Encrypted')

self.assertEqual(2, _get_luks_version(disk))

def _get_default_luks_version(self):
manager = self.get_object('/Manager')
default_encryption_type = self.get_property(manager, '.Manager', 'DefaultEncryptionType')
Expand Down
137 changes: 137 additions & 0 deletions src/udiskslinuxencrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,11 +1194,148 @@ handle_resize (UDisksEncrypted *encrypted,

/* ---------------------------------------------------------------------------------------------------- */

/* runs in thread dedicated to handling method call */
static gboolean
handle_convert (UDisksEncrypted *encrypted,
GDBusMethodInvocation *invocation,
const gchar *target_version,
GVariant *options)
{
UDisksObject *object = NULL;
UDisksBlock *block;
UDisksDaemon *daemon;
UDisksState *state = NULL;
uid_t caller_uid;
const gchar *action_id = NULL;
const gchar *message = NULL;
GError *error = NULL;
UDisksBaseJob *job = NULL;
BDCryptoLUKSVersion bd_target_version;

object = udisks_daemon_util_dup_object (encrypted, &error);
if (object == NULL)
{
g_dbus_method_invocation_return_gerror (invocation, error);
goto out;
}

block = udisks_object_peek_block (object);
daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
state = udisks_daemon_get_state (daemon);

udisks_linux_block_object_lock_for_cleanup (UDISKS_LINUX_BLOCK_OBJECT (object));
udisks_state_check_block (state, udisks_linux_block_object_get_device_number (UDISKS_LINUX_BLOCK_OBJECT (object)));

/* Fail if the device is not a LUKS device */
if (!(g_strcmp0 (udisks_block_get_id_usage (block), "crypto") == 0 &&
g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0))
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
"Device %s does not appear to be a LUKS device",
udisks_block_get_device (block));
goto out;
}

if (!udisks_daemon_util_get_caller_uid_sync (daemon, invocation, NULL /* GCancellable */, &caller_uid, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
goto out;
}

action_id = "org.freedesktop.udisks2.modify-device";
/* Translators: Shown in authentication dialog when the user
* requests conversion of an encrypted block device.
*
* Do not translate $(drive), it's a placeholder and
* will be replaced by the name of the drive/device in question
*/
message = N_("Authentication is required to convert device $(drive) to a different LUKS version.");
if (! udisks_daemon_util_setup_by_user (daemon, object, caller_uid))
{
if (udisks_block_get_hint_system (block))
{
action_id = "org.freedesktop.udisks2.modify-device-system";
}
else if (! udisks_daemon_util_on_user_seat (daemon, UDISKS_OBJECT (object), caller_uid))
{
action_id = "org.freedesktop.udisks2.modify-device-other-seat";
}
}

/* Check that the user is actually authorized to convert the device. */
if (! udisks_daemon_util_check_authorization_sync (daemon,
object,
action_id,
options,
message,
invocation))
goto out;

if (g_strcmp0 (target_version, "luks1") == 0) {
bd_target_version = BD_CRYPTO_LUKS_VERSION_LUKS1;
} else if (g_strcmp0 (target_version, "luks2") == 0) {
bd_target_version = BD_CRYPTO_LUKS_VERSION_LUKS2;
} else {
g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
"Unsupported target LUKS version: '%s'. Only 'luks1' and 'luks2' are supported.",
target_version);
goto out;
}

job = udisks_daemon_launch_simple_job (daemon,
UDISKS_OBJECT (object),
"encrypted-convert",
caller_uid,
NULL);
if (job == NULL)
{
g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
"Failed to create a job object");
goto out;
}

udisks_linux_block_encrypted_lock (block);

if (! bd_crypto_luks_convert (udisks_block_get_device (block),
bd_target_version,
&error))
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
"Error converting encrypted device %s: %s",
udisks_block_get_device (block),
error->message);
udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), FALSE, error->message);
udisks_linux_block_encrypted_unlock (block);
goto out;
}

udisks_linux_block_encrypted_unlock (block);

udisks_encrypted_complete_convert (encrypted, invocation);
udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), TRUE, NULL);

out:
if (object != NULL)
udisks_linux_block_object_release_cleanup_lock (UDISKS_LINUX_BLOCK_OBJECT (object));
if (state != NULL)
udisks_state_check (state);
g_clear_object (&object);
g_clear_error (&error);
return TRUE; /* returning TRUE means that we handled the method invocation */
}

/* ---------------------------------------------------------------------------------------------------- */

static void
encrypted_iface_init (UDisksEncryptedIface *iface)
{
iface->handle_unlock = handle_unlock;
iface->handle_lock = handle_lock;
iface->handle_change_passphrase = handle_change_passphrase;
iface->handle_resize = handle_resize;
iface->handle_convert = handle_convert;
}
1 change: 1 addition & 0 deletions udisks/udisksclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -2734,6 +2734,7 @@ udisks_client_get_job_description_from_operation (const gchar *operation)
g_hash_table_insert (hash, (gpointer) "encrypted-lock", (gpointer) C_("job", "Locking Device"));
g_hash_table_insert (hash, (gpointer) "encrypted-modify", (gpointer) C_("job", "Modifying Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "encrypted-resize", (gpointer) C_("job", "Resizing Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "encrypted-convert", (gpointer) C_("job", "Converting Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-start", (gpointer) C_("job", "Starting Swap Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-stop", (gpointer) C_("job", "Stopping Swap Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-modify", (gpointer) C_("job", "Modifying Swap Device"));
Expand Down

0 comments on commit da84236

Please sign in to comment.