s3: smbd: Make extract_snapshot_token() a wrapper for extract_snapshot_token_internal().
[Samba.git] / source3 / utils / net_vfs.c
blob90822bf368c2983556054f39fd03f15df535fb9a
1 /*
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/>.
20 #include "includes.h"
21 #include <talloc.h>
22 #include <tevent.h>
23 #include <ftw.h>
24 #include "system/filesys.h"
25 #include "system/passwd.h"
26 #include "lib/param/loadparm.h"
27 #include "lib/param/param.h"
28 #include "libcli/security/security.h"
29 #include "smbd/proto.h"
30 #include "locking/share_mode_lock.h"
31 #include "locking/proto.h"
32 #include "auth.h"
33 #include "client.h"
34 #include "util_sd.h"
35 #include "lib/adouble.h"
36 #include "lib/string_replace.h"
37 #include "utils/net.h"
38 #include "lib/global_contexts.h"
40 #define NET_VFS_CMD_STREAM_TO_ADOUBLE "stream2adouble"
42 static struct net_vfs_state {
43 TALLOC_CTX *mem_ctx;
44 struct net_context *c;
45 struct auth_session_info *session_info;
46 struct conn_struct_tos *conn_tos;
47 } state;
49 static void net_vfs_usage(void)
51 fprintf(stderr,
52 "Usage:\n"
53 "net vfs [OPTIONS] <share> ....\n");
56 static void net_vfs_getntacl_usage(void)
58 fprintf(stderr,
59 "Usage:\n"
60 "net vfs getntacl <share> <path>\n");
63 static void net_vfs_stream_to_appledouble_usage(void)
65 fprintf(stderr,
66 "Usage:\n"
67 "net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE
68 " [OPTIONS] <share> <path> [<path> ...]\n"
69 "Options:\n"
70 " --verbose verbose output\n"
71 " --continue continue on error\n"
72 " --recursive traverse directory hierarchy\n"
73 " --follow-symlinks follow symlinks\n");
76 static bool net_vfs_make_session_info(struct auth_session_info **session_info)
78 NTSTATUS status;
80 if (non_root_mode()) {
81 struct passwd *p = NULL;
83 p = getpwuid(geteuid());
84 if (p == NULL) {
85 fprintf(stderr, "getpwuid(%d) failed\n", geteuid());
86 return false;
89 status = make_session_info_from_username(state.mem_ctx,
90 p->pw_name,
91 false,
92 session_info);
93 if (!NT_STATUS_IS_OK(status)) {
94 fprintf(stderr, "session_info from username failed\n");
95 return false;
98 return true;
101 status = init_system_session_info(state.mem_ctx);
102 if (!NT_STATUS_IS_OK(status)) {
103 fprintf(stderr, "init_system_session_info failed\n");
104 return false;
107 status = make_session_info_system(state.mem_ctx, session_info);
108 if (!NT_STATUS_IS_OK(status)) {
109 fprintf(stderr, "make_session_info_system failed\n");
110 return false;
113 return true;
116 static int net_vfs_init(struct net_context *c, int argc, const char **argv)
118 const struct loadparm_substitution *lp_sub =
119 loadparm_s3_global_substitution();
120 const char *service = NULL;
121 char *share_root = NULL;
122 int snum;
123 NTSTATUS status;
124 bool ok;
125 int rc = 1;
127 state = (struct net_vfs_state) {
128 .c = c,
129 .mem_ctx = c,
132 if (argc < 1) {
133 net_vfs_usage();
134 goto done;
137 if (geteuid() != 0 && !uid_wrapper_enabled()) {
138 fprintf(stderr, "'net vfs' must be run as root.\n");
139 goto done;
142 smb_init_locale();
143 umask(0);
144 sec_init();
145 setup_logging("net", DEBUG_STDOUT);
146 lp_set_cmdline("log level", "0");
148 ok = lp_load_with_registry_shares(get_dyn_CONFIGFILE());
149 if (!ok) {
150 fprintf(stderr, "lp_load_with_registry_shares failed\n");
151 goto done;
154 ok = locking_init();
155 if (!ok) {
156 fprintf(stderr, "locking init failed\n");
157 goto done;
160 ok = net_vfs_make_session_info(&state.session_info);
161 if (!ok) {
162 goto done;
165 service = argv[0];
166 snum = lp_servicenumber(service);
167 if (snum == -1) {
168 fprintf(stderr, "unknown service: %s\n", service);
169 goto done;
172 share_root = lp_path(state.mem_ctx, lp_sub, snum);
173 if (share_root == NULL) {
174 fprintf(stderr, "Failed to find share root for service: %s\n",
175 service);
176 goto done;
179 status = create_conn_struct_tos_cwd(global_messaging_context(),
180 snum,
181 share_root,
182 state.session_info,
183 &state.conn_tos);
184 if (!NT_STATUS_IS_OK(status)) {
185 goto done;
188 state.conn_tos->conn->share_access = FILE_GENERIC_ALL;
189 state.conn_tos->conn->read_only = false;
190 file_init(state.conn_tos->conn->sconn);
192 ok = become_user_without_service_by_session(state.conn_tos->conn,
193 state.session_info);
194 if (!ok) {
195 fprintf(stderr,
196 "become_user_without_service_by_session failed\n");
197 goto done;
200 rc = 0;
201 done:
202 return rc;
205 static int net_vfs_get_ntacl(struct net_context *net,
206 int argc,
207 const char **argv)
209 const char *path = NULL;
210 struct smb_filename *smb_fname = NULL;
211 files_struct *fsp = NULL;
212 struct security_descriptor *sd = NULL;
213 NTSTATUS status;
214 int ret;
215 int rc = 1;
217 if (argc < 2 || net->display_usage) {
218 net_vfs_getntacl_usage();
219 goto done;
222 ret = net_vfs_init(net, argc, argv);
223 if (ret != 0) {
224 goto done;
227 path = argv[1];
228 smb_fname = synthetic_smb_fname(state.mem_ctx,
229 path,
230 NULL,
231 NULL,
234 if (smb_fname == NULL) {
235 goto done;
238 ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
239 if (ret != 0) {
240 fprintf(stderr, "stat [%s] failed: %s\n",
241 smb_fname_str_dbg(smb_fname), strerror(errno));
242 goto done;
245 status = openat_pathref_fsp(state.conn_tos->conn->cwd_fsp, smb_fname);
246 if (!NT_STATUS_IS_OK(status)) {
247 DBG_ERR("openat_pathref_fsp [%s] failed: %s\n",
248 smb_fname_str_dbg(smb_fname), nt_errstr(status));
249 goto done;
252 status = SMB_VFS_CREATE_FILE(
253 state.conn_tos->conn,
254 NULL, /* req */
255 NULL,
256 smb_fname,
257 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
258 FILE_SHARE_READ|FILE_SHARE_WRITE,
259 FILE_OPEN,
260 0, /* create_options */
261 0, /* file_attributes */
262 INTERNAL_OPEN_ONLY, /* oplock_request */
263 NULL, /* lease */
264 0, /* allocation_size */
265 0, /* private_flags */
266 NULL, /* sd */
267 NULL, /* ea_list */
268 &fsp,
269 NULL, /* info */
270 NULL, NULL); /* create context */
271 if (!NT_STATUS_IS_OK(status)) {
272 DBG_ERR("SMB_VFS_CREATE_FILE [%s] failed: %s\n",
273 smb_fname_str_dbg(smb_fname), nt_errstr(status));
274 goto done;
277 status = SMB_VFS_FGET_NT_ACL(fsp,
278 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL,
279 fsp,
280 &sd);
281 if (!NT_STATUS_IS_OK(status)) {
282 DBG_ERR("SMB_VFS_FGET_NT_ACL [%s] failed: %s\n",
283 smb_fname_str_dbg(smb_fname), nt_errstr(status));
284 goto done;
287 status = close_file_free(NULL, &fsp, NORMAL_CLOSE);
288 if (!NT_STATUS_IS_OK(status)) {
289 DBG_ERR("close_file [%s] failed: %s\n",
290 smb_fname_str_dbg(smb_fname),
291 nt_errstr(status));
292 goto done;
295 sec_desc_print(NULL, stdout, sd, true);
297 rc = 0;
298 done:
299 if (fsp != NULL) {
300 status = close_file_free(NULL, &fsp, NORMAL_CLOSE);
301 if (!NT_STATUS_IS_OK(status)) {
302 DBG_ERR("close_file_free() [%s] failed: %s\n",
303 smb_fname_str_dbg(smb_fname),
304 nt_errstr(status));
305 rc = 1;
308 return rc;
311 static bool do_unfruit(const char *path)
313 struct smb_filename *smb_fname = NULL;
314 char *p = NULL;
315 bool converted;
316 int ret;
317 bool ok;
319 p = strrchr_m(path, '/');
320 if (p != NULL) {
321 if (p[1] == '.' && p[2] == '_') {
322 return true;
326 smb_fname = synthetic_smb_fname(state.mem_ctx,
327 path,
328 NULL,
329 NULL,
332 if (smb_fname == NULL) {
333 return false;
336 ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
337 if (ret != 0) {
338 fprintf(stderr, "%s: %s\n", path, strerror(errno));
339 if (state.c->opt_continue_on_error) {
340 return true;
342 return false;
345 ok = ad_unconvert(state.mem_ctx,
346 state.conn_tos->conn->vfs_handles,
347 macos_string_replace_map,
348 smb_fname,
349 &converted);
350 if (!ok) {
351 fprintf(stderr, "Converting failed: %s\n", path);
352 if (state.c->opt_continue_on_error) {
353 return true;
355 return false;
358 if (converted) {
359 fprintf(stdout, "Converted: %s\n", path);
360 } else if (state.c->opt_verbose) {
361 fprintf(stdout, "%s\n", path);
363 return true;
366 static int nftw_cb(const char *path,
367 const struct stat *sb,
368 int typeflag,
369 struct FTW *ftwbuf)
371 bool ok;
373 if (typeflag == FTW_SL) {
374 if (state.c->opt_verbose) {
375 fprintf(stdout, "Ignoring symlink: %s\n", path);
377 return 0;
380 ok = do_unfruit(path);
381 if (!ok) {
382 return -1;
385 return 0;
388 static int net_vfs_stream_to_appledouble(struct net_context *net,
389 int argc,
390 const char **argv)
392 int i;
393 int ret;
394 bool ok;
395 int rc = 1;
397 if (argc < 2 || net->display_usage) {
398 net_vfs_stream_to_appledouble_usage();
399 goto done;
402 ret = net_vfs_init(net, argc, argv);
403 if (ret != 0) {
404 goto done;
407 for (i = 1; i < argc; i++) {
408 const char *path = argv[i];
410 if (path[0] == '/') {
411 fprintf(stderr, "ignoring absolute path: %s\n", path);
412 if (state.c->opt_continue_on_error) {
413 continue;
415 goto done;
418 if (!state.c->opt_recursive) {
419 ok = do_unfruit(path);
420 if (!ok) {
421 if (!state.c->opt_continue_on_error) {
422 goto done;
425 continue;
428 ret = nftw(path,
429 nftw_cb,
430 256,
431 state.c->opt_follow_symlink ? 0 : FTW_PHYS);
432 if (ret != 0) {
433 fprintf(stderr, "%s: %s\n", path, strerror(errno));
434 if (!state.c->opt_continue_on_error) {
435 goto done;
440 rc = 0;
442 done:
443 return rc;
446 static struct functable func[] = {
448 "getntacl",
449 net_vfs_get_ntacl,
450 NET_TRANSPORT_LOCAL,
451 N_("Display security descriptor of a file or directory"),
452 N_("net vfs getntacl <share> <path> [<path> ...]")
455 NET_VFS_CMD_STREAM_TO_ADOUBLE,
456 net_vfs_stream_to_appledouble,
457 NET_TRANSPORT_LOCAL,
458 N_("Convert streams to AppleDouble files"),
459 N_("net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE " [OPTIONS] <share> <path> [<path> ...]")
461 {NULL, NULL, 0, NULL, NULL}
464 int net_vfs(struct net_context *c, int argc, const char **argv)
466 return net_run_function(c, argc, argv, "net vfs", func);