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"
12 #include "stat-util.h"
14 #include "tmpfile-util.h"
23 assert(user_record_storage(h
) == USER_CIFS
);
25 if (FLAGS_SET(flags
, HOME_SETUP_ALREADY_ACTIVATED
))
26 setup
->root_fd
= open(user_record_home_directory(h
), O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
32 r
= home_unshare_and_mkdir();
36 STRV_FOREACH(pw
, h
->password
) {
37 _cleanup_(unlink_and_freep
) char *p
= NULL
;
38 _cleanup_free_
char *options
= NULL
;
39 _cleanup_(fclosep
) FILE *f
= NULL
;
43 r
= fopen_temporary(NULL
, &f
, &p
);
45 return log_error_errno(r
, "Failed to create temporary credentials file: %m");
50 user_record_cifs_user_name(h
),
54 fprintf(f
, "domain=%s\n", h
->cifs_domain
);
56 r
= fflush_and_check(f
);
58 return log_error_errno(r
, "Failed to write temporary credentials file: %m");
62 if (asprintf(&options
, "credentials=%s,uid=" UID_FMT
",forceuid,gid=" GID_FMT
",forcegid,file_mode=0%3o,dir_mode=0%3o",
63 p
, h
->uid
, user_record_gid(h
), user_record_access_mode(h
), user_record_access_mode(h
)) < 0)
66 r
= safe_fork("(mount)", FORK_RESET_SIGNALS
|FORK_RLIMIT_NOFILE_SAFE
|FORK_DEATHSIG
|FORK_LOG
|FORK_STDOUT_TO_STDERR
, &mount_pid
);
71 execl("/bin/mount", "/bin/mount", "-n", "-t", "cifs",
72 h
->cifs_service
, HOME_RUNTIME_WORK_DIR
,
75 log_error_errno(errno
, "Failed to execute mount: %m");
79 exit_status
= wait_for_terminate_and_check("mount", mount_pid
, WAIT_LOG_ABNORMAL
|WAIT_LOG_NON_ZERO_EXIT_STATUS
);
82 if (exit_status
!= EXIT_SUCCESS
)
90 return log_error_errno(SYNTHETIC_ERRNO(ENOKEY
),
91 "Failed to mount home directory with supplied password.");
93 setup
->root_fd
= open(HOME_RUNTIME_WORK_DIR
, O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
95 if (setup
->root_fd
< 0)
96 return log_error_errno(errno
, "Failed to open home directory: %m");
101 int home_activate_cifs(
104 PasswordCache
*cache
,
105 UserRecord
**ret_home
) {
107 _cleanup_(user_record_unrefp
) UserRecord
*new_home
= NULL
;
108 const char *hdo
, *hd
;
112 assert(user_record_storage(h
) == USER_CIFS
);
116 if (!h
->cifs_service
)
117 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "User record lacks CIFS service, refusing.");
119 assert_se(hdo
= user_record_home_directory(h
));
120 hd
= strdupa_safe(hdo
); /* copy the string out, since it might change later in the home record object */
122 r
= home_setup_cifs(h
, 0, setup
);
126 r
= home_refresh(h
, setup
, NULL
, cache
, NULL
, &new_home
);
130 setup
->root_fd
= safe_close(setup
->root_fd
);
132 r
= home_move_mount(NULL
, hd
);
136 setup
->undo_mount
= false;
137 setup
->do_drop_caches
= false;
139 log_info("Everything completed.");
141 *ret_home
= TAKE_PTR(new_home
);
145 int home_create_cifs(UserRecord
*h
, HomeSetup
*setup
, UserRecord
**ret_home
) {
146 _cleanup_(user_record_unrefp
) UserRecord
*new_home
= NULL
;
150 assert(user_record_storage(h
) == USER_CIFS
);
154 if (!h
->cifs_service
)
155 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "User record lacks CIFS service, refusing.");
157 if (access("/sbin/mount.cifs", F_OK
) < 0) {
159 return log_error_errno(SYNTHETIC_ERRNO(ENOLINK
), "/sbin/mount.cifs is missing.");
161 return log_error_errno(errno
, "Unable to detect whether /sbin/mount.cifs exists: %m");
164 r
= home_setup_cifs(h
, 0, setup
);
168 r
= dir_is_empty_at(setup
->root_fd
, NULL
);
170 return log_error_errno(r
, "Failed to detect if CIFS directory is empty: %m");
172 return log_error_errno(SYNTHETIC_ERRNO(ENOTEMPTY
), "Selected CIFS directory not empty, refusing.");
174 r
= home_populate(h
, setup
->root_fd
);
178 r
= home_sync_and_statfs(setup
->root_fd
, NULL
);
182 r
= user_record_clone(h
, USER_RECORD_LOAD_MASK_SECRET
|USER_RECORD_PERMISSIVE
, &new_home
);
184 return log_error_errno(r
, "Failed to clone record: %m");
186 r
= user_record_add_binding(
201 return log_error_errno(r
, "Failed to add binding to record: %m");
203 log_info("Everything completed.");
205 *ret_home
= TAKE_PTR(new_home
);