Compare commits
11 Commits
0328d672f3
...
a114ab6373
Author | SHA1 | Date |
---|---|---|
Frantisek Sumsal | a114ab6373 | |
Frantisek Sumsal | 94f660a8fe | |
Zbigniew Jędrzejewski-Szmek | f2a8372e37 | |
Lennart Poettering | 321330ecab | |
Lennart Poettering | feb86ca90c | |
Lennart Poettering | c76dd733af | |
Lennart Poettering | c07bf7a4ed | |
Lennart Poettering | 1dfe5de095 | |
Lennart Poettering | 0d5e523461 | |
Lennart Poettering | a43eddbdf4 | |
Lennart Poettering | ed9c0851e5 |
|
@ -3,7 +3,18 @@
|
|||
# See: https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
|
||||
name: CIFuzz
|
||||
on: [pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**/meson.build'
|
||||
- '.github/workflows/**'
|
||||
- 'meson_options.txt'
|
||||
- 'src/**'
|
||||
- 'test/fuzz/**'
|
||||
- 'tools/oss-fuzz.sh'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
4
TODO
4
TODO
|
@ -51,11 +51,11 @@ Features:
|
|||
* homed: add a way to "adopt" a home directory, i.e. strip foreign signatures
|
||||
and insert a local signature instead.
|
||||
|
||||
* Maybe expose path_is_encrypted() as a new ConditionPathIsEncrypted=?
|
||||
|
||||
* busctl: maybe expose a verb "ping" for pinging a dbus service to see if it
|
||||
exists and responds.
|
||||
|
||||
* homed: add homed.conf setting DefaultStorage= or so
|
||||
|
||||
* homed: maybe pre-create ~/.cache as subvol so that it can have separate quota
|
||||
easily?
|
||||
|
||||
|
|
|
@ -51,6 +51,15 @@
|
|||
<variablelist id='efi-variables' />
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Home Area/User Account directives</title>
|
||||
|
||||
<para>Directives for configuring home areas and user accounts via
|
||||
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<variablelist id='home-directives' />
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>UDEV directives</title>
|
||||
|
||||
|
|
|
@ -504,9 +504,9 @@
|
|||
<listitem><para>Selects the storage mechanism to use for this home directory. Takes one of
|
||||
<literal>luks</literal>, <literal>fscrypt</literal>, <literal>directory</literal>,
|
||||
<literal>subvolume</literal>, <literal>cifs</literal>. For details about these mechanisms, see
|
||||
above. If a new home directory is created and the storage type is not specifically specified defaults
|
||||
to <literal>luks</literal> if supported, <literal>subvolume</literal> as first fallback if supported,
|
||||
and <literal>directory</literal> if not.</para></listitem>
|
||||
above. If a new home directory is created and the storage type is not specifically specified,
|
||||
<citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
defines which default storage to use.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -525,9 +525,10 @@
|
|||
|
||||
<listitem><para>When LUKS2 storage is used configures the file system type to use inside the home
|
||||
directory LUKS2 container. One of <literal>ext4</literal>, <literal>xfs</literal>,
|
||||
<literal>btrfs</literal>. If not specified defaults to <literal>ext4</literal>. Note that
|
||||
<literal>xfs</literal> is not recommended as its support for file system resizing is too
|
||||
limited.</para></listitem>
|
||||
<literal>btrfs</literal>. If not specified
|
||||
<citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
defines which default file system type to use. Note that <literal>xfs</literal> is not recommended as
|
||||
its support for file system resizing is too limited.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -837,6 +838,7 @@ homectl update lafcadio --pkcs11-token-uri=…</programlisting>
|
|||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry project='man-pages'><refentrytitle>useradd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry project='man-pages'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version='1.0'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
|
||||
|
||||
<refentry id="homed.conf" conditional='ENABLE_RESOLVE'
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<refentryinfo>
|
||||
<title>homed.conf</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>homed.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>homed.conf</refname>
|
||||
<refname>homed.conf.d</refname>
|
||||
<refpurpose>Home area/user account manager configuration files</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>/etc/systemd/homed.conf</filename></para>
|
||||
<para><filename>/etc/systemd/homed.conf.d/*.conf</filename></para>
|
||||
<para><filename>/run/systemd/homed.conf.d/*.conf</filename></para>
|
||||
<para><filename>/usr/lib/systemd/homed.conf.d/*.conf</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>These configuration files control default parameters for home areas/user accounts created and
|
||||
managed by
|
||||
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<xi:include href="standard-conf.xml" xpointer="main-conf" />
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<para>The following options are available in the <literal>[Home]</literal> section:</para>
|
||||
|
||||
<variablelist class='home-directives'>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DefaultStorage=</varname></term>
|
||||
<listitem><para>The default storage to use for home areas. Takes one of <literal>luks</literal>,
|
||||
<literal>fscrypt</literal>, <literal>directory</literal>, <literal>subvolume</literal>,
|
||||
<literal>cifs</literal>. For details about these options, see
|
||||
<citerefentry><refentrytitle>homectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. If not
|
||||
configured or assigned the empty string, the default storage is automatically determined: if not
|
||||
running in a container enviroment and <filename>/home/</filename> is not itself encrypted, defaults
|
||||
to <literal>luks</literal>. Otherwise defaults to <literal>subvolume</literal> if
|
||||
<filename>/home/</filename> is on a btrfs file system, and <literal>directory</literal>
|
||||
otherwise. Note that the storage selected on the <command>homectl</command> command line always takes
|
||||
precedence.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DefaultFileSystemType=</varname></term>
|
||||
<listitem><para>When using <literal>luks</literal> as storage (see above), selects the default file
|
||||
system to use inside the user's LUKS volume. Takes one of <literal>ext4</literal>,
|
||||
<literal>xfs</literal> or <literal>btrfs</literal>. If not specified defaults to
|
||||
<literal>ext4</literal>. This setting has no effect if a different storage mechanism is used. The
|
||||
file system type selected on the <command>homectl</command> command line always takes
|
||||
precedence.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
|
@ -18,6 +18,7 @@ manpages = [
|
|||
['file-hierarchy', '7', [], ''],
|
||||
['halt', '8', ['poweroff', 'reboot'], ''],
|
||||
['homectl', '1', [], 'ENABLE_HOMED'],
|
||||
['homed.conf', '5', ['homed.conf.d'], 'ENABLE_RESOLVE'],
|
||||
['hostname', '5', [], ''],
|
||||
['hostnamectl', '1', [], 'ENABLE_HOSTNAMED'],
|
||||
['hwdb', '7', [], 'ENABLE_HWDB'],
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>homed.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>homectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>pam_systemd_home</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
|
|
|
@ -1492,6 +1492,7 @@ meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
|
|||
|
||||
includes = include_directories('src/basic',
|
||||
'src/boot',
|
||||
'src/home',
|
||||
'src/shared',
|
||||
'src/systemd',
|
||||
'src/journal',
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "blockdev-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "log.h"
|
||||
|
@ -1488,3 +1490,26 @@ int open_parent(const char *path, int flags, mode_t mode) {
|
|||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int path_is_encrypted(const char *path) {
|
||||
_cleanup_free_ char *uuids = NULL;
|
||||
char p[SYS_BLOCK_PATH_MAX("/dm/uuid")];
|
||||
dev_t devt;
|
||||
int r;
|
||||
|
||||
r = get_block_device(path, &devt);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* doesn't have a block device */
|
||||
return false;
|
||||
|
||||
xsprintf_sys_block_path(p, "/dm/uuid", devt);
|
||||
r = read_one_line_file(p, &uuids);
|
||||
if (r == -ENOENT)
|
||||
return false;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
|
||||
return !!startswith(uuids, "CRYPT-");
|
||||
}
|
||||
|
|
|
@ -122,3 +122,5 @@ int fsync_path_at(int at_fd, const char *path);
|
|||
int syncfs_path(int atfd, const char *path);
|
||||
|
||||
int open_parent(const char *path, int flags, mode_t mode);
|
||||
|
||||
int path_is_encrypted(const char *path);
|
||||
|
|
|
@ -64,6 +64,12 @@ int suitable_image_path(const char *path) {
|
|||
path_is_absolute(path);
|
||||
}
|
||||
|
||||
bool supported_fstype(const char *fstype) {
|
||||
/* Limit the set of supported file systems a bit, as protection against little tested kernel file
|
||||
* systems. Also, we only support the resize ioctls for these file systems. */
|
||||
return STR_IN_SET(fstype, "ext4", "btrfs", "xfs");
|
||||
}
|
||||
|
||||
int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm) {
|
||||
_cleanup_free_ char *user_name = NULL, *realm = NULL;
|
||||
const char *c;
|
||||
|
|
|
@ -12,6 +12,8 @@ bool suitable_user_name(const char *name);
|
|||
int suitable_realm(const char *realm);
|
||||
int suitable_image_path(const char *path);
|
||||
|
||||
bool supported_fstype(const char *fstype);
|
||||
|
||||
int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm);
|
||||
|
||||
int bus_message_append_secret(sd_bus_message *m, UserRecord *secret);
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "def.h"
|
||||
#include "home-util.h"
|
||||
#include "homed-conf.h"
|
||||
|
||||
int manager_parse_config_file(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = config_parse_many_nulstr(PKGSYSCONFDIR "/homed.conf",
|
||||
CONF_PATHS_NULSTR("systemd/homed.conf.d"),
|
||||
"Home\0",
|
||||
config_item_perf_lookup, homed_gperf_lookup,
|
||||
CONFIG_PARSE_WARN, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_default_storage, user_storage, UserStorage, "Failed to parse default storage setting");
|
||||
|
||||
int config_parse_default_file_system_type(
|
||||
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 **s = data;
|
||||
|
||||
assert(rvalue);
|
||||
assert(s);
|
||||
|
||||
if (!isempty(rvalue) && !supported_fstype(rvalue)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Unsupported file system, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return free_and_strdup_warn(s, empty_to_null(rvalue));
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "homed-manager.h"
|
||||
|
||||
int manager_parse_config_file(Manager *m);
|
||||
|
||||
const struct ConfigPerfItem* homed_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_default_storage);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_default_file_system_type);
|
|
@ -0,0 +1,21 @@
|
|||
%{
|
||||
#if __GNUC__ >= 7
|
||||
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include "conf-parser.h"
|
||||
#include "homed-conf.h"
|
||||
%}
|
||||
struct ConfigPerfItem;
|
||||
%null_strings
|
||||
%language=ANSI-C
|
||||
%define slot-name section_and_lvalue
|
||||
%define hash-function-name homed_gperf_hash
|
||||
%define lookup-function-name homed_gperf_lookup
|
||||
%readonly-tables
|
||||
%omit-struct-type
|
||||
%struct-type
|
||||
%includes
|
||||
%%
|
||||
Home.DefaultStorage, config_parse_default_storage, 0, offsetof(Manager, default_storage)
|
||||
Home.DefaultFileSystemType, config_parse_default_file_system_type, 0, offsetof(Manager, default_file_system_type)
|
|
@ -1011,6 +1011,18 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord
|
|||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (h->manager->default_storage >= 0)
|
||||
if (setenv("SYSTEMD_HOME_DEFAULT_STORAGE", user_storage_to_string(h->manager->default_storage), 1) < 0) {
|
||||
log_error_errno(errno, "Failed to set $SYSTEMD_HOME_DEFAULT_STORAGE: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (h->manager->default_file_system_type)
|
||||
if (setenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE", h->manager->default_file_system_type, 1) < 0) {
|
||||
log_error_errno(errno, "Failed to set $SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = rearrange_stdio(stdin_fd, stdout_fd, STDERR_FILENO);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to rearrange stdin/stdout/stderr: %m");
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "fs-util.h"
|
||||
#include "gpt.h"
|
||||
#include "home-util.h"
|
||||
#include "homed-conf.h"
|
||||
#include "homed-home-bus.h"
|
||||
#include "homed-home.h"
|
||||
#include "homed-manager-bus.h"
|
||||
|
@ -184,10 +185,18 @@ int manager_new(Manager **ret) {
|
|||
|
||||
assert(ret);
|
||||
|
||||
m = new0(Manager, 1);
|
||||
m = new(Manager, 1);
|
||||
if (!m)
|
||||
return -ENOMEM;
|
||||
|
||||
*m = (Manager) {
|
||||
.default_storage = _USER_STORAGE_INVALID,
|
||||
};
|
||||
|
||||
r = manager_parse_config_file(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_default(&m->event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -251,6 +260,8 @@ Manager* manager_free(Manager *m) {
|
|||
|
||||
varlink_server_unref(m->varlink_server);
|
||||
|
||||
free(m->default_file_system_type);
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ struct Manager {
|
|||
Hashmap *homes_by_sysfs;
|
||||
|
||||
bool scan_slash_home;
|
||||
UserStorage default_storage;
|
||||
char *default_file_system_type;
|
||||
|
||||
sd_event_source *inotify_event_source;
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Entries in this file show the compile time defaults.
|
||||
# You can change settings by editing this file.
|
||||
# Defaults can be restored by simply deleting this file.
|
||||
#
|
||||
# See homed.conf(5) for details
|
||||
|
||||
[Resolve]
|
||||
#DefaultStorage=
|
||||
#DefaultFileSystemType=ext4
|
|
@ -16,6 +16,7 @@
|
|||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "fsck-util.h"
|
||||
#include "home-util.h"
|
||||
#include "homework-luks.h"
|
||||
#include "homework-mount.h"
|
||||
#include "id128-util.h"
|
||||
|
@ -39,12 +40,6 @@
|
|||
* strictly round disk sizes down to the next 1K boundary.*/
|
||||
#define DISK_SIZE_ROUND_DOWN(x) ((x) & ~UINT64_C(1023))
|
||||
|
||||
static bool supported_fstype(const char *fstype) {
|
||||
/* Limit the set of supported file systems a bit, as protection against little tested kernel file
|
||||
* systems. Also, we only support the resize ioctls for these file systems. */
|
||||
return STR_IN_SET(fstype, "ext4", "btrfs", "xfs");
|
||||
}
|
||||
|
||||
static int probe_file_system_by_fd(
|
||||
int fd,
|
||||
char **ret_fstype,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "copy.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "home-util.h"
|
||||
#include "homework-cifs.h"
|
||||
#include "homework-directory.h"
|
||||
|
@ -862,9 +863,68 @@ static int user_record_compile_effective_passwords(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int determine_default_storage(UserStorage *ret) {
|
||||
UserStorage storage = _USER_STORAGE_INVALID;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* homed tells us via an environment variable which default storage to use */
|
||||
e = getenv("SYSTEMD_HOME_DEFAULT_STORAGE");
|
||||
if (e) {
|
||||
storage = user_storage_from_string(e);
|
||||
if (storage < 0)
|
||||
log_warning("$SYSTEMD_HOME_DEFAULT_STORAGE set to invalid storage type, ignoring: %s", e);
|
||||
else {
|
||||
log_info("Using configured default storage '%s'.", user_storage_to_string(storage));
|
||||
*ret = storage;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* When neither user nor admin specified the storage type to use, fix it to be LUKS — unless we run
|
||||
* in a container where loopback devices and LUKS/DM are not available. Also, if /home is encrypted
|
||||
* anyway, let's avoid duplicate encryption. Note that we typically default to the assumption of
|
||||
* "classic" storage for most operations. However, if we create a new home, then let's user LUKS if
|
||||
* nothing is specified. */
|
||||
|
||||
r = detect_container();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine whether we are in a container: %m");
|
||||
if (r == 0) {
|
||||
r = path_is_encrypted("/home");
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine if /home is encrypted, ignoring: %m");
|
||||
if (r <= 0) {
|
||||
log_info("Using automatic default storage of '%s'.", user_storage_to_string(USER_LUKS));
|
||||
*ret = USER_LUKS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("/home is encrypted, not using '%s' storage, in order to avoid double encryption.", user_storage_to_string(USER_LUKS));
|
||||
} else
|
||||
log_info("Running in container, not using '%s' storage.", user_storage_to_string(USER_LUKS));
|
||||
|
||||
r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine file system of /home, ignoring: %m");
|
||||
if (r > 0) {
|
||||
log_info("/home is on btrfs, using '%s' as storage.", user_storage_to_string(USER_SUBVOLUME));
|
||||
*ret = USER_SUBVOLUME;
|
||||
} else {
|
||||
log_info("/home is on simple file system, using '%s' as storage.", user_storage_to_string(USER_DIRECTORY));
|
||||
*ret = USER_DIRECTORY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int home_create(UserRecord *h, UserRecord **ret_home) {
|
||||
_cleanup_(strv_free_erasep) char **effective_passwords = NULL, **pkcs11_decrypted_passwords = NULL;
|
||||
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
|
||||
UserStorage new_storage = _USER_STORAGE_INVALID;
|
||||
const char *new_fs = NULL;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
|
@ -884,27 +944,18 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
|
|||
if (r != USER_TEST_ABSENT)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Home directory %s already exists, refusing.", user_record_home_directory(h));
|
||||
|
||||
/* When the user didn't specify the storage type to use, fix it to be LUKS -- unless we run in a
|
||||
* container where loopback devices and LUKS/DM are not available. Note that we typically default to
|
||||
* the assumption of "classic" storage for most operations. However, if we create a new home, then
|
||||
* let's user LUKS if nothing is specified. */
|
||||
if (h->storage < 0) {
|
||||
UserStorage new_storage;
|
||||
|
||||
r = detect_container();
|
||||
r = determine_default_storage(&new_storage);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine whether we are in a container: %m");
|
||||
if (r > 0) {
|
||||
new_storage = USER_DIRECTORY;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = path_is_fs_type("/home", BTRFS_SUPER_MAGIC);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to determine file system of /home, ignoring: %m");
|
||||
|
||||
new_storage = r > 0 ? USER_SUBVOLUME : USER_DIRECTORY;
|
||||
} else
|
||||
new_storage = USER_LUKS;
|
||||
if ((h->storage == USER_LUKS ||
|
||||
(h->storage < 0 && new_storage == USER_LUKS)) &&
|
||||
!h->file_system_type)
|
||||
new_fs = getenv("SYSTEMD_HOME_DEFAULT_FILE_SYSTEM_TYPE");
|
||||
|
||||
if (new_storage >= 0 || new_fs) {
|
||||
r = user_record_add_binding(
|
||||
h,
|
||||
new_storage,
|
||||
|
@ -915,18 +966,12 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
|
|||
NULL,
|
||||
NULL,
|
||||
UINT64_MAX,
|
||||
NULL,
|
||||
new_fs,
|
||||
NULL,
|
||||
UID_INVALID,
|
||||
GID_INVALID);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change storage type to LUKS: %m");
|
||||
|
||||
if (!h->image_path_auto) {
|
||||
h->image_path_auto = strjoin("/home/", user_record_user_name_and_realm(h), new_storage == USER_LUKS ? ".home" : ".homedir");
|
||||
if (!h->image_path_auto)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
r = user_record_test_image_path_and_warn(h);
|
||||
|
|
|
@ -31,6 +31,8 @@ systemd_homed_sources = files('''
|
|||
home-util.h
|
||||
homed-bus.c
|
||||
homed-bus.h
|
||||
homed-conf.c
|
||||
homed-conf.h
|
||||
homed-home-bus.c
|
||||
homed-home-bus.h
|
||||
homed-home.c
|
||||
|
@ -52,6 +54,14 @@ systemd_homed_sources = files('''
|
|||
user-record-util.h
|
||||
'''.split())
|
||||
|
||||
homed_gperf_c = custom_target(
|
||||
'homed_gperf.c',
|
||||
input : 'homed-gperf.gperf',
|
||||
output : 'homed-gperf.c',
|
||||
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
|
||||
|
||||
systemd_homed_sources += [homed_gperf_c]
|
||||
|
||||
homectl_sources = files('''
|
||||
home-util.c
|
||||
home-util.h
|
||||
|
@ -78,4 +88,7 @@ if conf.get('ENABLE_HOMED') == 1
|
|||
install_dir : dbussystemservicedir)
|
||||
install_data('org.freedesktop.home1.policy',
|
||||
install_dir : polkitpolicydir)
|
||||
|
||||
install_data('homed.conf',
|
||||
install_dir : pkgsysconfdir)
|
||||
endif
|
||||
|
|
|
@ -276,7 +276,7 @@ int user_record_add_binding(
|
|||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL;
|
||||
char smid[SD_ID128_STRING_MAX], partition_uuids[37], luks_uuids[37], fs_uuids[37];
|
||||
_cleanup_free_ char *ip = NULL, *hd = NULL;
|
||||
_cleanup_free_ char *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL;
|
||||
sd_id128_t mid;
|
||||
int r;
|
||||
|
||||
|
@ -294,6 +294,10 @@ int user_record_add_binding(
|
|||
ip = strdup(image_path);
|
||||
if (!ip)
|
||||
return -ENOMEM;
|
||||
} else if (!h->image_path && storage >= 0) {
|
||||
r = user_record_build_image_path(storage, user_record_user_name_and_realm(h), &ip_auto);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (home_directory) {
|
||||
|
@ -302,6 +306,24 @@ int user_record_add_binding(
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (file_system_type) {
|
||||
fst = strdup(file_system_type);
|
||||
if (!fst)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (luks_cipher) {
|
||||
lc = strdup(luks_cipher);
|
||||
if (!lc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (luks_cipher_mode) {
|
||||
lcm = strdup(luks_cipher_mode);
|
||||
if (!lcm)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = json_build(&new_binding_entry,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)),
|
||||
|
@ -348,6 +370,8 @@ int user_record_add_binding(
|
|||
|
||||
if (ip)
|
||||
free_and_replace(h->image_path, ip);
|
||||
if (ip_auto)
|
||||
free_and_replace(h->image_path_auto, ip_auto);
|
||||
|
||||
if (!sd_id128_is_null(partition_uuid))
|
||||
h->partition_uuid = partition_uuid;
|
||||
|
@ -358,11 +382,22 @@ int user_record_add_binding(
|
|||
if (!sd_id128_is_null(fs_uuid))
|
||||
h->file_system_uuid = fs_uuid;
|
||||
|
||||
if (lc)
|
||||
free_and_replace(h->luks_cipher, lc);
|
||||
if (lcm)
|
||||
free_and_replace(h->luks_cipher_mode, lcm);
|
||||
if (luks_volume_key_size != UINT64_MAX)
|
||||
h->luks_volume_key_size = luks_volume_key_size;
|
||||
|
||||
if (fst)
|
||||
free_and_replace(h->file_system_type, fst);
|
||||
if (hd)
|
||||
free_and_replace(h->home_directory, hd);
|
||||
|
||||
if (uid_is_valid(uid))
|
||||
h->uid = uid;
|
||||
if (gid_is_valid(gid))
|
||||
h->gid = gid;
|
||||
|
||||
h->mask |= USER_RECORD_BINDING;
|
||||
return 1;
|
||||
|
|
|
@ -1059,7 +1059,34 @@ static int dispatch_status(const char *name, JsonVariant *variant, JsonDispatchF
|
|||
return json_dispatch(m, status_dispatch_table, NULL, flags, userdata);
|
||||
}
|
||||
|
||||
int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret) {
|
||||
const char *suffix;
|
||||
char *z;
|
||||
|
||||
assert(storage >= 0);
|
||||
assert(user_name_and_realm);
|
||||
assert(ret);
|
||||
|
||||
if (storage == USER_LUKS)
|
||||
suffix = ".home";
|
||||
else if (IN_SET(storage, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT))
|
||||
suffix = ".homedir";
|
||||
else {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
z = strjoin("/home/", user_name_and_realm, suffix);
|
||||
if (!z)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = z;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) {
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
|
||||
if (!FLAGS_SET(h->mask, USER_RECORD_REGULAR))
|
||||
|
@ -1084,22 +1111,9 @@ static int user_record_augment(UserRecord *h, JsonDispatchFlags json_flags) {
|
|||
}
|
||||
|
||||
if (!h->image_path && !h->image_path_auto) {
|
||||
const char *suffix;
|
||||
UserStorage storage;
|
||||
|
||||
storage = user_record_storage(h);
|
||||
if (storage == USER_LUKS)
|
||||
suffix = ".home";
|
||||
else if (IN_SET(storage, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT))
|
||||
suffix = ".homedir";
|
||||
else
|
||||
suffix = NULL;
|
||||
|
||||
if (suffix) {
|
||||
h->image_path_auto = strjoin("/home/", user_record_user_name_and_realm(h), suffix);
|
||||
if (!h->image_path_auto)
|
||||
return json_log_oom(h->json, json_flags);
|
||||
}
|
||||
r = user_record_build_image_path(user_record_storage(h), user_record_user_name_and_realm(h), &h->image_path_auto);
|
||||
if (r < 0)
|
||||
return json_log(h->json, json_flags, r, "Failed to determine default image path: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -349,6 +349,8 @@ usec_t user_record_ratelimit_interval_usec(UserRecord *h);
|
|||
uint64_t user_record_ratelimit_burst(UserRecord *h);
|
||||
bool user_record_can_authenticate(UserRecord *h);
|
||||
|
||||
int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret);
|
||||
|
||||
bool user_record_equal(UserRecord *a, UserRecord *b);
|
||||
bool user_record_compatible(UserRecord *a, UserRecord *b);
|
||||
int user_record_compare_last_change(UserRecord *a, UserRecord *b);
|
||||
|
|
|
@ -846,6 +846,28 @@ static void test_chmod_and_chown_unsafe(void) {
|
|||
assert_se(S_ISLNK(st.st_mode));
|
||||
}
|
||||
|
||||
static void test_path_is_encrypted_one(const char *p, int expect) {
|
||||
int r;
|
||||
|
||||
r = path_is_encrypted(p);
|
||||
assert_se(r >= 0);
|
||||
|
||||
printf("%s encrypted: %s\n", p, yes_no(r));
|
||||
|
||||
assert_se(expect < 0 || ((r > 0) == (expect > 0)));
|
||||
}
|
||||
|
||||
static void test_path_is_encrypted(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
test_path_is_encrypted_one("/home", -1);
|
||||
test_path_is_encrypted_one("/var", -1);
|
||||
test_path_is_encrypted_one("/", -1);
|
||||
test_path_is_encrypted_one("/proc", false);
|
||||
test_path_is_encrypted_one("/sys", false);
|
||||
test_path_is_encrypted_one("/dev", false);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
|
@ -864,6 +886,7 @@ int main(int argc, char *argv[]) {
|
|||
test_rename_noreplace();
|
||||
test_chmod_and_chown();
|
||||
test_chmod_and_chown_unsafe();
|
||||
test_path_is_encrypted();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue