Compare commits

..

No commits in common. "13b6c4c8de3d2e5b0157a78f90bde42f846f7d3d" and "e16f18bddf5f13514d30b8886838e81abfc10528" have entirely different histories.

45 changed files with 238 additions and 3261 deletions

View File

@ -449,7 +449,7 @@ mouse:usb:v046dp406a:name:Logitech MX Anywhere 2S:
mouse:bluetooth:v046dpb01a:name:MX Anywhere 2S Mouse:
MOUSE_WHEEL_CLICK_ANGLE=20
# Logitech MX Master (via Logitech Unifying Receiver)
# Logitech MX Master
# Horiz wheel has 14 stops, angle is rounded up
mouse:usb:v046dp4060:name:Logitech MX Master:
mouse:usb:v046dp4041:name:Logitech MX Master:
@ -459,15 +459,6 @@ mouse:usb:v046dp4041:name:Logitech MX Master:
MOUSE_WHEEL_CLICK_COUNT=24
MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14
# Logitech MX Master (via Bluetooth)
# Horiz wheel has 14 stops, angle is rounded up
mouse:bluetooth:v046dpb012:name:MX Master Mouse:
MOUSE_DPI=1000@2000
MOUSE_WHEEL_CLICK_ANGLE=15
MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26
MOUSE_WHEEL_CLICK_COUNT=24
MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14
# Logitech MX Master 2S (via Logitech Unifying Receiver)
# Horiz wheel has 14 stops, angle is rounded up
mouse:usb:v046dp4069:name:Logitech MX Master 2s:

View File

@ -10,7 +10,7 @@
The Red Hat version has been written by Miloslav Trmac <mitr@redhat.com>.
-->
<refentry id="crypttab" conditional='HAVE_LIBCRYPTSETUP' xmlns:xi="http://www.w3.org/2001/XInclude">
<refentry id="crypttab" conditional='HAVE_LIBCRYPTSETUP'>
<refentryinfo>
<title>crypttab</title>
@ -413,22 +413,9 @@
<varlistentry>
<term><option>verify</option></term>
<listitem><para>If the encryption password is read from console, it has to be entered twice to
prevent typos.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>pkcs11-uri=</option></term>
<listitem><para>Takes a <ulink url="https://tools.ietf.org/html/rfc7512">RFC7512 PKCS#11 URI</ulink>
pointing to a private RSA key which is used to decrypt the key specified in the third column of the
line. This is useful for unlocking encrypted volumes through security tokens or smartcards. See below
for an example how to set up this mechanism for unlocking a LUKS volume with a YubiKey security
token. The specified URI can refer directly to a private RSA key stored on a token or alternatively
just to a slot or token in which case a suitable private RSA key object is automatically searched on
it. In this case if multiple suitable objects are found the token is refused. The key configured in
the third column is passed as is to RSA decryption. The resulting decrypted key is then base64
encoded before it is used to unlock the LUKS volume.</para></listitem>
<listitem><para> If the encryption password is read from
console, it has to be entered twice to prevent
typos.</para></listitem>
</varlistentry>
<varlistentry>
@ -471,7 +458,7 @@
</refsect1>
<refsect1>
<title>Examples</title>
<title>Example</title>
<example>
<title>/etc/crypttab example</title>
<para>Set up four encrypted block devices. One using LUKS for
@ -484,27 +471,6 @@ truecrypt /dev/sda2 /etc/container_password tcrypt
hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile
external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s</programlisting>
</example>
<example>
<title>Yubikey-based Volume Unlocking Example</title>
<para>The PKCS#11 logic allows hooking up any compatible security token that is capable of storing RSA
decryption keys. Here's an example how to set up a Yubikey security token for this purpose:</para>
<programlisting><xi:include href="yubikey-crypttab.sh" parse="text" /></programlisting>
<para>A few notes on the above:</para>
<itemizedlist>
<listitem><para>We use RSA (and not ECC), since Yubikeys support PKCS#11 Decrypt() only for RSA keys</para></listitem>
<listitem><para>We use RSA2048, which is the longest key size current Yubikeys support</para></listitem>
<listitem><para>LUKS key size must be shorter than 2048bit due to RSA padding, hence we use 128 bytes</para></listitem>
<listitem><para>We use Yubikey key slot 9d, since that's apparently the keyslot to use for decryption purposes,
<ulink url="https://developers.yubico.com/PIV/Introduction/Certificate_slots.html">see
documentation</ulink>.</para></listitem>
</itemizedlist>
</example>
</refsect1>
<refsect1>

View File

@ -356,24 +356,12 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>AlternativeNamesPolicy=</varname></term>
<listitem>
<para>A space-separated list of policies by which the interface's alternative names
should be set. Each of the policies may fail, and all successful policies are used. The
available policies are <literal>database</literal>, <literal>onboard</literal>,
<literal>slot</literal>, <literal>path</literal>, and <literal>mac</literal>. If the
kernel does not support the alternative names, then this setting will be ignored.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>AlternativeName=</varname></term>
<listitem>
<para>The alternative interface name to use. This option can be specified multiple times.
If the empty string is assigned to this option, the list is reset, and all prior assignments
have no effect. If the kernel does not support the alternative names, then this setting will
be ignored.</para>
have no effect.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -2515,76 +2515,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingFlowLimit=</varname></term>
<listitem>
<para>Specifies the hard limit on the maximum number of packets queued per flow. Defaults to
unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingQuantum=</varname></term>
<listitem>
<para>Specifies the credit per dequeue RR round, i.e. the amount of bytes a flow is allowed
to dequeue at once. When suffixed with K, M, or G, the specified size is parsed as Kilobytes,
Megabytes, or Gigabytes, respectively, to the base of 1024. Defaults to unset and kernel's
default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingInitialQuantum=</varname></term>
<listitem>
<para>Specifies the initial sending rate credit, i.e. the amount of bytes a new flow is
allowed to dequeue initially. When suffixed with K, M, or G, the specified size is parsed as
Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1024. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingMaximumRate=</varname></term>
<listitem>
<para>Specifies the maximum sending rate of a flow. When suffixed with K, M, or G, the
specified size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of
1000. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingBuckets=</varname></term>
<listitem>
<para>Specifies the size of the hash table used for flow lookups. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingOrphanMask=</varname></term>
<listitem>
<para>Takes an unsigned integer. For packets not owned by a socket, fq is able to mask a part
of hash and reduce number of buckets associated with the traffic. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingPacing=</varname></term>
<listitem>
<para>Takes a boolean, and enables or disables flow pacing. Defaults to unset and kernel's
default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingCEThresholdSec=</varname></term>
<listitem>
<para>Takes a timespan. This sets a threshold above which all packets are marked with ECN
Congestion Experienced (CE). Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -1,45 +0,0 @@
# Make sure noone can read the files we generate but us
umask 077
# Destroy any old key on the Yubikey (careful!)
ykman piv reset
# Generate a new private/public key pair on the device, store the public key in 'pubkey.pem'.
ykman piv generate-key -a RSA2048 9d pubkey.pem
# Create a self-signed certificate from this public key, and store it on the device.
ykman piv generate-certificate --subject "Knobelei" 9d pubkey.pem
# Check if the newly create key on the Yubikey shows up as token in PKCS#11. Have a look at the output, and
# copy the resulting token URI to the clipboard.
p11tool --list-tokens
# Generate a (secret) random key to use as LUKS decryption key.
dd if=/dev/urandom of=plaintext.bin bs=128 count=1
# Encode the secret key also as base64 text (with all whitespace removed)
base64 &lt; plaintext.bin | tr -d '\n\r\t ' &gt; plaintext.base64
# Encrypt this newly generated (binary) LUKS decryption key using the public key whose private key is on the
# Yubikey, store the result in /etc/encrypted-luks-key.bin, where we'll look for it during boot.
openssl rsautl -encrypt -pubin -inkey pubkey.pem -in plaintext.bin -out /etc/encrypted-luks-key.bin
# Configure the LUKS decryption key on the LUKS device. We use very low pbkdf settings since the key already
# has quite a high quality (it comes directly from /dev/urandom after all), and thus we don't need to do much
# key derivation.
cryptsetup luksAddKey /dev/sda1 plaintext.base64 --pbkdf=pbkdf2 --pbkdf-force-iterations=1000
# Now securely delete the plain text LUKS key, we don't need it anymore, and since it contains secret key
# material it should be removed from disk thoroughly.
shred -u plaintext.bin plaintext.base64
# We don't need the public key anymore either, let's remove it too. Since this one is not security
# sensitive we just do a regular "rm" here.
rm pubkey.pem
# Test: Let's run systemd-cryptsetup to test if this all worked. The option string should contain the full
# PKCS#11 URI we have in the clipboard, it tells the tool how to decypher the encrypted LUKS key.
systemd-cryptsetup attach mytest /dev/sda1 /etc/encrypted-luks-key.bin 'pkcs11-uri=pkcs11:…'
# If that worked, let's now add the same line persistently to /etc/crypttab, for the future.
echo "mytest /dev/sda1 /etc/encrypted-luks-key 'pkcs11-uri=pkcs11:…' >> /etc/crypttab

View File

