diff options
author | Lennart Poettering <lennart@poettering.net> | 2023-01-03 13:05:32 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2023-01-05 18:24:21 +0100 |
commit | ea575e176aac9fa8f430bb30a3e8abd8da767a10 (patch) | |
tree | e0299499fce39c3b74c9c73d13a941032642ded5 | |
parent | Merge pull request #25929 from poettering/resolvectl-loopback-fix (diff) | |
download | systemd-ea575e176aac9fa8f430bb30a3e8abd8da767a10.tar.xz systemd-ea575e176aac9fa8f430bb30a3e8abd8da767a10.zip |
vconsole: permit configuration of vconsole settings via credentials
Diffstat (limited to '')
-rw-r--r-- | man/systemd-firstboot.xml | 10 | ||||
-rw-r--r-- | man/systemd-vconsole-setup.service.xml | 38 | ||||
-rw-r--r-- | man/systemd.system-credentials.xml | 12 | ||||
-rw-r--r-- | src/shared/creds-util.c | 50 | ||||
-rw-r--r-- | src/shared/creds-util.h | 5 | ||||
-rw-r--r-- | src/test/meson.build | 2 | ||||
-rw-r--r-- | src/test/test-creds.c | 74 | ||||
-rw-r--r-- | src/vconsole/vconsole-setup.c | 18 | ||||
-rw-r--r-- | units/systemd-vconsole-setup.service.in | 5 |
9 files changed, 210 insertions, 4 deletions
diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml index 3f01836ddd..cfce8a40ad 100644 --- a/man/systemd-firstboot.xml +++ b/man/systemd-firstboot.xml @@ -325,7 +325,15 @@ <term><literal>firstboot.keymap</literal></term> <listitem><para>This credential specifies the keyboard setting to set during first boot, in place of - prompting the user.</para></listitem> + prompting the user.</para> + + <para>Note the relationship to the <literal>vconsole.keymap</literal> credential understood by + <citerefentry><refentrytitle>systemd-vconsole-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>: + both ultimately affect the same setting, but <varname>firstboot.keymap</varname> is written into + <filename>/etc/vconsole.conf</filename> on first boot (if not already configured), and then read from + there by <command>systemd-vconsole-setup</command>, while <varname>vconsole.keymap</varname> is read + on every boot, and is not persisted to disk (but any configuration in + <filename>vconsole.conf</filename> will take precedence if present).</para></listitem> </varlistentry> <varlistentry> diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml index 80577edba0..98d9e2ad01 100644 --- a/man/systemd-vconsole-setup.service.xml +++ b/man/systemd-vconsole-setup.service.xml @@ -50,6 +50,44 @@ </refsect1> <refsect1> + <title>Credentials</title> + + <para><command>systemd-vconsole-setup</command> supports the service credentials logic as implemented by + <varname>LoadCredential=</varname>/<varname>SetCredential=</varname> (see + <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry> for + details). The following credentials are used when passed in:</para> + + <variablelist> + <varlistentry> + <term><varname>vconsole.keymap</varname></term> + <term><varname>vconsole.keymap_toggle</varname></term> + + <listitem><para>The keymap (and toggle keymap) to apply. The matching options in + <filename>vconsole.conf</filename> and on the kernel command line take precedence over these + credentials.</para> + + <para>Note the relationship to the <varname>firstboot.keymap</varname> credential understood by + <citerefentry><refentrytitle>systemd-firstboot.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>: + both ultimately affect the same setting, but <varname>firstboot.keymap</varname> is written into + <filename>/etc/vconsole.conf</filename> on first boot (if not already configured), and then read from + there by <command>systemd-vconsole-setup</command>, while <varname>vconsole.keymap</varname> is read + on every boot, and is not persisted to disk (but any configuration in + <filename>vconsole.conf</filename> will take precedence if present).</para></listitem> + </varlistentry> + + <varlistentry> + <term><varname>vconsole.font</varname></term> + <term><varname>vconsole.font_map</varname></term> + <term><varname>vconsole.font_unimap</varname></term> + + <listitem><para>The console font settings to apply. The matching options in + <filename>vconsole.conf</filename> and on the kernel command line take precedence over these + credentials.</para></listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> <title>See Also</title> <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, diff --git a/man/systemd.system-credentials.xml b/man/systemd.system-credentials.xml index 3ec7ae8d4f..3eadf9b985 100644 --- a/man/systemd.system-credentials.xml +++ b/man/systemd.system-credentials.xml @@ -178,6 +178,18 @@ </listitem> </varlistentry> + <varlistentry> + <term><varname>vconsole.keymap</varname></term> + <term><varname>vconsole.keymap_toggle</varname></term> + <term><varname>vconsole.font</varname></term> + <term><varname>vconsole.font_map</varname></term> + <term><varname>vconsole.font_unimap</varname></term> + <listitem> + <para>Console settings to apply, see + <citerefentry><refentrytitle>systemd-vconsole-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> for details.</para> + </listitem> + </varlistentry> + </variablelist> </refsect1> diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 9f4d0832ab..a68837b70b 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -86,6 +86,56 @@ int read_credential(const char *name, void **ret, size_t *ret_size) { (char**) ret, ret_size); } +int read_credential_strings_many_internal( + const char *first_name, char **first_value, + ...) { + + _cleanup_free_ void *b = NULL; + int r, ret = 0; + + /* Reads a bunch of credentials into the specified buffers. If the specified buffers are already + * non-NULL frees them if a credential is found. Only supports string-based credentials + * (i.e. refuses embedded NUL bytes) */ + + if (!first_name) + return 0; + + r = read_credential(first_name, &b, NULL); + if (r == -ENXIO) /* no creds passed at all? propagate this */ + return r; + if (r < 0) + ret = r; + else + free_and_replace(*first_value, b); + + va_list ap; + va_start(ap, first_value); + + for (;;) { + _cleanup_free_ void *bb = NULL; + const char *name; + char **value; + + name = va_arg(ap, const char *); + if (!name) + break; + + value = va_arg(ap, char **); + if (*value) + continue; + + r = read_credential(name, &bb, NULL); + if (r < 0) { + if (ret >= 0) + ret = r; + } else + free_and_replace(*value, bb); + } + + va_end(ap); + return ret; +} + int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed) { _cleanup_(erase_and_freep) char *creds_password = NULL; _cleanup_free_ char *cn = NULL; diff --git a/src/shared/creds-util.h b/src/shared/creds-util.h index cf3d6c7dc6..05d8b74634 100644 --- a/src/shared/creds-util.h +++ b/src/shared/creds-util.h @@ -36,6 +36,11 @@ int get_encrypted_credentials_dir(const char **ret); int read_credential(const char *name, void **ret, size_t *ret_size); +int read_credential_strings_many_internal(const char *first_name, char **first_value, ...); + +#define read_credential_strings_many(first_name, first_value, ...) \ + read_credential_strings_many_internal(first_name, first_value, __VA_ARGS__, NULL) + typedef enum CredentialSecretFlags { CREDENTIAL_SECRET_GENERATE = 1 << 0, CREDENTIAL_SECRET_WARN_NOT_ENCRYPTED = 1 << 1, diff --git a/src/test/meson.build b/src/test/meson.build index 0b7ba3fb02..f9ee919019 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -260,6 +260,8 @@ tests += [ [files('test-umask-util.c')], + [files('test-creds.c')], + [files('test-proc-cmdline.c')], [files('test-fd-util.c'), diff --git a/src/test/test-creds.c b/src/test/test-creds.c new file mode 100644 index 0000000000..44022e7324 --- /dev/null +++ b/src/test/test-creds.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "creds-util.h" +#include "fileio.h" +#include "path-util.h" +#include "rm-rf.h" +#include "tests.h" +#include "tmpfile-util.h" + +TEST(read_credential_strings) { + _cleanup_free_ char *x = NULL, *y = NULL, *saved = NULL, *p = NULL; + _cleanup_(rm_rf_physical_and_freep) char *tmp = NULL; + _cleanup_fclose_ FILE *f = NULL; + + const char *e = getenv("CREDENTIALS_DIRECTORY"); + if (e) + assert_se(saved = strdup(e)); + + assert_se(read_credential_strings_many("foo", &x, "bar", &y) == -ENXIO); + assert_se(x == NULL); + assert_se(y == NULL); + + assert_se(mkdtemp_malloc(NULL, &tmp) >= 0); + + assert_se(setenv("CREDENTIALS_DIRECTORY", tmp, /* override= */ true) >= 0); + + assert_se(read_credential_strings_many("foo", &x, "bar", &y) == -ENOENT); + assert_se(x == NULL); + assert_se(y == NULL); + + assert_se(p = path_join(tmp, "bar")); + assert_se(write_string_file(p, "piff", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_AVOID_NEWLINE) >= 0); + + assert_se(read_credential_strings_many("foo", &x, "bar", &y) == -ENOENT); + assert_se(x == NULL); + assert_se(streq(y, "piff")); + + assert_se(write_string_file(p, "paff", WRITE_STRING_FILE_TRUNCATE|WRITE_STRING_FILE_AVOID_NEWLINE) >= 0); + + assert_se(read_credential_strings_many("foo", &x, "bar", &y) == -ENOENT); + assert_se(x == NULL); + assert_se(streq(y, "piff")); + + p = mfree(p); + assert_se(p = path_join(tmp, "foo")); + assert_se(write_string_file(p, "knurz", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_AVOID_NEWLINE) >= 0); + + assert_se(read_credential_strings_many("foo", &x, "bar", &y) >= 0); + assert_se(streq(x, "knurz")); + assert_se(streq(y, "piff")); + + y = mfree(y); + + assert_se(read_credential_strings_many("foo", &x, "bar", &y) >= 0); + assert_se(streq(x, "knurz")); + assert_se(streq(y, "paff")); + + p = mfree(p); + assert_se(p = path_join(tmp, "bazz")); + assert_se(f = fopen(p, "w")); + assert_se(fwrite("x\0y", 1, 3, f) == 3); /* embedded NUL byte should result in EBADMSG when reading back with read_credential_strings_many() */ + f = safe_fclose(f); + + assert_se(read_credential_strings_many("bazz", &x, "foo", &y) == -EBADMSG); + assert_se(streq(x, "knurz")); + assert_se(streq(y, "paff")); + + if (saved) + assert_se(setenv("CREDENTIALS_DIRECTORY", saved, /* override= */ 1) >= 0); + else + assert_se(unsetenv("CREDENTIALS_DIRECTORY") >= 0); +} + +DEFINE_TEST_MAIN(LOG_INFO); diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index ecc859a2c3..7d3e9db73f 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -19,6 +19,7 @@ #include <unistd.h> #include "alloc-util.h" +#include "creds-util.h" #include "env-file.h" #include "errno-util.h" #include "fd-util.h" @@ -434,6 +435,17 @@ int main(int argc, char **argv) { utf8 = is_locale_utf8(); + /* Load data from credentials (lowest priority) */ + r = read_credential_strings_many( + "vconsole.keymap", &vc_keymap, + "vconsole.keymap_toggle", &vc_keymap_toggle, + "vconsole.font", &vc_font, + "vconsole.font_map", &vc_font_map, + "vconsole.font_unimap", &vc_font_unimap); + if (r < 0 && r != -ENXIO) + log_warning_errno(r, "Failed to import credentials, ignoring: %m"); + + /* Load data from configuration file (middle priority) */ r = parse_env_file(NULL, "/etc/vconsole.conf", "KEYMAP", &vc_keymap, "KEYMAP_TOGGLE", &vc_keymap_toggle, @@ -441,9 +453,9 @@ int main(int argc, char **argv) { "FONT_MAP", &vc_font_map, "FONT_UNIMAP", &vc_font_unimap); if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m"); + log_warning_errno(r, "Failed to read /etc/vconsole.conf, ignoring: %m"); - /* Let the kernel command line override /etc/vconsole.conf */ + /* Let the kernel command line override /etc/vconsole.conf (highest priority) */ r = proc_cmdline_get_key_many( PROC_CMDLINE_STRIP_RD_PREFIX, "vconsole.keymap", &vc_keymap, @@ -456,7 +468,7 @@ int main(int argc, char **argv) { "vconsole.font.map", &vc_font_map, "vconsole.font.unimap", &vc_font_unimap); if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to read /proc/cmdline: %m"); + log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); (void) toggle_utf8_sysfs(utf8); (void) toggle_utf8_vc(vc, fd, utf8); diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in index 23f5ac2f50..c07869fedd 100644 --- a/units/systemd-vconsole-setup.service.in +++ b/units/systemd-vconsole-setup.service.in @@ -18,3 +18,8 @@ ConditionPathExists=/dev/tty0 Type=oneshot RemainAfterExit=yes ExecStart={{ROOTLIBEXECDIR}}/systemd-vconsole-setup +LoadCredential=vconsole.keymap +LoadCredential=vconsole.keymap_toggle +LoadCredential=vconsole.font +LoadCredential=vconsole.font_map +LoadCredential=vconsole.font_unimap |