LCOV - code coverage report
Current view: top level - source4/torture/raw - samba3hide.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 117 160 73.1 %
Date: 2024-04-21 15:09:00 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Test samba3 hide unreadable/unwriteable
       4             :    Copyright (C) Volker Lendecke 2006
       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 "system/time.h"
      22             : #include "system/filesys.h"
      23             : #include "libcli/libcli.h"
      24             : #include "torture/util.h"
      25             : #include "torture/raw/proto.h"
      26             : 
      27          14 : static void init_unixinfo_nochange(union smb_setfileinfo *info)
      28             : {
      29          14 :         ZERO_STRUCTP(info);
      30          14 :         info->unix_basic.level = RAW_SFILEINFO_UNIX_BASIC;
      31          14 :         info->unix_basic.in.mode = SMB_MODE_NO_CHANGE;
      32             : 
      33          14 :         info->unix_basic.in.end_of_file = SMB_SIZE_NO_CHANGE_HI;
      34          14 :         info->unix_basic.in.end_of_file <<= 32;
      35          14 :         info->unix_basic.in.end_of_file |= SMB_SIZE_NO_CHANGE_LO;
      36             :         
      37          14 :         info->unix_basic.in.num_bytes = SMB_SIZE_NO_CHANGE_HI;
      38          14 :         info->unix_basic.in.num_bytes <<= 32;
      39          14 :         info->unix_basic.in.num_bytes |= SMB_SIZE_NO_CHANGE_LO;
      40             :         
      41          14 :         info->unix_basic.in.status_change_time = SMB_TIME_NO_CHANGE_HI;
      42          14 :         info->unix_basic.in.status_change_time <<= 32;
      43          14 :         info->unix_basic.in.status_change_time |= SMB_TIME_NO_CHANGE_LO;
      44             : 
      45          14 :         info->unix_basic.in.access_time = SMB_TIME_NO_CHANGE_HI;
      46          14 :         info->unix_basic.in.access_time <<= 32;
      47          14 :         info->unix_basic.in.access_time |= SMB_TIME_NO_CHANGE_LO;
      48             : 
      49          14 :         info->unix_basic.in.change_time = SMB_TIME_NO_CHANGE_HI;
      50          14 :         info->unix_basic.in.change_time <<= 32;
      51          14 :         info->unix_basic.in.change_time |= SMB_TIME_NO_CHANGE_LO;
      52             : 
      53          14 :         info->unix_basic.in.uid = SMB_UID_NO_CHANGE;
      54          14 :         info->unix_basic.in.gid = SMB_GID_NO_CHANGE;
      55          14 : }
      56             : 
      57             : struct list_state {
      58             :         const char *fname;
      59             :         bool visible;
      60             : };
      61             : 
      62         246 : static void set_visible(struct clilist_file_info *i, const char *mask,
      63             :                         void *priv)
      64             : {
      65         246 :         struct list_state *state = (struct list_state *)priv;
      66             : 
      67         246 :         if (strcasecmp_m(state->fname, i->name) == 0)
      68          12 :                 state->visible = true;
      69         246 : }
      70             : 
      71          18 : static bool is_visible(struct smbcli_tree *tree, const char *fname)
      72             : {
      73           0 :         struct list_state state;
      74             : 
      75          18 :         state.visible = false;
      76          18 :         state.fname = fname;
      77             : 
      78          18 :         if (smbcli_list(tree, "*.*", 0, set_visible, &state) < 0) {
      79           0 :                 return false;
      80             :         }
      81          18 :         return state.visible;
      82             : }
      83             : 
      84           6 : static bool is_readable(struct smbcli_tree *tree, const char *fname)
      85             : {
      86           0 :         int fnum;
      87           6 :         fnum = smbcli_open(tree, fname, O_RDONLY, DENY_NONE);
      88           6 :         if (fnum < 0) {
      89           2 :                 return false;
      90             :         }
      91           4 :         smbcli_close(tree, fnum);
      92           4 :         return true;
      93             : }
      94             : 
      95           6 : static bool is_writeable(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
      96             :                          const char *fname)
      97             : {
      98           0 :         int fnum;
      99           6 :         fnum = smbcli_open(tree, fname, O_WRONLY, DENY_NONE);
     100           6 :         if (fnum < 0) {
     101           4 :                 return false;
     102             :         }
     103           2 :         smbcli_close(tree, fnum);
     104           2 :         return true;
     105             : }
     106             : 
     107             : /*
     108             :  * This is not an exact method because there's a ton of reasons why a getatr
     109             :  * might fail. But for our purposes it's sufficient.
     110             :  */
     111             : 
     112           2 : static bool smbcli_file_exists(struct smbcli_tree *tree, const char *fname)
     113             : {
     114           2 :         return NT_STATUS_IS_OK(smbcli_getatr(tree, fname, NULL, NULL, NULL));
     115             : }
     116             : 
     117           4 : static NTSTATUS smbcli_setup_unix(struct smbcli_tree *tree)
     118             : {
     119           0 :         union smb_fsinfo fsinfo;
     120           0 :         union smb_setfsinfo set_fsinfo;
     121           0 :         NTSTATUS status;
     122             : 
     123           4 :         ZERO_STRUCT(fsinfo);
     124           4 :         ZERO_STRUCT(set_fsinfo);
     125             : 
     126           4 :         fsinfo.generic.level = RAW_QFS_UNIX_INFO;
     127           4 :         status = smb_raw_fsinfo(tree, NULL, &fsinfo);
     128           4 :         if (!NT_STATUS_IS_OK(status)) {
     129           0 :                 printf("smb_raw_fsinfo failed %s\n",
     130             :                         nt_errstr(status));
     131           0 :                 return status;
     132             :         }
     133             : 
     134           4 :         set_fsinfo.generic.level = RAW_SETFS_UNIX_INFO;
     135           4 :         set_fsinfo.unix_info.in.major_version = fsinfo.unix_info.out.major_version;
     136           4 :         set_fsinfo.unix_info.in.minor_version = fsinfo.unix_info.out.minor_version;
     137           4 :         set_fsinfo.unix_info.in.capability = fsinfo.unix_info.out.capability;
     138             : 
     139           4 :         status = smb_raw_setfsinfo(tree, NULL, &set_fsinfo);
     140           4 :         if (!NT_STATUS_IS_OK(status)) {
     141           0 :                 printf("smb_raw_setfsinfo failed %s\n",
     142             :                         nt_errstr(status));
     143             :         }
     144           4 :         return status;
     145             : }
     146             : 
     147          14 : static NTSTATUS smbcli_chmod(struct smbcli_tree *tree, const char *fname,
     148             :                              uint64_t permissions)
     149             : {
     150           0 :         union smb_setfileinfo sfinfo;
     151          14 :         init_unixinfo_nochange(&sfinfo);
     152          14 :         sfinfo.unix_basic.in.file.path = fname;
     153          14 :         sfinfo.unix_basic.in.permissions = permissions;
     154          14 :         return smb_raw_setpathinfo(tree, &sfinfo);
     155             : }
     156             : 
     157           4 : bool torture_samba3_hide(struct torture_context *torture, struct smbcli_state *cli)
     158             : {
     159           4 :         const char *fname = "torture_samba3_hide.txt";
     160           0 :         int fnum;
     161           0 :         NTSTATUS status;
     162           0 :         struct smbcli_tree *hideunread;
     163           0 :         struct smbcli_tree *hideunwrite;
     164             : 
     165           4 :         status = smbcli_setup_unix(cli->tree);
     166           4 :         if (!NT_STATUS_IS_OK(status)) {
     167           0 :                 torture_fail(torture,
     168             :                         talloc_asprintf(torture, "smbcli_setup_unix failed %s\n",
     169             :                                 nt_errstr(status)));
     170             :         }
     171             : 
     172           4 :         status = torture_second_tcon(torture, cli->session, "hideunread",
     173             :                                      &hideunread);
     174           4 :         torture_assert_ntstatus_ok(torture, status, "second_tcon(hideunread) failed\n");
     175             : 
     176           4 :         status = torture_second_tcon(torture, cli->session, "hideunwrite",
     177             :                                      &hideunwrite);
     178           4 :         torture_assert_ntstatus_ok(torture, status, "second_tcon(hideunwrite) failed\n");
     179             : 
     180           2 :         status = smbcli_unlink(cli->tree, fname);
     181           2 :         if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
     182           0 :                 smbcli_setatr(cli->tree, fname, 0, -1);
     183           0 :                 smbcli_unlink(cli->tree, fname);
     184             :         }
     185             : 
     186           2 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     187           2 :         if (fnum == -1) {
     188           0 :                 torture_fail(torture,
     189             :                         talloc_asprintf(torture, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
     190             :         }
     191             : 
     192           2 :         smbcli_close(cli->tree, fnum);
     193             : 
     194           2 :         if (!smbcli_file_exists(cli->tree, fname)) {
     195           0 :                 torture_fail(torture, talloc_asprintf(torture, "%s does not exist\n", fname));
     196             :         }
     197             : 
     198             :         /* R/W file should be visible everywhere */
     199             : 
     200           2 :         status = smbcli_chmod(cli->tree, fname, UNIX_R_USR|UNIX_W_USR);
     201           2 :         torture_assert_ntstatus_ok(torture, status, "smbcli_chmod failed\n");
     202             : 
     203           2 :         if (!is_writeable(torture, cli->tree, fname)) {
     204           0 :                 torture_fail(torture, "File not writable\n");
     205             :         }
     206           2 :         if (!is_readable(cli->tree, fname)) {
     207           0 :                 torture_fail(torture, "File not readable\n");
     208             :         }
     209           2 :         if (!is_visible(cli->tree, fname)) {
     210           0 :                 torture_fail(torture, "r/w file not visible via normal share\n");
     211             :         }
     212           2 :         if (!is_visible(hideunread, fname)) {
     213           0 :                 torture_fail(torture, "r/w file not visible via hide unreadable\n");
     214             :         }
     215           2 :         if (!is_visible(hideunwrite, fname)) {
     216           0 :                 torture_fail(torture, "r/w file not visible via hide unwriteable\n");
     217             :         }
     218             : 
     219             :         /* R/O file should not be visible via hide unwriteable files */
     220             : 
     221           2 :         status = smbcli_chmod(cli->tree, fname, UNIX_R_USR);
     222           2 :         torture_assert_ntstatus_ok(torture, status, "smbcli_chmod failed\n");
     223             : 
     224           2 :         if (is_writeable(torture, cli->tree, fname)) {
     225           0 :                 torture_fail(torture, "r/o is writable\n");
     226             :         }
     227           2 :         if (!is_readable(cli->tree, fname)) {
     228           0 :                 torture_fail(torture, "r/o not readable\n");
     229             :         }
     230           2 :         if (!is_visible(cli->tree, fname)) {
     231           0 :                 torture_fail(torture, "r/o file not visible via normal share\n");
     232             :         }
     233           2 :         if (!is_visible(hideunread, fname)) {
     234           0 :                 torture_fail(torture, "r/o file not visible via hide unreadable\n");
     235             :         }
     236           2 :         if (is_visible(hideunwrite, fname)) {
     237           0 :                 torture_fail(torture, "r/o file visible via hide unwriteable\n");
     238             :         }
     239             : 
     240             :         /* inaccessible file should be only visible on normal share */
     241             : 
     242           2 :         status = smbcli_chmod(cli->tree, fname, 0);
     243           2 :         torture_assert_ntstatus_ok(torture, status, "smbcli_chmod failed\n");
     244             : 
     245           2 :         if (is_writeable(torture, cli->tree, fname)) {
     246           0 :                 torture_fail(torture, "inaccessible file is writable\n");
     247             :         }
     248           2 :         if (is_readable(cli->tree, fname)) {
     249           0 :                 torture_fail(torture, "inaccessible file is readable\n");
     250             :         }
     251           2 :         if (!is_visible(cli->tree, fname)) {
     252           0 :                 torture_fail(torture, "inaccessible file not visible via normal share\n");
     253             :         }
     254           2 :         if (is_visible(hideunread, fname)) {
     255           0 :                 torture_fail(torture, "inaccessible file visible via hide unreadable\n");
     256             :         }
     257           2 :         if (is_visible(hideunwrite, fname)) {
     258           0 :                 torture_fail(torture, "inaccessible file visible via hide unwriteable\n");
     259             :         }
     260             : 
     261           2 :         smbcli_chmod(cli->tree, fname, UNIX_R_USR|UNIX_W_USR);
     262           2 :         smbcli_unlink(cli->tree, fname);
     263             :         
     264           2 :         return true;
     265             : }
     266             : 
     267             : /*
     268             :  * Try to force smb_close to return an error. The only way I can think of is
     269             :  * to open a file with delete on close, chmod the parent dir to 000 and then
     270             :  * close. smb_close should return NT_STATUS_ACCESS_DENIED.
     271             :  */
     272             : 
     273           6 : bool torture_samba3_closeerr(struct torture_context *tctx, struct smbcli_state *cli)
     274             : {
     275           6 :         bool result = false;
     276           0 :         NTSTATUS status;
     277           6 :         const char *dname = "closeerr.dir";
     278           6 :         const char *fname = "closeerr.dir\\closerr.txt";
     279           0 :         int fnum;
     280             : 
     281           6 :         smbcli_deltree(cli->tree, dname);
     282             : 
     283           6 :         torture_assert_ntstatus_ok(
     284             :                 tctx, smbcli_mkdir(cli->tree, dname),
     285             :                 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
     286             :                                 smbcli_errstr(cli->tree)));
     287             : 
     288           6 :         fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR,
     289             :                             DENY_NONE);
     290           6 :         torture_assert(tctx, fnum != -1, 
     291             :                        talloc_asprintf(tctx, "smbcli_open failed: %s\n",
     292             :                                        smbcli_errstr(cli->tree)));
     293           6 :         smbcli_close(cli->tree, fnum);
     294             : 
     295           6 :         fnum = smbcli_nt_create_full(cli->tree, fname, 0, 
     296             :                                       SEC_RIGHTS_FILE_ALL,
     297             :                                       FILE_ATTRIBUTE_NORMAL,
     298             :                                       NTCREATEX_SHARE_ACCESS_DELETE,
     299             :                                       NTCREATEX_DISP_OPEN, 0, 0);
     300             : 
     301           6 :         torture_assert(tctx, fnum != -1, 
     302             :                        talloc_asprintf(tctx, "smbcli_open failed: %s\n",
     303             :                                        smbcli_errstr(cli->tree)));
     304             : 
     305           6 :         status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
     306             : 
     307           6 :         torture_assert_ntstatus_ok(tctx, status, 
     308             :                                    "setting delete_on_close on file failed !");
     309             : 
     310           6 :         status = smbcli_chmod(cli->tree, dname, 0);
     311             : 
     312           6 :         torture_assert_ntstatus_ok(tctx, status, 
     313             :                                    "smbcli_chmod on file failed !");
     314             : 
     315           0 :         status = smbcli_close(cli->tree, fnum);
     316             : 
     317           0 :         smbcli_chmod(cli->tree, dname, UNIX_R_USR|UNIX_W_USR|UNIX_X_USR);
     318           0 :         smbcli_deltree(cli->tree, dname);
     319             : 
     320           0 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_ACCESS_DENIED,
     321             :                                       "smbcli_close");
     322             : 
     323           0 :         result = true;
     324             :         
     325           0 :         return result;
     326             : }

Generated by: LCOV version 1.14