@ -1104,18 +1104,6 @@ else
endif
conf.set10('HAVE_OPENSSL', have)
want_p11kit = get_option('p11kit')
if want_p11kit != 'false' and not skip_deps
libp11kit = dependency('p11-kit-1',
version : '>= 0.23.3',
required : want_p11kit == 'true')
have = libp11kit.found()
else
have = false
libp11kit = []
endif
conf.set10('HAVE_P11KIT', have)
want_elfutils = get_option('elfutils')
if want_elfutils != 'false' and not skip_deps
libdw = dependency('libdw',
@ -2009,21 +1997,11 @@ executable('systemd-system-update-generator',
install_dir : systemgeneratordir)
if conf.get('HAVE_LIBCRYPTSETUP') == 1
systemd_cryptsetup_sources = files('''
src/cryptsetup/cryptsetup.c
src/cryptsetup/cryptsetup-pkcs11.h
'''.split())
if conf.get('HAVE_P11KIT') == 1
systemd_cryptsetup_sources += files('src/cryptsetup/cryptsetup-pkcs11.c')
endif
executable('systemd-cryptsetup',
systemd_cryptsetup_sources,
'src/cryptsetup/cryptsetup.c',
include_directories : includes,
link_with : [libshared],
dependencies : [libcryptsetup,
libp11kit],
dependencies : [libcryptsetup],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@ -3216,7 +3194,6 @@ missing = []
foreach tuple : [
['libcryptsetup'],
['PAM'],
['p11kit'],
['AUDIT'],
['IMA'],
['AppArmor'],

View File

@ -282,8 +282,6 @@ option('gnutls', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'gnutls support')
option('openssl', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'openssl support')
option('p11kit', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'p11kit support')
option('elfutils', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'elfutils support')
option('zlib', type : 'combo', choices : ['auto', 'true', 'false'],

View File

@ -12,5 +12,4 @@ OriginalName=*
[Link]
NamePolicy=keep kernel database onboard slot path
AlternativeNamesPolicy=database onboard slot path
MACAddressPolicy=persistent

View File

@ -4,10 +4,4 @@ ACTION=="remove", GOTO="fido_id_end"
SUBSYSTEM=="hidraw", IMPORT{program}="fido_id"
# Tag any form of security token as such
ENV{ID_SECURITY_TOKEN}=="1", TAG+="security-device"
# Tag any CCID device (i.e. Smartcard Reader) as security token
SUBSYSTEM=="usb", ATTR{bInterfaceClass}=="0b", TAG+="security-device"
LABEL="fido_id_end"

View File

@ -136,18 +136,13 @@ static int write_string_file_atomic(
assert(fn);
assert(line);
/* Note that we'd really like to use O_TMPFILE here, but can't really, since we want replacement
* semantics here, and O_TMPFILE can't offer that. i.e. rename() replaces but linkat() doesn't. */
r = fopen_temporary(fn, &f, &p);
if (r < 0)
return r;
r = write_string_stream_ts(f, line, flags, ts);
if (r < 0)
goto fail;
(void) fchmod_umask(fileno(f), 0644);
r = fchmod_umask(fileno(f), FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0644);
r = write_string_stream_ts(f, line, flags, ts);
if (r < 0)
goto fail;
@ -170,7 +165,7 @@ int write_string_file_ts(
struct timespec *ts) {
_cleanup_fclose_ FILE *f = NULL;
int q, r, fd;
int q, r;
assert(fn);
assert(line);
@ -195,20 +190,26 @@ int write_string_file_ts(
} else
assert(!ts);
/* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */
fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY |
(FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0),
(FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0666));
if (fd < 0) {
r = -errno;
goto fail;
}
if (flags & WRITE_STRING_FILE_CREATE) {
r = fopen_unlocked(fn, "we", &f);
if (r < 0)
goto fail;
} else {
int fd;
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
safe_close(fd);
goto fail;
/* We manually build our own version of fopen(..., "we") that
* works without O_CREAT */
fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | ((flags & WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (fd < 0) {
r = -errno;
goto fail;
}
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
safe_close(fd);
goto fail;
}
}
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
@ -542,19 +543,17 @@ finalize:
return r;
}
int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(filename);
assert(contents);
r = xfopenat(dir_fd, filename, "re", 0, &f);
r = fopen_unlocked(filename, "re", &f);
if (r < 0)
return r;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
return read_full_stream_full(f, filename, flags, contents, size);
}
@ -681,81 +680,6 @@ DIR *xopendirat(int fd, const char *name, int flags) {
return d;
}
static int mode_to_flags(const char *mode) {
const char *p;
int flags;
if ((p = startswith(mode, "r+")))
flags = O_RDWR;
else if ((p = startswith(mode, "r")))
flags = O_RDONLY;
else if ((p = startswith(mode, "w+")))
flags = O_RDWR|O_CREAT|O_TRUNC;
else if ((p = startswith(mode, "w")))
flags = O_WRONLY|O_CREAT|O_TRUNC;
else if ((p = startswith(mode, "a+")))
flags = O_RDWR|O_CREAT|O_APPEND;
else if ((p = startswith(mode, "a")))
flags = O_WRONLY|O_CREAT|O_APPEND;
else
return -EINVAL;
for (; *p != 0; p++) {
switch (*p) {
case 'e':
flags |= O_CLOEXEC;
break;
case 'x':
flags |= O_EXCL;
break;
case 'm':
/* ignore this here, fdopen() might care later though */
break;
case 'c': /* not sure what to do about this one */
default:
return -EINVAL;
}
}
return flags;
}
int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret) {
FILE *f;
/* A combination of fopen() with openat() */
if (dir_fd == AT_FDCWD && flags == 0) {
f = fopen(path, mode);
if (!f)
return -errno;
} else {
int fd, mode_flags;
mode_flags = mode_to_flags(mode);
if (mode_flags < 0)
return mode_flags;
fd = openat(dir_fd, path, mode_flags | flags);
if (fd < 0)
return -errno;
f = fdopen(fd, mode);
if (!f) {
safe_close(fd);
return -errno;
}
}
*ret = f;
return 0;
}
static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
char **i;

View File

@ -6,7 +6,6 @@
#include <stddef.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include "macro.h"
@ -23,7 +22,6 @@ typedef enum {
WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5,
WRITE_STRING_FILE_NOFOLLOW = 1 << 6,
WRITE_STRING_FILE_MKDIR_0755 = 1 << 7,
WRITE_STRING_FILE_MODE_0600 = 1 << 8,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
@ -54,9 +52,9 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
int read_one_line_file(const char *filename, char **line);
int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
static inline int read_full_file(const char *filename, char **contents, size_t *size) {
return read_full_file_full(AT_FDCWD, filename, 0, contents, size);
return read_full_file_full(filename, 0, contents, size);
}
int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size);
int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
@ -71,7 +69,6 @@ int executable_is_script(const char *path, char **interpreter);
int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field);
DIR *xopendirat(int dirfd, const char *name, int flags);
int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret);
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);

View File

