source: trunk/server/source4/torture/raw/samba3hide.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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