LCOV - code coverage report
Current view: top level - source4/libcli/smb2 - util.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 150 180 83.3 %
Date: 2024-04-21 15:09:00 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 client utility functions
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2005
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/raw/libcliraw.h"
      24             : #include "libcli/raw/raw_proto.h"
      25             : #include "libcli/smb2/smb2.h"
      26             : #include "libcli/smb2/smb2_calls.h"
      27             : #include "libcli/smb_composite/smb_composite.h"
      28             : #include "librpc/gen_ndr/ndr_security.h"
      29             : 
      30             : /*
      31             :   simple close wrapper with SMB2
      32             : */
      33      219884 : NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
      34             : {
      35         126 :         struct smb2_close c;
      36             : 
      37      219884 :         ZERO_STRUCT(c);
      38      219884 :         c.in.file.handle = h;
      39             : 
      40      219884 :         return smb2_close(tree, &c);
      41             : }
      42             : 
      43             : /*
      44             :   unlink a file with SMB2
      45             : */
      46      358783 : NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
      47             : {
      48         188 :         union smb_unlink io;
      49             :         
      50      358783 :         ZERO_STRUCT(io);
      51      358783 :         io.unlink.in.pattern = fname;
      52             : 
      53      358783 :         return smb2_composite_unlink(tree, &io);
      54             : }
      55             : 
      56             : 
      57             : /*
      58             :   rmdir with SMB2
      59             : */
      60        2492 : NTSTATUS smb2_util_rmdir(struct smb2_tree *tree, const char *dname)
      61             : {
      62           2 :         struct smb_rmdir io;
      63             :         
      64        2492 :         ZERO_STRUCT(io);
      65        2492 :         io.in.path = dname;
      66             : 
      67        2492 :         return smb2_composite_rmdir(tree, &io);
      68             : }
      69             : 
      70             : 
      71             : /*
      72             :   mkdir with SMB2
      73             : */
      74         391 : NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname)
      75             : {
      76           2 :         union smb_mkdir io;
      77             :         
      78         391 :         ZERO_STRUCT(io);
      79         391 :         io.mkdir.level = RAW_MKDIR_MKDIR;
      80         391 :         io.mkdir.in.path = dname;
      81             : 
      82         391 :         return smb2_composite_mkdir(tree, &io);
      83             : }
      84             : 
      85             : 
      86             : /*
      87             :   set file attribute with SMB2
      88             : */
      89          88 : NTSTATUS smb2_util_setatr(struct smb2_tree *tree, const char *name, uint32_t attrib)
      90             : {
      91          88 :         struct smb2_create cr = {0};
      92          88 :         struct smb2_handle h1 = {{0}};
      93           0 :         union smb_setfileinfo setinfo;
      94           0 :         NTSTATUS status;
      95             : 
      96          88 :         cr = (struct smb2_create) {
      97             :                 .in.desired_access = SEC_FILE_WRITE_ATTRIBUTE,
      98             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
      99             :                 .in.create_disposition = FILE_OPEN,
     100             :                 .in.fname = name,
     101             :         };
     102          88 :         status = smb2_create(tree, tree, &cr);
     103          88 :         if (!NT_STATUS_IS_OK(status)) {
     104          64 :                 return status;
     105             :         }
     106          24 :         h1 = cr.out.file.handle;
     107             : 
     108          24 :         setinfo = (union smb_setfileinfo) {
     109             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
     110             :                 .basic_info.in.file.handle = h1,
     111             :                 .basic_info.in.attrib = attrib,
     112             :         };
     113             : 
     114          24 :         status = smb2_setinfo_file(tree, &setinfo);
     115          24 :         if (!NT_STATUS_IS_OK(status)) {
     116           0 :                 smb2_util_close(tree, h1);
     117           0 :                 return status;
     118             :         }
     119             : 
     120          24 :         smb2_util_close(tree, h1);
     121          24 :         return NT_STATUS_OK;
     122             : }
     123             : 
     124             : 
     125             : /*
     126             :   get file attribute with SMB2
     127             : */
     128         515 : NTSTATUS smb2_util_getatr(struct smb2_tree *tree, const char *fname,
     129             :                           uint16_t *attr, size_t *size, time_t *t)
     130             : {
     131           0 :         union smb_fileinfo parms;
     132           0 :         NTSTATUS status;
     133         515 :         struct smb2_create create_io = {0};
     134             : 
     135         515 :         create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
     136         515 :         create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     137         515 :         create_io.in.create_disposition = FILE_OPEN;
     138         515 :         create_io.in.fname = fname;
     139         515 :         status = smb2_create(tree, tree, &create_io);
     140         515 :         if (!NT_STATUS_IS_OK(status)) {
     141           0 :                 return status;
     142             :         }
     143             : 
     144         515 :         ZERO_STRUCT(parms);
     145         515 :         parms.all_info2.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
     146         515 :         parms.all_info2.in.file.handle = create_io.out.file.handle;
     147         515 :         status = smb2_getinfo_file(tree, tree, &parms);
     148         515 :         if (!NT_STATUS_IS_OK(status)) {
     149           0 :                 return status;
     150             :         }
     151             : 
     152         515 :         status = smb2_util_close(tree, create_io.out.file.handle);
     153         515 :         if (!NT_STATUS_IS_OK(status)) {
     154           0 :                 return status;
     155             :         }
     156             : 
     157         515 :         if (size) {
     158           0 :                 *size = parms.all_info2.out.size;
     159             :         }
     160             : 
     161         515 :         if (t) {
     162           0 :                 *t = parms.all_info2.out.write_time;
     163             :         }
     164             : 
     165         515 :         if (attr) {
     166         515 :                 *attr = parms.all_info2.out.attrib;
     167             :         }
     168             : 
     169         515 :         return status;
     170             : }
     171             : 
     172             : 
     173             : /* 
     174             :    recursively descend a tree deleting all files
     175             :    returns the number of files deleted, or -1 on error
     176             : */
     177        3286 : int smb2_deltree(struct smb2_tree *tree, const char *dname)
     178             : {
     179           4 :         NTSTATUS status;
     180        3286 :         uint32_t total_deleted = 0;
     181           4 :         unsigned int count, i;
     182           4 :         union smb_search_data *list;
     183        3286 :         TALLOC_CTX *tmp_ctx = talloc_new(tree);
     184           4 :         struct smb2_find f;
     185           4 :         struct smb2_create create_parm;
     186           4 :         bool did_delete;
     187             : 
     188             :         /* it might be a file */
     189        3286 :         status = smb2_util_unlink(tree, dname);
     190        3286 :         if (NT_STATUS_IS_OK(status)) {
     191         101 :                 talloc_free(tmp_ctx);
     192         101 :                 return 1;
     193             :         }
     194        3185 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
     195        2082 :             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
     196        2049 :             NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
     197        1134 :                 talloc_free(tmp_ctx);
     198        1134 :                 return 0;
     199             :         }
     200             : 
     201        2049 :         if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
     202             :                 /* it could be read-only */
     203           6 :                 smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
     204           6 :                 status = smb2_util_unlink(tree, dname);
     205             :         }
     206        2051 :         if (NT_STATUS_IS_OK(status)) {
     207           6 :                 talloc_free(tmp_ctx);
     208           6 :                 return 1;
     209             :         }
     210             : 
     211        2045 :         ZERO_STRUCT(create_parm);
     212        2045 :         create_parm.in.desired_access = SEC_FILE_READ_DATA;
     213        2045 :         create_parm.in.share_access = 
     214             :                 NTCREATEX_SHARE_ACCESS_READ|
     215             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     216        2045 :         create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     217        2045 :         create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
     218        2045 :         create_parm.in.fname = dname;
     219             : 
     220        2045 :         status = smb2_create(tree, tmp_ctx, &create_parm);
     221        2045 :         if (NT_STATUS_IS_ERR(status)) {
     222         151 :                 DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status)));
     223         151 :                 talloc_free(tmp_ctx);
     224         151 :                 return -1;
     225             :         }
     226             :         
     227             : 
     228           2 :         do {
     229        2680 :                 did_delete = false;
     230             : 
     231        2680 :                 ZERO_STRUCT(f);
     232        2680 :                 f.in.file.handle       = create_parm.out.file.handle;
     233        2680 :                 f.in.max_response_size = 0x10000;
     234        2680 :                 f.in.level             = SMB2_FIND_NAME_INFO;
     235        2680 :                 f.in.pattern           = "*";
     236             :                 
     237        2680 :                 status = smb2_find_level(tree, tmp_ctx, &f, &count, &list);
     238        2680 :                 if (NT_STATUS_IS_ERR(status)) {
     239           0 :                         DEBUG(2,("Failed to list %s - %s\n", 
     240             :                                  dname, nt_errstr(status)));
     241           0 :                         smb2_util_close(tree, create_parm.out.file.handle);
     242           0 :                         talloc_free(tmp_ctx);
     243           0 :                         return -1;
     244             :                 }
     245             :                 
     246      355038 :                 for (i=0;i<count;i++) {
     247           6 :                         char *name;
     248      352358 :                         if (strcmp(".", list[i].name_info.name.s) == 0 ||
     249      349730 :                             strcmp("..", list[i].name_info.name.s) == 0) {
     250        5256 :                                 continue;
     251             :                         }
     252      347102 :                         name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s);
     253      347102 :                         status = smb2_util_unlink(tree, name);
     254      347102 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
     255             :                                 /* it could be read-only */
     256           9 :                                 smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL);
     257           9 :                                 status = smb2_util_unlink(tree, name);
     258             :                         }
     259             :                         
     260      347102 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
     261           0 :                                 int ret;
     262         775 :                                 ret = smb2_deltree(tree, name);
     263         775 :                                 if (ret > 0) total_deleted += ret;
     264             :                         }
     265      347102 :                         talloc_free(name);
     266      347102 :                         if (NT_STATUS_IS_OK(status)) {
     267      193193 :                                 total_deleted++;
     268      193193 :                                 did_delete = true;
     269             :                         }
     270             :                 }
     271        2680 :         } while (did_delete);
     272             : 
     273        1894 :         smb2_util_close(tree, create_parm.out.file.handle);
     274             : 
     275        1894 :         status = smb2_util_rmdir(tree, dname);
     276        1894 :         if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
     277             :                 /* it could be read-only */
     278           0 :                 smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
     279           0 :                 status = smb2_util_rmdir(tree, dname);
     280             :         }
     281             : 
     282        1894 :         if (NT_STATUS_IS_ERR(status)) {
     283          76 :                 DEBUG(2,("Failed to delete %s - %s\n", 
     284             :                          dname, nt_errstr(status)));
     285          76 :                 talloc_free(tmp_ctx);
     286          76 :                 return -1;
     287             :         }
     288             : 
     289        1818 :         talloc_free(tmp_ctx);
     290             : 
     291        1818 :         return total_deleted;
     292             : }
     293             : 
     294             : /*
     295             :   check if two SMB2 file handles are the same
     296             : */
     297         816 : bool smb2_util_handle_equal(const struct smb2_handle h1,
     298             :                             const struct smb2_handle h2)
     299             : {
     300         816 :         return (h1.data[0] == h2.data[0]) && (h1.data[1] == h2.data[1]);
     301             : }
     302             : 
     303         816 : bool smb2_util_handle_empty(const struct smb2_handle h)
     304             : {
     305           0 :         struct smb2_handle empty;
     306             : 
     307         816 :         ZERO_STRUCT(empty);
     308             : 
     309         816 :         return smb2_util_handle_equal(h, empty);
     310             : }
     311             : 
     312             : /****************************************************************************
     313             : send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
     314             : ****************************************************************************/
     315          50 : NTSTATUS smb2_qpathinfo_alt_name(TALLOC_CTX *ctx, struct smb2_tree *tree,
     316             :                                  const char *fname, const char **alt_name)
     317             : {
     318           0 :         union smb_fileinfo parms;
     319           0 :         TALLOC_CTX *mem_ctx;
     320           0 :         NTSTATUS status;
     321          50 :         struct smb2_create create_io = {0};
     322             : 
     323          50 :         mem_ctx = talloc_new(ctx);
     324          50 :         if (!mem_ctx) {
     325           0 :                 return NT_STATUS_NO_MEMORY;
     326             :         }
     327             : 
     328          50 :         create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
     329          50 :         create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     330          50 :         create_io.in.create_disposition = FILE_OPEN;
     331          50 :         create_io.in.fname = fname;
     332          50 :         status = smb2_create(tree, mem_ctx, &create_io);
     333          50 :         if (!NT_STATUS_IS_OK(status)) {
     334           0 :                 talloc_free(mem_ctx);
     335           0 :                 return status;
     336             :         }
     337             : 
     338          50 :         parms.alt_name_info.level = RAW_FILEINFO_SMB2_ALT_NAME_INFORMATION;
     339          50 :         parms.alt_name_info.in.file.handle = create_io.out.file.handle;
     340             : 
     341          50 :         status = smb2_getinfo_file(tree, mem_ctx, &parms);
     342          50 :         if (!NT_STATUS_IS_OK(status)) {
     343           0 :                 talloc_free(mem_ctx);
     344           0 :                 return status;
     345             :         }
     346             : 
     347          50 :         status = smb2_util_close(tree, create_io.out.file.handle);
     348          50 :         if (!NT_STATUS_IS_OK(status)) {
     349           0 :                 talloc_free(mem_ctx);
     350           0 :                 return status;
     351             :         }
     352             : 
     353          50 :         if (!parms.alt_name_info.out.fname.s) {
     354           0 :                 *alt_name = talloc_strdup(ctx, "");
     355             :         } else {
     356          50 :                 *alt_name = talloc_strdup(ctx,
     357             :                                           parms.alt_name_info.out.fname.s);
     358             :         }
     359             : 
     360          50 :         talloc_free(mem_ctx);
     361             : 
     362          50 :         return NT_STATUS_OK;
     363             : }

Generated by: LCOV version 1.14