@ -366,7 +366,7 @@ static int create_disk(
r = generator_write_timeouts(arg_dest, device, name, options, &filtered);
if (r < 0)
log_warning_errno(r, "Failed to write device timeout drop-in: %m");
return r;
if (filtered) {
filtered_escaped = specifier_escape(filtered);
@ -419,11 +419,11 @@ static int create_disk(
return r;
if (!noauto && !nofail) {
r = write_drop_in(arg_dest, dmname, 40, "device-timeout",
"# Automatically generated by systemd-cryptsetup-generator\n\n"
r = write_drop_in(arg_dest, dmname, 90, "device-timeout",
"# Automatically generated by systemd-cryptsetup-generator \n\n"
"[Unit]\nJobTimeoutSec=0");
if (r < 0)
log_warning_errno(r, "Failed to write device timeout drop-in: %m");
return log_error_errno(r, "Failed to write device drop-in: %m");
}
return 0;
@ -650,6 +650,7 @@ static int add_proc_cmdline_devices(void) {
crypto_device *d;
HASHMAP_FOREACH(d, arg_disks, i) {
const char *options;
_cleanup_free_ char *device = NULL;
if (!d->create)
@ -665,11 +666,14 @@ static int add_proc_cmdline_devices(void) {
if (!device)
return log_oom();
r = create_disk(d->name,
device,
d->keyfile ?: arg_default_keyfile,
d->keydev,
d->options ?: arg_default_options);
if (d->options)
options = d->options;
else if (arg_default_options)
options = arg_default_options;
else
options = "timeout=0";
r = create_disk(d->name, device, d->keyfile ?: arg_default_keyfile, d->keydev, options);
if (r < 0)
return r;
}

View File

@ -1,172 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <p11-kit/p11-kit.h>
#include <p11-kit/uri.h>
#include "alloc-util.h"
#include "ask-password-api.h"
#include "cryptsetup-pkcs11.h"
#include "escape.h"
#include "fd-util.h"
#include "macro.h"
#include "memory-util.h"
#include "pkcs11-util.h"
#include "stat-util.h"
#include "strv.h"
static int load_key_file(
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
void **ret_encrypted_key,
size_t *ret_encrypted_key_size) {
_cleanup_(erase_and_freep) char *buffer = NULL;
_cleanup_close_ int fd = -1;
ssize_t n;
int r;
assert(key_file);
assert(ret_encrypted_key);
assert(ret_encrypted_key_size);
fd = open(key_file, O_RDONLY|O_CLOEXEC);
if (fd < 0)
return log_error_errno(errno, "Failed to load encrypted PKCS#11 key: %m");
if (key_file_size == 0) {
struct stat st;
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat key file: %m");
r = stat_verify_regular(&st);
if (r < 0)
return log_error_errno(r, "Key file is not a regular file: %m");
if (st.st_size == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file is empty, refusing.");
if ((uint64_t) st.st_size > SIZE_MAX)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Key file too large, refusing.");
if (key_file_offset >= (uint64_t) st.st_size)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key file offset too large for file, refusing.");
key_file_size = st.st_size - key_file_offset;
}
buffer = malloc(key_file_size);
if (!buffer)
return log_oom();
if (key_file_offset > 0)
n = pread(fd, buffer, key_file_size, key_file_offset);
else
n = read(fd, buffer, key_file_size);
if (n < 0)
return log_error_errno(errno, "Failed to read PKCS#11 key file: %m");
if (n == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
*ret_encrypted_key = TAKE_PTR(buffer);
*ret_encrypted_key_size = (size_t) n;
return 0;
}
struct pkcs11_callback_data {
const char *friendly_name;
usec_t until;
void *encrypted_key;
size_t encrypted_key_size;
void *decrypted_key;
size_t decrypted_key_size;
};
static void pkcs11_callback_data_release(struct pkcs11_callback_data *data) {
free(data->decrypted_key);
free(data->encrypted_key);
}
static int pkcs11_callback(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,
CK_SLOT_ID slot_id,
const CK_SLOT_INFO *slot_info,
const CK_TOKEN_INFO *token_info,
P11KitUri *uri,
void *userdata) {
struct pkcs11_callback_data *data = userdata;
CK_OBJECT_HANDLE object;
int r;
assert(m);
assert(slot_info);
assert(token_info);
assert(uri);
assert(data);
/* Called for every token matching our URI */
r = pkcs11_token_login(m, session, slot_id, token_info, data->friendly_name, "drive-harddisk", "pkcs11-pin", data->until, NULL);
if (r < 0)
return r;
/* We are likely called during early boot, where entropy is scarce. Mix some data from the PKCS#11
* token, if it supports that. It should be cheap, given that we already are talking to it anyway and
* shouldn't hurt. */
(void) pkcs11_token_acquire_rng(m, session);
r = pkcs11_token_find_private_key(m, session, uri, &object);
if (r < 0)
return r;
r = pkcs11_token_decrypt_data(m, session, object, data->encrypted_key, data->encrypted_key_size, &data->decrypted_key, &data->decrypted_key_size);
if (r < 0)
return r;
return 1;
}
int decrypt_pkcs11_key(
const char *friendly_name,
const char *pkcs11_uri,
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
usec_t until,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
_cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = {
.friendly_name = friendly_name,
.until = until,
};
int r;
assert(friendly_name);
assert(pkcs11_uri);
assert(key_file);
assert(ret_decrypted_key);
assert(ret_decrypted_key_size);
/* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
r = load_key_file(key_file, key_file_size, key_file_offset, &data.encrypted_key, &data.encrypted_key_size);
if (r < 0)
return r;
r = pkcs11_find_token(pkcs11_uri, pkcs11_callback, &data);
if (r < 0)
return r;
*ret_decrypted_key = TAKE_PTR(data.decrypted_key);
*ret_decrypted_key_size = data.decrypted_key_size;
return 0;
}

View File

@ -1,37 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <sys/types.h>
#include "log.h"
#include "time-util.h"
#if HAVE_P11KIT
int decrypt_pkcs11_key(
const char *friendly_name,
const char *pkcs11_uri,
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
usec_t until,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size);
#else
static inline int decrypt_pkcs11_key(
const char *friendly_name,
const char *pkcs11_uri,
const char *key_file,
size_t key_file_size,
uint64_t key_file_offset,
usec_t until,
void **ret_decrypted_key,
size_t *ret_decrypted_key_size) {
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"PKCS#11 Token support not available.");
}
#endif

View File

@ -12,19 +12,16 @@
#include "alloc-util.h"
#include "ask-password-api.h"
#include "crypt-util.h"
#include "cryptsetup-pkcs11.h"
#include "device-util.h"
#include "escape.h"
#include "fileio.h"
#include "fstab-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "main-func.h"
#include "mount-util.h"
#include "nulstr-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "pkcs11-util.h"
#include "pretty-print.h"
#include "string-util.h"
#include "strv.h"
@ -57,13 +54,11 @@ static char **arg_tcrypt_keyfiles = NULL;
static uint64_t arg_offset = 0;
static uint64_t arg_skip = 0;
static usec_t arg_timeout = USEC_INFINITY;
static char *arg_pkcs11_uri = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep);
STATIC_DESTRUCTOR_REGISTER(arg_hash, freep);
STATIC_DESTRUCTOR_REGISTER(arg_header, freep);
STATIC_DESTRUCTOR_REGISTER(arg_tcrypt_keyfiles, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
/* Options Debian's crypttab knows we don't:
@ -233,15 +228,6 @@ static int parse_one_option(const char *option) {
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", option);
} else if ((val = startswith(option, "pkcs11-uri="))) {
if (!pkcs11_uri_valid(val))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "pkcs11-uri= parameter expects a PKCS#11 URI, refusing");
r = free_and_strdup(&arg_pkcs11_uri, val);
if (r < 0)
return log_oom();
} else if (!streq(option, "x-initrd.attach"))
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
@ -328,19 +314,28 @@ static char *disk_mount_point(const char *label) {
return NULL;
}
static char *friendly_disk_name(const char *src, const char *vol) {
_cleanup_free_ char *description = NULL, *mount_point = NULL;
char *name_buffer = NULL;
int r;
static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***ret) {
_cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL, *text = NULL, *disk_path = NULL;
_cleanup_strv_free_erase_ char **passwords = NULL;
const char *name = NULL;
char **p, *id;
int r = 0;
assert(src);
assert(vol);
assert(src);
assert(ret);
description = disk_description(src);
mount_point = disk_mount_point(vol);
/* If the description string is simply the volume name, then let's not show this twice */
disk_path = cescape(src);
if (!disk_path)
return log_oom();
if (description && streq(vol, description))
/* If the description string is simply the
* volume name, then let's not show this
* twice */
description = mfree(description);
if (mount_point && description)
@ -349,39 +344,13 @@ static char *friendly_disk_name(const char *src, const char *vol) {
r = asprintf(&name_buffer, "%s on %s", vol, mount_point);
else if (description)
r = asprintf(&name_buffer, "%s (%s)", description, vol);
else
return strdup(vol);
if (r < 0)
return NULL;
return name_buffer;
}
static int get_password(
const char *vol,
const char *src,
usec_t until,
bool accept_cached,
char ***ret) {
_cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL;
_cleanup_strv_free_erase_ char **passwords = NULL;
char **p, *id;
int r = 0;
assert(vol);
assert(src);
assert(ret);
friendly = friendly_disk_name(src, vol);
if (!friendly)
return log_oom();
if (asprintf(&text, "Please enter passphrase for disk %s:", friendly) < 0)
return log_oom();
name = name_buffer ? name_buffer : vol;
disk_path = cescape(src);
if (!disk_path)
if (asprintf(&text, "Please enter passphrase for disk %s:", name) < 0)
return log_oom();
id = strjoina("cryptsetup:", disk_path);
@ -397,7 +366,7 @@ static int get_password(
assert(strv_length(passwords) == 1);
if (asprintf(&text, "Please enter passphrase for disk %s (verification):", friendly) < 0)
if (asprintf(&text, "Please enter passphrase for disk %s (verification):", name) < 0)
return log_oom();
id = strjoina("cryptsetup-verification:", disk_path);
@ -455,11 +424,6 @@ static int attach_tcrypt(
assert(name);
assert(key_file || (passwords && passwords[0]));
if (arg_pkcs11_uri) {
log_error("Sorry, but tcrypt devices are currently not supported in conjunction with pkcs11 support.");
return -EAGAIN; /* Ask for a regular password */
}
if (arg_tcrypt_hidden)
params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
@ -503,14 +467,14 @@ static int attach_luks_or_plain(
const char *name,
const char *key_file,
char **passwords,
uint32_t flags,
usec_t until) {
uint32_t flags) {
int r = 0;
bool pass_volume_key = false;
assert(cd);
assert(name);
assert(key_file || passwords);
if ((!arg_type && !crypt_get_type(cd)) || streq_ptr(arg_type, CRYPT_PLAIN)) {
struct crypt_params_plain params = {
@ -564,111 +528,7 @@ static int attach_luks_or_plain(
crypt_get_volume_key_size(cd)*8,
crypt_get_device_name(cd));
if (arg_pkcs11_uri) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_free_ void *decrypted_key = NULL;
_cleanup_free_ char *friendly = NULL;
size_t decrypted_key_size = 0;
if (!key_file)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
friendly = friendly_disk_name(crypt_get_device_name(cd), name);
if (!friendly)
return log_oom();
for (;;) {
bool processed = false;
r = decrypt_pkcs11_key(
friendly,
arg_pkcs11_uri,
key_file,
arg_keyfile_size, arg_keyfile_offset,
until,
&decrypted_key, &decrypted_key_size);
if (r >= 0)
break;
if (r != -EAGAIN) /* EAGAIN means: token not found */
return r;
if (!monitor) {
/* We didn't find the token. In this case, watch for it via udev. Let's
* create an event loop and monitor first. */
assert(!event);
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
r = sd_device_monitor_new(&monitor);
if (r < 0)
return log_error_errno(r, "Failed to allocate device monitor: %m");
r = sd_device_monitor_filter_add_match_tag(monitor, "security-device");
if (r < 0)
return log_error_errno(r, "Failed to configure device monitor: %m");
r = sd_device_monitor_attach_event(monitor, event);
if (r < 0)
return log_error_errno(r, "Failed to attach device monitor: %m");
r = sd_device_monitor_start(monitor, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to start device monitor: %m");
log_notice("Security token %s not present for unlocking volume %s, please plug it in.",
arg_pkcs11_uri, friendly);
/* Let's immediately rescan in case the token appeared in the time we needed
* to create and configure the monitor */
continue;
}
for (;;) {
/* Wait for one event, and then eat all subsequent events until there are no
* further ones */
r = sd_event_run(event, processed ? 0 : UINT64_MAX);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
if (r == 0)
break;
processed = true;
}
log_debug("Got one or more potentially relevant udev events, rescanning PKCS#11...");
}
if (pass_volume_key)
r = crypt_activate_by_volume_key(cd, name, decrypted_key, decrypted_key_size, flags);
else {
_cleanup_free_ char *base64_encoded = NULL;
/* Before using this key as passphrase we base64 encode it. Why? For compatibility
* with homed's PKCS#11 hookup: there we want to use the key we acquired through
* PKCS#11 for other authentication/decryption mechanisms too, and some of them do
* not not take arbitrary binary blobs, but require NUL-terminated strings most
* importantly UNIX password hashes. Hence, for compatibility we want to use a string
* without embedded NUL here too, and that's easiest to generate from a binary blob
* via base64 encoding. */
r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
if (r < 0)
return log_oom();
r = crypt_activate_by_passphrase(cd, name, arg_key_slot, base64_encoded, strlen(base64_encoded), flags);
}
if (r == -EPERM) {
log_error_errno(r, "Failed to activate with PKCS#11 decrypted key. (Key incorrect?)");
return -EAGAIN; /* log actual error, but return EAGAIN */
}
if (r < 0)
return log_error_errno(r, "Failed to activate with PKCS#11 acquired key: %m");
} else if (key_file) {
if (key_file) {
r = crypt_activate_by_keyfile_device_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags);
if (r == -EPERM) {
log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file);
@ -857,7 +717,7 @@ static int run(int argc, char *argv[]) {
for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) {
_cleanup_strv_free_erase_ char **passwords = NULL;
if (!key_file && !arg_pkcs11_uri) {
if (!key_file) {
r = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
if (r == -EAGAIN)
continue;
@ -868,7 +728,7 @@ static int run(int argc, char *argv[]) {
if (streq_ptr(arg_type, CRYPT_TCRYPT))
r = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
else
r = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags, until);
r = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags);
if (r >= 0)
break;
if (r != -EAGAIN)
@ -876,7 +736,6 @@ static int run(int argc, char *argv[]) {
/* Passphrase not correct? Let's try again! */
key_file = NULL;
arg_pkcs11_uri = NULL;
}
if (arg_tries != 0 && tries >= arg_tries)

View File

@ -18,7 +18,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
f = fmemopen_unlocked((char*) data, size, "re");
assert_se(f);
if (json_parse_file(f, NULL, 0, &v, NULL, NULL) < 0)
if (json_parse_file(f, NULL, &v, NULL, NULL) < 0)
return 0;
g = open_memstream_unlocked(&out, &out_size);

View File

@ -5,7 +5,6 @@
#include <unistd.h>
#include "alloc-util.h"
#include "dropin.h"
#include "fstab-util.h"
#include "generator.h"
#include "log.h"
@ -69,18 +68,18 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
}
static int process_resume(void) {
_cleanup_free_ char *service_unit = NULL, *device_unit = NULL, *lnk = NULL;
_cleanup_free_ char *name = NULL, *lnk = NULL;
const char *opts;
int r;
if (!arg_resume_device)
return 0;
r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service",
&service_unit);
r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service", &name);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", service_unit);
lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", name);
if (!lnk)
return log_oom();
@ -88,21 +87,12 @@ static int process_resume(void) {
if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-hibernate-resume@.service", lnk) < 0)
return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
r = unit_name_from_path(arg_resume_device, ".device", &device_unit);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
if (arg_resume_options)
opts = arg_resume_options;
else
opts = arg_root_options;
r = write_drop_in(arg_dest, device_unit, 40, "device-timeout",
"# Automatically generated by systemd-cryptsetup-generator\n\n"
"[Unit]\nJobTimeoutSec=0");
if (r < 0)
log_warning_errno(r, "Failed to write device timeout drop-in: %m");
r = generator_write_timeouts(arg_dest,
arg_resume_device,
arg_resume_device,
arg_resume_options ?: arg_root_options,
NULL);
r = generator_write_timeouts(arg_dest, arg_resume_device, arg_resume_device, opts, NULL);
if (r < 0)
return r;

View File

@ -694,7 +694,6 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
const char *local, *object;
Manager *m = userdata;
TransferType type;
struct stat st;
uint32_t id;
assert(msg);
@ -718,11 +717,9 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (r < 0)
return r;
if (fstat(fd, &st) < 0)
return -errno;
if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode))
return -EINVAL;
r = fd_verify_regular(fd);
if (r < 0)
return r;
if (!machine_name_is_valid(local))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local);
@ -832,7 +829,6 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
const char *local, *object, *format;
Manager *m = userdata;
TransferType type;
struct stat st;
uint32_t id;
assert(msg);
@ -859,11 +855,9 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (!machine_name_is_valid(local))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local);
if (fstat(fd, &st) < 0)
return -errno;
if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode))
return -EINVAL;
r = fd_verify_regular(fd);
if (r < 0)
return r;
type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ? TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW;

View File

@ -757,7 +757,7 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint
r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint32_t))
else if ((size_t)r < sizeof(uint32_t))
return -EIO;
if (data) {
@ -783,7 +783,7 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t) r < sizeof(struct ether_addr))
else if ((size_t)r < sizeof(struct ether_addr))
return -EIO;
if (data)
@ -805,7 +805,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t) r < sizeof(struct ifa_cacheinfo))
else if ((size_t)r < sizeof(struct ifa_cacheinfo))
return -EIO;
if (info)
@ -827,7 +827,7 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type,
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t) r < sizeof(struct in_addr))
else if ((size_t)r < sizeof(struct in_addr))
return -EIO;
if (data)
@ -849,7 +849,7 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t) r < sizeof(struct in6_addr))
else if ((size_t)r < sizeof(struct in6_addr))
return -EIO;
if (data)
@ -864,7 +864,7 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
const NLType *nl_type;
struct rtattr *rta;
void *container;
size_t rt_len;
unsigned short rt_len;
int r;
assert_return(m, -EINVAL);
@ -896,14 +896,10 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
if (r < 0)
return r;
rt_len = (size_t) r;
rt_len = (unsigned short) r;
rta = container;
/* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
* LGTM.com analysis does not like the type difference. Hence, here we
* introduce an unsigned short variable as a workaround. */
unsigned short len = rt_len;
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
unsigned short type;
type = RTA_TYPE(rta);
@ -922,15 +918,11 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
static int netlink_container_parse(sd_netlink_message *m,
struct netlink_container *container,
struct rtattr *rta,
size_t rt_len) {
unsigned rt_len) {
_cleanup_free_ struct netlink_attribute *attributes = NULL;
size_t n_allocated = 0;
/* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
* LGTM.com analysis does not like the type difference. Hence, here we
* introduce an unsigned short variable as a workaround. */
unsigned short len = rt_len;
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
unsigned short type;
type = RTA_TYPE(rta);
@ -1029,7 +1021,8 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
if (r < 0)
return r;
size = (size_t) r;
size = (size_t)r;
m->n_containers++;
r = netlink_container_parse(m,
@ -1059,6 +1052,7 @@ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id
return r;
size = (size_t) r;
m->n_containers++;
r = netlink_container_parse(m,

View File

@ -756,7 +756,6 @@ static const NLType rtnl_tca_option_data_fq_types[] = {
[TCA_FQ_FLOW_REFILL_DELAY] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_ORPHAN_MASK] = { .type = NETLINK_TYPE_U32 },
};
static const NLType rtnl_tca_option_data_fq_codel_types[] = {

View File

@ -981,7 +981,7 @@ static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
(void) warn_file_is_world_accessible(sa->key_file, NULL, NULL, 0);
r = read_full_file_full(AT_FDCWD, sa->key_file, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNHEX, (char **) &key, &key_len);
r = read_full_file_full(sa->key_file, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNHEX, (char **) &key, &key_len);
if (r < 0)
return log_netdev_error_errno(netdev, r,
"Failed to read key from '%s', ignoring: %m",

View File

@ -902,7 +902,7 @@ static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_
(void) warn_file_is_world_accessible(filename, NULL, NULL, 0);
r = read_full_file_full(AT_FDCWD, filename, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNBASE64, &key, &key_len);
r = read_full_file_full(filename, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNBASE64, &key, &key_len);
if (r < 0)
return r;

View File

@ -266,15 +266,7 @@ TrafficControlQueueingDiscipline.FairQueuingControlledDelayTargetSec, con
TrafficControlQueueingDiscipline.FairQueuingControlledDelayIntervalSec, config_parse_tc_fair_queuing_controlled_delay_usec, 0, 0
TrafficControlQueueingDiscipline.FairQueuingControlledDelayCEThresholdSec, config_parse_tc_fair_queuing_controlled_delay_usec, 0, 0
TrafficControlQueueingDiscipline.FairQueuingControlledDelayECN, config_parse_tc_fair_queuing_controlled_delay_bool, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacketLimit, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingFlowLimit, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingQuantum, config_parse_tc_fair_queue_traffic_policing_size, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingInitialQuantum, config_parse_tc_fair_queue_traffic_policing_size, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingMaximumRate, config_parse_tc_fair_queue_traffic_policing_max_rate, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingBuckets, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingOrphanMask, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacing, config_parse_tc_fair_queue_traffic_policing_bool, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingCEThresholdSec, config_parse_tc_fair_queue_traffic_policing_usec, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacketLimit, config_parse_tc_fair_queue_traffic_policing_packet_limit, 0, 0
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)

View File

@ -9,20 +9,6 @@
#include "netlink-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "util.h"
static int fair_queue_traffic_policing_init(QDisc *qdisc) {
FairQueueTrafficPolicing *fq;
assert(qdisc);
fq = FQ(qdisc);
fq->pacing = -1;
fq->ce_threshold_usec = USEC_INFINITY;
return 0;
}
static int fair_queue_traffic_policing_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
FairQueueTrafficPolicing *fq;
@ -38,62 +24,9 @@ static int fair_queue_traffic_policing_fill_message(Link *link, QDisc *qdisc, sd
if (r < 0)
return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
if (fq->packet_limit > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_PLIMIT, fq->packet_limit);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_PLIMIT attribute: %m");
}
if (fq->flow_limit > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_FLOW_PLIMIT, fq->flow_limit);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_FLOW_PLIMIT attribute: %m");
}
if (fq->quantum > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_QUANTUM, fq->quantum);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_QUANTUM attribute: %m");
}
if (fq->initial_quantum > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_INITIAL_QUANTUM, fq->initial_quantum);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_INITIAL_QUANTUM attribute: %m");
}
if (fq->pacing >= 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_RATE_ENABLE, fq->pacing);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_RATE_ENABLE attribute: %m");
}
if (fq->max_rate > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_FLOW_MAX_RATE, fq->max_rate);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_FLOW_MAX_RATE attribute: %m");
}
if (fq->buckets > 0) {
uint32_t l;
l = log2u(fq->buckets);
r = sd_netlink_message_append_u32(req, TCA_FQ_BUCKETS_LOG, l);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_BUCKETS_LOG attribute: %m");
}
if (fq->orphan_mask > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_ORPHAN_MASK, fq->orphan_mask);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_ORPHAN_MASK attribute: %m");
}
if (fq->ce_threshold_usec != USEC_INFINITY) {
r = sd_netlink_message_append_u32(req, TCA_FQ_CE_THRESHOLD, fq->ce_threshold_usec);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_CE_THRESHOLD attribute: %m");
}
r = sd_netlink_message_append_u32(req, TCA_FQ_PLIMIT, fq->limit);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_PLIMIT attribute: %m");
r = sd_netlink_message_close_container(req);
if (r < 0)
@ -102,137 +35,7 @@ static int fair_queue_traffic_policing_fill_message(Link *link, QDisc *qdisc, sd
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_u32(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
FairQueueTrafficPolicing *fq;
Network *network = data;
uint32_t *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"More than one kind of queueing discipline, ignoring assignment: %m");
fq = FQ(qdisc);
if (streq(lvalue, "FairQueueTrafficPolicingPacketLimit"))
p = &fq->packet_limit;
else if (streq(lvalue, "FairQueueTrafficPolicingFlowLimit"))
p = &fq->flow_limit;
else if (streq(lvalue, "FairQueueTrafficPolicingBuckets"))
p = &fq->buckets;
else if (streq(lvalue, "FairQueueTrafficPolicingOrphanMask"))
p = &fq->orphan_mask;
else
assert_not_reached("Invalid lvalue");
if (isempty(rvalue)) {
*p = 0;
qdisc = NULL;
return 0;
}
r = safe_atou32(rvalue, p);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_size(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
FairQueueTrafficPolicing *fq;
Network *network = data;
uint64_t sz;
uint32_t *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"More than one kind of queueing discipline, ignoring assignment: %m");
fq = FQ(qdisc);
if (streq(lvalue, "FairQueueTrafficPolicingQuantum"))
p = &fq->quantum;
else if (streq(lvalue, "FairQueueTrafficPolicingInitialQuantum"))
p = &fq->initial_quantum;
else
assert_not_reached("Invalid lvalue");
if (isempty(rvalue)) {
*p = 0;
qdisc = NULL;
return 0;
}
r = parse_size(rvalue, 1024, &sz);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sz > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Specified '%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
*p = sz;
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_bool(
int config_parse_tc_fair_queue_traffic_policing_packet_limit(
const char *unit,
const char *filename,
unsigned line,
@ -264,13 +67,13 @@ int config_parse_tc_fair_queue_traffic_policing_bool(
fq = FQ(qdisc);
if (isempty(rvalue)) {
fq->pacing = -1;
fq->limit = 0;
qdisc = NULL;
return 0;
}
r = parse_boolean(rvalue);
r = safe_atou32(rvalue, &fq->limit);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
@ -278,132 +81,12 @@ int config_parse_tc_fair_queue_traffic_policing_bool(
return 0;
}
fq->pacing = r;
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_usec(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
FairQueueTrafficPolicing *fq;
Network *network = data;
usec_t sec;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"More than one kind of queueing discipline, ignoring assignment: %m");
fq = FQ(qdisc);
if (isempty(rvalue)) {
fq->ce_threshold_usec = USEC_INFINITY;
qdisc = NULL;
return 0;
}
r = parse_sec(rvalue, &sec);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sec > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Specified '%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
fq->ce_threshold_usec = sec;
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_max_rate(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
FairQueueTrafficPolicing *fq;
Network *network = data;
uint64_t sz;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"More than one kind of queueing discipline, ignoring assignment: %m");
fq = FQ(qdisc);
if (isempty(rvalue)) {
fq->max_rate = 0;
qdisc = NULL;
return 0;
}
r = parse_size(rvalue, 1000, &sz);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sz / 8 > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Specified '%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
fq->max_rate = sz / 8;
qdisc = NULL;
return 0;
}
const QDiscVTable fq_vtable = {
.init = fair_queue_traffic_policing_init,
.object_size = sizeof(FairQueueTrafficPolicing),
.tca_kind = "fq",
.fill_message = fair_queue_traffic_policing_fill_message,

View File

@ -8,22 +8,10 @@
typedef struct FairQueueTrafficPolicing {
QDisc meta;
uint32_t packet_limit;
uint32_t flow_limit;
uint32_t quantum;
uint32_t initial_quantum;
uint32_t max_rate;
uint32_t buckets;
uint32_t orphan_mask;
int pacing;
usec_t ce_threshold_usec;
uint32_t limit;
} FairQueueTrafficPolicing;
DEFINE_QDISC_CAST(FQ, FairQueueTrafficPolicing);
extern const QDiscVTable fq_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_u32);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_size);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_bool);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_usec);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_max_rate);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_packet_limit);

