diff options
-rw-r--r-- | docs/USER_RECORD.md | 4 | ||||
-rw-r--r-- | man/homectl.xml | 7 | ||||
-rw-r--r-- | src/home/homework-cifs.c | 32 | ||||
-rw-r--r-- | src/home/homework.c | 2 | ||||
-rw-r--r-- | src/home/homework.h | 5 |
5 files changed, 43 insertions, 7 deletions
diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md index 6b607dfd45..6710b00c0c 100644 --- a/docs/USER_RECORD.md +++ b/docs/USER_RECORD.md @@ -411,7 +411,9 @@ useful when `cifs` is used as storage mechanism for the user's home directory, see above. `cifsService` → A string indicating the Windows File Share service (CIFS) to -mount as home directory of the user on login. +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. `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` diff --git a/man/homectl.xml b/man/homectl.xml index c2b1ec6c9b..f670566593 100644 --- a/man/homectl.xml +++ b/man/homectl.xml @@ -690,8 +690,11 @@ <term><option>--cifs-service=</option><replaceable>SERVICE</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.</para></listitem> + 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> </varlistentry> <varlistentry> diff --git a/src/home/homework-cifs.c b/src/home/homework-cifs.c index b920053163..55b8c2588d 100644 --- a/src/home/homework-cifs.c +++ b/src/home/homework-cifs.c @@ -7,6 +7,7 @@ #include "fs-util.h" #include "homework-cifs.h" #include "homework-mount.h" +#include "mkdir.h" #include "mount-util.h" #include "process-util.h" #include "stat-util.h" @@ -18,6 +19,7 @@ int home_setup_cifs( HomeSetupFlags flags, HomeSetup *setup) { + _cleanup_free_ char *chost = NULL, *cservice = NULL, *cdir = NULL, *chost_and_service = NULL, *j = NULL; char **pw; int r; @@ -38,6 +40,15 @@ int home_setup_cifs( if (!h->cifs_service) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks CIFS service, refusing."); + r = parse_cifs_service(h->cifs_service, &chost, &cservice, &cdir); + if (r < 0) + return log_error_errno(r, "Failed parse CIFS service specification: %m"); + + /* Just the host and service part, without the directory */ + chost_and_service = strjoin("//", chost, "/", cservice); + if (!chost_and_service) + return log_oom(); + r = home_unshare_and_mkdir(); if (r < 0) return r; @@ -78,7 +89,7 @@ int home_setup_cifs( if (r == 0) { /* Child */ execl("/bin/mount", "/bin/mount", "-n", "-t", "cifs", - h->cifs_service, HOME_RUNTIME_WORK_DIR, + chost_and_service, HOME_RUNTIME_WORK_DIR, "-o", options, NULL); log_error_errno(errno, "Failed to execute mount: %m"); @@ -104,10 +115,23 @@ int home_setup_cifs( if (r < 0) return r; - setup->root_fd = open(HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + if (cdir) { + j = path_join(HOME_RUNTIME_WORK_DIR, cdir); + if (!j) + return log_oom(); + + if (FLAGS_SET(flags, HOME_SETUP_CIFS_MKDIR)) { + r = mkdir_p(j, 0700); + if (r < 0) + return log_error_errno(r, "Failed to create CIFS subdirectory: %m"); + } + } + + setup->root_fd = open(j ?: HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (setup->root_fd < 0) return log_error_errno(errno, "Failed to open home directory: %m"); + setup->mount_suffix = TAKE_PTR(cdir); return 0; } @@ -139,7 +163,7 @@ int home_activate_cifs( setup->root_fd = safe_close(setup->root_fd); - r = home_move_mount(NULL, hd); + r = home_move_mount(setup->mount_suffix, hd); if (r < 0) return r; @@ -171,7 +195,7 @@ int home_create_cifs(UserRecord *h, HomeSetup *setup, UserRecord **ret_home) { return log_error_errno(errno, "Unable to detect whether /sbin/mount.cifs exists: %m"); } - r = home_setup_cifs(h, 0, setup); + r = home_setup_cifs(h, HOME_SETUP_CIFS_MKDIR, setup); if (r < 0) return r; diff --git a/src/home/homework.c b/src/home/homework.c index cfc0c945de..8ffed82742 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -365,6 +365,8 @@ int home_setup_done(HomeSetup *setup) { if (setup->do_drop_caches) drop_caches_now(); + setup->mount_suffix = mfree(setup->mount_suffix); + return r; } diff --git a/src/home/homework.h b/src/home/homework.h index 1fa5a1e37a..08d97b8261 100644 --- a/src/home/homework.h +++ b/src/home/homework.h @@ -37,6 +37,8 @@ typedef struct HomeSetup { uint64_t partition_offset; uint64_t partition_size; + + char *mount_suffix; /* The directory to use as home dir is this path below /run/systemd/user-home-mount */ } HomeSetup; typedef struct PasswordCache { @@ -66,6 +68,9 @@ static inline bool password_cache_contains(const PasswordCache *cache, const cha /* Various flags for the operation of setting up a home directory */ typedef enum HomeSetupFlags { HOME_SETUP_ALREADY_ACTIVATED = 1 << 0, /* Open an already activated home, rather than activate it afresh */ + + /* CIFS backend: */ + HOME_SETUP_CIFS_MKDIR = 1 << 1, /* Create CIFS subdir when missing */ } HomeSetupFlags; int home_setup_done(HomeSetup *setup); |