]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #15703 from poettering/homed-tweak-default-storage
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 8 May 2020 14:57:14 +0000 (16:57 +0200)
committerGitHub <noreply@github.com>
Fri, 8 May 2020 14:57:14 +0000 (16:57 +0200)
homed: avoid double encryption

25 files changed:
TODO
man/directives-template.xml
man/homectl.xml
man/homed.conf.xml [new file with mode: 0644]
man/rules/meson.build
man/systemd-homed.service.xml
meson.build
src/basic/fs-util.c
src/basic/fs-util.h
src/home/home-util.c
src/home/home-util.h
src/home/homed-conf.c [new file with mode: 0644]
src/home/homed-conf.h [new file with mode: 0644]
src/home/homed-gperf.gperf [new file with mode: 0644]
src/home/homed-home.c
src/home/homed-manager.c
src/home/homed-manager.h
src/home/homed.conf [new file with mode: 0644]
src/home/homework-luks.c
src/home/homework.c
src/home/meson.build
src/home/user-record-util.c
src/shared/user-record.c
src/shared/user-record.h
src/test/test-fs-util.c

diff --git a/TODO b/TODO
index fda2e67764e961d9bd1edf09a9e616bc1c106326..b59ba01208b55b87f1e8ee29128b187b3ee23af0 100644 (file)
--- 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?
 
index 5ab0beb4cfa88937e3372548c20e67d8535f71e6..5038061467389b927158c26bdf28baf565356bdf 100644 (file)
     <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>
 
index 632c8b95bbf8564e6c26b91f214a81e078c22cca..14877a0cde047e24265139e170443e624e671c8a 100644 (file)
         <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>
 
         <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>
diff --git a/man/homed.conf.xml b/man/homed.conf.xml
new file mode 100644 (file)
index 0000000..03590fe
--- /dev/null
@@ -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>
index 5bbee35e9f8c57e87c9da82e4c810b6bdd3fdc8c..941e248d72acadedfc9513248d574503b2f7bc45 100644 (file)
@@ -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'],
index a51bd36d4104ab6ac53dff49e8c13c9b46d60962..049b7e9097ca7335deff3f48f43ad8b24b7d6b34 100644 (file)
     <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>
index 97ee0856a0441bd3f0987b74209dc91f04054d17..4c997ab6f7ed0bc9f5dc34a3077fcd07ddd04ff8 100644 (file)
@@ -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',
index e16bfef3c3bda9dd8c5e9a6a23723cae087f752b..e568c70684219870eb8497bf7daee180c6cb8950 100644 (file)
@@ -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-");
+}
index c2c39c4315d47f31d547c4ebb209ea338e434aa2..08892398291a5b6710f64e5d3905041bd295f39a 100644 (file)
@@ -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);
index 51406fd234567a7421eaae33f4fb9dcd2653f67e..3fd57639f84192d0a329ed8a8e5554cf57d44d0a 100644 (file)
@@ -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;
index df20c0af71e57d6a3494442df1917b220aadb88e..78d6e7b41768340b840d2f30ec3d978e2711b342 100644 (file)
@@ -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 (file)
index 0000000..14ec8b3
--- /dev/null
@@ -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 (file)
index 0000000..00eb3fd
--- /dev/null
@@ -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 (file)
index 0000000..970da5f
--- /dev/null
@@ -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)
index 07356e60c4f94f8097d278b62444666efc09abfb..65e363c23c1d1b3dc0ea52d677543f8a599e5986 100644 (file)
@@ -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");
index 70673fc84d6e1fcd39a97809e2879ff4b038abfc..df0ed2f4f36f550b6a7d6fc3e2f53f43fde8a155 100644 (file)
@@ -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);
 }
 
index 6deffb0d26bd9532159f436c03331c8512548813..83a714462792a103cc0d0f010df40fe40ad52555 100644 (file)
@@ -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 (file)
index 0000000..a8a48fe
--- /dev/null
@@ -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
index 694f215b30d5da5d0c3c5c037406badac1908197..caa4168265a0a2ef50f74119f98a1fef74415f40 100644 (file)
@@ -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"
  * 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,
index 77afc402d383936ad89c32a03f8e6be29fb4fc8b..71e7cfdb499aaa0585e0bda939a7ef4e2d3dd9e9 100644 (file)
@@ -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;
-
-                        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");
+                        return r;
+        }
 
-                        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);
index eb6da0b6969b5865bc9a30e42abf684900b40a68..2c5664aae1d9702b1b3d808921c06e6afc1503b3 100644 (file)
@@ -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
index 430a952e6f7224087054d48f8ee2597fe49a4b92..8f51f8d6e82ea40442abf1cee632814d0566bdba 100644 (file)
@@ -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;
index f64831120876f776c67232702f4663472175b482..83d86f69e761ab0a22a2366a0b20476a3a489072 100644 (file)
@@ -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;
index 83c5a71d4e7d6d1c8f65cb4303366450364307f3..9fd10610d926acce14ab26edb184fcdd0c2a68ab 100644 (file)
@@ -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);
index d97ccfda3bcc7c59adaa01aef67fbe649b01a5a9..d005b3e8e5f640d564091b6789669fa69f2c09cd 100644 (file)
@@ -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;
 }