View File

@ -172,13 +172,24 @@ static int oci_env(const char *name, JsonVariant *v, JsonDispatchFlags flags, vo
static int oci_args(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
_cleanup_strv_free_ char **l = NULL;
char ***value = userdata;
JsonVariant *e;
int r;
assert(value);
r = json_variant_strv(v, &l);
if (r < 0)
return json_log(v, flags, r, "Cannot parse arguments as list of strings: %m");
JSON_VARIANT_ARRAY_FOREACH(e, v) {
const char *n;
if (!json_variant_is_string(e))
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
"Argument is not a string.");
assert_se(n = json_variant_string(e));
r = strv_extend(&l, n);
if (r < 0)
return log_oom();
}
if (strv_isempty(l))
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
@ -2203,7 +2214,7 @@ int oci_load(FILE *f, const char *bundle, Settings **ret) {
path = strjoina(bundle, "/config.json");
r = json_parse_file(f, path, 0, &oci, &line, &column);
r = json_parse_file(f, path, &oci, &line, &column);
if (r < 0) {
if (line != 0 && column != 0)
return log_error_errno(r, "Failed to parse '%s' at %u:%u: %m", path, line, column);

View File

@ -237,12 +237,10 @@ int generator_write_timeouts(
return log_error_errno(r, "Failed to make unit name from path: %m");
return write_drop_in_format(dir, unit, 50, "device-timeout",
"# Automatically generated by %s\n"
"# from supplied options \"%s\"\n\n"
"# Automatically generated by %s\n\n"
"[Unit]\n"
"JobRunningTimeoutSec=%s",
program_invocation_short_name,
opts,
timeout);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -55,7 +54,6 @@ typedef enum JsonVariantType {
} JsonVariantType;
int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n);
int json_variant_new_integer(JsonVariant **ret, intmax_t i);
int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u);
int json_variant_new_real(JsonVariant **ret, long double d);
@ -122,10 +120,6 @@ static inline bool json_variant_is_null(JsonVariant *v) {
}
bool json_variant_is_negative(JsonVariant *v);
bool json_variant_is_blank_object(JsonVariant *v);
bool json_variant_is_blank_array(JsonVariant *v);
bool json_variant_is_normalized(JsonVariant *v);
bool json_variant_is_sorted(JsonVariant *v);
size_t json_variant_elements(JsonVariant *v);
JsonVariant *json_variant_by_index(JsonVariant *v, size_t index);
@ -134,8 +128,6 @@ JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVaria
bool json_variant_equal(JsonVariant *a, JsonVariant *b);
void json_variant_sensitive(JsonVariant *v);
struct json_variant_foreach_state {
JsonVariant *variant;
size_t idx;
@ -161,48 +153,21 @@ struct json_variant_foreach_state {
int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column);
typedef enum JsonFormatFlags {
JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
JSON_FORMAT_PRETTY_AUTO = 1 << 2, /* same, but only if connected to a tty (and JSON_FORMAT_NEWLINE otherwise) */
JSON_FORMAT_COLOR = 1 << 3, /* insert ANSI color sequences */
JSON_FORMAT_COLOR_AUTO = 1 << 4, /* insert ANSI color sequences if colors_enabled() says so */
JSON_FORMAT_SOURCE = 1 << 5, /* prefix with source filename/line/column */
JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */
JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */
JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */
JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
JSON_FORMAT_COLOR = 1 << 2, /* insert ANSI color sequences */
JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insert ANSI color sequences if colors_enabled() says so */
JSON_FORMAT_SOURCE = 1 << 4, /* prefix with source filename/line/column */
JSON_FORMAT_SSE = 1 << 5, /* prefix/suffix with W3C server-sent events */
JSON_FORMAT_SEQ = 1 << 6, /* prefix/suffix with RFC 7464 application/json-seq */
} JsonFormatFlags;
int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret);
void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix);
int json_variant_filter(JsonVariant **v, char **to_remove);
int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value);
int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value);
int json_variant_set_field_integer(JsonVariant **v, const char *field, intmax_t value);
int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uintmax_t value);
int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b);
int json_variant_append_array(JsonVariant **v, JsonVariant *element);
int json_variant_merge(JsonVariant **v, JsonVariant *m);
int json_variant_strv(JsonVariant *v, char ***ret);
int json_variant_sort(JsonVariant **v);
int json_variant_normalize(JsonVariant **v);
typedef enum JsonParseFlags {
JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */
} JsonParseFlags;
int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
static inline int json_parse_file(FILE *f, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
return json_parse_file_at(f, AT_FDCWD, path, flags, ret, ret_line, ret_column);
}
int json_parse(const char *string, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
enum {
_JSON_BUILD_STRING,
@ -218,10 +183,8 @@ enum {
_JSON_BUILD_PAIR_CONDITION,
_JSON_BUILD_NULL,
_JSON_BUILD_VARIANT,
_JSON_BUILD_VARIANT_ARRAY,
_JSON_BUILD_LITERAL,
_JSON_BUILD_STRV,
_JSON_BUILD_BASE64,
_JSON_BUILD_MAX,
};
@ -231,17 +194,13 @@ enum {
#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, ({ long double _x = d; _x; })
#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, ({ bool _x = b; _x; })
#define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END
#define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END
#define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END
#define JSON_BUILD_EMPTY_OBJECT _JSON_BUILD_OBJECT_BEGIN, _JSON_BUILD_OBJECT_END
#define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, ({ const char *_x = n; _x; }), __VA_ARGS__
#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, ({ bool _x = c; _x; }), ({ const char *_x = n; _x; }), __VA_ARGS__
#define JSON_BUILD_NULL _JSON_BUILD_NULL
#define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, ({ JsonVariant *_x = v; _x; })
#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, ({ JsonVariant **_x = v; _x; }), ({ size_t _y = n; _y; })
#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, ({ const char *_x = l; _x; })
#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, ({ char **_x = l; _x; })
#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, ({ const void *_x = p; _x; }), ({ size_t _y = n; _y; })
int json_build(JsonVariant **ret, ...);
int json_buildv(JsonVariant **ret, va_list ap);
@ -254,11 +213,10 @@ typedef enum JsonDispatchFlags {
JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this property? */
JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */
JSON_LOG = 1 << 2, /* Should the parser log about errors? */
JSON_SAFE = 1 << 3, /* Don't accept "unsafe" strings in json_dispatch_string() + json_dispatch_string() */
/* The following two may be passed into log_json() in addition to the three above */
JSON_DEBUG = 1 << 4, /* Indicates that this log message is a debug message */
JSON_WARNING = 1 << 5, /* Indicates that this log message is a warning message */
JSON_DEBUG = 1 << 3, /* Indicates that this log message is a debug message */
JSON_WARNING = 1 << 4, /* Indicates that this log message is a warning message */
} JsonDispatchFlags;
typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
@ -274,7 +232,6 @@ typedef struct JsonDispatch {
int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata);
int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
@ -283,10 +240,6 @@ int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFl
int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
assert_cc(sizeof(uintmax_t) == sizeof(uint64_t));
#define json_dispatch_uint64 json_dispatch_unsigned
@ -322,9 +275,6 @@ int json_log_internal(JsonVariant *variant, int level, int error, const char *fi
: -ERRNO_VALUE(_e); \
})
#define json_log_oom(variant, flags) \
json_log(variant, flags, SYNTHETIC_ERRNO(ENOMEM), "Out of memory.")
#define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x))
#define _JSON_VARIANT_STRING_CONST(xq, x) \
@ -334,7 +284,5 @@ int json_log_internal(JsonVariant *variant, int level, int error, const char *fi
(JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \
})
int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size);
const char *json_variant_type_to_string(JsonVariantType t);
JsonVariantType json_variant_type_from_string(const char *s);

View File

@ -132,7 +132,6 @@ shared_sources = files('''
nscd-flush.h
nsflags.c
nsflags.h
openssl-util.h
os-util.c
os-util.h
output-mode.c
@ -142,8 +141,6 @@ shared_sources = files('''
path-lookup.c
path-lookup.h
pe-header.h
pkcs11-util.c
pkcs11-util.h
pretty-print.c
pretty-print.h
ptyfwd.c
@ -280,8 +277,6 @@ libshared_deps = [threads,
libkmod,
liblz4,
libmount,
libopenssl,
libp11kit,
librt,
libseccomp,
libselinux,

View File

@ -1,9 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <openssl/pem.h>
DEFINE_TRIVIAL_CLEANUP_FUNC(X509*, X509_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(X509_NAME*, X509_NAME_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY_CTX*, EVP_PKEY_CTX_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free);

View File

@ -1,912 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include "ask-password-api.h"
#include "escape.h"
#include "fd-util.h"
#include "io-util.h"
#include "memory-util.h"
#if HAVE_OPENSSL
#include "openssl-util.h"
#endif
#include "pkcs11-util.h"
#include "random-util.h"
#include "string-util.h"
#include "strv.h"
bool pkcs11_uri_valid(const char *uri) {
const char *p;
/* A very superficial checker for RFC7512 PKCS#11 URI syntax */
if (isempty(uri))
return false;
p = startswith(uri, "pkcs11:");
if (!p)
return false;
if (isempty(p))
return false;
if (!in_charset(p, ALPHANUMERICAL "-_?;&%="))
return false;
return true;
}
#if HAVE_P11KIT
int uri_from_string(const char *p, P11KitUri **ret) {
_cleanup_(p11_kit_uri_freep) P11KitUri *uri = NULL;
assert(p);
assert(ret);
uri = p11_kit_uri_new();
if (!uri)
return -ENOMEM;
if (p11_kit_uri_parse(p, P11_KIT_URI_FOR_ANY, uri) != P11_KIT_URI_OK)
return -EINVAL;
*ret = TAKE_PTR(uri);
return 0;
}
P11KitUri *uri_from_module_info(const CK_INFO *info) {
P11KitUri *uri;
assert(info);
uri = p11_kit_uri_new();
if (!uri)
return NULL;
*p11_kit_uri_get_module_info(uri) = *info;
return uri;
}
P11KitUri *uri_from_slot_info(const CK_SLOT_INFO *slot_info) {
P11KitUri *uri;
assert(slot_info);
uri = p11_kit_uri_new();
if (!uri)
return NULL;
*p11_kit_uri_get_slot_info(uri) = *slot_info;
return uri;
}
P11KitUri *uri_from_token_info(const CK_TOKEN_INFO *token_info) {
P11KitUri *uri;
assert(token_info);
uri = p11_kit_uri_new();
if (!uri)
return NULL;
*p11_kit_uri_get_token_info(uri) = *token_info;
return uri;
}
CK_RV pkcs11_get_slot_list_malloc(
CK_FUNCTION_LIST *m,
CK_SLOT_ID **ret_slotids,
CK_ULONG *ret_n_slotids) {
CK_RV rv;
assert(m);
assert(ret_slotids);
assert(ret_n_slotids);
for (unsigned tries = 0; tries < 16; tries++) {
_cleanup_free_ CK_SLOT_ID *slotids = NULL;
CK_ULONG n_slotids = 0;
rv = m->C_GetSlotList(0, NULL, &n_slotids);
if (rv != CKR_OK)
return rv;
if (n_slotids == 0) {
*ret_slotids = NULL;
*ret_n_slotids = 0;
return CKR_OK;
}
slotids = new(CK_SLOT_ID, n_slotids);
if (!slotids)
return CKR_HOST_MEMORY;
rv = m->C_GetSlotList(0, slotids, &n_slotids);
if (rv == CKR_OK) {
*ret_slotids = TAKE_PTR(slotids);
*ret_n_slotids = n_slotids;
return CKR_OK;
}
if (rv != CKR_BUFFER_TOO_SMALL)
return rv;
/* Hu? Maybe somebody plugged something in and things changed? Let's try again */
}
return CKR_BUFFER_TOO_SMALL;
}
char *pkcs11_token_label(const CK_TOKEN_INFO *token_info) {
char *t;
/* The label is not NUL terminated and likely padded with spaces, let's make a copy here, so that we
* can strip that. */
t = strndup((char*) token_info->label, sizeof(token_info->label));
if (!t)
return NULL;
strstrip(t);
return t;
}
int pkcs11_token_login(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,
CK_SLOT_ID slotid,
const CK_TOKEN_INFO *token_info,
const char *friendly_name,
const char *icon_name,
const char *keyname,
usec_t until,
char **ret_used_pin) {
_cleanup_free_ char *token_uri_string = NULL, *token_uri_escaped = NULL, *id = NULL, *token_label = NULL;
_cleanup_(p11_kit_uri_freep) P11KitUri *token_uri = NULL;
CK_TOKEN_INFO updated_token_info;
int uri_result;
CK_RV rv;
int r;
assert(m);
assert(token_info);
token_label = pkcs11_token_label(token_info);
if (!token_label)
return log_oom();
token_uri = uri_from_token_info(token_info);
if (!token_uri)
return log_oom();
uri_result = p11_kit_uri_format(token_uri, P11_KIT_URI_FOR_ANY, &token_uri_string);
if (uri_result != P11_KIT_URI_OK)
return log_warning_errno(SYNTHETIC_ERRNO(EAGAIN), "Failed to format slot URI: %s", p11_kit_uri_message(uri_result));
if (FLAGS_SET(token_info->flags, CKF_PROTECTED_AUTHENTICATION_PATH)) {
rv = m->C_Login(session, CKU_USER, NULL, 0);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
log_info("Successully logged into security token '%s' via protected authentication path.", token_label);
*ret_used_pin = NULL;
return 0;
}
if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
log_info("No login into security token '%s' required.", token_label);
*ret_used_pin = NULL;
return 0;
}
token_uri_escaped = cescape(token_uri_string);
if (!token_uri_escaped)
return log_oom();
id = strjoin("pkcs11:", token_uri_escaped);
if (!id)
return log_oom();
for (unsigned tries = 0; tries < 3; tries++) {
_cleanup_strv_free_erase_ char **passwords = NULL;
_cleanup_free_ char *text = NULL;
char **i, *e;
if (FLAGS_SET(token_info->flags, CKF_USER_PIN_FINAL_TRY))
r = asprintf(&text,
"Please enter correct PIN for security token '%s' in order to unlock %s (final try):",
token_label, friendly_name);
if (FLAGS_SET(token_info->flags, CKF_USER_PIN_COUNT_LOW))
r = asprintf(&text,
"PIN has been entered incorrectly previously, please enter correct PIN for security token '%s' in order to unlock %s:",
token_label, friendly_name);
else if (tries == 0)
r = asprintf(&text,
"Please enter PIN for security token '%s' in order to unlock %s:",
token_label, friendly_name);
else
r = asprintf(&text,
"Please enter PIN for security token '%s' in order to unlock %s (try #%u):",
token_label, friendly_name, tries+1);
if (r < 0)
return log_oom();
e = getenv("PIN");
if (e) {
passwords = strv_new(e);
if (!passwords)
return log_oom();
string_erase(e);
if (unsetenv("PIN") < 0)
return log_error_errno(errno, "Failed to unset $PIN: %m");
} else {
/* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
r = ask_password_auto(text, icon_name, id, keyname, until, 0, &passwords);
if (r < 0)
return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label);
}
STRV_FOREACH(i, passwords) {
rv = m->C_Login(session, CKU_USER, (CK_UTF8CHAR*) *i, strlen(*i));
if (rv == CKR_OK) {
if (ret_used_pin) {
char *c;
c = strdup(*i);
if (!c)
return log_oom();
*ret_used_pin = c;
}
log_info("Successfully logged into security token '%s'.", token_label);
return 0;
}
if (rv == CKR_PIN_LOCKED)
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
"PIN has been locked, please reset PIN of security token '%s'.", token_label);
if (!IN_SET(rv, CKR_PIN_INCORRECT, CKR_PIN_LEN_RANGE))
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
/* Referesh the token info, so that we can prompt knowing the new flags if they changed. */
rv = m->C_GetTokenInfo(slotid, &updated_token_info);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to acquire updated security token information for slot %lu: %s",
slotid, p11_kit_strerror(rv));
token_info = &updated_token_info;
log_notice("PIN for token '%s' is incorrect, please try again.", token_label);
}
}
return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Too many attempts to log into token '%s'.", token_label);
}
int pkcs11_token_find_x509_certificate(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,
P11KitUri *search_uri,
CK_OBJECT_HANDLE *ret_object) {
bool found_class = false, found_certificate_type = false;
_cleanup_free_ CK_ATTRIBUTE *attributes_buffer = NULL;
CK_ULONG n_attributes, a, n_objects;
CK_ATTRIBUTE *attributes = NULL;
CK_OBJECT_HANDLE objects[2];
CK_RV rv, rv2;
assert(m);
assert(search_uri);
assert(ret_object);
attributes = p11_kit_uri_get_attributes(search_uri, &n_attributes);
for (a = 0; a < n_attributes; a++) {
/* We use the URI's included match attributes, but make them more strict. This allows users
* to specify a token URL instead of an object URL and the right thing should happen if
* there's only one suitable key on the token. */
switch (attributes[a].type) {
case CKA_CLASS: {
CK_OBJECT_CLASS c;
if (attributes[a].ulValueLen != sizeof(c))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PKCS#11 CKA_CLASS attribute size.");
memcpy(&c, attributes[a].pValue, sizeof(c));
if (c != CKO_CERTIFICATE)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Selected PKCS#11 object is not an X.509 certificate, refusing.");
found_class = true;
break;
}
case CKA_CERTIFICATE_TYPE: {
CK_CERTIFICATE_TYPE t;
if (attributes[a].ulValueLen != sizeof(t))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PKCS#11 CKA_CERTIFICATE_TYPE attribute size.");
memcpy(&t, attributes[a].pValue, sizeof(t));
if (t != CKC_X_509)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Selected PKCS#11 object is not an X.509 certificate, refusing.");
found_certificate_type = true;
break;
}}
}
if (!found_class || !found_certificate_type) {
/* Hmm, let's slightly extend the attribute list we search for */
attributes_buffer = new(CK_ATTRIBUTE, n_attributes + !found_class + !found_certificate_type);
if (!attributes_buffer)
return log_oom();
memcpy(attributes_buffer, attributes, sizeof(CK_ATTRIBUTE) * n_attributes);
if (!found_class) {
static const CK_OBJECT_CLASS class = CKO_CERTIFICATE;
attributes_buffer[n_attributes++] = (CK_ATTRIBUTE) {
.type = CKA_CLASS,
.pValue = (CK_OBJECT_CLASS*) &class,
.ulValueLen = sizeof(class),
};
}
if (!found_certificate_type) {
static const CK_CERTIFICATE_TYPE type = CKC_X_509;
attributes_buffer[n_attributes++] = (CK_ATTRIBUTE) {
.type = CKA_CERTIFICATE_TYPE,
.pValue = (CK_CERTIFICATE_TYPE*) &type,
.ulValueLen = sizeof(type),
};
}
attributes = attributes_buffer;
}
rv = m->C_FindObjectsInit(session, attributes, n_attributes);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to initialize object find call: %s", p11_kit_strerror(rv));
rv = m->C_FindObjects(session, objects, ELEMENTSOF(objects), &n_objects);
rv2 = m->C_FindObjectsFinal(session);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to find objects: %s", p11_kit_strerror(rv));
if (rv2 != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to finalize object find call: %s", p11_kit_strerror(rv));
if (n_objects == 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
"Failed to find selected X509 certificate on token.");
if (n_objects > 1)
return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
"Configured URI matches multiple certificates, refusing.");
*ret_object = objects[0];
return 0;
}
#if HAVE_OPENSSL
int pkcs11_token_read_x509_certificate(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object,
X509 **ret_cert) {
_cleanup_free_ void *buffer = NULL;
_cleanup_free_ char *t = NULL;
CK_ATTRIBUTE attribute = {
.type = CKA_VALUE
};
CK_RV rv;
_cleanup_(X509_freep) X509 *x509 = NULL;
X509_NAME *name = NULL;
const unsigned char *p;
rv = m->C_GetAttributeValue(session, object, &attribute, 1);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to read X.509 certificate size off token: %s", p11_kit_strerror(rv));
buffer = malloc(attribute.ulValueLen);
if (!buffer)
return log_oom();
attribute.pValue = buffer;
rv = m->C_GetAttributeValue(session, object, &attribute, 1);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to read X.509 certificate data off token: %s", p11_kit_strerror(rv));
p = attribute.pValue;
x509 = d2i_X509(NULL, &p, attribute.ulValueLen);
if (!x509)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed parse X.509 certificate.");
name = X509_get_subject_name(x509);
if (!name)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to acquire X.509 subject name.");
t = X509_NAME_oneline(name, NULL, 0);
if (!t)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to format X.509 subject name as string.");
log_debug("Using X.509 certificate issued for '%s'.", t);
*ret_cert = TAKE_PTR(x509);
return 0;
}
#endif
int pkcs11_token_find_private_key(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,
P11KitUri *search_uri,
CK_OBJECT_HANDLE *ret_object) {
bool found_decrypt = false, found_class = false, found_key_type = false;
_cleanup_free_ CK_ATTRIBUTE *attributes_buffer = NULL;
CK_ULONG n_attributes, a, n_objects;
CK_ATTRIBUTE *attributes = NULL;
CK_OBJECT_HANDLE objects[2];
CK_RV rv, rv2;
assert(m);
assert(search_uri);
assert(ret_object);
attributes = p11_kit_uri_get_attributes(search_uri, &n_attributes);
for (a = 0; a < n_attributes; a++) {
/* We use the URI's included match attributes, but make them more strict. This allows users
* to specify a token URL instead of an object URL and the right thing should happen if
* there's only one suitable key on the token. */
switch (attributes[a].type) {
case CKA_CLASS: {
CK_OBJECT_CLASS c;
if (attributes[a].ulValueLen != sizeof(c))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PKCS#11 CKA_CLASS attribute size.");
memcpy(&c, attributes[a].pValue, sizeof(c));
if (c != CKO_PRIVATE_KEY)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Selected PKCS#11 object is not a private key, refusing.");
found_class = true;
break;
}
case CKA_DECRYPT: {
CK_BBOOL b;
if (attributes[a].ulValueLen != sizeof(b))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PKCS#11 CKA_DECRYPT attribute size.");
memcpy(&b, attributes[a].pValue, sizeof(b));
if (!b)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Selected PKCS#11 object is not suitable for decryption, refusing.");
found_decrypt = true;
break;
}
case CKA_KEY_TYPE: {
CK_KEY_TYPE t;
if (attributes[a].ulValueLen != sizeof(t))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PKCS#11 CKA_KEY_TYPE attribute size.");
memcpy(&t, attributes[a].pValue, sizeof(t));
if (t != CKK_RSA)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Selected PKCS#11 object is not an RSA key, refusing.");
found_key_type = true;
break;
}}
}
if (!found_decrypt || !found_class || !found_key_type) {
/* Hmm, let's slightly extend the attribute list we search for */
attributes_buffer = new(CK_ATTRIBUTE, n_attributes + !found_decrypt + !found_class + !found_key_type);
if (!attributes_buffer)
return log_oom();
memcpy(attributes_buffer, attributes, sizeof(CK_ATTRIBUTE) * n_attributes);
if (!found_decrypt) {
static const CK_BBOOL yes = true;
attributes_buffer[n_attributes++] = (CK_ATTRIBUTE) {
.type = CKA_DECRYPT,
.pValue = (CK_BBOOL*) &yes,
.ulValueLen = sizeof(yes),
};
}
if (!found_class) {
static const CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
attributes_buffer[n_attributes++] = (CK_ATTRIBUTE) {
.type = CKA_CLASS,
.pValue = (CK_OBJECT_CLASS*) &class,
.ulValueLen = sizeof(class),
};
}
if (!found_key_type) {
static const CK_KEY_TYPE type = CKK_RSA;
attributes_buffer[n_attributes++] = (CK_ATTRIBUTE) {
.type = CKA_KEY_TYPE,
.pValue = (CK_KEY_TYPE*) &type,
.ulValueLen = sizeof(type),
};
}
attributes = attributes_buffer;
}
rv = m->C_FindObjectsInit(session, attributes, n_attributes);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to initialize object find call: %s", p11_kit_strerror(rv));
rv = m->C_FindObjects(session, objects, ELEMENTSOF(objects), &n_objects);
rv2 = m->C_FindObjectsFinal(session);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to find objects: %s", p11_kit_strerror(rv));
if (rv2 != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to finalize object find call: %s", p11_kit_strerror(rv));
if (n_objects == 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
"Failed to find selected private key suitable for decryption on token.");
if (n_objects > 1)
return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
"Configured private key URI matches multiple keys, refusing.");
*ret_object = objects[0];
return 0;
}
int pkcs11_token_decrypt_data(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object,
const void *encrypted_data,
size_t encrypted_data_size,
void **ret_decrypted_data,
size_t *ret_decrypted_data_size) {
static const CK_MECHANISM mechanism = {
.mechanism = CKM_RSA_PKCS
};
_cleanup_(erase_and_freep) CK_BYTE *dbuffer = NULL;
CK_ULONG dbuffer_size = 0;
CK_RV rv;
assert(m);
assert(encrypted_data);
assert(encrypted_data_size > 0);
assert(ret_decrypted_data);
assert(ret_decrypted_data_size);
rv = m->C_DecryptInit(session, (CK_MECHANISM*) &mechanism, object);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to initialize decryption on security token: %s", p11_kit_strerror(rv));
dbuffer_size = encrypted_data_size; /* Start with something reasonable */
dbuffer = malloc(dbuffer_size);
if (!dbuffer)
return log_oom();
rv = m->C_Decrypt(session, (CK_BYTE*) encrypted_data, encrypted_data_size, dbuffer, &dbuffer_size);
if (rv == CKR_BUFFER_TOO_SMALL) {
erase_and_free(dbuffer);
dbuffer = malloc(dbuffer_size);
if (!dbuffer)
return log_oom();
rv = m->C_Decrypt(session, (CK_BYTE*) encrypted_data, encrypted_data_size, dbuffer, &dbuffer_size);
}
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to decrypt key on security token: %s", p11_kit_strerror(rv));
log_info("Successfully decrypted key with security token.");
*ret_decrypted_data = TAKE_PTR(dbuffer);
*ret_decrypted_data_size = dbuffer_size;
return 0;
}
int pkcs11_token_acquire_rng(
CK_FUNCTION_LIST *m,
CK_SESSION_HANDLE session) {
_cleanup_free_ void *buffer = NULL;
_cleanup_close_ int fd = -1;
size_t rps;
CK_RV rv;
int r;
assert(m);
/* While we are at it, let's read some RNG data from the PKCS#11 token and pass it to the kernel
* random pool. This should be cheap if we are talking to the device already. Note that we don't
* credit any entropy, since we don't know about the quality of the pkcs#11 token's RNG. Why bother
* at all? There are two sides to the argument whether to generate private keys on tokens or on the
* host. By crediting some data from the token RNG to the host's pool we at least can say that any
* key generated from it is at least as good as both sources individually. */
rps = random_pool_size();
buffer = malloc(rps);
if (!buffer)
return log_oom();
rv = m->C_GenerateRandom(session, buffer, rps);
if (rv != CKR_OK)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Failed to generate RNG data on security token: %s", p11_kit_strerror(rv));
fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return log_debug_errno(errno, "Failed to open /dev/urandom for writing: %m");
r = loop_write(fd, buffer, rps, false);
if (r < 0)
return log_debug_errno(r, "Failed to write PKCS#11 acquired random data to /dev/urandom: %m");
log_debug("Successfully written %zu bytes random data acquired via PKCS#11 to kernel random pool.", rps);
return 0;
}
static int token_process(
CK_FUNCTION_LIST *m,
CK_SLOT_ID slotid,
const CK_SLOT_INFO *slot_info,
const CK_TOKEN_INFO *token_info,
P11KitUri *search_uri,
pkcs11_find_token_callback_t callback,
void *userdata) {
_cleanup_free_ char *token_label = NULL;
CK_SESSION_HANDLE session;
CK_RV rv;
int r;
assert(m);
assert(slot_info);
assert(token_info);
assert(search_uri);
token_label = pkcs11_token_label(token_info);
if (!token_label)
return log_oom();
rv = m->C_OpenSession(slotid, CKF_SERIAL_SESSION, NULL, NULL, &session);
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to create session for security token '%s': %s", token_label, p11_kit_strerror(rv));
if (callback)
r = callback(m, session, slotid, slot_info, token_info, search_uri, userdata);
else
r = 1; /* if not callback was specified, just say we found what we were looking for */
rv = m->C_CloseSession(session);
if (rv != CKR_OK)
log_warning("Failed to close session on PKCS#11 token, ignoring: %s", p11_kit_strerror(rv));
return r;
}
static int slot_process(
CK_FUNCTION_LIST *m,
CK_SLOT_ID slotid,
P11KitUri *search_uri,
pkcs11_find_token_callback_t callback,
void *userdata) {
_cleanup_(p11_kit_uri_freep) P11KitUri* slot_uri = NULL, *token_uri = NULL;
_cleanup_free_ char *token_uri_string = NULL;
CK_TOKEN_INFO token_info;
CK_SLOT_INFO slot_info;
int uri_result;
CK_RV rv;
assert(m);
assert(search_uri);
/* We return -EAGAIN for all failures we can attribute to a specific slot in some way, so that the
* caller might try other slots before giving up. */
rv = m->C_GetSlotInfo(slotid, &slot_info);
if (rv != CKR_OK) {
log_warning("Failed to acquire slot info for slot %lu, ignoring slot: %s", slotid, p11_kit_strerror(rv));
return -EAGAIN;
}
slot_uri = uri_from_slot_info(&slot_info);
if (!slot_uri)
return log_oom();
if (DEBUG_LOGGING) {
_cleanup_free_ char *slot_uri_string = NULL;
uri_result = p11_kit_uri_format(slot_uri, P11_KIT_URI_FOR_ANY, &slot_uri_string);
if (uri_result != P11_KIT_URI_OK) {
log_warning("Failed to format slot URI, ignoring slot: %s", p11_kit_uri_message(uri_result));
return -EAGAIN;
}
log_debug("Found slot with URI %s", slot_uri_string);
}
rv = m->C_GetTokenInfo(slotid, &token_info);
if (rv == CKR_TOKEN_NOT_PRESENT) {
log_debug("Token not present in slot, ignoring.");
return -EAGAIN;
} else if (rv != CKR_OK) {
log_warning("Failed to acquire token info for slot %lu, ignoring slot: %s", slotid, p11_kit_strerror(rv));
return -EAGAIN;
}
token_uri = uri_from_token_info(&token_info);
if (!token_uri)
return log_oom();
uri_result = p11_kit_uri_format(token_uri, P11_KIT_URI_FOR_ANY, &token_uri_string);
if (uri_result != P11_KIT_URI_OK) {
log_warning("Failed to format slot URI: %s", p11_kit_uri_message(uri_result));
return -EAGAIN;
}
if (!p11_kit_uri_match_token_info(search_uri, &token_info)) {
log_debug("Found non-matching token with URI %s.", token_uri_string);
return -EAGAIN;
}
log_debug("Found matching token with URI %s.", token_uri_string);
return token_process(
m,
slotid,
&slot_info,
&token_info,
search_uri,
callback,
userdata);
}
static int module_process(
CK_FUNCTION_LIST *m,
P11KitUri *search_uri,
pkcs11_find_token_callback_t callback,
void *userdata) {
_cleanup_free_ char *name = NULL, *module_uri_string = NULL;
_cleanup_(p11_kit_uri_freep) P11KitUri* module_uri = NULL;
_cleanup_free_ CK_SLOT_ID *slotids = NULL;
CK_ULONG n_slotids = 0;
int uri_result;
CK_INFO info;
size_t k;
CK_RV rv;
int r;
assert(m);
assert(search_uri);
/* We ignore most errors from modules here, in order to skip over faulty modules: one faulty module
* should not have the effect that we don't try the others anymore. We indicate such per-module
* failures with -EAGAIN, which let's the caller try the next module. */
name = p11_kit_module_get_name(m);
if (!name)
return log_oom();
log_debug("Trying PKCS#11 module %s.", name);
rv = m->C_GetInfo(&info);
if (rv != CKR_OK) {
log_warning("Failed to get info on PKCS#11 module, ignoring module: %s", p11_kit_strerror(rv));
return -EAGAIN;
}
module_uri = uri_from_module_info(&info);
if (!module_uri)
return log_oom();
uri_result = p11_kit_uri_format(module_uri, P11_KIT_URI_FOR_ANY, &module_uri_string);
if (uri_result != P11_KIT_URI_OK) {
log_warning("Failed to format module URI, ignoring module: %s", p11_kit_uri_message(uri_result));
return -EAGAIN;
}
log_debug("Found module with URI %s", module_uri_string);
rv = pkcs11_get_slot_list_malloc(m, &slotids, &n_slotids);
if (rv != CKR_OK) {
log_warning("Failed to get slot list, ignoring module: %s", p11_kit_strerror(rv));
return -EAGAIN;
}
if (n_slotids == 0) {
log_debug("This module has no slots? Ignoring module.");
return -EAGAIN;
}
for (k = 0; k < n_slotids; k++) {
r = slot_process(
m,
slotids[k],
search_uri,
callback,
userdata);
if (r != -EAGAIN)
return r;
}
return -EAGAIN;
}
int pkcs11_find_token(
const char *pkcs11_uri,
pkcs11_find_token_callback_t callback,
void *userdata) {
_cleanup_(p11_kit_modules_finalize_and_releasep) CK_FUNCTION_LIST **modules = NULL;
_cleanup_(p11_kit_uri_freep) P11KitUri *search_uri = NULL;
int r;
assert(pkcs11_uri);
/* Execute the specified callback for each matching token found. If nothing is found returns
* -EAGAIN. Logs about all errors, except for EAGAIN, which the caller has to log about. */
r = uri_from_string(pkcs11_uri, &search_uri);
if (r < 0)
return log_error_errno(r, "Failed to parse PKCS#11 URI '%s': %m", pkcs11_uri);
modules = p11_kit_modules_load_and_initialize(0);
if (!modules)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize pkcs11 modules");
for (CK_FUNCTION_LIST **i = modules; *i; i++) {
r = module_process(
*i,
search_uri,
callback,
userdata);
if (r != -EAGAIN)
return r;
}
return -EAGAIN;
}
#endif

View File

@ -1,48 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#if HAVE_P11KIT
#include <p11-kit/p11-kit.h>
#include <p11-kit/uri.h>
#if HAVE_OPENSSL
#include <openssl/pem.h>
#endif
#endif
#include "macro.h"
#include "time-util.h"
bool pkcs11_uri_valid(const char *uri);
#if HAVE_P11KIT
int uri_from_string(const char *p, P11KitUri **ret);
P11KitUri *uri_from_module_info(const CK_INFO *info);
P11KitUri *uri_from_slot_info(const CK_SLOT_INFO *slot_info);
P11KitUri *uri_from_token_info(const CK_TOKEN_INFO *token_info);
DEFINE_TRIVIAL_CLEANUP_FUNC(P11KitUri*, p11_kit_uri_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(CK_FUNCTION_LIST**, p11_kit_modules_finalize_and_release);
CK_RV pkcs11_get_slot_list_malloc(CK_FUNCTION_LIST *m, CK_SLOT_ID **ret_slotids, CK_ULONG *ret_n_slotids);
char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *keyname, usec_t until, char **ret_used_pin);
int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
#if HAVE_OPENSSL
int pkcs11_token_read_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, X509 **ret_cert);
#endif
int pkcs11_token_find_private_key(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
int pkcs11_token_decrypt_data(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, const void *encrypted_data, size_t encrypted_data_size, void **ret_decrypted_data, size_t *ret_decrypted_data_size);
int pkcs11_token_acquire_rng(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session);
typedef int (*pkcs11_find_token_callback_t)(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_SLOT_INFO *slot_info, const CK_TOKEN_INFO *token_info, P11KitUri *uri, void *userdata);
int pkcs11_find_token(const char *pkcs11_uri, pkcs11_find_token_callback_t callback, void *userdata);
#endif

View File

@ -577,7 +577,7 @@ static int varlink_parse_message(Varlink *v) {
varlink_log(v, "New incoming message: %s", begin);
r = json_parse(begin, 0, &v->current, NULL, NULL);
r = json_parse(begin, &v->current, NULL, NULL);
if (r < 0)
return r;

View File

@ -7956,9 +7956,6 @@ static int systemctl_help(void) {
" --what=RESOURCES Which types of resources to remove\n"
" --now Start or stop unit after enabling or disabling it\n"
" --dry-run Only print what would be done\n"
" Currently supported by verbs: halt, poweroff, reboot,\n"
" kexec, suspend, hibernate, suspend-then-hibernate,\n"
" hybrid-sleep, default, rescue, emergency, and exit.\n"
" -q --quiet Suppress output\n"
" --wait For (re)start, wait until service stopped again\n"
" For is-system-running, wait until startup is completed\n"

View File

@ -82,7 +82,7 @@ static void test_variant(const char *data, Test test) {
_cleanup_free_ char *s = NULL;
int r;
r = json_parse(data, 0, &v, NULL, NULL);
r = json_parse(data, &v, NULL, NULL);
assert_se(r == 0);
assert_se(v);
@ -93,7 +93,7 @@ static void test_variant(const char *data, Test test) {
log_info("formatted normally: %s\n", s);
r = json_parse(data, JSON_PARSE_SENSITIVE, &w, NULL, NULL);
r = json_parse(data, &w, NULL, NULL);
assert_se(r == 0);
assert_se(w);
assert_se(json_variant_has_type(v, json_variant_type(w)));
@ -110,7 +110,7 @@ static void test_variant(const char *data, Test test) {
log_info("formatted prettily:\n%s", s);
r = json_parse(data, 0, &w, NULL, NULL);
r = json_parse(data, &w, NULL, NULL);
assert_se(r == 0);
assert_se(w);
@ -302,7 +302,7 @@ static void test_build(void) {
assert_se(json_variant_format(a, 0, &s) >= 0);
log_info("GOT: %s\n", s);
assert_se(json_parse(s, 0, &b, NULL, NULL) >= 0);
assert_se(json_parse(s, &b, NULL, NULL) >= 0);
assert_se(json_variant_equal(a, b));
a = json_variant_unref(a);
@ -313,7 +313,7 @@ static void test_build(void) {
s = mfree(s);
assert_se(json_variant_format(a, 0, &s) >= 0);
log_info("GOT: %s\n", s);
assert_se(json_parse(s, 0, &b, NULL, NULL) >= 0);
assert_se(json_parse(s, &b, NULL, NULL) >= 0);
assert_se(json_variant_format(b, 0, &t) >= 0);
log_info("GOT: %s\n", t);
@ -365,7 +365,7 @@ static void test_source(void) {
assert_se(f = fmemopen_unlocked((void*) data, strlen(data), "r"));
assert_se(json_parse_file(f, "waldo", 0, &v, NULL, NULL) >= 0);
assert_se(json_parse_file(f, "waldo", &v, NULL, NULL) >= 0);
printf("--- non-pretty begin ---\n");
json_variant_dump(v, 0, stdout, NULL);
@ -415,93 +415,6 @@ static void test_depth(void) {
fputs("\n", stdout);
}
static void test_normalize(void) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
_cleanup_free_ char *t = NULL;
assert_se(json_build(&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("b", JSON_BUILD_STRING("x")),
JSON_BUILD_PAIR("c", JSON_BUILD_STRING("y")),
JSON_BUILD_PAIR("a", JSON_BUILD_STRING("z")))) >= 0);
assert_se(!json_variant_is_sorted(v));
assert_se(!json_variant_is_normalized(v));
assert_se(json_variant_format(v, 0, &t) >= 0);
assert_se(streq(t, "{\"b\":\"x\",\"c\":\"y\",\"a\":\"z\"}"));
t = mfree(t);
assert_se(json_build(&w, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("bar", JSON_BUILD_STRING("zzz")),
JSON_BUILD_PAIR("foo", JSON_BUILD_VARIANT(v)))) >= 0);
assert_se(json_variant_is_sorted(w));
assert_se(!json_variant_is_normalized(w));
assert_se(json_variant_format(w, 0, &t) >= 0);
assert_se(streq(t, "{\"bar\":\"zzz\",\"foo\":{\"b\":\"x\",\"c\":\"y\",\"a\":\"z\"}}"));
t = mfree(t);
assert_se(json_variant_sort(&v) >= 0);
assert_se(json_variant_is_sorted(v));
assert_se(json_variant_is_normalized(v));
assert_se(json_variant_format(v, 0, &t) >= 0);
assert_se(streq(t, "{\"a\":\"z\",\"b\":\"x\",\"c\":\"y\"}"));
t = mfree(t);
assert_se(json_variant_normalize(&w) >= 0);
assert_se(json_variant_is_sorted(w));
assert_se(json_variant_is_normalized(w));
assert_se(json_variant_format(w, 0, &t) >= 0);
assert_se(streq(t, "{\"bar\":\"zzz\",\"foo\":{\"a\":\"z\",\"b\":\"x\",\"c\":\"y\"}}"));
t = mfree(t);
}
static void test_bisect(void) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
char c;
/* Tests the bisection logic in json_variant_by_key() */
for (c = 'z'; c >= 'a'; c--) {
if ((c % 3) == 0)
continue;
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
assert_se(json_variant_new_stringn(&w, (char[4]) { '<', c, c, '>' }, 4) >= 0);
assert_se(json_variant_set_field(&v, (char[2]) { c, 0 }, w) >= 0);
}
json_variant_dump(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, NULL, NULL);
assert_se(!json_variant_is_sorted(v));
assert_se(!json_variant_is_normalized(v));
assert_se(json_variant_normalize(&v) >= 0);
assert_se(json_variant_is_sorted(v));
assert_se(json_variant_is_normalized(v));
json_variant_dump(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, NULL, NULL);
for (c = 'a'; c <= 'z'; c++) {
JsonVariant *k;
const char *z;
k = json_variant_by_key(v, (char[2]) { c, 0 });
assert_se(!k == ((c % 3) == 0));
if (!k)
continue;
assert_se(json_variant_is_string(k));
z = (char[5]){ '<', c, c, '>', 0};
assert_se(streq(json_variant_string(k), z));
}
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
@ -549,11 +462,10 @@ int main(int argc, char *argv[]) {
test_variant("[ 0, -0, 0.0, -0.0, 0.000, -0.000, 0e0, -0e0, 0e+0, -0e-0, 0e-0, -0e000, 0e+000 ]", test_zeroes);
test_build();
test_source();
test_depth();
test_normalize();
test_bisect();
test_source();
test_depth();
return 0;
}

View File

@ -19,41 +19,40 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
Match.OriginalName, config_parse_match_ifnames, 0, offsetof(link_config, match_name)
Match.Path, config_parse_match_strv, 0, offsetof(link_config, match_path)
Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match_driver)
Match.Type, config_parse_match_strv, 0, offsetof(link_config, match_type)
Match.Property, config_parse_match_property, 0, offsetof(link_config, match_property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, conditions)
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, conditions)
Link.Description, config_parse_string, 0, offsetof(link_config, description)
Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(link_config, mac_address_policy)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac)
Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
Link.AlternativeName, config_parse_ifnames, 1, offsetof(link_config, alternative_names)
Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy)
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol)
Link.Port, config_parse_port, 0, offsetof(link_config, port)
Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO])
Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO])
Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6])
Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO])
Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO])
Link.RxChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.TxChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.OtherChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.CombinedChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.Advertise, config_parse_advertise, 0, offsetof(link_config, advertise)
Link.RxBufferSize, config_parse_nic_buffer_size, 0, offsetof(link_config, ring)
Link.TxBufferSize, config_parse_nic_buffer_size, 0, offsetof(link_config, ring)
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
Match.OriginalName, config_parse_match_ifnames, 0, offsetof(link_config, match_name)
Match.Path, config_parse_match_strv, 0, offsetof(link_config, match_path)
Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match_driver)
Match.Type, config_parse_match_strv, 0, offsetof(link_config, match_type)
Match.Property, config_parse_match_property, 0, offsetof(link_config, match_property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, conditions)
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, conditions)
Link.Description, config_parse_string, 0, offsetof(link_config, description)
Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(link_config, mac_address_policy)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac)
Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
Link.AlternativeName, config_parse_ifnames, 1, offsetof(link_config, alternative_names)
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol)
Link.Port, config_parse_port, 0, offsetof(link_config, port)
Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO])
Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO])
Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6])
Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO])
Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO])
Link.RxChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.TxChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.OtherChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.CombinedChannels, config_parse_channel, 0, offsetof(link_config, channels)
Link.Advertise, config_parse_advertise, 0, offsetof(link_config, advertise)
Link.RxBufferSize, config_parse_nic_buffer_size, 0, offsetof(link_config, ring)
Link.TxBufferSize, config_parse_nic_buffer_size, 0, offsetof(link_config, ring)

