pylibsmb: Return reparse_tag from directory listing
[Samba.git] / source3 / utils / net_vfs.c
blob410eef3106aaeca71c420325bcf9428de4e86fa1
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 lpcfg_set_cmdline(c->lp_ctx, "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 talloc_tos(),
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 TALLOC_FREE(sd);
301 if (fsp != NULL) {
302 status = close_file_free(NULL, &fsp, NORMAL_CLOSE);
303 if (!NT_STATUS_IS_OK(status)) {
304 DBG_ERR("close_file_free() [%s] failed: %s\n",
305 smb_fname_str_dbg(smb_fname),
306 nt_errstr(status));
307 rc = 1;
310 return rc;
313 static bool do_unfruit(const char *path)
315 struct smb_filename *smb_fname = NULL;
316 char *p = NULL;
317 bool converted;
318 int ret;
319 bool ok;
321 p = strrchr_m(path, '/');
322 if (p != NULL) {
323 if (p[1] == '.' && p[2] == '_') {
324 return true;
328 smb_fname = synthetic_smb_fname(state.mem_ctx,
329 path,
330 NULL,
331 NULL,
334 if (smb_fname == NULL) {
335 return false;
338 ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
339 if (ret != 0) {
340 fprintf(stderr, "%s: %s\n", path, strerror(errno));
341 if (state.c->opt_continue_on_error) {
342 return true;
344 return false;
347 ok = ad_unconvert(state.mem_ctx,
348 state.conn_tos->conn->vfs_handles,
349 macos_string_replace_map,
350 smb_fname,
351 &converted);
352 if (!ok) {
353 fprintf(stderr, "Converting failed: %s\n", path);
354 if (state.c->opt_continue_on_error) {
355 return true;
357 return false;
360 if (converted) {
361 fprintf(stdout, "Converted: %s\n", path);
362 } else if (state.c->opt_verbose) {
363 fprintf(stdout, "%s\n", path);
365 return true;
368 static int nftw_cb(const char *path,
369 const struct stat *sb,
370 int typeflag,
371 struct FTW *ftwbuf)
373 bool ok;
375 if (typeflag == FTW_SL) {
376 if (state.c->opt_verbose) {
377 fprintf(stdout, "Ignoring symlink: %s\n", path);
379 return 0;
382 ok = do_unfruit(path);
383 if (!ok) {
384 return -1;
387 return 0;
390 static int net_vfs_stream_to_appledouble(struct net_context *net,
391 int argc,
392 const char **argv)
394 int i;
395 int ret;
396 bool ok;
397 int rc = 1;
399 if (argc < 2 || net->display_usage) {
400 net_vfs_stream_to_appledouble_usage();
401 goto done;
404 ret = net_vfs_init(net, argc, argv);
405 if (ret != 0) {
406 goto done;
409 for (i = 1; i < argc; i++) {
410 const char *path = argv[i];
412 if (path[0] == '/') {
413 fprintf(stderr, "ignoring absolute path: %s\n", path);
414 if (state.c->opt_continue_on_error) {
415 continue;
417 goto done;
420 if (!state.c->opt_recursive) {
421 ok = do_unfruit(path);
422 if (!ok) {
423 if (!state.c->opt_continue_on_error) {
424 goto done;
427 continue;
430 ret = nftw(path,
431 nftw_cb,
432 256,
433 state.c->opt_follow_symlink ? 0 : FTW_PHYS);
434 if (ret != 0) {
435 fprintf(stderr, "%s: %s\n", path, strerror(errno));
436 if (!state.c->opt_continue_on_error) {
437 goto done;
442 rc = 0;
444 done:
445 return rc;
448 static struct functable func[] = {
450 "getntacl",
451 net_vfs_get_ntacl,
452 NET_TRANSPORT_LOCAL,
453 N_("Display security descriptor of a file or directory"),
454 N_("net vfs getntacl <share> <path> [<path> ...]")
457 NET_VFS_CMD_STREAM_TO_ADOUBLE,
458 net_vfs_stream_to_appledouble,
459 NET_TRANSPORT_LOCAL,
460 N_("Convert streams to AppleDouble files"),
461 N_("net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE " [OPTIONS] <share> <path> [<path> ...]")
463 {NULL, NULL, 0, NULL, NULL}
466 int net_vfs(struct net_context *c, int argc, const char **argv)
468 return net_run_function(c, argc, argv, "net vfs", func);