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

Last change on this file was 920, checked in by Silvan Scherrer, 9 years ago

Samba Server: apply latest security patches to trunk

File size: 30.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Test some misc Samba3 code paths
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 "torture/torture.h"
22#include "libcli/raw/libcliraw.h"
23#include "libcli/raw/raw_proto.h"
24#include "system/time.h"
25#include "system/filesys.h"
26#include "libcli/libcli.h"
27#include "torture/util.h"
28#include "lib/events/events.h"
29#include "param/param.h"
30
31#define CHECK_STATUS(status, correct) do { \
32 if (!NT_STATUS_EQUAL(status, correct)) { \
33 printf("(%s) Incorrect status %s - should be %s\n", \
34 __location__, nt_errstr(status), nt_errstr(correct)); \
35 ret = false; \
36 } \
37} while (0)
38
39bool torture_samba3_checkfsp(struct torture_context *torture)
40{
41 struct smbcli_state *cli;
42 const char *fname = "test.txt";
43 const char *dirname = "testdir";
44 int fnum;
45 NTSTATUS status;
46 bool ret = true;
47 TALLOC_CTX *mem_ctx;
48 ssize_t nread;
49 char buf[16];
50 struct smbcli_tree *tree2;
51
52 if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
53 d_printf("talloc_init failed\n");
54 return false;
55 }
56
57 if (!torture_open_connection_share(
58 torture, &cli, torture, torture_setting_string(torture, "host", NULL),
59 torture_setting_string(torture, "share", NULL), torture->ev)) {
60 d_printf("torture_open_connection_share failed\n");
61 ret = false;
62 goto done;
63 }
64
65 smbcli_deltree(cli->tree, dirname);
66
67 status = torture_second_tcon(torture, cli->session,
68 torture_setting_string(torture, "share", NULL),
69 &tree2);
70 CHECK_STATUS(status, NT_STATUS_OK);
71 if (!NT_STATUS_IS_OK(status))
72 goto done;
73
74 /* Try a read on an invalid FID */
75
76 nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
77 CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
78
79 /* Try a read on a directory handle */
80
81 status = smbcli_mkdir(cli->tree, dirname);
82 if (!NT_STATUS_IS_OK(status)) {
83 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
84 ret = false;
85 goto done;
86 }
87
88 /* Open the directory */
89 {
90 union smb_open io;
91 io.generic.level = RAW_OPEN_NTCREATEX;
92 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
93 io.ntcreatex.in.root_fid.fnum = 0;
94 io.ntcreatex.in.security_flags = 0;
95 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
96 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
97 io.ntcreatex.in.alloc_size = 0;
98 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
99 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
100 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
101 io.ntcreatex.in.create_options = 0;
102 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
103 io.ntcreatex.in.fname = dirname;
104 status = smb_raw_open(cli->tree, mem_ctx, &io);
105 if (!NT_STATUS_IS_OK(status)) {
106 d_printf("smb_open on the directory failed: %s\n",
107 nt_errstr(status));
108 ret = false;
109 goto done;
110 }
111 fnum = io.ntcreatex.out.file.fnum;
112 }
113
114 /* Try a read on the directory */
115
116 nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
117 if (nread >= 0) {
118 d_printf("smbcli_read on a directory succeeded, expected "
119 "failure\n");
120 ret = false;
121 }
122
123 CHECK_STATUS(smbcli_nt_error(cli->tree),
124 NT_STATUS_INVALID_DEVICE_REQUEST);
125
126 /* Same test on the second tcon */
127
128 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
129 if (nread >= 0) {
130 d_printf("smbcli_read on a directory succeeded, expected "
131 "failure\n");
132 ret = false;
133 }
134
135 CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
136
137 smbcli_close(cli->tree, fnum);
138
139 /* Try a normal file read on a second tcon */
140
141 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
142 if (fnum == -1) {
143 d_printf("Failed to create %s - %s\n", fname,
144 smbcli_errstr(cli->tree));
145 ret = false;
146 goto done;
147 }
148
149 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
150 CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
151
152 smbcli_close(cli->tree, fnum);
153
154 done:
155 smbcli_deltree(cli->tree, dirname);
156 torture_close_connection(cli);
157 talloc_free(mem_ctx);
158
159 return ret;
160}
161
162static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
163{
164 union smb_open open_parms;
165 unsigned int openfn=0;
166 unsigned int accessmode=0;
167 TALLOC_CTX *mem_ctx;
168 NTSTATUS status;
169
170 mem_ctx = talloc_init("raw_open");
171 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
172
173 if (flags & O_CREAT) {
174 openfn |= OPENX_OPEN_FUNC_CREATE;
175 }
176 if (!(flags & O_EXCL)) {
177 if (flags & O_TRUNC) {
178 openfn |= OPENX_OPEN_FUNC_TRUNC;
179 } else {
180 openfn |= OPENX_OPEN_FUNC_OPEN;
181 }
182 }
183
184 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
185
186 if ((flags & O_ACCMODE) == O_RDWR) {
187 accessmode |= OPENX_MODE_ACCESS_RDWR;
188 } else if ((flags & O_ACCMODE) == O_WRONLY) {
189 accessmode |= OPENX_MODE_ACCESS_WRITE;
190 } else if ((flags & O_ACCMODE) == O_RDONLY) {
191 accessmode |= OPENX_MODE_ACCESS_READ;
192 }
193
194#if defined(O_SYNC)
195 if ((flags & O_SYNC) == O_SYNC) {
196 accessmode |= OPENX_MODE_WRITE_THRU;
197 }
198#endif
199
200 if (share_mode == DENY_FCB) {
201 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
202 }
203
204 open_parms.openx.level = RAW_OPEN_OPENX;
205 open_parms.openx.in.flags = 0;
206 open_parms.openx.in.open_mode = accessmode;
207 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
208 open_parms.openx.in.file_attrs = 0;
209 open_parms.openx.in.write_time = 0;
210 open_parms.openx.in.open_func = openfn;
211 open_parms.openx.in.size = 0;
212 open_parms.openx.in.timeout = 0;
213 open_parms.openx.in.fname = fname;
214
215 status = smb_raw_open(tree, mem_ctx, &open_parms);
216 talloc_free(mem_ctx);
217
218 if (fnum && NT_STATUS_IS_OK(status)) {
219 *fnum = open_parms.openx.out.file.fnum;
220 }
221
222 return status;
223}
224
225static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
226{
227 union smb_open io;
228 unsigned int openfn=0;
229 unsigned int accessmode=0;
230 TALLOC_CTX *mem_ctx;
231 NTSTATUS status;
232
233 mem_ctx = talloc_init("raw_t2open");
234 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
235
236 if (flags & O_CREAT) {
237 openfn |= OPENX_OPEN_FUNC_CREATE;
238 }
239 if (!(flags & O_EXCL)) {
240 if (flags & O_TRUNC) {
241 openfn |= OPENX_OPEN_FUNC_TRUNC;
242 } else {
243 openfn |= OPENX_OPEN_FUNC_OPEN;
244 }
245 }
246
247 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
248
249 if ((flags & O_ACCMODE) == O_RDWR) {
250 accessmode |= OPENX_MODE_ACCESS_RDWR;
251 } else if ((flags & O_ACCMODE) == O_WRONLY) {
252 accessmode |= OPENX_MODE_ACCESS_WRITE;
253 } else if ((flags & O_ACCMODE) == O_RDONLY) {
254 accessmode |= OPENX_MODE_ACCESS_READ;
255 }
256
257#if defined(O_SYNC)
258 if ((flags & O_SYNC) == O_SYNC) {
259 accessmode |= OPENX_MODE_WRITE_THRU;
260 }
261#endif
262
263 if (share_mode == DENY_FCB) {
264 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
265 }
266
267 memset(&io, '\0', sizeof(io));
268 io.t2open.level = RAW_OPEN_T2OPEN;
269 io.t2open.in.flags = 0;
270 io.t2open.in.open_mode = accessmode;
271 io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
272 io.t2open.in.file_attrs = 0;
273 io.t2open.in.write_time = 0;
274 io.t2open.in.open_func = openfn;
275 io.t2open.in.size = 0;
276 io.t2open.in.timeout = 0;
277 io.t2open.in.fname = fname;
278
279 io.t2open.in.num_eas = 1;
280 io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
281 io.t2open.in.eas[0].flags = 0;
282 io.t2open.in.eas[0].name.s = ".CLASSINFO";
283 io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
284
285 status = smb_raw_open(tree, mem_ctx, &io);
286 talloc_free(mem_ctx);
287
288 if (fnum && NT_STATUS_IS_OK(status)) {
289 *fnum = io.openx.out.file.fnum;
290 }
291
292 return status;
293}
294
295static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
296{
297 union smb_open io;
298 TALLOC_CTX *mem_ctx;
299 NTSTATUS status;
300
301 mem_ctx = talloc_init("raw_t2open");
302 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
303
304 memset(&io, '\0', sizeof(io));
305 io.generic.level = RAW_OPEN_NTCREATEX;
306 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
307 io.ntcreatex.in.root_fid.fnum = 0;
308 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
309 io.ntcreatex.in.alloc_size = 0;
310 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
311 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
312 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
313 io.ntcreatex.in.create_options = 0;
314 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
315 io.ntcreatex.in.security_flags = 0;
316 io.ntcreatex.in.fname = fname;
317
318 status = smb_raw_open(tree, mem_ctx, &io);
319 talloc_free(mem_ctx);
320
321 if (fnum && NT_STATUS_IS_OK(status)) {
322 *fnum = io.openx.out.file.fnum;
323 }
324
325 return status;
326}
327
328
329bool torture_samba3_badpath(struct torture_context *torture)
330{
331 struct smbcli_state *cli_nt;
332 struct smbcli_state *cli_dos;
333 const char *fname = "test.txt";
334 const char *fname1 = "test1.txt";
335 const char *dirname = "testdir";
336 char *fpath;
337 char *fpath1;
338 int fnum;
339 NTSTATUS status;
340 bool ret = true;
341 TALLOC_CTX *mem_ctx;
342 bool nt_status_support;
343 bool client_ntlmv2_auth;
344
345 if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
346 d_printf("talloc_init failed\n");
347 return false;
348 }
349
350 nt_status_support = lpcfg_nt_status_support(torture->lp_ctx);
351 client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(torture->lp_ctx);
352
353 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n");
354 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", "yes"), ret, fail, "Could not set 'client ntlmv2 auth = yes'\n");
355
356 if (!torture_open_connection(&cli_nt, torture, 0)) {
357 goto fail;
358 }
359
360 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n");
361 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", "no"), ret, fail, "Could not set 'client ntlmv2 auth = no'\n");
362
363 if (!torture_open_connection(&cli_dos, torture, 1)) {
364 goto fail;
365 }
366
367 if (!lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
368 nt_status_support ? "yes":"no")) {
369 printf("Could not reset 'nt status support = yes'");
370 goto fail;
371 }
372
373 smbcli_deltree(cli_nt->tree, dirname);
374 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
375 nt_status_support ? "yes":"no"),
376 ret, fail, "Could not set 'nt status support' back to where it was\n");
377 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth",
378 client_ntlmv2_auth ? "yes":"no"),
379 ret, fail, "Could not set 'client ntlmv2 auth' back to where it was\n");
380
381 status = smbcli_mkdir(cli_nt->tree, dirname);
382 if (!NT_STATUS_IS_OK(status)) {
383 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
384 ret = false;
385 goto done;
386 }
387
388 status = smbcli_chkpath(cli_nt->tree, dirname);
389 CHECK_STATUS(status, NT_STATUS_OK);
390
391 status = smbcli_chkpath(cli_nt->tree,
392 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
393 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
394
395 status = smbcli_chkpath(cli_dos->tree,
396 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
397 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
398
399 status = smbcli_chkpath(cli_nt->tree,
400 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
401 dirname));
402 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
403 status = smbcli_chkpath(cli_dos->tree,
404 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
405 dirname));
406 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
407
408 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
409 goto fail;
410 }
411 fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
412 if (fnum == -1) {
413 d_printf("Could not create file %s: %s\n", fpath,
414 smbcli_errstr(cli_nt->tree));
415 goto fail;
416 }
417 smbcli_close(cli_nt->tree, fnum);
418
419 if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
420 goto fail;
421 }
422 fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
423 if (fnum == -1) {
424 d_printf("Could not create file %s: %s\n", fpath1,
425 smbcli_errstr(cli_nt->tree));
426 goto fail;
427 }
428 smbcli_close(cli_nt->tree, fnum);
429
430 /*
431 * Do a whole bunch of error code checks on chkpath
432 */
433
434 status = smbcli_chkpath(cli_nt->tree, fpath);
435 CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
436 status = smbcli_chkpath(cli_dos->tree, fpath);
437 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
438
439 status = smbcli_chkpath(cli_nt->tree, "..");
440 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
441 status = smbcli_chkpath(cli_dos->tree, "..");
442 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
443
444 status = smbcli_chkpath(cli_nt->tree, ".");
445 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
446 status = smbcli_chkpath(cli_dos->tree, ".");
447 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
448
449 status = smbcli_chkpath(cli_nt->tree, "\t");
450 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
451 status = smbcli_chkpath(cli_dos->tree, "\t");
452 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
453
454 status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
455 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
456 status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
457 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
458
459 status = smbcli_chkpath(cli_nt->tree, "<");
460 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
461 status = smbcli_chkpath(cli_dos->tree, "<");
462 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
463
464 status = smbcli_chkpath(cli_nt->tree, "<\\bla");
465 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
466 status = smbcli_chkpath(cli_dos->tree, "<\\bla");
467 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
468
469 /*
470 * .... And the same gang against getatr. Note that the DOS error codes
471 * differ....
472 */
473
474 status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
475 CHECK_STATUS(status, NT_STATUS_OK);
476 status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
477 CHECK_STATUS(status, NT_STATUS_OK);
478
479 status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
480 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
481 status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
482 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
483
484 status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
485 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
486 status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
487 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
488
489 status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
490 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
491 status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
492 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
493
494 status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
495 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
496 status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
497 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
498
499 status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
500 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
501 status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
502 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
503
504 status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
505 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
506 status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
507 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
508
509 /* Try the same set with openX. */
510
511 status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
512 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
513 status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
514 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
515
516 status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
517 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
518 status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
519 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
520
521 status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
522 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
523 status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
524 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
525
526 status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
527 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
528 status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
529 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
530
531 status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
532 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
533 status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
534 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
535
536 status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
537 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
538 status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
539 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
540
541 /* Let's test EEXIST error code mapping. */
542 status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
543 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
544 status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
545 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
546
547 status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
548 if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
549 || !torture_setting_bool(torture, "samba3", false)) {
550 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
551 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
552 }
553 status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
554 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
555 || !torture_setting_bool(torture, "samba3", false)) {
556 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
557 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
558 }
559
560 status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
561 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
562 status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
563 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
564
565 /* Try the rename test. */
566 {
567 union smb_rename io;
568 memset(&io, '\0', sizeof(io));
569 io.rename.in.pattern1 = fpath1;
570 io.rename.in.pattern2 = fpath;
571
572 /* Try with SMBmv rename. */
573 status = smb_raw_rename(cli_nt->tree, &io);
574 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
575 status = smb_raw_rename(cli_dos->tree, &io);
576 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
577
578 /* Try with NT rename. */
579 io.generic.level = RAW_RENAME_NTRENAME;
580 io.ntrename.in.old_name = fpath1;
581 io.ntrename.in.new_name = fpath;
582 io.ntrename.in.attrib = 0;
583 io.ntrename.in.cluster_size = 0;
584 io.ntrename.in.flags = RENAME_FLAG_RENAME;
585
586 status = smb_raw_rename(cli_nt->tree, &io);
587 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
588 status = smb_raw_rename(cli_dos->tree, &io);
589 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
590 }
591
592 goto done;
593
594 fail:
595 ret = false;
596
597 done:
598 if (cli_nt != NULL) {
599 smbcli_deltree(cli_nt->tree, dirname);
600 torture_close_connection(cli_nt);
601 }
602 if (cli_dos != NULL) {
603 torture_close_connection(cli_dos);
604 }
605 talloc_free(mem_ctx);
606
607 return ret;
608}
609
610static void count_fn(struct clilist_file_info *info, const char *name,
611 void *private_data)
612{
613 int *counter = (int *)private_data;
614 *counter += 1;
615}
616
617bool torture_samba3_caseinsensitive(struct torture_context *torture)
618{
619 struct smbcli_state *cli;
620 TALLOC_CTX *mem_ctx;
621 NTSTATUS status;
622 const char *dirname = "insensitive";
623 const char *ucase_dirname = "InSeNsItIvE";
624 const char *fname = "foo";
625 char *fpath;
626 int fnum;
627 int counter = 0;
628 bool ret = false;
629
630 if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
631 d_printf("talloc_init failed\n");
632 return false;
633 }
634
635 if (!torture_open_connection(&cli, torture, 0)) {
636 goto done;
637 }
638
639 smbcli_deltree(cli->tree, dirname);
640
641 status = smbcli_mkdir(cli->tree, dirname);
642 torture_assert_ntstatus_ok(torture, status, "smbcli_mkdir failed");
643 if (!NT_STATUS_IS_OK(status)) {
644 goto done;
645 }
646
647 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
648 goto done;
649 }
650 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
651 if (fnum == -1) {
652 torture_result(torture, TORTURE_FAIL,
653 "Could not create file %s: %s", fpath,
654 smbcli_errstr(cli->tree));
655 goto done;
656 }
657 smbcli_close(cli->tree, fnum);
658
659 smbcli_list(cli->tree, talloc_asprintf(
660 mem_ctx, "%s\\*", ucase_dirname),
661 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
662 |FILE_ATTRIBUTE_SYSTEM,
663 count_fn, (void *)&counter);
664
665 if (counter == 3) {
666 ret = true;
667 }
668 else {
669 torture_result(torture, TORTURE_FAIL,
670 "expected 3 entries, got %d", counter);
671 ret = false;
672 }
673
674 done:
675 talloc_free(mem_ctx);
676 return ret;
677}
678
679static void close_locked_file(struct tevent_context *ev,
680 struct tevent_timer *te,
681 struct timeval now,
682 void *private_data)
683{
684 int *pfd = (int *)private_data;
685
686 TALLOC_FREE(te);
687
688 if (*pfd != -1) {
689 close(*pfd);
690 *pfd = -1;
691 }
692}
693
694struct lock_result_state {
695 NTSTATUS status;
696 bool done;
697};
698
699static void receive_lock_result(struct smbcli_request *req)
700{
701 struct lock_result_state *state =
702 (struct lock_result_state *)req->async.private_data;
703
704 state->status = smbcli_request_simple_recv(req);
705 state->done = true;
706}
707
708/*
709 * Check that Samba3 correctly deals with conflicting posix byte range locks
710 * on an underlying file
711 *
712 * Note: This test depends on "posix locking = yes".
713 * Note: To run this test, use "--option=torture:localdir=<LOCALDIR>"
714 */
715
716bool torture_samba3_posixtimedlock(struct torture_context *tctx)
717{
718 struct smbcli_state *cli;
719 NTSTATUS status;
720 bool ret = true;
721 const char *dirname = "posixlock";
722 const char *fname = "locked";
723 const char *fpath;
724 const char *localdir;
725 const char *localname;
726 int fnum = -1;
727
728 int fd = -1;
729 struct flock posix_lock;
730
731 union smb_lock io;
732 struct smb_lock_entry lock_entry;
733 struct smbcli_request *req;
734 struct lock_result_state lock_result;
735
736 struct tevent_timer *te;
737
738 if (!torture_open_connection(&cli, tctx, 0)) {
739 ret = false;
740 goto done;
741 }
742
743 smbcli_deltree(cli->tree, dirname);
744
745 status = smbcli_mkdir(cli->tree, dirname);
746 if (!NT_STATUS_IS_OK(status)) {
747 torture_warning(tctx, "smbcli_mkdir failed: %s\n",
748 nt_errstr(status));
749 ret = false;
750 goto done;
751 }
752
753 if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
754 torture_warning(tctx, "talloc failed\n");
755 ret = false;
756 goto done;
757 }
758 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
759 if (fnum == -1) {
760 torture_warning(tctx, "Could not create file %s: %s\n", fpath,
761 smbcli_errstr(cli->tree));
762 ret = false;
763 goto done;
764 }
765
766 if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
767 torture_warning(tctx, "Need 'localdir' setting\n");
768 ret = false;
769 goto done;
770 }
771
772 if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
773 fname))) {
774 torture_warning(tctx, "talloc failed\n");
775 ret = false;
776 goto done;
777 }
778
779 /*
780 * Lock a byte range from posix
781 */
782
783 fd = open(localname, O_RDWR);
784 if (fd == -1) {
785 torture_warning(tctx, "open(%s) failed: %s\n",
786 localname, strerror(errno));
787 goto done;
788 }
789
790 posix_lock.l_type = F_WRLCK;
791 posix_lock.l_whence = SEEK_SET;
792 posix_lock.l_start = 0;
793 posix_lock.l_len = 1;
794
795 if (fcntl(fd, F_SETLK, &posix_lock) == -1) {
796 torture_warning(tctx, "fcntl failed: %s\n", strerror(errno));
797 ret = false;
798 goto done;
799 }
800
801 /*
802 * Try a cifs brlock without timeout to see if posix locking = yes
803 */
804
805 io.lockx.in.ulock_cnt = 0;
806 io.lockx.in.lock_cnt = 1;
807
808 lock_entry.count = 1;
809 lock_entry.offset = 0;
810 lock_entry.pid = cli->tree->session->pid;
811
812 io.lockx.level = RAW_LOCK_LOCKX;
813 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
814 io.lockx.in.timeout = 0;
815 io.lockx.in.locks = &lock_entry;
816 io.lockx.in.file.fnum = fnum;
817
818 status = smb_raw_lock(cli->tree, &io);
819
820 ret = true;
821 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
822
823 if (!ret) {
824 goto done;
825 }
826
827 /*
828 * Now fire off a timed brlock, unlock the posix lock and see if the
829 * timed lock gets through.
830 */
831
832 io.lockx.in.timeout = 5000;
833
834 req = smb_raw_lock_send(cli->tree, &io);
835 if (req == NULL) {
836 torture_warning(tctx, "smb_raw_lock_send failed\n");
837 ret = false;
838 goto done;
839 }
840
841 lock_result.done = false;
842 req->async.fn = receive_lock_result;
843 req->async.private_data = &lock_result;
844
845 te = tevent_add_timer(req->transport->socket->event.ctx,
846 tctx, timeval_current_ofs(1, 0),
847 close_locked_file, &fd);
848 if (te == NULL) {
849 torture_warning(tctx, "tevent_add_timer failed\n");
850 ret = false;
851 goto done;
852 }
853
854 while ((fd != -1) || (!lock_result.done)) {
855 if (tevent_loop_once(req->transport->socket->event.ctx)
856 == -1) {
857 torture_warning(tctx, "tevent_loop_once failed: %s\n",
858 strerror(errno));
859 ret = false;
860 goto done;
861 }
862 }
863
864 CHECK_STATUS(lock_result.status, NT_STATUS_OK);
865
866 done:
867 if (fnum != -1) {
868 smbcli_close(cli->tree, fnum);
869 }
870 if (fd != -1) {
871 close(fd);
872 }
873 smbcli_deltree(cli->tree, dirname);
874 return ret;
875}
876
877bool torture_samba3_rootdirfid(struct torture_context *tctx)
878{
879 struct smbcli_state *cli;
880 NTSTATUS status;
881 uint16_t dnum;
882 union smb_open io;
883 const char *fname = "testfile";
884 bool ret = false;
885
886 if (!torture_open_connection(&cli, tctx, 0)) {
887 ret = false;
888 goto done;
889 }
890
891 smbcli_unlink(cli->tree, fname);
892
893 ZERO_STRUCT(io);
894 io.generic.level = RAW_OPEN_NTCREATEX;
895 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
896 io.ntcreatex.in.root_fid.fnum = 0;
897 io.ntcreatex.in.security_flags = 0;
898 io.ntcreatex.in.access_mask =
899 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
900 io.ntcreatex.in.alloc_size = 0;
901 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
902 io.ntcreatex.in.share_access =
903 NTCREATEX_SHARE_ACCESS_READ
904 | NTCREATEX_SHARE_ACCESS_READ;
905 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
906 io.ntcreatex.in.create_options = 0;
907 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
908 io.ntcreatex.in.fname = "\\";
909 status = smb_raw_open(cli->tree, tctx, &io);
910 if (!NT_STATUS_IS_OK(status)) {
911 d_printf("smb_open on the directory failed: %s\n",
912 nt_errstr(status));
913 ret = false;
914 goto done;
915 }
916 dnum = io.ntcreatex.out.file.fnum;
917
918 io.ntcreatex.in.flags =
919 NTCREATEX_FLAGS_REQUEST_OPLOCK
920 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
921 io.ntcreatex.in.root_fid.fnum = dnum;
922 io.ntcreatex.in.security_flags = 0;
923 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
924 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
925 io.ntcreatex.in.alloc_size = 0;
926 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
927 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
928 io.ntcreatex.in.create_options = 0;
929 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
930 io.ntcreatex.in.fname = fname;
931
932 status = smb_raw_open(cli->tree, tctx, &io);
933 if (!NT_STATUS_IS_OK(status)) {
934 d_printf("smb_open on the file %s failed: %s\n",
935 fname, nt_errstr(status));
936 ret = false;
937 goto done;
938 }
939
940 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
941 smbcli_close(cli->tree, dnum);
942 smbcli_unlink(cli->tree, fname);
943
944 ret = true;
945 done:
946 return ret;
947}
948
949bool torture_samba3_oplock_logoff(struct torture_context *tctx)
950{
951 struct smbcli_state *cli;
952 NTSTATUS status;
953 uint16_t fnum1;
954 union smb_open io;
955 const char *fname = "testfile";
956 bool ret = false;
957 struct smbcli_request *req;
958 struct smb_echo echo_req;
959
960 if (!torture_open_connection(&cli, tctx, 0)) {
961 ret = false;
962 goto done;
963 }
964
965 smbcli_unlink(cli->tree, fname);
966
967 ZERO_STRUCT(io);
968 io.generic.level = RAW_OPEN_NTCREATEX;
969 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
970 io.ntcreatex.in.root_fid.fnum = 0;
971 io.ntcreatex.in.security_flags = 0;
972 io.ntcreatex.in.access_mask =
973 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
974 io.ntcreatex.in.alloc_size = 0;
975 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
976 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
977 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
978 io.ntcreatex.in.create_options = 0;
979 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
980 io.ntcreatex.in.fname = "testfile";
981 status = smb_raw_open(cli->tree, tctx, &io);
982 if (!NT_STATUS_IS_OK(status)) {
983 d_printf("first smb_open failed: %s\n", nt_errstr(status));
984 ret = false;
985 goto done;
986 }
987 fnum1 = io.ntcreatex.out.file.fnum;
988
989 /*
990 * Create a conflicting open, causing the one-second delay
991 */
992
993 req = smb_raw_open_send(cli->tree, &io);
994 if (req == NULL) {
995 d_printf("smb_raw_open_send failed\n");
996 ret = false;
997 goto done;
998 }
999
1000 /*
1001 * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3
1002 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors
1003 * as long as the client is still connected.
1004 */
1005
1006 status = smb_raw_ulogoff(cli->session);
1007
1008 if (!NT_STATUS_IS_OK(status)) {
1009 d_printf("ulogoff failed: %s\n", nt_errstr(status));
1010 ret = false;
1011 goto done;
1012 }
1013
1014 echo_req.in.repeat_count = 1;
1015 echo_req.in.size = 1;
1016 echo_req.in.data = discard_const_p(uint8_t, "");
1017
1018 status = smb_raw_echo(cli->session->transport, &echo_req);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 d_printf("smb_raw_echo returned %s\n",
1021 nt_errstr(status));
1022 ret = false;
1023 goto done;
1024 }
1025
1026 ret = true;
1027 done:
1028 return ret;
1029}
Note: See TracBrowser for help on using the repository browser.