1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "dirent-util.h"
6 #include "format-util.h"
8 #include "homework-cifs.h"
9 #include "homework-mount.h"
10 #include "mount-util.h"
11 #include "process-util.h"
13 #include "tmpfile-util.h"
15 int home_prepare_cifs(
17 bool already_activated
,
22 assert(user_record_storage(h
) == USER_CIFS
);
24 if (already_activated
)
25 setup
->root_fd
= open(user_record_home_directory(h
), O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
31 r
= home_unshare_and_mount(NULL
, NULL
, false, user_record_mount_flags(h
));
35 STRV_FOREACH(pw
, h
->password
) {
36 _cleanup_(unlink_and_freep
) char *p
= NULL
;
37 _cleanup_free_
char *options
= NULL
;
38 _cleanup_(fclosep
) FILE *f
= NULL
;
42 r
= fopen_temporary(NULL
, &f
, &p
);
44 return log_error_errno(r
, "Failed to create temporary credentials file: %m");
49 user_record_cifs_user_name(h
),
53 fprintf(f
, "domain=%s\n", h
->cifs_domain
);
55 r
= fflush_and_check(f
);
57 return log_error_errno(r
, "Failed to write temporary credentials file: %m");
61 if (asprintf(&options
, "credentials=%s,uid=" UID_FMT
",forceuid,gid=" UID_FMT
",forcegid,file_mode=0%3o,dir_mode=0%3o",
62 p
, h
->uid
, h
->uid
, h
->access_mode
, h
->access_mode
) < 0)
65 r
= safe_fork("(mount)", FORK_RESET_SIGNALS
|FORK_RLIMIT_NOFILE_SAFE
|FORK_DEATHSIG
|FORK_LOG
|FORK_STDOUT_TO_STDERR
, &mount_pid
);
70 execl("/bin/mount", "/bin/mount", "-n", "-t", "cifs",
71 h
->cifs_service
, "/run/systemd/user-home-mount",
74 log_error_errno(errno
, "Failed to execute fsck: %m");
78 exit_status
= wait_for_terminate_and_check("mount", mount_pid
, WAIT_LOG_ABNORMAL
|WAIT_LOG_NON_ZERO_EXIT_STATUS
);
81 if (exit_status
!= EXIT_SUCCESS
)
89 return log_error_errno(ENOKEY
, "Failed to mount home directory with supplied password.");
91 setup
->root_fd
= open("/run/systemd/user-home-mount", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
93 if (setup
->root_fd
< 0)
94 return log_error_errno(errno
, "Failed to open home directory: %m");
99 int home_activate_cifs(
101 PasswordCache
*cache
,
102 UserRecord
**ret_home
) {
104 _cleanup_(home_setup_undo
) HomeSetup setup
= HOME_SETUP_INIT
;
105 _cleanup_(user_record_unrefp
) UserRecord
*new_home
= NULL
;
106 const char *hdo
, *hd
;
110 assert(user_record_storage(h
) == USER_CIFS
);
113 if (!h
->cifs_service
)
114 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "User record lacks CIFS service, refusing.");
116 assert_se(hdo
= user_record_home_directory(h
));
117 hd
= strdupa(hdo
); /* copy the string out, since it might change later in the home record object */
119 r
= home_prepare_cifs(h
, false, &setup
);
123 r
= home_refresh(h
, &setup
, NULL
, cache
, NULL
, &new_home
);
127 setup
.root_fd
= safe_close(setup
.root_fd
);
129 r
= home_move_mount(NULL
, hd
);
133 setup
.undo_mount
= false;
135 log_info("Everything completed.");
137 *ret_home
= TAKE_PTR(new_home
);
141 int home_create_cifs(UserRecord
*h
, UserRecord
**ret_home
) {
142 _cleanup_(home_setup_undo
) HomeSetup setup
= HOME_SETUP_INIT
;
143 _cleanup_(user_record_unrefp
) UserRecord
*new_home
= NULL
;
144 _cleanup_(closedirp
) DIR *d
= NULL
;
145 _cleanup_close_
int copy
= -1;
149 assert(user_record_storage(h
) == USER_CIFS
);
152 if (!h
->cifs_service
)
153 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "User record lacks CIFS service, refusing.");
155 if (access("/sbin/mount.cifs", F_OK
) < 0) {
157 return log_error_errno(SYNTHETIC_ERRNO(ENOLINK
), "/sbin/mount.cifs is missing.");
159 return log_error_errno(errno
, "Unable to detect whether /sbin/mount.cifs exists: %m");
162 r
= home_prepare_cifs(h
, false, &setup
);
166 copy
= fcntl(setup
.root_fd
, F_DUPFD_CLOEXEC
, 3);
170 d
= take_fdopendir(©
);
175 if (readdir_no_dot(d
))
176 return log_error_errno(SYNTHETIC_ERRNO(ENOTEMPTY
), "Selected CIFS directory not empty, refusing.");
178 return log_error_errno(errno
, "Failed to detect if CIFS directory is empty: %m");
180 r
= home_populate(h
, setup
.root_fd
);
184 r
= home_sync_and_statfs(setup
.root_fd
, NULL
);
188 r
= user_record_clone(h
, USER_RECORD_LOAD_MASK_SECRET
, &new_home
);
190 return log_error_errno(r
, "Failed to clone record: %m");
192 r
= user_record_add_binding(
207 return log_error_errno(r
, "Failed to add binding to record: %m");
209 log_info("Everything completed.");
211 *ret_home
= TAKE_PTR(new_home
);