]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homework: allow specifying explicit additional mount options when using CIFS backend 21162/head
authorLennart Poettering <lennart@poettering.net>
Tue, 26 Oct 2021 14:58:56 +0000 (16:58 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 27 Oct 2021 20:46:46 +0000 (22:46 +0200)
This is useful since certain shares can only be mounted with additional
mount flags. For example the SMB share in modern AVM Fritz!Boxes
requires "noserverino" to be set to work from Linux.

docs/USER_RECORD.md
man/homectl.xml
src/home/homectl.c
src/home/homework-cifs.c
src/shared/user-record.c
src/shared/user-record.h

index 6710b00c0c531346d6ea14e6719c084984a5eb76..c134ec42e3fb136bf2b288bbd309f95ee2ca98cb 100644 (file)
@@ -415,6 +415,9 @@ mount as home directory of the user on login. Should be in format
 `//<host>/<service>/<directory/…>`. The directory part is optional. If missing
 the top-level directory of the CIFS share is used.
 
+`cifsExtraMountOptions` → A string with additional mount options to pass to
+`mount.cifs` when mounting the home directory CIFS share.
+
 `imagePath` → A string with an absolute file system path to the file, directory
 or block device to use for storage backing the home directory. If the `luks`
 storage is used this refers to the loopback file or block device node to store
@@ -707,15 +710,16 @@ that may be used in this section are identical to the equally named ones in the
 `notAfterUSec`, `storage`, `diskSize`, `diskSizeRelative`, `skeletonDirectory`,
 `accessMode`, `tasksMax`, `memoryHigh`, `memoryMax`, `cpuWeight`, `ioWeight`,
 `mountNoDevices`, `mountNoSuid`, `mountNoExecute`, `cifsDomain`,
-`cifsUserName`, `cifsService`, `imagePath`, `uid`, `gid`, `memberOf`,
-`fileSystemType`, `partitionUuid`, `luksUuid`, `fileSystemUuid`, `luksDiscard`,
-`luksOfflineDiscard`, `luksCipher`, `luksCipherMode`, `luksVolumeKeySize`,
-`luksPbkdfHashAlgorithm`, `luksPbkdfType`, `luksPbkdfTimeCostUSec`,
-`luksPbkdfMemoryCost`, `luksPbkdfParallelThreads`, `rateLimitIntervalUSec`,
-`rateLimitBurst`, `enforcePasswordPolicy`, `autoLogin`, `stopDelayUSec`,
-`killProcesses`, `passwordChangeMinUSec`, `passwordChangeMaxUSec`,
-`passwordChangeWarnUSec`, `passwordChangeInactiveUSec`, `passwordChangeNow`,
-`pkcs11TokenUri`, `fido2HmacCredential`.
+`cifsUserName`, `cifsService`, `cifsExtraMountOptions`, `imagePath`, `uid`,
+`gid`, `memberOf`, `fileSystemType`, `partitionUuid`, `luksUuid`,
+`fileSystemUuid`, `luksDiscard`, `luksOfflineDiscard`, `luksCipher`,
+`luksCipherMode`, `luksVolumeKeySize`, `luksPbkdfHashAlgorithm`,
+`luksPbkdfType`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`,
+`luksPbkdfParallelThreads`, `rateLimitIntervalUSec`, `rateLimitBurst`,
+`enforcePasswordPolicy`, `autoLogin`, `stopDelayUSec`, `killProcesses`,
+`passwordChangeMinUSec`, `passwordChangeMaxUSec`, `passwordChangeWarnUSec`,
+`passwordChangeInactiveUSec`, `passwordChangeNow`, `pkcs11TokenUri`,
+`fido2HmacCredential`.
 
 ## Fields in the `binding` section
 
index f670566593df4e5b881db82ae8ec54293e92a802..01e9c3b29b99bd4315447a4412b2008755922655 100644 (file)
         <term><option>--cifs-domain=</option><replaceable>DOMAIN</replaceable></term>
         <term><option>--cifs-user-name=</option><replaceable>USER</replaceable></term>
         <term><option>--cifs-service=</option><replaceable>SERVICE</replaceable></term>
+        <term><option>--cifs-extra-mount-options=</option><replaceable>OPTIONS</replaceable></term>
 
         <listitem><para>Configures the Windows File Sharing (CIFS) domain and user to associate with the home
         directory/user account, as well as the file share ("service") to mount as directory. The latter is
         used when <literal>cifs</literal> storage is selected. The file share should be specified in format
         <literal>//<replaceable>host</replaceable>/<replaceable>share</replaceable>/<replaceable>directory/…</replaceable></literal>. The
         directory part is optional — if not specified the home directory will be placed in the top-level
-        directory of the share.</para></listitem>
+        directory of the share. The <option>--cifs-extra-mount-options=</option> setting allows specifying
+        additional mount options when mounting the share, see <citerefentry
+        project='man-pages'><refentrytitle>mount.cifs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        for details.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 502329eedd90cb3a7bbb06a7a21a0b382c6d91c4..4f1aebfe307cbd77db47767a73c421987ff194bd 100644 (file)
@@ -2161,6 +2161,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --cifs-domain=DOMAIN      CIFS (Windows) domain\n"
                "     --cifs-user-name=USER     CIFS (Windows) user name\n"
                "     --cifs-service=SERVICE    CIFS (Windows) service to mount as home area\n"
+               "     --cifs-extra-mount-options=OPTIONS\n"
+               "                               CIFS (Windows) extra mount options\n"
                "\n%4$sLogin Behaviour User Record Properties:%5$s\n"
                "     --stop-delay=SECS         How long to leave user services running after\n"
                "                               logout\n"
@@ -2217,6 +2219,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_CIFS_DOMAIN,
                 ARG_CIFS_USER_NAME,
                 ARG_CIFS_SERVICE,
+                ARG_CIFS_EXTRA_MOUNT_OPTIONS,
                 ARG_TASKS_MAX,
                 ARG_MEMORY_HIGH,
                 ARG_MEMORY_MAX,
@@ -2309,6 +2312,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "cifs-user-name",              required_argument, NULL, ARG_CIFS_USER_NAME              },
                 { "cifs-domain",                 required_argument, NULL, ARG_CIFS_DOMAIN                 },
                 { "cifs-service",                required_argument, NULL, ARG_CIFS_SERVICE                },
+                { "cifs-extra-mount-options",    required_argument, NULL, ARG_CIFS_EXTRA_MOUNT_OPTIONS    },
                 { "rate-limit-interval",         required_argument, NULL, ARG_RATE_LIMIT_INTERVAL         },
                 { "rate-limit-burst",            required_argument, NULL, ARG_RATE_LIMIT_BURST            },
                 { "stop-delay",                  required_argument, NULL, ARG_STOP_DELAY                  },
@@ -2447,15 +2451,17 @@ static int parse_argv(int argc, char *argv[]) {
                 case ARG_LOCATION:
                 case ARG_ICON_NAME:
                 case ARG_CIFS_USER_NAME:
-                case ARG_CIFS_DOMAIN: {
+                case ARG_CIFS_DOMAIN:
+                case ARG_CIFS_EXTRA_MOUNT_OPTIONS: {
 
                         const char *field =
-                                c == ARG_EMAIL_ADDRESS ? "emailAddress" :
-                                     c == ARG_LOCATION ? "location" :
-                                    c == ARG_ICON_NAME ? "iconName" :
-                               c == ARG_CIFS_USER_NAME ? "cifsUserName" :
-                                  c == ARG_CIFS_DOMAIN ? "cifsDomain" :
-                                                         NULL;
+                                           c == ARG_EMAIL_ADDRESS ? "emailAddress" :
+                                                c == ARG_LOCATION ? "location" :
+                                               c == ARG_ICON_NAME ? "iconName" :
+                                          c == ARG_CIFS_USER_NAME ? "cifsUserName" :
+                                             c == ARG_CIFS_DOMAIN ? "cifsDomain" :
+                                c == ARG_CIFS_EXTRA_MOUNT_OPTIONS ? "cifsExtraMountOptions" :
+                                                                    NULL;
 
                         assert(field);
 
index 6184d7c30e1e8be79e8a7411be406497c0fee27d..6a4431c2299bb159d154148f1cc9d59a5ab26830 100644 (file)
@@ -83,6 +83,10 @@ int home_setup_cifs(
                              p, h->uid, user_record_gid(h), user_record_access_mode(h), user_record_access_mode(h)) < 0)
                         return log_oom();
 
+                if (h->cifs_extra_mount_options)
+                        if (!strextend_with_separator(&options, ",", h->cifs_extra_mount_options))
+                                return log_oom();
+
                 r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid);
                 if (r < 0)
                         return r;
index 9b2029bfcfb0d214f5afbac9f7201cc3385717f1..49febade2a3dcfacf8d9d8aba54987bc053f465e 100644 (file)
@@ -271,6 +271,7 @@ static UserRecord* user_record_free(UserRecord *h) {
         free(h->cifs_service);
         free(h->cifs_user_name);
         free(h->cifs_domain);
+        free(h->cifs_extra_mount_options);
 
         free(h->image_path);
         free(h->image_path_auto);
@@ -1267,6 +1268,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
                 { "cifsDomain",                 JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_domain),                   JSON_SAFE },
                 { "cifsUserName",               JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_user_name),                JSON_SAFE },
                 { "cifsService",                JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_service),                  JSON_SAFE },
+                { "cifsExtraMountOptions",      JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_extra_mount_options),      0         },
                 { "imagePath",                  JSON_VARIANT_STRING,        json_dispatch_path,                   offsetof(UserRecord, image_path),                    0         },
                 { "uid",                        JSON_VARIANT_UNSIGNED,      json_dispatch_uid_gid,                offsetof(UserRecord, uid),                           0         },
                 { "gid",                        JSON_VARIANT_UNSIGNED,      json_dispatch_uid_gid,                offsetof(UserRecord, gid),                           0         },
@@ -1612,6 +1614,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
                 { "cifsDomain",                 JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_domain),                   JSON_SAFE },
                 { "cifsUserName",               JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_user_name),                JSON_SAFE },
                 { "cifsService",                JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_service),                  JSON_SAFE },
+                { "cifsExtraMountOptions",      JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, cifs_extra_mount_options),      0         },
                 { "imagePath",                  JSON_VARIANT_STRING,        json_dispatch_path,                   offsetof(UserRecord, image_path),                    0         },
                 { "homeDirectory",              JSON_VARIANT_STRING,        json_dispatch_home_directory,         offsetof(UserRecord, home_directory),                0         },
                 { "uid",                        JSON_VARIANT_UNSIGNED,      json_dispatch_uid_gid,                offsetof(UserRecord, uid),                           0         },
index 975e3e175bcb75a42162c25bf515fa751ac898e1..acf2cdc9d4d1bbaf225b32c7e8358163014f1e6b 100644 (file)
@@ -304,6 +304,7 @@ typedef struct UserRecord {
         char *cifs_domain;
         char *cifs_user_name;
         char *cifs_service;
+        char *cifs_extra_mount_options;
 
         char *image_path;
         char *image_path_auto; /* when none is configured explicitly, this is where we place the implicit image */