]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
import-creds: add support for binary credentials specified on the kernel cmdline
authorLennart Poettering <lennart@poettering.net>
Tue, 4 Jul 2023 09:46:37 +0000 (11:46 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 4 Jul 2023 21:19:48 +0000 (23:19 +0200)
docs/CREDENTIALS.md
man/kernel-command-line.xml
man/systemd.exec.xml
man/systemd.xml
src/core/import-creds.c
test/TEST-54-CREDS/test.sh
test/units/testsuite-54.sh

index da5152c16457b7b099ef9d4400cca1592f78077a..9d06c45f1f0576aeadcd849d1a49c734fd13dd92 100644 (file)
@@ -322,10 +322,11 @@ services where they are ultimately consumed.
    be sure they can be accessed securely from initrd context.
 
 4. Credentials can also be passed into a system via the kernel command line,
-   via the `systemd.set-credential=` kernel command line option. Note though
-   that any data specified here is visible to all userspace applications (even
-   unprivileged ones) via `/proc/cmdline`. Typically, this is hence not useful
-   to pass sensitive information, and should be avoided.
+   via the `systemd.set_credential=` and `systemd.set_credential_binary=`
+   kernel command line options (the latter takes Base64 encoded binary
+   data). Note though that any data specified here is visible to all userspace
+   applications (even unprivileged ones) via `/proc/cmdline`. Typically, this
+   is hence not useful to pass sensitive information, and should be avoided.
 
 Credentials passed to the system may be enumerated/displayed via `systemd-creds
 --system`. They may also be propagated down to services, via the
index 93ed4f6acb53d13605d64f46306e99b7be73441d..43247fe5341517c4075666c007b3bf1852a45fe3 100644 (file)
@@ -72,6 +72,7 @@
         <term><varname>systemd.setenv=</varname></term>
         <term><varname>systemd.machine_id=</varname></term>
         <term><varname>systemd.set_credential=</varname></term>
+        <term><varname>systemd.set_credential_binary=</varname></term>
         <term><varname>systemd.import_credentials=</varname></term>
         <term><varname>systemd.reload_limit_interval_sec=</varname></term>
         <term><varname>systemd.reload_limit_burst=</varname></term>
index ccec6ec4235de2f4cce9f11fcafa0bed9b90533a..e077407367777e1f4d3b86208b23af81cbb6c197 100644 (file)
@@ -3285,7 +3285,8 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
         <citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
         from the initrd (see
         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>), or be
-        specified on the kernel command line using the <literal>systemd.set_credential=</literal> switch (see
+        specified on the kernel command line using the <literal>systemd.set_credential=</literal> and
+        <literal>systemd.set_credential_binary=</literal> switches (see
         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> – this is
         not recommended since unprivileged userspace can read the kernel command line). </para>
 
index 754aadbb6aac386ba64c5d4c4841bc7d7f59a39c..21c98efecd4dd855180d21e2c635e7461b019770 100644 (file)
 
       <varlistentry>
         <term><varname>systemd.set_credential=</varname></term>
+        <term><varname>systemd.set_credential_binary=</varname></term>
 
         <listitem><para>Sets a system credential, which can then be propagated to system services using the
         <varname>ImportCredential=</varname> or <varname>LoadCredential=</varname> setting, see
         <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
-        details. Takes a pair of credential name and value, separated by a colon. Note that the kernel
-        command line is typically accessible by unprivileged programs in
+        details. Takes a pair of credential name and value, separated by a colon. The
+        <varname>systemd.set_credential=</varname> parameter expects the credential value in literal text
+        form, the <varname>systemd.set_credential_binary=</varname> parameter takes binary data encoded in
+        Base64. Note that the kernel command line is typically accessible by unprivileged programs in
         <filename>/proc/cmdline</filename>. Thus, this mechanism is not suitable for transferring sensitive
         data. Use it only for data that is not sensitive (e.g. public keys/certificates, rather than private
         keys), or in testing/debugging environments.</para>
index 6bf6ded44c5d1724eb0af3ed47c1cf2979ac6513..40cbf10dad8d4c74f7607c921fa2c1792cf71a8f 100644 (file)
@@ -278,15 +278,21 @@ static int import_credentials_boot(void) {
 
 static int proc_cmdline_callback(const char *key, const char *value, void *data) {
         ImportCredentialContext *c = ASSERT_PTR(data);
+        _cleanup_free_ void *binary = NULL;
         _cleanup_free_ char *n = NULL;
         _cleanup_close_ int nfd = -EBADF;
-        const char *colon;
+        const char *colon, *d;
+        bool base64;
         size_t l;
         int r;
 
         assert(key);
 
-        if (!proc_cmdline_key_streq(key, "systemd.set_credential"))
+        if (proc_cmdline_key_streq(key, "systemd.set_credential"))
+                base64 = false;
+        else if (proc_cmdline_key_streq(key, "systemd.set_credential_binary"))
+                base64 = true;
+        else
                 return 0;
 
         colon = value ? strchr(value, ':') : NULL;
@@ -305,7 +311,19 @@ static int proc_cmdline_callback(const char *key, const char *value, void *data)
         }
 
         colon++;
-        l = strlen(colon);
+
+        if (base64) {
+                r = unbase64mem(colon, SIZE_MAX, &binary, &l);
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to decode binary credential '%s' data, ignoring: %m", n);
+                        return 0;
+                }
+
+                d = binary;
+        } else {
+                d = colon;
+                l = strlen(colon);
+        }
 
         if (!credential_size_ok(c, n, l))
                 return 0;
@@ -320,7 +338,7 @@ static int proc_cmdline_callback(const char *key, const char *value, void *data)
         if (nfd < 0)
                 return nfd;
 
-        r = loop_write(nfd, colon, l, /* do_poll= */ false);
+        r = loop_write(nfd, d, l, /* do_poll= */ false);
         if (r < 0) {
                 (void) unlinkat(c->target_dir_fd, n, 0);
                 return log_error_errno(r, "Failed to write credential: %m");
index 55882422305e5a59256dfa25f36fb0a3931e3b94..c0a9d7a53d506cb33ecdaa1c5a3a267130799990 100755 (executable)
@@ -25,6 +25,7 @@ KERNEL_CREDS=(
     "systemd.set_credential=sysctl.extra:kernel.domainname=sysctltest"
     "systemd.set_credential=login.motd:hello"
     "systemd.set_credential=login.issue:welcome"
+    "systemd.set_credential_binary=waldi:d29vb29mZmZ3dWZmZnd1ZmYK"
     "rd.systemd.import_credentials=no"
 )
 KERNEL_APPEND="${KERNEL_APPEND:-} ${KERNEL_CREDS[*]}"
index 8ba327a3b11773f9e28db607716f0d877affcdbb..6c4e0065009bae139ab516e177de3de2952d4cc3 100755 (executable)
@@ -176,6 +176,7 @@ if systemd-detect-virt -q -c ; then
 elif [ -d /sys/firmware/qemu_fw_cfg/by_name ]; then
     # Verify that passing creds through kernel cmdline works
     [ "$(systemd-creds --system cat kernelcmdlinecred)" = "uff" ]
+    [ "$(systemd-creds --system cat waldi)" = "woooofffwufffwuff" ]
 
     # And that it also works via SMBIOS
     [ "$(systemd-creds --system cat smbioscredential)" = "magicdata" ]