View File

@ -59,7 +59,6 @@ static void link_config_free(link_config *link) {
free(link->name_policy);
free(link->name);
strv_free(link->alternative_names);
free(link->alternative_names_policy);
free(link->alias);
free(link);
@ -327,7 +326,6 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
int link_config_apply(link_config_ctx *ctx, link_config *config,
sd_device *device, const char **name) {
_cleanup_strv_free_ char **altnames = NULL;
struct ether_addr generated_mac;
struct ether_addr *mac = NULL;
const char *new_name = NULL;
@ -403,7 +401,7 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
}
if (ctx->enable_name_policy && config->name_policy)
for (NamePolicy *p = config->name_policy; *p != _NAMEPOLICY_INVALID; p++) {
for (NamePolicy *p = config->name_policy; !new_name && *p != _NAMEPOLICY_INVALID; p++) {
policy = *p;
switch (policy) {
@ -440,8 +438,6 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
default:
assert_not_reached("invalid policy");
}
if (ifname_valid(new_name))
break;
}
if (new_name)
@ -463,52 +459,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
if (r < 0)
return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
if (config->alternative_names) {
altnames = strv_copy(config->alternative_names);
if (!altnames)
return log_oom();
}
if (config->alternative_names_policy)
for (NamePolicy *p = config->alternative_names_policy; *p != _NAMEPOLICY_INVALID; p++) {
const char *n;
switch (*p) {
case NAMEPOLICY_DATABASE:
(void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &n);
break;
case NAMEPOLICY_ONBOARD:
(void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &n);
break;
case NAMEPOLICY_SLOT:
(void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &n);
break;
case NAMEPOLICY_PATH:
(void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &n);
break;
case NAMEPOLICY_MAC:
(void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &n);
break;
default:
assert_not_reached("invalid policy");
}
if (!isempty(n)) {
r = strv_extend(&altnames, n);
if (r < 0)
return log_oom();
}
}
if (new_name)
strv_remove(altnames, new_name);
strv_remove(altnames, old_name);
strv_uniq(altnames);
r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, altnames);
if (r == -EOPNOTSUPP)
log_debug_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s, ignoring: %m", old_name);
else if (r < 0)
return log_warning_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s: %m", old_name);
r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, config->alternative_names);
if (r < 0)
return log_warning_errno(r, "Could not set AlternativeName= on %s: %m", old_name);
*name = new_name;
@ -556,16 +509,3 @@ DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy,
_NAMEPOLICY_INVALID,
"Failed to parse interface name policy");
static const char* const alternative_names_policy_table[_NAMEPOLICY_MAX] = {
[NAMEPOLICY_DATABASE] = "database",
[NAMEPOLICY_ONBOARD] = "onboard",
[NAMEPOLICY_SLOT] = "slot",
[NAMEPOLICY_PATH] = "path",
[NAMEPOLICY_MAC] = "mac",
};
DEFINE_STRING_TABLE_LOOKUP(alternative_names_policy, NamePolicy);
DEFINE_CONFIG_PARSE_ENUMV(config_parse_alternative_names_policy, alternative_names_policy, NamePolicy,
_NAMEPOLICY_INVALID,
"Failed to parse alternative names policy");

