LCOV - code coverage report
Current view: top level - source3/utils - net_vfs.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 85 213 39.9 %
Date: 2024-04-21 15:09:00 Functions: 6 10 60.0 %

          Line data    Source code
       1             : /*
       2             :  * Samba Unix/Linux SMB client library
       3             :  * Distributed SMB/CIFS Server Management Utility
       4             :  * Copyright (C) 2019 Ralph Boehme <slow@samba.org>
       5             :  *
       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.
      10             :  *
      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.
      15             :  *
      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/>.
      18             :  */
      19             : 
      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"
      39             : 
      40             : #define NET_VFS_CMD_STREAM_TO_ADOUBLE "stream2adouble"
      41             : 
      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;
      48             : 
      49           0 : static void net_vfs_usage(void)
      50             : {
      51           0 :         fprintf(stderr,
      52             :                 "Usage:\n"
      53             :                 "net vfs [OPTIONS] <share> ....\n");
      54           0 : }
      55             : 
      56           0 : static void net_vfs_getntacl_usage(void)
      57             : {
      58           0 :         fprintf(stderr,
      59             :                 "Usage:\n"
      60             :                 "net vfs getntacl <share> <path>\n");
      61           0 : }
      62             : 
      63           0 : static void net_vfs_stream_to_appledouble_usage(void)
      64             : {
      65           0 :         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");
      74           0 : }
      75             : 
      76           6 : static bool net_vfs_make_session_info(struct auth_session_info **session_info)
      77             : {
      78           0 :         NTSTATUS status;
      79             : 
      80           6 :         if (non_root_mode()) {
      81           6 :                 struct passwd *p = NULL;
      82             : 
      83           6 :                 p = getpwuid(geteuid());
      84           6 :                 if (p == NULL) {
      85           0 :                         fprintf(stderr, "getpwuid(%d) failed\n", geteuid());
      86           0 :                         return false;
      87             :                 }
      88             : 
      89           6 :                 status = make_session_info_from_username(state.mem_ctx,
      90           6 :                                                          p->pw_name,
      91             :                                                          false,
      92             :                                                          session_info);
      93           6 :                 if (!NT_STATUS_IS_OK(status)) {
      94           0 :                         fprintf(stderr, "session_info from username failed\n");
      95           0 :                         return false;
      96             :                 }
      97             : 
      98           6 :                 return true;
      99             :         }
     100             : 
     101           0 :         status = init_system_session_info(state.mem_ctx);
     102           0 :         if (!NT_STATUS_IS_OK(status)) {
     103           0 :                 fprintf(stderr, "init_system_session_info failed\n");
     104           0 :                 return false;
     105             :         }
     106             : 
     107           0 :         status = make_session_info_system(state.mem_ctx, session_info);
     108           0 :         if (!NT_STATUS_IS_OK(status)) {
     109           0 :                 fprintf(stderr, "make_session_info_system failed\n");
     110           0 :                 return false;
     111             :         }
     112             : 
     113           0 :         return true;
     114             : }
     115             : 
     116           6 : static int net_vfs_init(struct net_context *c, int argc, const char **argv)
     117             : {
     118           0 :         const struct loadparm_substitution *lp_sub =
     119           6 :                 loadparm_s3_global_substitution();
     120           6 :         const char *service = NULL;
     121           6 :         char *share_root = NULL;
     122           0 :         int snum;
     123           0 :         NTSTATUS status;
     124           0 :         bool ok;
     125           6 :         int rc = 1;
     126             : 
     127           6 :         state = (struct net_vfs_state) {
     128             :                 .c = c,
     129             :                 .mem_ctx = c,
     130             :         };
     131             : 
     132           6 :         if (argc < 1) {
     133           0 :                 net_vfs_usage();
     134           0 :                 goto done;
     135             :         }
     136             : 
     137           6 :         if (geteuid() != 0 && !uid_wrapper_enabled()) {
     138           0 :                 fprintf(stderr, "'net vfs' must be run as root.\n");
     139           0 :                 goto done;
     140             :         }
     141             : 
     142           6 :         smb_init_locale();
     143           6 :         umask(0);
     144           6 :         sec_init();
     145           6 :         setup_logging("net", DEBUG_STDOUT);
     146           6 :         lpcfg_set_cmdline(c->lp_ctx, "log level", "0");
     147             : 
     148           6 :         ok = lp_load_with_registry_shares(get_dyn_CONFIGFILE());
     149           6 :         if (!ok) {
     150           0 :                 fprintf(stderr, "lp_load_with_registry_shares failed\n");
     151           0 :                 goto done;
     152             :         }
     153             : 
     154           6 :         ok = locking_init();
     155           6 :         if (!ok) {
     156           0 :                 fprintf(stderr, "locking init failed\n");
     157           0 :                 goto done;
     158             :         }
     159             : 
     160           6 :         ok = net_vfs_make_session_info(&state.session_info);
     161           6 :         if (!ok) {
     162           0 :                 goto done;
     163             :         }
     164             : 
     165           6 :         service = argv[0];
     166           6 :         snum = lp_servicenumber(service);
     167           6 :         if (snum == -1) {
     168           0 :                 fprintf(stderr, "unknown service: %s\n", service);
     169           0 :                 goto done;
     170             :         }
     171             : 
     172           6 :         share_root = lp_path(state.mem_ctx, lp_sub, snum);
     173           6 :         if (share_root == NULL) {
     174           0 :                 fprintf(stderr, "Failed to find share root for service: %s\n",
     175             :                         service);
     176           0 :                 goto done;
     177             :         }
     178             : 
     179           6 :         status = create_conn_struct_tos_cwd(global_messaging_context(),
     180             :                                             snum,
     181             :                                             share_root,
     182           6 :                                             state.session_info,
     183             :                                             &state.conn_tos);
     184           6 :         if (!NT_STATUS_IS_OK(status)) {
     185           0 :                 goto done;
     186             :         }
     187             : 
     188           6 :         state.conn_tos->conn->share_access = FILE_GENERIC_ALL;
     189           6 :         state.conn_tos->conn->read_only = false;
     190           6 :         file_init(state.conn_tos->conn->sconn);
     191             : 
     192           6 :         ok = become_user_without_service_by_session(state.conn_tos->conn,
     193           6 :                                                     state.session_info);
     194           6 :         if (!ok) {
     195           0 :                 fprintf(stderr,
     196             :                         "become_user_without_service_by_session failed\n");
     197           0 :                 goto done;
     198             :         }
     199             : 
     200           6 :         rc = 0;
     201           6 : done:
     202           6 :         return rc;
     203             : }
     204             : 
     205           0 : static int net_vfs_get_ntacl(struct net_context *net,
     206             :                              int argc,
     207             :                              const char **argv)
     208             : {
     209           0 :         const char *path = NULL;
     210           0 :         struct smb_filename *smb_fname = NULL;
     211           0 :         files_struct *fsp = NULL;
     212           0 :         struct security_descriptor *sd = NULL;
     213           0 :         NTSTATUS status;
     214           0 :         int ret;
     215           0 :         int rc = 1;
     216             : 
     217           0 :         if (argc < 2 || net->display_usage) {
     218           0 :                 net_vfs_getntacl_usage();
     219           0 :                 goto done;
     220             :         }
     221             : 
     222           0 :         ret = net_vfs_init(net, argc, argv);
     223           0 :         if (ret != 0) {
     224           0 :                 goto done;
     225             :         }
     226             : 
     227           0 :         path = argv[1];
     228           0 :         smb_fname = synthetic_smb_fname(state.mem_ctx,
     229             :                                         path,
     230             :                                         NULL,
     231             :                                         NULL,
     232             :                                         0,
     233             :                                         0);
     234           0 :         if (smb_fname == NULL) {
     235           0 :                 goto done;
     236             :         }
     237             : 
     238           0 :         ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
     239           0 :         if (ret != 0) {
     240           0 :                 fprintf(stderr, "stat [%s] failed: %s\n",
     241           0 :                         smb_fname_str_dbg(smb_fname), strerror(errno));
     242           0 :                 goto done;
     243             :         }
     244             : 
     245           0 :         status = openat_pathref_fsp(state.conn_tos->conn->cwd_fsp, smb_fname);
     246           0 :         if (!NT_STATUS_IS_OK(status)) {
     247           0 :                 DBG_ERR("openat_pathref_fsp [%s] failed: %s\n",
     248             :                         smb_fname_str_dbg(smb_fname), nt_errstr(status));
     249           0 :                 goto done;
     250             :         }
     251             : 
     252           0 :         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           0 :         if (!NT_STATUS_IS_OK(status)) {
     272           0 :                 DBG_ERR("SMB_VFS_CREATE_FILE [%s] failed: %s\n",
     273             :                         smb_fname_str_dbg(smb_fname), nt_errstr(status));
     274           0 :                 goto done;
     275             :         }
     276             : 
     277           0 :         status = SMB_VFS_FGET_NT_ACL(fsp,
     278             :                                      SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL,
     279             :                                      talloc_tos(),
     280             :                                      &sd);
     281           0 :         if (!NT_STATUS_IS_OK(status)) {
     282           0 :                 DBG_ERR("SMB_VFS_FGET_NT_ACL [%s] failed: %s\n",
     283             :                         smb_fname_str_dbg(smb_fname), nt_errstr(status));
     284           0 :                 goto done;
     285             :         }
     286             : 
     287           0 :         status = close_file_free(NULL, &fsp, NORMAL_CLOSE);
     288           0 :         if (!NT_STATUS_IS_OK(status)) {
     289           0 :                 DBG_ERR("close_file [%s] failed: %s\n",
     290             :                         smb_fname_str_dbg(smb_fname),
     291             :                         nt_errstr(status));
     292           0 :                 goto done;
     293             :         }
     294             : 
     295           0 :         sec_desc_print(NULL, stdout, sd, true);
     296             : 
     297           0 :         rc = 0;
     298           0 : done:
     299           0 :         TALLOC_FREE(sd);
     300             : 
     301           0 :         if (fsp != NULL) {
     302           0 :                 status = close_file_free(NULL, &fsp, NORMAL_CLOSE);
     303           0 :                 if (!NT_STATUS_IS_OK(status)) {
     304           0 :                         DBG_ERR("close_file_free() [%s] failed: %s\n",
     305             :                                 smb_fname_str_dbg(smb_fname),
     306             :                                 nt_errstr(status));
     307           0 :                         rc = 1;
     308             :                 }
     309             :         }
     310           0 :         return rc;
     311             : }
     312             : 
     313          16 : static bool do_unfruit(const char *path)
     314             : {
     315          16 :         struct smb_filename *smb_fname = NULL;
     316          16 :         char *p = NULL;
     317           0 :         bool converted;
     318           0 :         int ret;
     319           0 :         bool ok;
     320             : 
     321          16 :         p = strrchr_m(path, '/');
     322          16 :         if (p != NULL) {
     323          10 :                 if (p[1] == '.' && p[2] == '_') {
     324           4 :                         return true;
     325             :                 }
     326             :         }
     327             : 
     328          12 :         smb_fname = synthetic_smb_fname(state.mem_ctx,
     329             :                                         path,
     330             :                                         NULL,
     331             :                                         NULL,
     332             :                                         0,
     333             :                                         0);
     334          12 :         if (smb_fname == NULL) {
     335           0 :                 return false;
     336             :         }
     337             : 
     338          12 :         ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
     339          12 :         if (ret != 0) {
     340           0 :                 fprintf(stderr, "%s: %s\n", path, strerror(errno));
     341           0 :                 if (state.c->opt_continue_on_error) {
     342           0 :                         return true;
     343             :                 }
     344           0 :                 return false;
     345             :         }
     346             : 
     347          12 :         ok = ad_unconvert(state.mem_ctx,
     348          12 :                           state.conn_tos->conn->vfs_handles,
     349             :                           macos_string_replace_map,
     350             :                           smb_fname,
     351             :                           &converted);
     352          12 :         if (!ok) {
     353           0 :                 fprintf(stderr, "Converting failed: %s\n", path);
     354           0 :                 if (state.c->opt_continue_on_error) {
     355           0 :                         return true;
     356             :                 }
     357           0 :                 return false;
     358             :         }
     359             : 
     360          12 :         if (converted) {
     361           6 :                 fprintf(stdout, "Converted: %s\n", path);
     362           6 :         } else if (state.c->opt_verbose) {
     363           0 :                 fprintf(stdout, "%s\n", path);
     364             :         }
     365          12 :         return true;
     366             : }
     367             : 
     368          16 : static int nftw_cb(const char *path,
     369             :                    const struct stat *sb,
     370             :                    int typeflag,
     371             :                    struct FTW *ftwbuf)
     372             : {
     373           0 :         bool ok;
     374             : 
     375          16 :         if (typeflag == FTW_SL) {
     376           0 :                 if (state.c->opt_verbose) {
     377           0 :                         fprintf(stdout, "Ignoring symlink: %s\n", path);
     378             :                 }
     379           0 :                 return 0;
     380             :         }
     381             : 
     382          16 :         ok = do_unfruit(path);
     383          16 :         if (!ok) {
     384           0 :                 return -1;
     385             :         }
     386             : 
     387          16 :         return 0;
     388             : }
     389             : 
     390           6 : static int net_vfs_stream_to_appledouble(struct net_context *net,
     391             :                                          int argc,
     392             :                                          const char **argv)
     393             : {
     394           0 :         int i;
     395           0 :         int ret;
     396           0 :         bool ok;
     397           6 :         int rc = 1;
     398             : 
     399           6 :         if (argc < 2 || net->display_usage) {
     400           0 :                 net_vfs_stream_to_appledouble_usage();
     401           0 :                 goto done;
     402             :         }
     403             : 
     404           6 :         ret = net_vfs_init(net, argc, argv);
     405           6 :         if (ret != 0) {
     406           0 :                 goto done;
     407             :         }
     408             : 
     409          12 :         for (i = 1; i < argc; i++) {
     410           6 :                 const char *path = argv[i];
     411             : 
     412           6 :                 if (path[0] == '/') {
     413           0 :                         fprintf(stderr, "ignoring absolute path: %s\n", path);
     414           0 :                         if (state.c->opt_continue_on_error) {
     415           0 :                                 continue;
     416             :                         }
     417           0 :                         goto done;
     418             :                 }
     419             : 
     420           6 :                 if (!state.c->opt_recursive) {
     421           0 :                         ok = do_unfruit(path);
     422           0 :                         if (!ok) {
     423           0 :                                 if (!state.c->opt_continue_on_error) {
     424           0 :                                         goto done;
     425             :                                 }
     426             :                         }
     427           0 :                         continue;
     428             :                 }
     429             : 
     430           6 :                 ret = nftw(path,
     431             :                            nftw_cb,
     432             :                            256,
     433           6 :                            state.c->opt_follow_symlink ? 0 : FTW_PHYS);
     434           6 :                 if (ret != 0) {
     435           0 :                         fprintf(stderr, "%s: %s\n", path, strerror(errno));
     436           0 :                         if (!state.c->opt_continue_on_error) {
     437           0 :                                 goto done;
     438             :                         }
     439             :                 }
     440             :         }
     441             : 
     442           6 :         rc = 0;
     443             : 
     444           6 : done:
     445           6 :         return rc;
     446             : }
     447             : 
     448             : static struct functable func[] = {
     449             :         {
     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> ...]")
     455             :         },
     456             :         {
     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> ...]")
     462             :         },
     463             :         {NULL, NULL, 0, NULL, NULL}
     464             : };
     465             : 
     466           6 : int net_vfs(struct net_context *c, int argc, const char **argv)
     467             : {
     468           6 :         return net_run_function(c, argc, argv, "net vfs", func);
     469             : }

Generated by: LCOV version 1.14