1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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=" GID_FMT
",forcegid,file_mode=0%3o,dir_mode=0%3o",
62 p
, h
->uid
, user_record_gid(h
), user_record_access_mode(h
), user_record_access_mode(h
)) < 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 mount: %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(SYNTHETIC_ERRNO(ENOKEY
),
90 "Failed to mount home directory with supplied password.");
92 setup
->root_fd
= open("/run/systemd/user-home-mount", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
94 if (setup
->root_fd
< 0)
95 return log_error_errno(errno
, "Failed to open home directory: %m");
100 int home_activate_cifs(
102 PasswordCache
*cache
,
103 UserRecord
**ret_home
) {
105 _cleanup_(home_setup_undo
) HomeSetup setup
= HOME_SETUP_INIT
;
106 _cleanup_(user_record_unrefp
) UserRecord
*new_home
= NULL
;
107 const char *hdo
, *hd
;
111 assert(user_record_storage(h
) == USER_CIFS
);
114 if (!h
->cifs_service
)
115 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "User record lacks CIFS service, refusing.");
117 assert_se(hdo
= user_record_home_directory(h
));
118 hd
= strdupa(hdo
); /* copy the string out, since it might change later in the home record object */
120 r
= home_prepare_cifs(h
, false, &setup
);
124 r
= home_refresh(h
, &setup
, NULL
, cache
, NULL
, &new_home
);
128 setup
.root_fd
= safe_close(setup
.root_fd
);
130 r
= home_move_mount(NULL
, hd
);
134 setup
.undo_mount
= false;
136 log_info("Everything completed.");
138 *ret_home
= TAKE_PTR(new_home
);
142 int home_create_cifs(UserRecord
*h
, UserRecord
**ret_home
) {
143 _cleanup_(home_setup_undo
) HomeSetup setup
= HOME_SETUP_INIT
;
144 _cleanup_(user_record_unrefp
) UserRecord
*new_home
= NULL
;
145 _cleanup_(closedirp
) DIR *d
= NULL
;
146 _cleanup_close_
int copy
= -1;
150 assert(user_record_storage(h
) == USER_CIFS
);
153 if (!h
->cifs_service
)
154 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "User record lacks CIFS service, refusing.");
156 if (access("/sbin/mount.cifs", F_OK
) < 0) {
158 return log_error_errno(SYNTHETIC_ERRNO(ENOLINK
), "/sbin/mount.cifs is missing.");
160 return log_error_errno(errno
, "Unable to detect whether /sbin/mount.cifs exists: %m");
163 r
= home_prepare_cifs(h
, false, &setup
);
167 copy
= fcntl(setup
.root_fd
, F_DUPFD_CLOEXEC
, 3);
171 d
= take_fdopendir(©
);
176 if (readdir_no_dot(d
))
177 return log_error_errno(SYNTHETIC_ERRNO(ENOTEMPTY
), "Selected CIFS directory not empty, refusing.");
179 return log_error_errno(errno
, "Failed to detect if CIFS directory is empty: %m");
181 r
= home_populate(h
, setup
.root_fd
);
185 r
= home_sync_and_statfs(setup
.root_fd
, NULL
);
189 r
= user_record_clone(h
, USER_RECORD_LOAD_MASK_SECRET
|USER_RECORD_PERMISSIVE
, &new_home
);
191 return log_error_errno(r
, "Failed to clone record: %m");
193 r
= user_record_add_binding(
208 return log_error_errno(r
, "Failed to add binding to record: %m");
210 log_info("Everything completed.");
212 *ret_home
= TAKE_PTR(new_home
);