1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-26 08:55:40 +03:00

cryptsetup-generator: Add luks.link-volume-key= command line option.

This option adds link-volume-key= option to all configured LUKS
device activated by systemd-cryptsetup. The device unit may
origin in either crypttab file or kernel command line option.

The resulting link-volume-key= paramater replaces all eventually
added link-volume-key options added per device either in crypttab
file or kernel command line.

The value may be in following formats:

link-volume-key="@u" (all keys linked in the root user keyring, user type)
link-volume-key="@u::%logon" (all keys linked in the root user keyring, logon type)
link-volume-key="my_custom_keyring" (all keys linked in my_custom_keyring keyring, user type)
link-volume-key="my_custom_keyring::%logon" (all keys linked in my_custom_keyring keyring, logon type)

The referenced keyring (via keyring description) must exist
in advance of invoking device activation units.
This commit is contained in:
Ondrej Kozina 2024-05-31 12:00:20 +02:00
parent bca6c78daf
commit c91c6c2a47
2 changed files with 123 additions and 1 deletions

View File

@ -221,6 +221,63 @@
<xi:include href="version-info.xml" xpointer="v208"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>luks.link-volume-key=</varname></term>
<term><varname>rd.luks.link-volume-key=</varname></term>
<listitem><para>Specifies a kernel key type and a kernel keyring where
LUKS2 volume keys get linked during the device activation. This option
only supports the automatic flavor where key description of a linked
key is derived from LUKS device uuid upon activation (unlike
<literal>link-vokume-key</literal> parameter of
<option>luks.options</option> where also specific key description
may be added).</para>
<para>If this option is used, all units originating from either
<filename>/etc/crypttab</filename> or kernel command line will get
<literal>link-volume-key</literal> option added among LUKS parameters.
It will eventually replace original parameter specified either
in the file or on the kernel commandl line.</para>
<para>The key type and kernel keyring may be specified like follows (first
matching rule will apply):</para>
<para>The value<literal>auto</literal> will get all volume keys uploaded
in a <literal>user</literal> type keys linked in the user keyring
(<literal>@u</literal>).</para>
<para>The value<literal>auto-logon</literal> will get all volume keys uploaded
in a <literal>logon</literal> type keys linked in the user keyring
(<literal>@u</literal>).</para>
<para>If no <literal>::</literal> substring is specified, the value gets
interpreted as a target keyring description where volume keys
will be linked in <literal>user</literal> type keys. The prefix
<literal>%:</literal> or <literal>%keyring:</literal> may be ommited
from keyring descriptions.</para>
<para>If <literal>::</literal> substring is specified, the substring
in front of <literal>::</literal> gets interpreted as a keyring
description. The remaining string beyond <literal>::</literal> must
represent key type description. The prefix
<literal>%:</literal> or <literal>%keyring:</literal> may be ommited
from keyring descriptions.</para>
<para>See
<citerefentry project='man-pages'><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for more information on key descriptions (KEY IDENTIFIERS section).</para>
<para>Note that the linked volume keys are not cleaned up automatically when
devices are detached.</para>
<para><varname>rd.luks.link-volume-key=</varname> is honored only by initial
RAM disk (initrd) while <varname>luks.link-volume-key=</varname> is
honored by both the main system and in the initrd.</para>
<xi:include href="version-info.xml" xpointer="v257"/>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -20,6 +20,7 @@
#include "path-util.h"
#include "proc-cmdline.h"
#include "specifier.h"
#include "string-util-fundamental.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@ -44,10 +45,12 @@ static bool arg_allow_list = false;
static Hashmap *arg_disks = NULL;
static char *arg_default_options = NULL;
static char *arg_default_keyfile = NULL;
static char *arg_default_key_keyring = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_disks, hashmap_freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_options, freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_keyfile, freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_key_keyring, freep);
static int split_locationspec(const char *locationspec, char **ret_file, char **ret_device) {
_cleanup_free_ char *file = NULL, *device = NULL;
@ -790,13 +793,35 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
free_and_replace(d->name, uuid_value);
} else
log_warning("Failed to parse luks name switch %s. Ignoring.", value);
} else if (streq(key, "luks.link-volume-key")) {
const char *c, *sep;
if (proc_cmdline_value_missing(key, value))
return 0;
sep = strstr(value, "::");
/* reject specification including key description */
if (sep && sep[2] != '%')
return log_warning_errno(0, "Failed to parse default luks keyring switch %s. Ignoring.", value);
if (sep) {
/* reject full specification */
c = strchr(sep + 3, ':');
if (c)
return log_warning_errno(0, "Failed to parse default luks keyring switch %s. Ignoring.", value);
}
if (free_and_strdup(&arg_default_key_keyring, value) < 0)
return log_oom();
}
return 0;
}
static int add_crypttab_device(const char *name, const char *device, const char *keyspec, const char *options) {
_cleanup_free_ char *keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL;
_cleanup_free_ char *keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL,
*new_options = NULL;
crypto_device *d = NULL;
char *uuid;
int r;
@ -825,6 +850,17 @@ static int add_crypttab_device(const char *name, const char *device, const char
options = filtered_header;
}
if (arg_default_key_keyring && options && (!d || !d->options)) {
if (isempty(options))
new_options = strjoin("link-volume-key=", arg_default_key_keyring);
else
new_options = strjoin(options, ",link-volume-key=", arg_default_key_keyring);
if (!new_options)
return log_oom();
options = new_options;
}
r = create_disk(name,
device,
keyfile,
@ -916,6 +952,31 @@ static int add_proc_cmdline_devices(void) {
return ret;
}
static int add_default_key_keyring_to_devices(void) {
crypto_device *d;
if (!arg_default_key_keyring)
return 0;
HASHMAP_FOREACH(d, arg_disks) {
_cleanup_free_ char *new_options = NULL;
if (!d->create)
continue;
if (isempty(d->options))
new_options = strjoin("link-volume-key=", arg_default_key_keyring);
else
new_options = strjoin(d->options, ",link-volume-key=", arg_default_key_keyring);
if (!new_options)
return log_oom();
free_and_replace(d->options, new_options);
}
return 0;
}
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(crypt_device_hash_ops, char, string_hash_func, string_compare_func,
crypto_device, crypt_device_free);
@ -938,6 +999,10 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
if (!arg_enabled)
return 0;
r = add_default_key_keyring_to_devices();
if (r < 0)
return r;
r = add_crypttab_devices();
RET_GATHER(r, add_proc_cmdline_devices());