View File

@ -47,7 +47,6 @@ struct link_config {
struct ether_addr *mac;
MACAddressPolicy mac_address_policy;
NamePolicy *name_policy;
NamePolicy *alternative_names_policy;
char *name;
char **alternative_names;
char *alias;
@ -80,9 +79,6 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret);
const char *name_policy_to_string(NamePolicy p) _const_;
NamePolicy name_policy_from_string(const char *p) _pure_;
const char *alternative_names_policy_to_string(NamePolicy p) _const_;
NamePolicy alternative_names_policy_from_string(const char *p) _pure_;
const char *mac_address_policy_to_string(MACAddressPolicy p) _const_;
MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
@ -91,4 +87,3 @@ const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_alternative_names_policy);

View File

@ -19,7 +19,6 @@
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/pci_regs.h>
#include "alloc-util.h"
@ -57,22 +56,22 @@ struct netnames {
bool mac_valid;
sd_device *pcidev;
char pci_slot[ALTIFNAMSIZ];
char pci_path[ALTIFNAMSIZ];
char pci_onboard[ALTIFNAMSIZ];
char pci_slot[IFNAMSIZ];
char pci_path[IFNAMSIZ];
char pci_onboard[IFNAMSIZ];
const char *pci_onboard_label;
char usb_ports[ALTIFNAMSIZ];
char bcma_core[ALTIFNAMSIZ];
char ccw_busid[ALTIFNAMSIZ];
char vio_slot[ALTIFNAMSIZ];
char platform_path[ALTIFNAMSIZ];
char netdevsim_path[ALTIFNAMSIZ];
char usb_ports[IFNAMSIZ];
char bcma_core[IFNAMSIZ];
char ccw_busid[IFNAMSIZ];
char vio_slot[IFNAMSIZ];
char platform_path[IFNAMSIZ];
char netdevsim_path[IFNAMSIZ];
};
struct virtfn_info {
sd_device *physfn_pcidev;
char suffix[ALTIFNAMSIZ];
char suffix[IFNAMSIZ];
};
/* skip intermediate virtio devices */
@ -105,7 +104,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
_cleanup_free_ char *virtfn_pci_syspath = NULL;
struct dirent *dent;
_cleanup_closedir_ DIR *dir = NULL;
char suffix[ALTIFNAMSIZ];
char suffix[IFNAMSIZ];
int r;
assert(dev);
@ -820,7 +819,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
r = names_mac(dev, &names);
if (r >= 0 && names.mac_valid) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
xsprintf(str, "%sx%02x%02x%02x%02x%02x%02x", prefix,
names.mac[0], names.mac[1], names.mac[2],
@ -832,7 +831,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* get path names for Linux on System z network devices */
if (names_ccw(dev, &names) >= 0 && names.type == NET_CCW) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.ccw_busid))
udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
@ -841,7 +840,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* get ibmveth/ibmvnic slot-based names. */
if (names_vio(dev, &names) >= 0 && names.type == NET_VIO) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.vio_slot))
udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
@ -850,7 +849,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* get ACPI path names for ARM64 platform devices */
if (names_platform(dev, &names, test) >= 0 && names.type == NET_PLATFORM) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.platform_path))
udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
@ -859,7 +858,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* get netdevsim path names */
if (names_netdevsim(dev, &names) >= 0 && names.type == NET_NETDEVSIM) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.netdevsim_path))
udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
@ -873,7 +872,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* plain PCI device */
if (names.type == NET_PCI) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (names.pci_onboard[0] &&
snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_onboard))
@ -897,7 +896,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* USB device */
if (names_usb(dev, &names) >= 0 && names.type == NET_USB) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (names.pci_path[0] &&
snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.usb_ports))
@ -911,7 +910,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
/* Broadcom bus */
if (names_bcma(dev, &names) >= 0 && names.type == NET_BCMA) {
char str[ALTIFNAMSIZ];
char str[IFNAMSIZ];
if (names.pci_path[0] &&
snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.bcma_core))

