diff --git a/TODO b/TODO
index fda2e67764..b59ba01208 100644
--- a/TODO
+++ b/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?
diff --git a/man/directives-template.xml b/man/directives-template.xml
index 5ab0beb4cf..5038061467 100644
--- a/man/directives-template.xml
+++ b/man/directives-template.xml
@@ -51,6 +51,15 @@
+
+ Home Area/User Account directives
+
+ Directives for configuring home areas and user accounts via
+ systemd-homed.service8.
+
+
+
+
UDEV directives
diff --git a/man/homectl.xml b/man/homectl.xml
index 632c8b95bb..14877a0cde 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -504,9 +504,9 @@
Selects the storage mechanism to use for this home directory. Takes one of
luks, fscrypt, directory,
subvolume, cifs. For details about these mechanisms, see
- above. If a new home directory is created and the storage type is not specifically specified defaults
- to luks if supported, subvolume as first fallback if supported,
- and directory if not.
+ above. If a new home directory is created and the storage type is not specifically specified,
+ homed.conf5
+ defines which default storage to use.
@@ -525,9 +525,10 @@
When LUKS2 storage is used configures the file system type to use inside the home
directory LUKS2 container. One of ext4, xfs,
- btrfs. If not specified defaults to ext4. Note that
- xfs is not recommended as its support for file system resizing is too
- limited.
+ btrfs. If not specified
+ homed.conf5
+ defines which default file system type to use. Note that xfs is not recommended as
+ its support for file system resizing is too limited.
@@ -837,6 +838,7 @@ homectl update lafcadio --pkcs11-token-uri=…
systemd1,
systemd-homed.service8,
+ homed.conf5,
userdbctl1,
useradd8,
cryptsetup8
diff --git a/man/homed.conf.xml b/man/homed.conf.xml
new file mode 100644
index 0000000000..03590feeaa
--- /dev/null
+++ b/man/homed.conf.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+ homed.conf
+ systemd
+
+
+
+ homed.conf
+ 5
+
+
+
+ homed.conf
+ homed.conf.d
+ Home area/user account manager configuration files
+
+
+
+ /etc/systemd/homed.conf
+ /etc/systemd/homed.conf.d/*.conf
+ /run/systemd/homed.conf.d/*.conf
+ /usr/lib/systemd/homed.conf.d/*.conf
+
+
+
+ Description
+
+ These configuration files control default parameters for home areas/user accounts created and
+ managed by
+ systemd-homed.service8.
+
+
+
+
+
+
+ Options
+
+ The following options are available in the [Home] section:
+
+
+
+
+ DefaultStorage=
+ The default storage to use for home areas. Takes one of luks,
+ fscrypt, directory, subvolume,
+ cifs. For details about these options, see
+ homectl1. If not
+ configured or assigned the empty string, the default storage is automatically determined: if not
+ running in a container enviroment and /home/ is not itself encrypted, defaults
+ to luks. Otherwise defaults to subvolume if
+ /home/ is on a btrfs file system, and directory
+ otherwise. Note that the storage selected on the homectl command line always takes
+ precedence.
+
+
+
+ DefaultFileSystemType=
+ When using luks as storage (see above), selects the default file
+ system to use inside the user's LUKS volume. Takes one of ext4,
+ xfs or btrfs. If not specified defaults to
+ ext4. This setting has no effect if a different storage mechanism is used. The
+ file system type selected on the homectl command line always takes
+ precedence.
+
+
+
+
+
+
+ See Also
+
+ systemd1,
+ systemd-homed.service8
+
+
+
+
diff --git a/man/rules/meson.build b/man/rules/meson.build
index 5bbee35e9f..941e248d72 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -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'],
diff --git a/man/systemd-homed.service.xml b/man/systemd-homed.service.xml
index a51bd36d41..049b7e9097 100644
--- a/man/systemd-homed.service.xml
+++ b/man/systemd-homed.service.xml
@@ -100,6 +100,7 @@
See Also
systemd1,
+ homed.conf5,
homectl1,
pam_systemd_home8,
userdbctl1
diff --git a/meson.build b/meson.build
index 97ee0856a0..4c997ab6f7 100644
--- a/meson.build
+++ b/meson.build
@@ -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',
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index e16bfef3c3..e568c70684 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -8,8 +8,10 @@
#include
#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-");
+}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index c2c39c4315..0889239829 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -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);
diff --git a/src/home/home-util.c b/src/home/home-util.c
index 51406fd234..3fd57639f8 100644
--- a/src/home/home-util.c
+++ b/src/home/home-util.c
@@ -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;
diff --git a/src/home/home-util.h b/src/home/home-util.h
index df20c0af71..78d6e7b417 100644
--- a/src/home/home-util.h
+++ b/src/home/home-util.h
@@ -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);
diff --git a/src/home/homed-conf.c b/src/home/homed-conf.c
new file mode 100644
index 0000000000..14ec8b336d
--- /dev/null
+++ b/src/home/homed-conf.c
@@ -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));
+
+}
diff --git a/src/home/homed-conf.h b/src/home/homed-conf.h
new file mode 100644
index 0000000000..00eb3fdb68
--- /dev/null
+++ b/src/home/homed-conf.h
@@ -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);
diff --git a/src/home/homed-gperf.gperf b/src/home/homed-gperf.gperf
new file mode 100644
index 0000000000..970da5f790
--- /dev/null
+++ b/src/home/homed-gperf.gperf
@@ -0,0 +1,21 @@
+%{
+#if __GNUC__ >= 7
+_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
+#endif
+#include
+#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)
diff --git a/src/home/homed-home.c b/src/home/homed-home.c
index 07356e60c4..65e363c23c 100644
--- a/src/home/homed-home.c
+++ b/src/home/homed-home.c
@@ -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");
diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c
index 70673fc84d..df0ed2f4f3 100644
--- a/src/home/homed-manager.c
+++ b/src/home/homed-manager.c
@@ -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);
}
diff --git a/src/home/homed-manager.h b/src/home/homed-manager.h
index 6deffb0d26..83a7144627 100644
--- a/src/home/homed-manager.h
+++ b/src/home/homed-manager.h
@@ -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;
diff --git a/src/home/homed.conf b/src/home/homed.conf
new file mode 100644
index 0000000000..a8a48fe593
--- /dev/null
+++ b/src/home/homed.conf
@@ -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
diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c
index 694f215b30..caa4168265 100644
--- a/src/home/homework-luks.c
+++ b/src/home/homework-luks.c
@@ -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,
diff --git a/src/home/homework.c b/src/home/homework.c
index 77afc402d3..71e7cfdb49 100644
--- a/src/home/homework.c
+++ b/src/home/homework.c
@@ -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);
diff --git a/src/home/meson.build b/src/home/meson.build
index eb6da0b696..2c5664aae1 100644
--- a/src/home/meson.build
+++ b/src/home/meson.build
@@ -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
diff --git a/src/home/user-record-util.c b/src/home/user-record-util.c
index 430a952e6f..8f51f8d6e8 100644
--- a/src/home/user-record-util.c
+++ b/src/home/user-record-util.c
@@ -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;
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
index f648311208..83d86f69e7 100644
--- a/src/shared/user-record.c
+++ b/src/shared/user-record.c
@@ -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;
diff --git a/src/shared/user-record.h b/src/shared/user-record.h
index 83c5a71d4e..9fd10610d9 100644
--- a/src/shared/user-record.h
+++ b/src/shared/user-record.h
@@ -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);
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index d97ccfda3b..d005b3e8e5 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -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;
}