s4-torture: ran minimal_includes.pl over source4/torture
[Samba/ekacnet.git] / source4 / torture / raw / samba3hide.c
blob4f9e2ecf8fd1afc95a03ca7bcbf673e532665f9a
1 /*
2 Unix SMB/CIFS implementation.
3 Test samba3 hide unreadable/unwriteable
4 Copyright (C) Volker Lendecke 2006
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 "system/time.h"
22 #include "system/filesys.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
26 static void init_unixinfo_nochange(union smb_setfileinfo *info)
28 ZERO_STRUCTP(info);
29 info->unix_basic.level = RAW_SFILEINFO_UNIX_BASIC;
30 info->unix_basic.in.mode = SMB_MODE_NO_CHANGE;
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;
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;
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;
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;
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;
52 info->unix_basic.in.uid = SMB_UID_NO_CHANGE;
53 info->unix_basic.in.gid = SMB_GID_NO_CHANGE;
56 struct list_state {
57 const char *fname;
58 bool visible;
61 static void set_visible(struct clilist_file_info *i, const char *mask,
62 void *priv)
64 struct list_state *state = (struct list_state *)priv;
66 if (strcasecmp_m(state->fname, i->name) == 0)
67 state->visible = true;
70 static bool is_visible(struct smbcli_tree *tree, const char *fname)
72 struct list_state state;
74 state.visible = false;
75 state.fname = fname;
77 if (smbcli_list(tree, "*.*", 0, set_visible, &state) < 0) {
78 return false;
80 return state.visible;
83 static bool is_readable(struct smbcli_tree *tree, const char *fname)
85 int fnum;
86 fnum = smbcli_open(tree, fname, O_RDONLY, DENY_NONE);
87 if (fnum < 0) {
88 return false;
90 smbcli_close(tree, fnum);
91 return true;
94 static bool is_writeable(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
95 const char *fname)
97 int fnum;
98 fnum = smbcli_open(tree, fname, O_WRONLY, DENY_NONE);
99 if (fnum < 0) {
100 return false;
102 smbcli_close(tree, fnum);
103 return true;
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.
111 static bool smbcli_file_exists(struct smbcli_tree *tree, const char *fname)
113 return NT_STATUS_IS_OK(smbcli_getatr(tree, fname, NULL, NULL, NULL));
116 static NTSTATUS smbcli_chmod(struct smbcli_tree *tree, const char *fname,
117 uint64_t permissions)
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);
126 bool torture_samba3_hide(struct torture_context *torture)
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;
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 d_printf("torture_open_connection_share failed\n");
139 return false;
142 status = torture_second_tcon(torture, cli->session, "hideunread",
143 &hideunread);
144 if (!NT_STATUS_IS_OK(status)) {
145 d_printf("second_tcon(hideunread) failed: %s\n",
146 nt_errstr(status));
147 return false;
150 status = torture_second_tcon(torture, cli->session, "hideunwrite",
151 &hideunwrite);
152 if (!NT_STATUS_IS_OK(status)) {
153 d_printf("second_tcon(hideunwrite) failed: %s\n",
154 nt_errstr(status));
155 return false;
158 status = smbcli_unlink(cli->tree, fname);
159 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
160 smbcli_setatr(cli->tree, fname, 0, -1);
161 smbcli_unlink(cli->tree, fname);
164 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
165 if (fnum == -1) {
166 d_printf("Failed to create %s - %s\n", fname,
167 smbcli_errstr(cli->tree));
168 return false;
171 smbcli_close(cli->tree, fnum);
173 if (!smbcli_file_exists(cli->tree, fname)) {
174 d_printf("%s does not exist\n", fname);
175 return false;
178 /* R/W file should be visible everywhere */
180 status = smbcli_chmod(cli->tree, fname, UNIX_R_USR|UNIX_W_USR);
181 if (!NT_STATUS_IS_OK(status)) {
182 d_printf("smbcli_chmod failed: %s\n", nt_errstr(status));
183 return false;
185 if (!is_writeable(torture, cli->tree, fname)) {
186 d_printf("File not writable\n");
187 return false;
189 if (!is_readable(cli->tree, fname)) {
190 d_printf("File not readable\n");
191 return false;
193 if (!is_visible(cli->tree, fname)) {
194 d_printf("r/w file not visible via normal share\n");
195 return false;
197 if (!is_visible(hideunread, fname)) {
198 d_printf("r/w file not visible via hide unreadable\n");
199 return false;
201 if (!is_visible(hideunwrite, fname)) {
202 d_printf("r/w file not visible via hide unwriteable\n");
203 return false;
206 /* R/O file should not be visible via hide unwriteable files */
208 status = smbcli_chmod(cli->tree, fname, UNIX_R_USR);
210 if (!NT_STATUS_IS_OK(status)) {
211 d_printf("smbcli_chmod failed: %s\n", nt_errstr(status));
212 return false;
214 if (is_writeable(torture, cli->tree, fname)) {
215 d_printf("r/o is writable\n");
216 return false;
218 if (!is_readable(cli->tree, fname)) {
219 d_printf("r/o not readable\n");
220 return false;
222 if (!is_visible(cli->tree, fname)) {
223 d_printf("r/o file not visible via normal share\n");
224 return false;
226 if (!is_visible(hideunread, fname)) {
227 d_printf("r/o file not visible via hide unreadable\n");
228 return false;
230 if (is_visible(hideunwrite, fname)) {
231 d_printf("r/o file visible via hide unwriteable\n");
232 return false;
235 /* inaccessible file should be only visible on normal share */
237 status = smbcli_chmod(cli->tree, fname, 0);
238 if (!NT_STATUS_IS_OK(status)) {
239 d_printf("smbcli_chmod failed: %s\n", nt_errstr(status));
240 return false;
242 if (is_writeable(torture, cli->tree, fname)) {
243 d_printf("inaccessible file is writable\n");
244 return false;
246 if (is_readable(cli->tree, fname)) {
247 d_printf("inaccessible file is readable\n");
248 return false;
250 if (!is_visible(cli->tree, fname)) {
251 d_printf("inaccessible file not visible via normal share\n");
252 return false;
254 if (is_visible(hideunread, fname)) {
255 d_printf("inaccessible file visible via hide unreadable\n");
256 return false;
258 if (is_visible(hideunwrite, fname)) {
259 d_printf("inaccessible file visible via hide unwriteable\n");
260 return false;
263 smbcli_chmod(cli->tree, fname, UNIX_R_USR|UNIX_W_USR);
264 smbcli_unlink(cli->tree, fname);
266 return true;
270 * Try to force smb_close to return an error. The only way I can think of is
271 * to open a file with delete on close, chmod the parent dir to 000 and then
272 * close. smb_close should return NT_STATUS_ACCESS_DENIED.
275 bool torture_samba3_closeerr(struct torture_context *tctx)
277 struct smbcli_state *cli = NULL;
278 bool result = false;
279 NTSTATUS status;
280 const char *dname = "closeerr.dir";
281 const char *fname = "closeerr.dir\\closerr.txt";
282 int fnum;
284 if (!torture_open_connection(&cli, tctx, 0)) {
285 goto fail;
288 smbcli_deltree(cli->tree, dname);
290 torture_assert_ntstatus_ok(
291 tctx, smbcli_mkdir(cli->tree, dname),
292 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
293 smbcli_errstr(cli->tree)));
295 fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR,
296 DENY_NONE);
297 torture_assert(tctx, fnum != -1,
298 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
299 smbcli_errstr(cli->tree)));
300 smbcli_close(cli->tree, fnum);
302 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
303 SEC_RIGHTS_FILE_ALL,
304 FILE_ATTRIBUTE_NORMAL,
305 NTCREATEX_SHARE_ACCESS_DELETE,
306 NTCREATEX_DISP_OPEN, 0, 0);
308 torture_assert(tctx, fnum != -1,
309 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
310 smbcli_errstr(cli->tree)));
312 status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
314 torture_assert_ntstatus_ok(tctx, status,
315 "setting delete_on_close on file failed !");
317 status = smbcli_chmod(cli->tree, dname, 0);
319 torture_assert_ntstatus_ok(tctx, status,
320 "smbcli_chmod on file failed !");
322 status = smbcli_close(cli->tree, fnum);
324 smbcli_chmod(cli->tree, dname, UNIX_R_USR|UNIX_W_USR|UNIX_X_USR);
325 smbcli_deltree(cli->tree, dname);
327 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_ACCESS_DENIED,
328 "smbcli_close");
330 result = true;
332 fail:
333 if (cli) {
334 torture_close_connection(cli);
336 return result;