2 * Samba Unix/Linux SMB client library
3 * Distributed SMB/CIFS Server Management Utility
4 * Copyright (C) 2019 Ralph Boehme <slow@samba.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/filesys.h"
25 #include "system/passwd.h"
26 #include "popt_common.h"
27 #include "lib/param/loadparm.h"
28 #include "lib/param/param.h"
29 #include "libcli/security/security.h"
30 #include "smbd/proto.h"
31 #include "locking/proto.h"
35 #include "lib/adouble.h"
36 #include "lib/string_replace.h"
37 #include "utils/net.h"
39 #define NET_VFS_CMD_STREAM_TO_ADOUBLE "stream2adouble"
41 static struct net_vfs_state {
43 struct net_context *c;
44 struct auth_session_info *session_info;
45 struct conn_struct_tos *conn_tos;
48 static void net_vfs_usage(void)
52 "net vfs [OPTIONS] <share> ....\n");
55 static void net_vfs_getntacl_usage(void)
59 "net vfs getntacl <share> <path>\n");
62 static void net_vfs_stream_to_appledouble_usage(void)
66 "net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE
67 " [OPTIONS] <share> <path> [<path> ...]\n"
69 " --verbose verbose output\n"
70 " --continue continue on error\n"
71 " --recursive traverse directory hierarchy\n"
72 " --follow-symlinks follow symlinks\n");
75 static bool net_vfs_make_session_info(struct auth_session_info **session_info)
79 if (non_root_mode()) {
80 struct passwd *p = NULL;
82 p = getpwuid(geteuid());
84 fprintf(stderr, "getpwuid(%d) failed\n", geteuid());
88 status = make_session_info_from_username(state.mem_ctx,
92 if (!NT_STATUS_IS_OK(status)) {
93 fprintf(stderr, "session_info from username failed\n");
100 status = init_system_session_info(state.mem_ctx);
101 if (!NT_STATUS_IS_OK(status)) {
102 fprintf(stderr, "init_system_session_info failed\n");
106 status = make_session_info_system(state.mem_ctx, session_info);
107 if (!NT_STATUS_IS_OK(status)) {
108 fprintf(stderr, "make_session_info_system failed\n");
115 static int net_vfs_init(struct net_context *c, int argc, const char **argv)
117 const struct loadparm_substitution *lp_sub =
118 loadparm_s3_global_substitution();
119 const char *service = NULL;
120 char *share_root = NULL;
126 state = (struct net_vfs_state) {
136 if (geteuid() != 0 && !uid_wrapper_enabled()) {
137 fprintf(stderr, "'net vfs' must be run as root.\n");
144 setup_logging("net", DEBUG_STDOUT);
145 lp_set_cmdline("log level", "0");
147 ok = lp_load_with_registry_shares(get_dyn_CONFIGFILE());
149 fprintf(stderr, "lp_load_with_registry_shares failed\n");
155 fprintf(stderr, "locking init failed\n");
159 ok = net_vfs_make_session_info(&state.session_info);
165 snum = lp_servicenumber(service);
167 fprintf(stderr, "unknown service: %s\n", service);
171 share_root = lp_path(state.mem_ctx, lp_sub, snum);
172 if (share_root == NULL) {
173 fprintf(stderr, "Failed to find share root for service: %s\n",
178 status = create_conn_struct_tos_cwd(global_messaging_context(),
183 if (!NT_STATUS_IS_OK(status)) {
187 state.conn_tos->conn->share_access = FILE_GENERIC_ALL;
188 state.conn_tos->conn->read_only = false;
189 file_init(state.conn_tos->conn->sconn);
191 ok = become_user_without_service_by_session(state.conn_tos->conn,
195 "become_user_without_service_by_session failed\n");
204 static int net_vfs_get_ntacl(struct net_context *net,
208 const char *path = NULL;
209 struct smb_filename *smb_fname = NULL;
210 files_struct *fsp = NULL;
211 struct security_descriptor *sd = NULL;
216 if (argc < 2 || net->display_usage) {
217 net_vfs_getntacl_usage();
221 ret = net_vfs_init(net, argc, argv);
227 smb_fname = synthetic_smb_fname(state.mem_ctx,
233 if (smb_fname == NULL) {
237 ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
239 fprintf(stderr, "stat [%s] failed: %s\n",
240 smb_fname_str_dbg(smb_fname), strerror(errno));
244 status = SMB_VFS_CREATE_FILE(
245 state.conn_tos->conn,
248 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
249 FILE_SHARE_READ|FILE_SHARE_WRITE,
251 0, /* create_options */
252 0, /* file_attributes */
253 INTERNAL_OPEN_ONLY, /* oplock_request */
255 0, /* allocation_size */
256 0, /* private_flags */
261 NULL, NULL); /* create context */
262 if (!NT_STATUS_IS_OK(status)) {
263 DBG_ERR("SMB_VFS_CREATE_FILE [%s] failed: %s\n",
264 smb_fname_str_dbg(smb_fname), nt_errstr(status));
268 status = SMB_VFS_FGET_NT_ACL(fsp,
269 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL,
272 if (!NT_STATUS_IS_OK(status)) {
273 DBG_ERR("SMB_VFS_FGET_NT_ACL [%s] failed: %s\n",
274 smb_fname_str_dbg(smb_fname), nt_errstr(status));
278 status = close_file(NULL, fsp, NORMAL_CLOSE);
279 if (!NT_STATUS_IS_OK(status)) {
280 DBG_ERR("close_file [%s] failed: %s\n",
281 smb_fname_str_dbg(smb_fname),
287 sec_desc_print(NULL, stdout, sd, true);
292 status = close_file(NULL, fsp, NORMAL_CLOSE);
293 if (!NT_STATUS_IS_OK(status)) {
294 DBG_ERR("close_file [%s] failed: %s\n",
295 smb_fname_str_dbg(smb_fname),
303 static bool do_unfruit(const char *path)
305 struct smb_filename *smb_fname = NULL;
311 p = strrchr_m(path, '/');
313 if (p[1] == '.' && p[2] == '_') {
318 smb_fname = synthetic_smb_fname(state.mem_ctx,
324 if (smb_fname == NULL) {
328 ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
330 fprintf(stderr, "%s: %s\n", path, strerror(errno));
331 if (state.c->opt_continue_on_error) {
337 ok = ad_unconvert(state.mem_ctx,
338 state.conn_tos->conn->vfs_handles,
339 macos_string_replace_map,
343 fprintf(stderr, "Converting failed: %s\n", path);
344 if (state.c->opt_continue_on_error) {
351 fprintf(stdout, "Converted: %s\n", path);
352 } else if (state.c->opt_verbose) {
353 fprintf(stdout, "%s\n", path);
358 static int nftw_cb(const char *path,
359 const struct stat *sb,
365 if (typeflag == FTW_SL) {
366 if (state.c->opt_verbose) {
367 fprintf(stdout, "Ignoring symlink: %s\n", path);
372 ok = do_unfruit(path);
380 static int net_vfs_stream_to_appledouble(struct net_context *net,
389 if (argc < 2 || net->display_usage) {
390 net_vfs_stream_to_appledouble_usage();
394 ret = net_vfs_init(net, argc, argv);
399 for (i = 1; i < argc; i++) {
400 const char *path = argv[i];
402 if (path[0] == '/') {
403 fprintf(stderr, "ignoring absolute path: %s\n", path);
404 if (state.c->opt_continue_on_error) {
410 if (!state.c->opt_recursive) {
411 ok = do_unfruit(path);
413 if (!state.c->opt_continue_on_error) {
423 state.c->opt_follow_symlink ? 0 : FTW_PHYS);
425 fprintf(stderr, "%s: %s\n", path, strerror(errno));
426 if (!state.c->opt_continue_on_error) {
438 static struct functable func[] = {
443 N_("Display security descriptor of a file or directory"),
444 N_("net vfs getntacl <share> <path> [<path> ...]")
447 NET_VFS_CMD_STREAM_TO_ADOUBLE,
448 net_vfs_stream_to_appledouble,
450 N_("Convert streams to AppleDouble files"),
451 N_("net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE " [OPTIONS] <share> <path> [<path> ...]")
453 {NULL, NULL, 0, NULL, NULL}
456 int net_vfs(struct net_context *c, int argc, const char **argv)
458 return net_run_function(c, argc, argv, "net vfs", func);