mirror of
https://github.com/systemd/systemd
synced 2025-11-08 19:34:45 +01:00
Compare commits
No commits in common. "d08a6ec39c2cb786bbf8ba2a8d480ada2973ad59" and "44dcb318cc44c0830ec9ebfbf35eca2b3f67f9fd" have entirely different histories.
d08a6ec39c
...
44dcb318cc
3
NEWS
3
NEWS
@ -819,9 +819,6 @@ CHANGES WITH 243:
|
||||
* systemd-networkd's TUN support gained a new setting VnetHeader= for
|
||||
tweaking Generic Segment Offload support.
|
||||
|
||||
* The address family for policy rules may be specified using the new
|
||||
Family= option in the [RoutingPolicyRule] section.
|
||||
|
||||
* networkctl gained a new "delete" command for removing virtual network
|
||||
devices, as well as a new "--stats" switch for showing device
|
||||
statistics.
|
||||
|
||||
21
TODO
21
TODO
@ -22,12 +22,6 @@ Janitorial Clean-ups:
|
||||
|
||||
Features:
|
||||
|
||||
* machined: add API to acquire UID range. add API to mount/dissect loopback
|
||||
file. Both protected by PK. Then make nspawn use these APIs to run
|
||||
unprivileged containers. i.e. push the truly privileged bits into machined,
|
||||
so that the client side can remain entirely unprivileged, with SUID or
|
||||
anything like that.
|
||||
|
||||
* add "throttling" to sd-event event sources: optionally, when we wake up too
|
||||
often for one, let's turn it off entirely for a while. Use that for the
|
||||
/proc/self/mountinfo logic.
|
||||
@ -1209,14 +1203,17 @@ Features:
|
||||
* networkd:
|
||||
- add more keys to [Route] and [Address] sections
|
||||
- add support for more DHCPv4 options (and, longer term, other kinds of dynamic config)
|
||||
- add proper initrd support (in particular generate .network/.link files based on /proc/cmdline)
|
||||
- add reduced [Link] support to .network files
|
||||
- add Scope= parsing option for [Network]
|
||||
- properly handle routerless dhcp leases
|
||||
- work with non-Ethernet devices
|
||||
- add support for more bond options
|
||||
- dhcp: do we allow configuring dhcp routes on interfaces that are not the one we got the dhcp info from?
|
||||
- the DHCP lease data (such as NTP/DNS) is still made available when
|
||||
a carrier is lost on a link. It should be removed instantly.
|
||||
- expose in the API the following bits:
|
||||
- option 15, domain name
|
||||
- option 15, domain name and/or option 119, search list
|
||||
- option 12, hostname and/or option 81, fqdn
|
||||
- option 123, 144, geolocation
|
||||
- option 252, configure http proxy (PAC/wpad)
|
||||
@ -1225,8 +1222,12 @@ Features:
|
||||
- allow Name= to be specified repeatedly in the [Match] section. Maybe also
|
||||
support Name=foo*|bar*|baz ?
|
||||
- duplicate address check for static IPs (like ARPCHECK in network-scripts)
|
||||
- allow DUID/IAID to be customized, see issue #394.
|
||||
- whenever uplink info changes, make DHCP server send out FORCERENEW
|
||||
|
||||
* networkd-wait-online:
|
||||
- make operstates to wait for configurable?
|
||||
|
||||
* dhcp:
|
||||
- figure out how much we can increase Maximum Message Size
|
||||
|
||||
@ -1250,14 +1251,20 @@ External:
|
||||
- natively watch for dbus-*.service symlinks (PENDING)
|
||||
- teach dbus to activate all services it finds in /etc/systemd/services/org-*.service
|
||||
|
||||
* fix alsa mixer restore to not print error when no config is stored
|
||||
|
||||
* make cryptsetup lower --iter-time
|
||||
|
||||
* patch kernel for xattr support in /dev, /proc/, /sys?
|
||||
|
||||
* kernel: add device_type = "fb", "fbcon" to class "graphics"
|
||||
|
||||
* /usr/bin/service should actually show the new command line
|
||||
|
||||
* fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus=
|
||||
|
||||
* fedora: F20: go timer units all the way, leave cron.daily for cron
|
||||
|
||||
* neither pkexec nor sudo initialize environ[] from the PAM environment?
|
||||
|
||||
* fedora: update policy to declare access mode and ownership of unit files to root:root 0644, and add an rpmlint check for it
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
character are ignored. Each of the remaining lines describes one
|
||||
encrypted block device. Fields are delimited by white space.</para>
|
||||
|
||||
<para>Each line is in the form<programlisting><replaceable>volume-name</replaceable> <replaceable>encrypted-device</replaceable> <replaceable>key-file</replaceable> <replaceable>options</replaceable></programlisting>
|
||||
<para>Each line is in the form<programlisting><replaceable>name</replaceable> <replaceable>encrypted-device</replaceable> <replaceable>password</replaceable> <replaceable>options</replaceable></programlisting>
|
||||
The first two fields are mandatory, the remaining two are
|
||||
optional.</para>
|
||||
|
||||
@ -53,20 +53,24 @@
|
||||
it is opened as a LUKS device; otherwise, it is assumed to be in
|
||||
raw dm-crypt (plain mode) format.</para>
|
||||
|
||||
<para>The first field contains the name of the resulting encrypted volume; its block device is set up
|
||||
below <filename>/dev/mapper/</filename>.</para>
|
||||
<para>The first field contains the name of the resulting encrypted
|
||||
block device; the device is set up within
|
||||
<filename>/dev/mapper/</filename>.</para>
|
||||
|
||||
<para>The second field contains a path to the underlying block
|
||||
device or file, or a specification of a block device via
|
||||
<literal>UUID=</literal> followed by the UUID.</para>
|
||||
|
||||
<para>The third field specifies an absolute path to a file to read the encryption key from. If the field
|
||||
is not present or set to <literal>none</literal> or <literal>-</literal>, a key file named after the
|
||||
volume to unlock (i.e. the first column of the line), suffixed with <filename>.key</filename> is
|
||||
automatically loaded from the <filename>/etc/cryptsetup-keys.d/</filename> and
|
||||
<filename>/run/cryptsetup-keys.d/</filename> directories, if present. Otherwise, the password has to be
|
||||
manually entered during system boot. For swap encryption, <filename>/dev/urandom</filename> may be used
|
||||
as key file.</para>
|
||||
<para>The third field specifies the encryption password. If the
|
||||
field is not present or the password is set to
|
||||
<literal>none</literal> or <literal>-</literal>, the password has
|
||||
to be manually entered during system boot. Otherwise, the field is
|
||||
interpreted as an absolute path to a file containing the encryption
|
||||
password. For swap encryption, <filename>/dev/urandom</filename>
|
||||
or the hardware device <filename>/dev/hw_random</filename> can be
|
||||
used as the password file; using <filename>/dev/random</filename>
|
||||
may prevent boot completion if the system does not have enough
|
||||
entropy to generate a truly random encryption key.</para>
|
||||
|
||||
<para>The fourth field, if present, is a comma-delimited list of
|
||||
options. The following options are recognized:</para>
|
||||
@ -134,15 +138,6 @@
|
||||
size is then given by the key size.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>keyfile-erase</option></term>
|
||||
|
||||
<listitem><para>If enabled, the specified key file is erased after the volume is activated or when
|
||||
activation fails. This is in particular useful when the key file is only acquired transiently before
|
||||
activation (e.g. via a file in <filename>/run/</filename>, generated by a service running before
|
||||
activation), and shall be removed after use. Defaults to off.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>key-slot=</option></term>
|
||||
|
||||
@ -436,15 +431,6 @@
|
||||
before it is used to unlock the LUKS volume.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>try-empty-password=</option></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If enabled, right before asking the user for a password it
|
||||
is first attempted to unlock the volume with an empty password. This is useful for systems that are
|
||||
initialized with an encrypted volume with only an empty password set, which shall be replaced with a
|
||||
suitable password during first boot, but after activation.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.device-timeout=</option></term>
|
||||
|
||||
|
||||
@ -159,7 +159,7 @@ net.bridge.bridge-nf-call-arptables = 0
|
||||
|
||||
<example>
|
||||
<title>Set network routing properties for all interfaces</title>
|
||||
<para><filename>/etc/sysctl.d/20-rp_filter.conf</filename>:</para>
|
||||
<para><filename>/etc/systemd/20-rp_filter.conf</filename>:</para>
|
||||
|
||||
<programlisting>net.ipv4.conf.default.rp_filter = 2
|
||||
net.ipv4.conf.*.rp_filter = 2
|
||||
|
||||
@ -44,32 +44,6 @@
|
||||
<para>At early boot and when the system manager configuration is reloaded, <filename>/etc/crypttab</filename> is
|
||||
translated into <filename>systemd-cryptsetup@.service</filename> units by
|
||||
<citerefentry><refentrytitle>systemd-cryptsetup-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>In order to unlock a volume a password or binary key is
|
||||
required. <filename>systemd-cryptsetup@.service</filename> tries to acquire a suitable password or binary
|
||||
key via the following mechanisms, tried in order:</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem><para>If a key file is explicitly configured (via the third column in
|
||||
<filename>/etc/crypttab</filename>), a key read from it is used. If a PKCS#11 token is configured
|
||||
(using the <varname>pkcs11-uri=</varname> option) the key is decrypted before use.</para></listitem>
|
||||
|
||||
<listitem><para>If no key file is configured explicitly this way, a key file is automatically loaded
|
||||
from <filename>/etc/cryptsetup-keys.d/<replaceable>volume</replaceable>.key</filename> and
|
||||
<filename>/run/cryptsetup-keys.d/<replaceable>volume</replaceable>.key</filename>, if present. Here
|
||||
too, if a PKCS#11 token is configured, any key found this way is decrypted before
|
||||
use.</para></listitem>
|
||||
|
||||
<listitem><para>If the <varname>try-empty-password</varname> option is specified it is then attempted
|
||||
to unlock the volume with an empty password.</para></listitem>
|
||||
|
||||
<listitem><para>The kernel keyring is then checked for a suitable cached password from previous
|
||||
attempts.</para></listitem>
|
||||
|
||||
<listitem><para>Finally, the user is queried for a password, possibly multiple times.</para></listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>If no suitable key may be acquired via any of the mechanisms describes above, volume activation fails.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@ -1774,20 +1774,6 @@
|
||||
option numbers, the option number is an integer in the range 1..65536.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>UserClass=</varname></term>
|
||||
<listitem>
|
||||
<para>A DHCPv6 client can use User Class option to identify the type or category of user or applications
|
||||
it represents. The information contained in this option is a string that represents the user class of which
|
||||
the client is a member. Each class sets an identifying string of information to be used by the DHCP
|
||||
service to classify clients. Special characters in the data string may be escaped using
|
||||
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
|
||||
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
|
||||
then all options specified earlier are cleared. Takes a whitespace-separated list of strings. Note that
|
||||
currently NUL bytes are not allowed.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -23,9 +23,8 @@ dd if=/dev/urandom of=plaintext.bin bs=128 count=1
|
||||
base64 < plaintext.bin | tr -d '\n\r\t ' > 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/cryptsetup-keys.d/mytest.key, where we'll look for it during boot.
|
||||
mkdir -p /etc/cryptsetup-keys.d
|
||||
sudo openssl rsautl -encrypt -pubin -inkey pubkey.pem -in plaintext.bin -out /etc/cryptsetup-keys.d/mytest.key
|
||||
# Yubikey, store the result in /etc/encrypted-luks-key.bin, where we'll look for it during boot.
|
||||
sudo 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
|
||||
@ -41,10 +40,8 @@ shred -u plaintext.bin plaintext.base64
|
||||
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 decipher the encrypted LUKS key. Note that
|
||||
# systemd-cryptsetup automatically searches for the encrypted key in /etc/cryptsetup-keys.d/, hence we do
|
||||
# not need to specify the key file path explicitly here.
|
||||
sudo systemd-cryptsetup attach mytest /dev/sdXn - 'pkcs11-uri=pkcs11:…'
|
||||
# PKCS#11 URI we have in the clipboard, it tells the tool how to decipher the encrypted LUKS key.
|
||||
sudo systemd-cryptsetup attach mytest /dev/sdXn /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.
|
||||
sudo bash -c 'echo "mytest /dev/sdXn - \'pkcs11-uri=pkcs11:…\'" >> /etc/crypttab'
|
||||
sudo bash -c 'echo "mytest /dev/sdXn /etc/encrypted-luks-key \'pkcs11-uri=pkcs11:…\'" >> /etc/crypttab'
|
||||
|
||||
@ -2227,10 +2227,8 @@ executable(
|
||||
|
||||
if conf.get('HAVE_LIBCRYPTSETUP') == 1
|
||||
systemd_cryptsetup_sources = files('''
|
||||
src/cryptsetup/cryptsetup-pkcs11.h
|
||||
src/cryptsetup/cryptsetup-util.c
|
||||
src/cryptsetup/cryptsetup-util.h
|
||||
src/cryptsetup/cryptsetup.c
|
||||
src/cryptsetup/cryptsetup-pkcs11.h
|
||||
'''.split())
|
||||
|
||||
if conf.get('HAVE_P11KIT') == 1
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
@ -30,8 +29,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
|
||||
*ret = d;
|
||||
return 0;
|
||||
}
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
|
||||
/* If it is a partition find the originating device */
|
||||
xsprintf_sys_block_path(p, "/partition", d);
|
||||
@ -188,29 +185,3 @@ int get_block_device_harder(const char *path, dev_t *ret) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lock_whole_block_device(dev_t devt, int operation) {
|
||||
_cleanup_free_ char *whole_node = NULL;
|
||||
_cleanup_close_ int lock_fd = -1;
|
||||
dev_t whole_devt;
|
||||
int r;
|
||||
|
||||
/* Let's get a BSD file lock on the whole block device, as per: https://systemd.io/BLOCK_DEVICE_LOCKING */
|
||||
|
||||
r = block_get_whole_disk(devt, &whole_devt);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = device_path_make_major_minor(S_IFBLK, whole_devt, &whole_node);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
lock_fd = open(whole_node, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (lock_fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (flock(lock_fd, operation) < 0)
|
||||
return -errno;
|
||||
|
||||
return TAKE_FD(lock_fd);
|
||||
}
|
||||
|
||||
@ -18,5 +18,3 @@ int block_get_originating(dev_t d, dev_t *ret);
|
||||
int get_block_device(const char *path, dev_t *dev);
|
||||
|
||||
int get_block_device_harder(const char *path, dev_t *dev);
|
||||
|
||||
int lock_whole_block_device(dev_t devt, int operation);
|
||||
|
||||
@ -319,7 +319,7 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
return -ENODEV;
|
||||
|
||||
if (major(st.st_rdev) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
@ -1304,13 +1303,11 @@ void unlink_tempfilep(char (*p)[]) {
|
||||
(void) unlink_noerrno(*p);
|
||||
}
|
||||
|
||||
int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
|
||||
int unlinkat_deallocate(int fd, const char *name, int flags) {
|
||||
_cleanup_close_ int truncate_fd = -1;
|
||||
struct stat st;
|
||||
off_t l, bs;
|
||||
|
||||
assert((flags & ~(UNLINK_REMOVEDIR|UNLINK_ERASE)) == 0);
|
||||
|
||||
/* Operates like unlinkat() but also deallocates the file contents if it is a regular file and there's no other
|
||||
* link to it. This is useful to ensure that other processes that might have the file open for reading won't be
|
||||
* able to keep the data pinned on disk forever. This call is particular useful whenever we execute clean-up
|
||||
@ -1327,7 +1324,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
|
||||
* Note that we attempt deallocation, but failure to succeed with that is not considered fatal, as long as the
|
||||
* primary job – to delete the file – is accomplished. */
|
||||
|
||||
if (!FLAGS_SET(flags, UNLINK_REMOVEDIR)) {
|
||||
if ((flags & AT_REMOVEDIR) == 0) {
|
||||
truncate_fd = openat(fd, name, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK);
|
||||
if (truncate_fd < 0) {
|
||||
|
||||
@ -1343,7 +1340,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
if (unlinkat(fd, name, FLAGS_SET(flags, UNLINK_REMOVEDIR) ? AT_REMOVEDIR : 0) < 0)
|
||||
if (unlinkat(fd, name, flags) < 0)
|
||||
return -errno;
|
||||
|
||||
if (truncate_fd < 0) /* Don't have a file handle, can't do more ☹️ */
|
||||
@ -1354,45 +1351,7 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return 0;
|
||||
|
||||
if (FLAGS_SET(flags, UNLINK_ERASE) && st.st_size > 0 && st.st_nlink == 0) {
|
||||
uint64_t left = st.st_size;
|
||||
char buffer[64 * 1024];
|
||||
|
||||
/* If erasing is requested, let's overwrite the file with random data once before deleting
|
||||
* it. This isn't going to give you shred(1) semantics, but hopefully should be good enough
|
||||
* for stuff backed by tmpfs at least.
|
||||
*
|
||||
* Note that we only erase like this if the link count of the file is zero. If it is higer it
|
||||
* is still linked by someone else and we'll leave it to them to remove it securely
|
||||
* eventually! */
|
||||
|
||||
random_bytes(buffer, sizeof(buffer));
|
||||
|
||||
while (left > 0) {
|
||||
ssize_t n;
|
||||
|
||||
n = write(truncate_fd, buffer, MIN(sizeof(buffer), left));
|
||||
if (n < 0) {
|
||||
log_debug_errno(errno, "Failed to erase data in file '%s', ignoring.", name);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(left >= (size_t) n);
|
||||
left -= n;
|
||||
}
|
||||
|
||||
/* Let's refresh metadata */
|
||||
if (fstat(truncate_fd, &st) < 0) {
|
||||
log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring: %m", name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't dallocate if there's nothing to deallocate or if the file is linked elsewhere */
|
||||
if (st.st_blocks == 0 || st.st_nlink > 0)
|
||||
if (!S_ISREG(st.st_mode) || st.st_blocks == 0 || st.st_nlink > 0)
|
||||
return 0;
|
||||
|
||||
/* If this is a regular file, it actually took up space on disk and there are no other links it's time to
|
||||
|
||||
@ -113,13 +113,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);
|
||||
int access_fd(int fd, int mode);
|
||||
|
||||
void unlink_tempfilep(char (*p)[]);
|
||||
|
||||
typedef enum UnlinkDeallocateFlags {
|
||||
UNLINK_REMOVEDIR = 1 << 0,
|
||||
UNLINK_ERASE = 1 << 1,
|
||||
} UnlinkDeallocateFlags;
|
||||
|
||||
int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags);
|
||||
int unlinkat_deallocate(int fd, const char *name, int flags);
|
||||
|
||||
int fsync_directory_of_file(int fd);
|
||||
int fsync_full(int fd);
|
||||
|
||||
@ -61,11 +61,11 @@ int glob_exists(const char *path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int glob_extend(char ***strv, const char *path, int flags) {
|
||||
int glob_extend(char ***strv, const char *path) {
|
||||
_cleanup_globfree_ glob_t g = {};
|
||||
int k;
|
||||
|
||||
k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE|flags, &g);
|
||||
k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
|
||||
if (k < 0)
|
||||
return k;
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
int safe_glob(const char *path, int flags, glob_t *pglob);
|
||||
|
||||
int glob_exists(const char *path);
|
||||
int glob_extend(char ***strv, const char *path, int flags);
|
||||
int glob_extend(char ***strv, const char *path);
|
||||
|
||||
#define _cleanup_globfree_ _cleanup_(globfree)
|
||||
|
||||
|
||||
@ -1051,7 +1051,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
r = glob_extend(&names, path, 0);
|
||||
r = glob_extend(&names, path);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
|
||||
@ -856,24 +856,20 @@ static int on_interface(const char *interface, uint64_t flags, void *userdata) {
|
||||
assert(interface);
|
||||
assert(members);
|
||||
|
||||
m = new(Member, 1);
|
||||
m = new0(Member, 1);
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
*m = (Member) {
|
||||
.type = "interface",
|
||||
.flags = flags,
|
||||
};
|
||||
m->type = "interface";
|
||||
m->flags = flags;
|
||||
|
||||
r = free_and_strdup(&m->interface, interface);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = set_put(members, m);
|
||||
if (r == -EEXIST)
|
||||
return log_error_errno(r, "Invalid introspection data: duplicate interface '%s'.", interface);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate interface");
|
||||
|
||||
m = NULL;
|
||||
return 0;
|
||||
@ -887,14 +883,12 @@ static int on_method(const char *interface, const char *name, const char *signat
|
||||
assert(interface);
|
||||
assert(name);
|
||||
|
||||
m = new(Member, 1);
|
||||
m = new0(Member, 1);
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
*m = (Member) {
|
||||
.type = "method",
|
||||
.flags = flags,
|
||||
};
|
||||
m->type = "method";
|
||||
m->flags = flags;
|
||||
|
||||
r = free_and_strdup(&m->interface, interface);
|
||||
if (r < 0)
|
||||
@ -913,10 +907,8 @@ static int on_method(const char *interface, const char *name, const char *signat
|
||||
return log_oom();
|
||||
|
||||
r = set_put(members, m);
|
||||
if (r == -EEXIST)
|
||||
return log_error_errno(r, "Invalid introspection data: duplicate method '%s' on interface '%s'.", name, interface);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate method");
|
||||
|
||||
m = NULL;
|
||||
return 0;
|
||||
@ -930,14 +922,12 @@ static int on_signal(const char *interface, const char *name, const char *signat
|
||||
assert(interface);
|
||||
assert(name);
|
||||
|
||||
m = new(Member, 1);
|
||||
m = new0(Member, 1);
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
*m = (Member) {
|
||||
.type = "signal",
|
||||
.flags = flags,
|
||||
};
|
||||
m->type = "signal";
|
||||
m->flags = flags;
|
||||
|
||||
r = free_and_strdup(&m->interface, interface);
|
||||
if (r < 0)
|
||||
@ -952,10 +942,8 @@ static int on_signal(const char *interface, const char *name, const char *signat
|
||||
return log_oom();
|
||||
|
||||
r = set_put(members, m);
|
||||
if (r == -EEXIST)
|
||||
return log_error_errno(r, "Invalid introspection data: duplicate signal '%s' on interface '%s'.", name, interface);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate signal");
|
||||
|
||||
m = NULL;
|
||||
return 0;
|
||||
@ -969,15 +957,13 @@ static int on_property(const char *interface, const char *name, const char *sign
|
||||
assert(interface);
|
||||
assert(name);
|
||||
|
||||
m = new(Member, 1);
|
||||
m = new0(Member, 1);
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
*m = (Member) {
|
||||
.type = "property",
|
||||
.flags = flags,
|
||||
.writable = writable,
|
||||
};
|
||||
m->type = "property";
|
||||
m->flags = flags;
|
||||
m->writable = writable;
|
||||
|
||||
r = free_and_strdup(&m->interface, interface);
|
||||
if (r < 0)
|
||||
@ -992,10 +978,8 @@ static int on_property(const char *interface, const char *name, const char *sign
|
||||
return log_oom();
|
||||
|
||||
r = set_put(members, m);
|
||||
if (r == -EEXIST)
|
||||
return log_error_errno(r, "Invalid introspection data: duplicate property '%s' on interface '%s'.", name, interface);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate property");
|
||||
|
||||
m = NULL;
|
||||
return 0;
|
||||
|
||||
@ -237,7 +237,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
break;
|
||||
|
||||
@ -188,11 +188,7 @@ static int print_dependencies(FILE *f, const char* device_path) {
|
||||
/* None, nothing to do */
|
||||
return 0;
|
||||
|
||||
if (PATH_IN_SET(device_path,
|
||||
"/dev/urandom",
|
||||
"/dev/random",
|
||||
"/dev/hw_random",
|
||||
"/dev/hwrng")) {
|
||||
if (PATH_IN_SET(device_path, "/dev/urandom", "/dev/random", "/dev/hw_random")) {
|
||||
/* RNG device, add random dep */
|
||||
fputs("After=systemd-random-seed.service\n", f);
|
||||
return 0;
|
||||
@ -213,9 +209,7 @@ static int print_dependencies(FILE *f, const char* device_path) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate unit name: %m");
|
||||
|
||||
fprintf(f,
|
||||
"After=%1$s\n"
|
||||
"Requires=%1$s\n", unit);
|
||||
fprintf(f, "After=%1$s\nRequires=%1$s\n", unit);
|
||||
} else {
|
||||
/* Regular file, add mount dependency */
|
||||
_cleanup_free_ char *escaped_path = specifier_escape(device_path);
|
||||
@ -373,12 +367,12 @@ static int create_disk(
|
||||
|
||||
if (tmp)
|
||||
fprintf(f,
|
||||
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs ext2 '/dev/mapper/%s'\n",
|
||||
"ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
|
||||
name_escaped);
|
||||
|
||||
if (swap)
|
||||
fprintf(f,
|
||||
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs swap '/dev/mapper/%s'\n",
|
||||
"ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
|
||||
name_escaped);
|
||||
|
||||
if (keydev)
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "ask-password-api.h"
|
||||
#include "cryptsetup-pkcs11.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
@ -20,6 +19,73 @@
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
|
||||
|
||||
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 > KEY_FILE_SIZE_MAX) {
|
||||
char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
|
||||
"Key file larger (%s) than allowed maximum size (%s), refusing.",
|
||||
format_bytes(buf1, sizeof(buf1), st.st_size),
|
||||
format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
|
||||
}
|
||||
|
||||
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;
|
||||
@ -27,14 +93,11 @@ struct pkcs11_callback_data {
|
||||
size_t encrypted_key_size;
|
||||
void *decrypted_key;
|
||||
size_t decrypted_key_size;
|
||||
bool free_encrypted_key;
|
||||
};
|
||||
|
||||
static void pkcs11_callback_data_release(struct pkcs11_callback_data *data) {
|
||||
free(data->decrypted_key);
|
||||
|
||||
if (data->free_encrypted_key)
|
||||
free(data->encrypted_key);
|
||||
free(data->encrypted_key);
|
||||
}
|
||||
|
||||
static int pkcs11_callback(
|
||||
@ -97,11 +160,9 @@ static int pkcs11_callback(
|
||||
int decrypt_pkcs11_key(
|
||||
const char *friendly_name,
|
||||
const char *pkcs11_uri,
|
||||
const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
const void *key_data, /* … or key_data and key_data_size (for literal keys) */
|
||||
size_t key_data_size,
|
||||
usec_t until,
|
||||
void **ret_decrypted_key,
|
||||
size_t *ret_decrypted_key_size) {
|
||||
@ -114,24 +175,15 @@ int decrypt_pkcs11_key(
|
||||
|
||||
assert(friendly_name);
|
||||
assert(pkcs11_uri);
|
||||
assert(key_file || key_data);
|
||||
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" */
|
||||
|
||||
if (key_data) {
|
||||
data.encrypted_key = (void*) key_data;
|
||||
data.encrypted_key_size = key_data_size;
|
||||
|
||||
data.free_encrypted_key = false;
|
||||
} else {
|
||||
r = load_key_file(key_file, NULL, key_file_size, key_file_offset, &data.encrypted_key, &data.encrypted_key_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
data.free_encrypted_key = true;
|
||||
}
|
||||
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)
|
||||
|
||||
@ -14,8 +14,6 @@ int decrypt_pkcs11_key(
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
const void *key_data,
|
||||
size_t key_data_size,
|
||||
usec_t until,
|
||||
void **ret_decrypted_key,
|
||||
size_t *ret_decrypted_key_size);
|
||||
@ -28,8 +26,6 @@ static inline int decrypt_pkcs11_key(
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
const void *key_data,
|
||||
size_t key_data_size,
|
||||
usec_t until,
|
||||
void **ret_decrypted_key,
|
||||
size_t *ret_decrypted_key_size) {
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cryptsetup-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
#define KEY_FILE_SIZE_MAX (16U*1024U*1024U) /* 16 MiB */
|
||||
|
||||
int load_key_file(
|
||||
const char *key_file,
|
||||
char **search_path,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
void **ret_key,
|
||||
size_t *ret_key_size) {
|
||||
|
||||
_cleanup_(erase_and_freep) char *buffer = NULL;
|
||||
_cleanup_free_ char *discovered_path = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
ssize_t n;
|
||||
int r;
|
||||
|
||||
assert(key_file);
|
||||
assert(ret_key);
|
||||
assert(ret_key_size);
|
||||
|
||||
if (strv_isempty(search_path) || path_is_absolute(key_file)) {
|
||||
fd = open(key_file, O_RDONLY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to load key file '%s': %m", key_file);
|
||||
} else {
|
||||
char **i;
|
||||
|
||||
STRV_FOREACH(i, search_path) {
|
||||
_cleanup_free_ char *joined;
|
||||
|
||||
joined = path_join(*i, key_file);
|
||||
if (!joined)
|
||||
return log_oom();
|
||||
|
||||
fd = open(joined, O_RDONLY|O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
discovered_path = TAKE_PTR(joined);
|
||||
break;
|
||||
}
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to load key file '%s': %m", joined);
|
||||
}
|
||||
|
||||
if (!discovered_path) {
|
||||
/* Search path supplied, but file not found, report by returning NULL, but not failing */
|
||||
*ret_key = NULL;
|
||||
*ret_key_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(fd >= 0);
|
||||
key_file = discovered_path;
|
||||
}
|
||||
|
||||
if (key_file_size == 0) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat key file '%s': %m", key_file);
|
||||
|
||||
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 > KEY_FILE_SIZE_MAX) {
|
||||
char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
|
||||
"Key file larger (%s) than allowed maximum size (%s), refusing.",
|
||||
format_bytes(buf1, sizeof(buf1), st.st_size),
|
||||
format_bytes(buf2, sizeof(buf2), KEY_FILE_SIZE_MAX));
|
||||
}
|
||||
|
||||
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 key file '%s': %m", key_file);
|
||||
if (n == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty encrypted key found, refusing.");
|
||||
|
||||
*ret_key = TAKE_PTR(buffer);
|
||||
*ret_key_size = (size_t) n;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int load_key_file(
|
||||
const char *key_file,
|
||||
char **search_path,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
void **ret_key,
|
||||
size_t *ret_key_size);
|
||||
@ -13,16 +13,13 @@
|
||||
#include "ask-password-api.h"
|
||||
#include "crypt-util.h"
|
||||
#include "cryptsetup-pkcs11.h"
|
||||
#include "cryptsetup-util.h"
|
||||
#include "device-util.h"
|
||||
#include "escape.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "fstab-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "mount-util.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "parse-util.h"
|
||||
@ -45,8 +42,6 @@ static unsigned arg_sector_size = CRYPT_SECTOR_SIZE;
|
||||
static int arg_key_slot = CRYPT_ANY_SLOT;
|
||||
static unsigned arg_keyfile_size = 0;
|
||||
static uint64_t arg_keyfile_offset = 0;
|
||||
static bool arg_keyfile_erase = false;
|
||||
static bool arg_try_empty_password = false;
|
||||
static char *arg_hash = NULL;
|
||||
static char *arg_header = NULL;
|
||||
static unsigned arg_tries = 3;
|
||||
@ -72,14 +67,12 @@ STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
|
||||
|
||||
/* Options Debian's crypttab knows we don't:
|
||||
|
||||
precheck=
|
||||
check=
|
||||
checkargs=
|
||||
noearly
|
||||
loud
|
||||
quiet
|
||||
noearly=
|
||||
loud=
|
||||
keyscript=
|
||||
tmp= (the version without argument is supported)
|
||||
initramfs
|
||||
*/
|
||||
|
||||
static int parse_one_option(const char *option) {
|
||||
@ -133,8 +126,7 @@ static int parse_one_option(const char *option) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if ((val = startswith(option, "key-slot=")) ||
|
||||
(val = startswith(option, "keyslot="))) {
|
||||
} else if ((val = startswith(option, "key-slot="))) {
|
||||
|
||||
arg_type = ANY_LUKS;
|
||||
r = safe_atoi(val, &arg_key_slot);
|
||||
@ -168,20 +160,7 @@ static int parse_one_option(const char *option) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if ((val = startswith(option, "keyfile-erase="))) {
|
||||
|
||||
r = parse_boolean(val);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_keyfile_erase = r;
|
||||
|
||||
} else if (streq(option, "keyfile-erase"))
|
||||
arg_keyfile_erase = true;
|
||||
|
||||
else if ((val = startswith(option, "hash="))) {
|
||||
} else if ((val = startswith(option, "hash="))) {
|
||||
r = free_and_strdup(&arg_hash, val);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@ -223,13 +202,13 @@ static int parse_one_option(const char *option) {
|
||||
arg_type = ANY_LUKS;
|
||||
else if (streq(option, "tcrypt"))
|
||||
arg_type = CRYPT_TCRYPT;
|
||||
else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) {
|
||||
else if (streq(option, "tcrypt-hidden")) {
|
||||
arg_type = CRYPT_TCRYPT;
|
||||
arg_tcrypt_hidden = true;
|
||||
} else if (streq(option, "tcrypt-system")) {
|
||||
arg_type = CRYPT_TCRYPT;
|
||||
arg_tcrypt_system = true;
|
||||
} else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) {
|
||||
} else if (streq(option, "tcrypt-veracrypt")) {
|
||||
arg_type = CRYPT_TCRYPT;
|
||||
arg_tcrypt_veracrypt = true;
|
||||
} else if (STR_IN_SET(option, "plain", "swap", "tmp"))
|
||||
@ -263,20 +242,7 @@ static int parse_one_option(const char *option) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
} else if ((val = startswith(option, "try-empty-password="))) {
|
||||
|
||||
r = parse_boolean(val);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_try_empty_password = r;
|
||||
|
||||
} else if (streq(option, "try-empty-password"))
|
||||
arg_try_empty_password = true;
|
||||
|
||||
else if (!streq(option, "x-initrd.attach"))
|
||||
} else if (!streq(option, "x-initrd.attach"))
|
||||
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
|
||||
|
||||
return 0;
|
||||
@ -474,8 +440,6 @@ static int attach_tcrypt(
|
||||
struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *key_file,
|
||||
const void *key_data,
|
||||
size_t key_data_size,
|
||||
char **passwords,
|
||||
uint32_t flags) {
|
||||
|
||||
@ -489,7 +453,7 @@ static int attach_tcrypt(
|
||||
|
||||
assert(cd);
|
||||
assert(name);
|
||||
assert(key_file || key_data || !strv_isempty(passwords));
|
||||
assert(key_file || (passwords && passwords[0]));
|
||||
|
||||
if (arg_pkcs11_uri)
|
||||
/* Ask for a regular password */
|
||||
@ -505,33 +469,22 @@ static int attach_tcrypt(
|
||||
if (arg_tcrypt_veracrypt)
|
||||
params.flags |= CRYPT_TCRYPT_VERA_MODES;
|
||||
|
||||
if (key_data) {
|
||||
params.passphrase = key_data;
|
||||
params.passphrase_size = key_data_size;
|
||||
} else {
|
||||
if (key_file) {
|
||||
r = read_one_line_file(key_file, &passphrase);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to read password file '%s': %m", key_file);
|
||||
return -EAGAIN; /* log with the actual error, but return EAGAIN */
|
||||
}
|
||||
if (key_file) {
|
||||
r = read_one_line_file(key_file, &passphrase);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to read password file '%s': %m", key_file);
|
||||
return -EAGAIN; /* log with the actual error, but return EAGAIN */
|
||||
}
|
||||
|
||||
params.passphrase = passphrase;
|
||||
} else
|
||||
params.passphrase = passwords[0];
|
||||
|
||||
params.passphrase_size = strlen(params.passphrase);
|
||||
}
|
||||
params.passphrase = passphrase;
|
||||
} else
|
||||
params.passphrase = passwords[0];
|
||||
params.passphrase_size = strlen(params.passphrase);
|
||||
|
||||
r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
|
||||
if (r < 0) {
|
||||
if (r == -EPERM) {
|
||||
if (key_data)
|
||||
log_error_errno(r, "Failed to activate using discovered key. (Key not correct?)");
|
||||
|
||||
if (key_file)
|
||||
log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file);
|
||||
|
||||
if (key_file && r == -EPERM) {
|
||||
log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file);
|
||||
return -EAGAIN; /* log the actual error, but return EAGAIN */
|
||||
}
|
||||
|
||||
@ -549,8 +502,6 @@ static int attach_luks_or_plain(
|
||||
struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *key_file,
|
||||
const void *key_data,
|
||||
size_t key_data_size,
|
||||
char **passwords,
|
||||
uint32_t flags,
|
||||
usec_t until) {
|
||||
@ -620,7 +571,7 @@ static int attach_luks_or_plain(
|
||||
_cleanup_free_ char *friendly = NULL;
|
||||
size_t decrypted_key_size = 0;
|
||||
|
||||
if (!key_file && !key_data)
|
||||
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);
|
||||
@ -633,8 +584,8 @@ static int attach_luks_or_plain(
|
||||
r = decrypt_pkcs11_key(
|
||||
friendly,
|
||||
arg_pkcs11_uri,
|
||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||
key_data, key_data_size,
|
||||
key_file,
|
||||
arg_keyfile_size, arg_keyfile_offset,
|
||||
until,
|
||||
&decrypted_key, &decrypted_key_size);
|
||||
if (r >= 0)
|
||||
@ -669,7 +620,7 @@ static int attach_luks_or_plain(
|
||||
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);
|
||||
arg_pkcs11_uri, friendly);
|
||||
|
||||
/* Let's immediately rescan in case the token appeared in the time we needed
|
||||
* to create and configure the monitor */
|
||||
@ -717,18 +668,6 @@ static int attach_luks_or_plain(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to activate with PKCS#11 acquired key: %m");
|
||||
|
||||
} else if (key_data) {
|
||||
if (pass_volume_key)
|
||||
r = crypt_activate_by_volume_key(cd, name, key_data, key_data_size, flags);
|
||||
else
|
||||
r = crypt_activate_by_passphrase(cd, name, arg_key_slot, key_data, key_data_size, flags);
|
||||
if (r == -EPERM) {
|
||||
log_error_errno(r, "Failed to activate. (Key incorrect?)");
|
||||
return -EAGAIN; /* Log actual error, but return EAGAIN */
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to activate: %m");
|
||||
|
||||
} else 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) {
|
||||
@ -809,17 +748,6 @@ static uint32_t determine_flags(void) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void remove_and_erasep(const char **p) {
|
||||
int r;
|
||||
|
||||
if (!*p)
|
||||
return;
|
||||
|
||||
r = unlinkat_deallocate(AT_FDCWD, *p, UNLINK_ERASE);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Unable to erase key file '%s', ignoring: %m", *p);
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
@ -846,19 +774,13 @@ static int run(int argc, char *argv[]) {
|
||||
unsigned tries;
|
||||
usec_t until;
|
||||
crypt_status_info status;
|
||||
_cleanup_(remove_and_erasep) const char *destroy_key_file = NULL;
|
||||
const char *key_file = NULL;
|
||||
_cleanup_(erase_and_freep) void *key_data = NULL;
|
||||
size_t key_data_size = 0;
|
||||
|
||||
/* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */
|
||||
|
||||
if (argc < 4)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments.");
|
||||
|
||||
if (!filename_is_valid(argv[2]))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", argv[2]);
|
||||
|
||||
if (argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none")) {
|
||||
if (path_is_absolute(argv[4]))
|
||||
key_file = argv[4];
|
||||
@ -875,24 +797,6 @@ static int run(int argc, char *argv[]) {
|
||||
/* A delicious drop of snake oil */
|
||||
(void) mlockall(MCL_FUTURE);
|
||||
|
||||
if (!key_file) {
|
||||
const char *fn;
|
||||
|
||||
/* If a key file is not explicitly specified, search for a key in a well defined
|
||||
* search path, and load it. */
|
||||
|
||||
fn = strjoina(argv[2], ".key");
|
||||
r = load_key_file(fn,
|
||||
STRV_MAKE("/etc/cryptsetup-keys.d", "/run/cryptsetup-keys.d"),
|
||||
0, 0, /* Note we leave arg_keyfile_offset/arg_keyfile_size as something that only applies to arg_keyfile! */
|
||||
&key_data, &key_data_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
log_debug("Automatically discovered key for volume '%s'.", argv[2]);
|
||||
} else if (arg_keyfile_erase)
|
||||
destroy_key_file = key_file; /* let's get this baby erased when we leave */
|
||||
|
||||
if (arg_header) {
|
||||
log_debug("LUKS header: %s", arg_header);
|
||||
r = crypt_init(&cd, arg_header);
|
||||
@ -939,7 +843,7 @@ static int run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
/* Tokens are available in LUKS2 only, but it is ok to call (and fail) with LUKS1. */
|
||||
if (!key_file && !key_data) {
|
||||
if (!key_file) {
|
||||
r = crypt_activate_by_token(cd, argv[2], CRYPT_ANY_TOKEN, NULL, flags);
|
||||
if (r >= 0) {
|
||||
log_debug("Volume %s activated with LUKS token id %i.", argv[2], r);
|
||||
@ -953,53 +857,26 @@ static int run(int argc, char *argv[]) {
|
||||
for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) {
|
||||
_cleanup_strv_free_erase_ char **passwords = NULL;
|
||||
|
||||
/* When we were able to acquire multiple keys, let's always process them in this order:
|
||||
*
|
||||
* 1. A key acquired via PKCS#11 token
|
||||
* 2. The discovered key: i.e. key_data + key_data_size
|
||||
* 3. The configured key: i.e. key_file + arg_keyfile_offset + arg_keyfile_size
|
||||
* 4. The empty password, in case arg_try_empty_password is set
|
||||
* 5. We enquire the user for a password
|
||||
*/
|
||||
|
||||
if (!key_file && !key_data && !arg_pkcs11_uri) {
|
||||
|
||||
if (arg_try_empty_password) {
|
||||
/* Hmm, let's try an empty password now, but only once */
|
||||
arg_try_empty_password = false;
|
||||
|
||||
key_data = strdup("");
|
||||
if (!key_data)
|
||||
return log_oom();
|
||||
|
||||
key_data_size = 0;
|
||||
} else {
|
||||
/* Ask the user for a passphrase only as last resort, if we have
|
||||
* nothing else to check for */
|
||||
|
||||
r = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
|
||||
if (r == -EAGAIN)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (!key_file && !arg_pkcs11_uri) {
|
||||
r = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords);
|
||||
if (r == -EAGAIN)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (streq_ptr(arg_type, CRYPT_TCRYPT))
|
||||
r = attach_tcrypt(cd, argv[2], key_file, key_data, key_data_size, passwords, flags);
|
||||
r = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
|
||||
else
|
||||
r = attach_luks_or_plain(cd, argv[2], key_file, key_data, key_data_size, passwords, flags, until);
|
||||
r = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags, until);
|
||||
if (r >= 0)
|
||||
break;
|
||||
if (r != -EAGAIN)
|
||||
return r;
|
||||
|
||||
/* Key not correct? Let's try again! */
|
||||
|
||||
/* Passphrase not correct? Let's try again! */
|
||||
key_file = NULL;
|
||||
key_data = erase_and_free(key_data);
|
||||
key_data_size = 0;
|
||||
arg_pkcs11_uri = mfree(arg_pkcs11_uri);
|
||||
arg_pkcs11_uri = NULL;
|
||||
}
|
||||
|
||||
if (arg_tries != 0 && tries >= arg_tries)
|
||||
@ -1007,9 +884,6 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
} else if (streq(argv[1], "detach")) {
|
||||
|
||||
if (!filename_is_valid(argv[2]))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", argv[2]);
|
||||
|
||||
r = crypt_init_by_name(&cd, argv[2]);
|
||||
if (r == -ENODEV) {
|
||||
log_info("Volume %s already inactive.", argv[2]);
|
||||
|
||||
@ -720,7 +720,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
break;
|
||||
|
||||
@ -705,7 +705,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
* STDIN. To avoid confusion we hence don't document this feature. */
|
||||
arg_file_stdin = true;
|
||||
else {
|
||||
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
}
|
||||
|
||||
@ -97,7 +97,6 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
|
||||
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
|
||||
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class);
|
||||
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
|
||||
size_t *optlen, uint8_t **optvalue);
|
||||
int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
|
||||
|
||||
@ -167,36 +167,6 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) {
|
||||
_cleanup_free_ uint8_t *p = NULL;
|
||||
size_t total = 0, offset = 0;
|
||||
char **s;
|
||||
|
||||
assert_return(buf && *buf && buflen && user_class, -EINVAL);
|
||||
|
||||
STRV_FOREACH(s, user_class) {
|
||||
size_t len = strlen(*s);
|
||||
uint8_t *q;
|
||||
|
||||
if (len > 0xffff)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
q = realloc(p, total + len + 2);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
|
||||
p = q;
|
||||
|
||||
unaligned_write_be16(&p[offset], len);
|
||||
memcpy(&p[offset + 2], *s, len);
|
||||
|
||||
offset += 2 + len;
|
||||
total += 2 + len;
|
||||
}
|
||||
|
||||
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
|
||||
}
|
||||
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
|
||||
DHCP6Option *option = (DHCP6Option *)buf;
|
||||
size_t i = sizeof(*option) + sizeof(pd->ia_pd);
|
||||
|
||||
@ -67,7 +67,6 @@ struct sd_dhcp6_client {
|
||||
size_t req_opts_len;
|
||||
char *fqdn;
|
||||
char *mudurl;
|
||||
char **user_class;
|
||||
sd_event_source *receive_message;
|
||||
usec_t retransmit_time;
|
||||
uint8_t retransmit_count;
|
||||
@ -386,27 +385,6 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
|
||||
return free_and_strdup(&client->mudurl, mudurl);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
char **p;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
|
||||
assert_return(user_class, -EINVAL);
|
||||
|
||||
STRV_FOREACH(p, user_class)
|
||||
if (strlen(*p) > UINT16_MAX)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
s = strv_copy((char **) user_class);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
client->user_class = TAKE_PTR(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(delegation, -EINVAL);
|
||||
@ -587,12 +565,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (client->user_class) {
|
||||
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
|
||||
if (r < 0)
|
||||
@ -639,12 +611,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (client->user_class) {
|
||||
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
|
||||
if (r < 0)
|
||||
@ -679,12 +645,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (client->user_class) {
|
||||
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_class);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
|
||||
if (r < 0)
|
||||
@ -1642,10 +1602,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
|
||||
free(client->req_opts);
|
||||
free(client->fqdn);
|
||||
free(client->mudurl);
|
||||
|
||||
ordered_hashmap_free(client->extra_options);
|
||||
strv_free(client->user_class);
|
||||
|
||||
return mfree(client);
|
||||
}
|
||||
|
||||
|
||||
@ -267,68 +267,6 @@ int config_parse_dhcp6_pd_hint(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_user_class(
|
||||
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) {
|
||||
|
||||
char ***l = data;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*l = strv_free(*l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *w = NULL;
|
||||
|
||||
r = extract_first_word(&rvalue, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to split user classes option, ignoring: %s", rvalue);
|
||||
break;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (ltype == AF_INET) {
|
||||
if (strlen(w) > UINT8_MAX) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"%s length is not in the range 1-255, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (strlen(w) > UINT16_MAX) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"%s length is not in the range 1-65535, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r = strv_push(l, w);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
w = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp6_mud_url(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -340,6 +278,7 @@ int config_parse_dhcp6_mud_url(
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ char *unescaped = NULL;
|
||||
Network *network = data;
|
||||
int r;
|
||||
@ -360,7 +299,7 @@ int config_parse_dhcp6_mud_url(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!http_url_is_valid(unescaped) || strlen(unescaped) > UINT8_MAX) {
|
||||
if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"Failed to parse MUD URL '%s', ignoring: %m", rvalue);
|
||||
|
||||
@ -423,7 +362,7 @@ int config_parse_dhcp_send_option(
|
||||
"Invalid DHCP option, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (u16 < 1 || u16 >= UINT16_MAX) {
|
||||
if (u16 < 1 || u16 >= 65535) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"Invalid DHCP option, valid range is 1-65535, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
@ -435,7 +374,7 @@ int config_parse_dhcp_send_option(
|
||||
"Invalid DHCP option, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (u8 < 1 || u8 >= UINT8_MAX) {
|
||||
if (u8 < 1 || u8 >= 255) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
@ -631,7 +570,7 @@ int config_parse_dhcp_request_options(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i < 1 || i >= UINT8_MAX) {
|
||||
if (i < 1 || i >= 255) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"DHCP request option is invalid, valid range is 1-254, ignoring assignment: %s", n);
|
||||
continue;
|
||||
|
||||
@ -50,6 +50,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
|
||||
|
||||
@ -1605,6 +1605,60 @@ int config_parse_dhcp_black_listed_ip_address(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_user_class(
|
||||
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) {
|
||||
|
||||
char ***l = data;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*l = strv_free(*l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *w = NULL;
|
||||
|
||||
r = extract_first_word(&rvalue, &w, NULL, 0);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to split user classes option, ignoring: %s", rvalue);
|
||||
break;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (strlen(w) > 255) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"%s length is not in the range 1-255, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_push(l, w);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
w = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_ip_service_type(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@ -25,5 +25,6 @@ int dhcp4_set_promote_secondaries(Link *link);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url);
|
||||
|
||||
@ -706,12 +706,6 @@ int dhcp6_configure(Link *link) {
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for '%u': %m", option);
|
||||
}
|
||||
|
||||
if (link->network->dhcp6_user_class) {
|
||||
r = sd_dhcp6_client_set_request_user_class(client, link->network->dhcp6_user_class);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set user class: %m");
|
||||
}
|
||||
|
||||
r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m");
|
||||
|
||||
@ -174,7 +174,7 @@ DHCPv4.RequestBroadcast, config_parse_bool,
|
||||
DHCPv4.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCPv4.MUDURL, config_parse_dhcp_mud_url, 0, 0
|
||||
DHCPv4.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0
|
||||
DHCPv4.UserClass, config_parse_dhcp_user_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCPv4.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
|
||||
DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
|
||||
DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
|
||||
DHCPv4.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
|
||||
@ -194,7 +194,6 @@ DHCPv6.UseNTP, config_parse_bool,
|
||||
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
|
||||
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0
|
||||
DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0
|
||||
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
|
||||
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
|
||||
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
|
||||
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
|
||||
@ -385,7 +384,7 @@ DHCP.Hostname, config_parse_hostname,
|
||||
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCP.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
|
||||
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.UserClass, config_parse_dhcp_user_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
|
||||
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
|
||||
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
|
||||
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
|
||||
|
||||
@ -653,7 +653,6 @@ static Network *network_free(Network *network) {
|
||||
set_free(network->dhcp6_request_options);
|
||||
free(network->mac);
|
||||
free(network->dhcp6_mudurl);
|
||||
strv_free(network->dhcp6_user_class);
|
||||
|
||||
if (network->dhcp_acd)
|
||||
sd_ipv4acd_unref(network->dhcp_acd);
|
||||
|
||||
@ -132,7 +132,6 @@ struct Network {
|
||||
bool dhcp6_without_ra;
|
||||
uint8_t dhcp6_pd_length;
|
||||
char *dhcp6_mudurl;
|
||||
char **dhcp6_user_class;
|
||||
struct in6_addr dhcp6_pd_address;
|
||||
OrderedHashmap *dhcp6_client_send_options;
|
||||
Set *dhcp6_request_options;
|
||||
|
||||
@ -7,9 +7,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "dissect-image.h"
|
||||
#include "fd-util.h"
|
||||
#include "main-func.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
@ -44,7 +42,6 @@ static int makefs(const char *type, const char *device) {
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_free_ char *device = NULL, *type = NULL, *detected = NULL;
|
||||
_cleanup_close_ int lock_fd = -1;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
@ -57,31 +54,28 @@ static int run(int argc, char *argv[]) {
|
||||
/* type and device must be copied because makefs calls safe_fork, which clears argv[] */
|
||||
type = strdup(argv[1]);
|
||||
if (!type)
|
||||
return log_oom();
|
||||
return -ENOMEM;
|
||||
|
||||
device = strdup(argv[2]);
|
||||
if (!device)
|
||||
return log_oom();
|
||||
return -ENOMEM;
|
||||
|
||||
if (stat(device, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat \"%s\": %m", device);
|
||||
|
||||
if (S_ISBLK(st.st_mode)) {
|
||||
/* Lock the device so that udev doesn't interfere with our work */
|
||||
|
||||
lock_fd = lock_whole_block_device(st.st_rdev, LOCK_EX);
|
||||
if (lock_fd < 0)
|
||||
return log_error_errno(lock_fd, "Failed to lock whole block device of \"%s\": %m", device);
|
||||
} else
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
log_info("%s is not a block device.", device);
|
||||
|
||||
r = probe_filesystem(device, &detected);
|
||||
if (r == -EUCLEAN)
|
||||
return log_error_errno(r, "Ambiguous results of probing for file system on \"%s\", refusing to proceed.", device);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to probe \"%s\": %m", device);
|
||||
return log_warning_errno(r,
|
||||
r == -EUCLEAN ?
|
||||
"Cannot reliably determine probe \"%s\", refusing to proceed." :
|
||||
"Failed to probe \"%s\": %m",
|
||||
device);
|
||||
|
||||
if (detected) {
|
||||
log_info("'%s' is not empty (contains file system of type %s), exiting.", device, detected);
|
||||
log_info("%s is not empty (type %s), exiting", device, detected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -2233,6 +2233,7 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
assert(sd_id128_is_null(p->new_uuid));
|
||||
assert(!p->new_label);
|
||||
|
||||
/* Never touch foreign partitions */
|
||||
if (PARTITION_IS_FOREIGN(p)) {
|
||||
@ -2255,9 +2256,6 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (p->new_label) /* Explicitly set by user? */
|
||||
continue;
|
||||
|
||||
if (!isempty(p->current_label)) {
|
||||
p->new_label = strdup(p->current_label); /* never change initialized labels */
|
||||
if (!p->new_label)
|
||||
|
||||
@ -75,9 +75,10 @@ int probe_filesystem(const char *node, char **ret_fstype) {
|
||||
log_debug("No type detected on partition %s", node);
|
||||
goto not_found;
|
||||
}
|
||||
if (r == -2)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
|
||||
"Results ambiguous for partition %s", node);
|
||||
if (r == -2) {
|
||||
log_debug("Results ambiguous for partition %s", node);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (r != 0)
|
||||
return errno_or_else(EIO);
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ static int apply_all(OrderedHashmap *sysctl_options) {
|
||||
if (!pattern)
|
||||
return log_oom();
|
||||
|
||||
k = glob_extend(&paths, pattern, GLOB_NOCHECK);
|
||||
k = glob_extend(&paths, pattern);
|
||||
if (k < 0) {
|
||||
if (option->ignore_failure || ERRNO_IS_PRIVILEGE(k))
|
||||
log_debug_errno(k, "Failed to resolve glob '%s', ignoring: %m",
|
||||
|
||||
@ -4192,7 +4192,7 @@ static void print_status_info(
|
||||
|
||||
fs = !isempty(i->freezer_state) && !streq(i->freezer_state, "running") ? i->freezer_state : NULL;
|
||||
if (fs)
|
||||
printf(" %s(%s)%s", ansi_highlight_yellow(), fs, ansi_normal());
|
||||
printf(" %s(%s)%s", ansi_highlight_yellow(), fs, active_off);
|
||||
|
||||
if (!isempty(i->result) && !streq(i->result, "success"))
|
||||
printf(" (Result: %s)", i->result);
|
||||
|
||||
@ -125,10 +125,6 @@ int sd_dhcp6_client_set_request_option(
|
||||
int sd_dhcp6_client_set_request_mud_url(
|
||||
sd_dhcp6_client *client,
|
||||
const char *mudurl);
|
||||
|
||||
int sd_dhcp6_client_set_request_user_class(
|
||||
sd_dhcp6_client *client,
|
||||
char** user_class);
|
||||
int sd_dhcp6_client_set_prefix_delegation_hint(
|
||||
sd_dhcp6_client *client,
|
||||
uint8_t prefixlen,
|
||||
|
||||
@ -670,7 +670,7 @@ static void test_unlinkat_deallocate(void) {
|
||||
assert_se(st.st_blocks > 0);
|
||||
assert_se(st.st_nlink == 1);
|
||||
|
||||
assert_se(unlinkat_deallocate(AT_FDCWD, p, UNLINK_ERASE) >= 0);
|
||||
assert_se(unlinkat_deallocate(AT_FDCWD, p, 0) >= 0);
|
||||
|
||||
assert_se(fstat(fd, &st) >= 0);
|
||||
assert_se(IN_SET(st.st_size, 0, 6)); /* depending on whether hole punching worked the size will be 6
|
||||
@ -850,12 +850,6 @@ static void test_path_is_encrypted_one(const char *p, int expect) {
|
||||
int r;
|
||||
|
||||
r = path_is_encrypted(p);
|
||||
if (r == -ENOENT) /* This might fail, if btrfs is used and we run in a container. In that case we
|
||||
* cannot resolve the device node paths that BTRFS_IOC_DEV_INFO returns, because
|
||||
* the device nodes are unlikely to exist in the container. But if we can't stat()
|
||||
* them we cannot determine the dev_t of them, and thus cannot figure out if they
|
||||
* are enrypted. Hence let's just ignore ENOENT here. */
|
||||
return;
|
||||
assert_se(r >= 0);
|
||||
|
||||
printf("%s encrypted: %s\n", p, yes_no(r));
|
||||
|
||||
@ -115,7 +115,6 @@ WithoutRA=
|
||||
MUDURL=
|
||||
SendOption=
|
||||
RequestOptions=
|
||||
UserClass=
|
||||
[Route]
|
||||
Destination=
|
||||
Protocol=
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user