View File

@ -119,18 +119,6 @@ machinectl remove scratch4
! test -f /var/lib/machines/scratch4
! machinectl image-status scratch4
# Test import-tar hypen/stdin pipe behavior
cat /var/tmp/scratch.tar.gz | machinectl import-tar - scratch5
test -d /var/lib/machines/scratch5
machinectl image-status scratch5
diff -r /var/tmp/scratch/ /var/lib/machines/scratch5
# Test export-tar hypen/stdout pipe behavior
mkdir -p /var/tmp/extract
machinectl export-tar scratch5 - | tar xvf - -C /var/tmp/extract/
diff -r /var/tmp/scratch/ /var/tmp/extract/
rm -rf /var/tmp/extract
rm -rf /var/tmp/scratch
echo OK > /testok

View File

@ -16,7 +16,6 @@ MACAddressPolicy=
MACAddress=
NamePolicy=
Name=
AlternativeNamesPolicy=
AlternativeName=
Alias=
MTUBytes=

View File

@ -287,11 +287,3 @@ FairQueuingControlledDelayIntervalSec=
FairQueuingControlledDelayCEThresholdSec=
FairQueuingControlledDelayECN=
FairQueueTrafficPolicingPacketLimit=
FairQueueTrafficPolicingFlowLimit=
FairQueueTrafficPolicingQuantum=
FairQueueTrafficPolicingInitialQuantum=
FairQueueTrafficPolicingMaximumRate=
FairQueueTrafficPolicingBuckets=
FairQueueTrafficPolicingOrphanMask=
FairQueueTrafficPolicingPacing=
FairQueueTrafficPolicingCEThresholdSec=

View File

@ -8,11 +8,3 @@ Address=10.1.2.3/16
[TrafficControlQueueingDiscipline]
Parent=root
FairQueueTrafficPolicingPacketLimit=1000
FairQueueTrafficPolicingFlowLimit=200
FairQueueTrafficPolicingQuantum=1500
FairQueueTrafficPolicingInitialQuantum=13000
FairQueueTrafficPolicingMaximumRate=1M
FairQueueTrafficPolicingBuckets=512
FairQueueTrafficPolicingOrphanMask=511
FairQueueTrafficPolicingPacing=yes
FairQueueTrafficPolicingCEThresholdSec=100ms

View File

@ -2165,7 +2165,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('tc qdisc show dev dummy98')
print(output)
self.assertRegex(output, 'qdisc fq')
self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511 quantum 1500 initial_quantum 13000 maxrate 1Mbit')
self.assertRegex(output, 'limit 1000p')
class NetworkdStateFileTests(unittest.TestCase, Utilities):
links = [