Add extra bits to our 'netlogon' response in CLDAP and NBT.
[Samba.git] / source4 / torture / raw / samba3misc.c
blob27b4d42dd808937772dc28165314bcabbbbc896f
1 /*
2 Unix SMB/CIFS implementation.
3 Test some misc Samba3 code paths
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 "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"
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)
39 bool torture_samba3_checkfsp(struct torture_context *torture)
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;
52 if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
53 d_printf("talloc_init failed\n");
54 return false;
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;
65 smbcli_deltree(cli->tree, dirname);
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;
74 /* Try a read on an invalid FID */
76 nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
77 CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
79 /* Try a read on a directory handle */
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;
88 /* Open the directory */
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 = 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.fname = dirname;
103 status = smb_raw_open(cli->tree, mem_ctx, &io);
104 if (!NT_STATUS_IS_OK(status)) {
105 d_printf("smb_open on the directory failed: %s\n",
106 nt_errstr(status));
107 ret = false;
108 goto done;
110 fnum = io.ntcreatex.out.file.fnum;
113 /* Try a read on the directory */
115 nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
116 if (nread >= 0) {
117 d_printf("smbcli_read on a directory succeeded, expected "
118 "failure\n");
119 ret = false;
122 CHECK_STATUS(smbcli_nt_error(cli->tree),
123 NT_STATUS_INVALID_DEVICE_REQUEST);
125 /* Same test on the second tcon */
127 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
128 if (nread >= 0) {
129 d_printf("smbcli_read on a directory succeeded, expected "
130 "failure\n");
131 ret = false;
134 CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
136 smbcli_close(cli->tree, fnum);
138 /* Try a normal file read on a second tcon */
140 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
141 if (fnum == -1) {
142 d_printf("Failed to create %s - %s\n", fname,
143 smbcli_errstr(cli->tree));
144 ret = false;
145 goto done;
148 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
149 CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
151 smbcli_close(cli->tree, fnum);
153 done:
154 smbcli_deltree(cli->tree, dirname);
155 torture_close_connection(cli);
156 talloc_free(mem_ctx);
158 return ret;
161 static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
163 union smb_open open_parms;
164 uint_t openfn=0;
165 uint_t accessmode=0;
166 TALLOC_CTX *mem_ctx;
167 NTSTATUS status;
169 mem_ctx = talloc_init("raw_open");
170 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
172 if (flags & O_CREAT) {
173 openfn |= OPENX_OPEN_FUNC_CREATE;
175 if (!(flags & O_EXCL)) {
176 if (flags & O_TRUNC) {
177 openfn |= OPENX_OPEN_FUNC_TRUNC;
178 } else {
179 openfn |= OPENX_OPEN_FUNC_OPEN;
183 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
185 if ((flags & O_ACCMODE) == O_RDWR) {
186 accessmode |= OPENX_MODE_ACCESS_RDWR;
187 } else if ((flags & O_ACCMODE) == O_WRONLY) {
188 accessmode |= OPENX_MODE_ACCESS_WRITE;
189 } else if ((flags & O_ACCMODE) == O_RDONLY) {
190 accessmode |= OPENX_MODE_ACCESS_READ;
193 #if defined(O_SYNC)
194 if ((flags & O_SYNC) == O_SYNC) {
195 accessmode |= OPENX_MODE_WRITE_THRU;
197 #endif
199 if (share_mode == DENY_FCB) {
200 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
203 open_parms.openx.level = RAW_OPEN_OPENX;
204 open_parms.openx.in.flags = 0;
205 open_parms.openx.in.open_mode = accessmode;
206 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
207 open_parms.openx.in.file_attrs = 0;
208 open_parms.openx.in.write_time = 0;
209 open_parms.openx.in.open_func = openfn;
210 open_parms.openx.in.size = 0;
211 open_parms.openx.in.timeout = 0;
212 open_parms.openx.in.fname = fname;
214 status = smb_raw_open(tree, mem_ctx, &open_parms);
215 talloc_free(mem_ctx);
217 if (fnum && NT_STATUS_IS_OK(status)) {
218 *fnum = open_parms.openx.out.file.fnum;
221 return status;
224 static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
226 union smb_open io;
227 uint_t openfn=0;
228 uint_t accessmode=0;
229 TALLOC_CTX *mem_ctx;
230 NTSTATUS status;
232 mem_ctx = talloc_init("raw_t2open");
233 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
235 if (flags & O_CREAT) {
236 openfn |= OPENX_OPEN_FUNC_CREATE;
238 if (!(flags & O_EXCL)) {
239 if (flags & O_TRUNC) {
240 openfn |= OPENX_OPEN_FUNC_TRUNC;
241 } else {
242 openfn |= OPENX_OPEN_FUNC_OPEN;
246 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
248 if ((flags & O_ACCMODE) == O_RDWR) {
249 accessmode |= OPENX_MODE_ACCESS_RDWR;
250 } else if ((flags & O_ACCMODE) == O_WRONLY) {
251 accessmode |= OPENX_MODE_ACCESS_WRITE;
252 } else if ((flags & O_ACCMODE) == O_RDONLY) {
253 accessmode |= OPENX_MODE_ACCESS_READ;
256 #if defined(O_SYNC)
257 if ((flags & O_SYNC) == O_SYNC) {
258 accessmode |= OPENX_MODE_WRITE_THRU;
260 #endif
262 if (share_mode == DENY_FCB) {
263 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
266 memset(&io, '\0', sizeof(io));
267 io.t2open.level = RAW_OPEN_T2OPEN;
268 io.t2open.in.flags = 0;
269 io.t2open.in.open_mode = accessmode;
270 io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
271 io.t2open.in.file_attrs = 0;
272 io.t2open.in.write_time = 0;
273 io.t2open.in.open_func = openfn;
274 io.t2open.in.size = 0;
275 io.t2open.in.timeout = 0;
276 io.t2open.in.fname = fname;
278 io.t2open.in.num_eas = 1;
279 io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
280 io.t2open.in.eas[0].flags = 0;
281 io.t2open.in.eas[0].name.s = ".CLASSINFO";
282 io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
284 status = smb_raw_open(tree, mem_ctx, &io);
285 talloc_free(mem_ctx);
287 if (fnum && NT_STATUS_IS_OK(status)) {
288 *fnum = io.openx.out.file.fnum;
291 return status;
294 static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
296 union smb_open io;
297 TALLOC_CTX *mem_ctx;
298 NTSTATUS status;
300 mem_ctx = talloc_init("raw_t2open");
301 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
303 memset(&io, '\0', sizeof(io));
304 io.generic.level = RAW_OPEN_NTCREATEX;
305 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
306 io.ntcreatex.in.root_fid = 0;
307 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
308 io.ntcreatex.in.alloc_size = 0;
309 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
310 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
311 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
312 io.ntcreatex.in.create_options = 0;
313 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
314 io.ntcreatex.in.security_flags = 0;
315 io.ntcreatex.in.fname = fname;
317 status = smb_raw_open(tree, mem_ctx, &io);
318 talloc_free(mem_ctx);
320 if (fnum && NT_STATUS_IS_OK(status)) {
321 *fnum = io.openx.out.file.fnum;
324 return status;
328 bool torture_samba3_badpath(struct torture_context *torture)
330 struct smbcli_state *cli_nt;
331 struct smbcli_state *cli_dos;
332 const char *fname = "test.txt";
333 const char *fname1 = "test1.txt";
334 const char *dirname = "testdir";
335 char *fpath;
336 char *fpath1;
337 int fnum;
338 NTSTATUS status;
339 bool ret = true;
340 TALLOC_CTX *mem_ctx;
341 bool nt_status_support;
343 if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
344 d_printf("talloc_init failed\n");
345 return false;
348 nt_status_support = lp_nt_status_support(torture->lp_ctx);
350 if (!lp_set_cmdline(torture->lp_ctx, "nt status support", "yes")) {
351 printf("Could not set 'nt status support = yes'\n");
352 goto fail;
355 if (!torture_open_connection(&cli_nt, torture, 0)) {
356 goto fail;
359 if (!lp_set_cmdline(torture->lp_ctx, "nt status support", "no")) {
360 printf("Could not set 'nt status support = yes'\n");
361 goto fail;
364 if (!torture_open_connection(&cli_dos, torture, 1)) {
365 goto fail;
368 if (!lp_set_cmdline(torture->lp_ctx, "nt status support",
369 nt_status_support ? "yes":"no")) {
370 printf("Could not reset 'nt status support = yes'");
371 goto fail;
374 smbcli_deltree(cli_nt->tree, dirname);
376 status = smbcli_mkdir(cli_nt->tree, dirname);
377 if (!NT_STATUS_IS_OK(status)) {
378 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
379 ret = false;
380 goto done;
383 status = smbcli_chkpath(cli_nt->tree, dirname);
384 CHECK_STATUS(status, NT_STATUS_OK);
386 status = smbcli_chkpath(cli_nt->tree,
387 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
388 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
390 status = smbcli_chkpath(cli_dos->tree,
391 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
392 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
394 status = smbcli_chkpath(cli_nt->tree,
395 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
396 dirname));
397 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
398 status = smbcli_chkpath(cli_dos->tree,
399 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
400 dirname));
401 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
403 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
404 goto fail;
406 fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
407 if (fnum == -1) {
408 d_printf("Could not create file %s: %s\n", fpath,
409 smbcli_errstr(cli_nt->tree));
410 goto fail;
412 smbcli_close(cli_nt->tree, fnum);
414 if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
415 goto fail;
417 fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
418 if (fnum == -1) {
419 d_printf("Could not create file %s: %s\n", fpath1,
420 smbcli_errstr(cli_nt->tree));
421 goto fail;
423 smbcli_close(cli_nt->tree, fnum);
426 * Do a whole bunch of error code checks on chkpath
429 status = smbcli_chkpath(cli_nt->tree, fpath);
430 CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
431 status = smbcli_chkpath(cli_dos->tree, fpath);
432 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
434 status = smbcli_chkpath(cli_nt->tree, "..");
435 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
436 status = smbcli_chkpath(cli_dos->tree, "..");
437 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
439 status = smbcli_chkpath(cli_nt->tree, ".");
440 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
441 status = smbcli_chkpath(cli_dos->tree, ".");
442 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
444 status = smbcli_chkpath(cli_nt->tree, "\t");
445 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
446 status = smbcli_chkpath(cli_dos->tree, "\t");
447 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
449 status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
450 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
451 status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
452 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
454 status = smbcli_chkpath(cli_nt->tree, "<");
455 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
456 status = smbcli_chkpath(cli_dos->tree, "<");
457 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
459 status = smbcli_chkpath(cli_nt->tree, "<\\bla");
460 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
461 status = smbcli_chkpath(cli_dos->tree, "<\\bla");
462 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
465 * .... And the same gang against getatr. Note that the DOS error codes
466 * differ....
469 status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
470 CHECK_STATUS(status, NT_STATUS_OK);
471 status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
472 CHECK_STATUS(status, NT_STATUS_OK);
474 status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
475 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
476 status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
477 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
479 status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
480 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
481 status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
482 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
484 status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
485 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
486 status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
487 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
489 status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
490 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
491 status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
492 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
494 status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
495 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
496 status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
497 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
499 status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
500 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
501 status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
502 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
504 /* Try the same set with openX. */
506 status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
507 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
508 status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
509 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
511 status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
512 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
513 status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
514 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
516 status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
517 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
518 status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
519 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
521 status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
522 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
523 status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
524 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
526 status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
527 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
528 status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
529 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
531 status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
532 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
533 status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
534 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
536 /* Let's test EEXIST error code mapping. */
537 status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
538 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
539 status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
540 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
542 status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
543 if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
544 || !torture_setting_bool(torture, "samba3", false)) {
545 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
546 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
548 status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
549 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
550 || !torture_setting_bool(torture, "samba3", false)) {
551 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
552 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
555 status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
556 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
557 status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
558 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
560 /* Try the rename test. */
562 union smb_rename io;
563 memset(&io, '\0', sizeof(io));
564 io.rename.in.pattern1 = fpath1;
565 io.rename.in.pattern2 = fpath;
567 /* Try with SMBmv rename. */
568 status = smb_raw_rename(cli_nt->tree, &io);
569 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
570 status = smb_raw_rename(cli_dos->tree, &io);
571 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
573 /* Try with NT rename. */
574 io.generic.level = RAW_RENAME_NTRENAME;
575 io.ntrename.in.old_name = fpath1;
576 io.ntrename.in.new_name = fpath;
577 io.ntrename.in.attrib = 0;
578 io.ntrename.in.cluster_size = 0;
579 io.ntrename.in.flags = RENAME_FLAG_RENAME;
581 status = smb_raw_rename(cli_nt->tree, &io);
582 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
583 status = smb_raw_rename(cli_dos->tree, &io);
584 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
587 goto done;
589 fail:
590 ret = false;
592 done:
593 if (cli_nt != NULL) {
594 smbcli_deltree(cli_nt->tree, dirname);
595 torture_close_connection(cli_nt);
597 if (cli_dos != NULL) {
598 torture_close_connection(cli_dos);
600 talloc_free(mem_ctx);
602 return ret;
605 static void count_fn(struct clilist_file_info *info, const char *name,
606 void *private_data)
608 int *counter = (int *)private_data;
609 *counter += 1;
612 bool torture_samba3_caseinsensitive(struct torture_context *torture)
614 struct smbcli_state *cli;
615 TALLOC_CTX *mem_ctx;
616 NTSTATUS status;
617 const char *dirname = "insensitive";
618 const char *ucase_dirname = "InSeNsItIvE";
619 const char *fname = "foo";
620 char *fpath;
621 int fnum;
622 int counter = 0;
623 bool ret = true;
625 if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
626 d_printf("talloc_init failed\n");
627 return false;
630 if (!torture_open_connection(&cli, torture, 0)) {
631 goto done;
634 smbcli_deltree(cli->tree, dirname);
636 status = smbcli_mkdir(cli->tree, dirname);
637 if (!NT_STATUS_IS_OK(status)) {
638 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
639 goto done;
642 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
643 goto done;
645 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
646 if (fnum == -1) {
647 d_printf("Could not create file %s: %s\n", fpath,
648 smbcli_errstr(cli->tree));
649 goto done;
651 smbcli_close(cli->tree, fnum);
653 smbcli_list(cli->tree, talloc_asprintf(
654 mem_ctx, "%s\\*", ucase_dirname),
655 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
656 |FILE_ATTRIBUTE_SYSTEM,
657 count_fn, (void *)&counter);
659 if (counter == 3) {
660 ret = true;
662 else {
663 d_fprintf(stderr, "expected 3 entries, got %d\n", counter);
664 ret = false;
667 done:
668 talloc_free(mem_ctx);
669 return ret;
673 * Check that Samba3 correctly deals with conflicting posix byte range locks
674 * on an underlying file
677 bool torture_samba3_posixtimedlock(struct torture_context *tctx)
679 struct smbcli_state *cli;
680 NTSTATUS status;
681 bool ret = true;
682 const char *dirname = "posixlock";
683 const char *fname = "locked";
684 const char *fpath;
685 const char *localdir;
686 const char *localname;
687 int fnum = -1;
689 int fd = -1;
690 struct flock posix_lock;
692 union smb_lock io;
693 struct smb_lock_entry lock_entry;
694 struct smbcli_request *req;
696 if (!torture_open_connection(&cli, tctx, 0)) {
697 ret = false;
698 goto done;
701 smbcli_deltree(cli->tree, dirname);
703 status = smbcli_mkdir(cli->tree, dirname);
704 if (!NT_STATUS_IS_OK(status)) {
705 torture_warning(tctx, "smbcli_mkdir failed: %s\n",
706 nt_errstr(status));
707 ret = false;
708 goto done;
711 if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
712 torture_warning(tctx, "talloc failed\n");
713 ret = false;
714 goto done;
716 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
717 if (fnum == -1) {
718 torture_warning(tctx, "Could not create file %s: %s\n", fpath,
719 smbcli_errstr(cli->tree));
720 ret = false;
721 goto done;
724 if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
725 torture_warning(tctx, "Need 'localdir' setting\n");
726 ret = false;
727 goto done;
730 if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
731 fname))) {
732 torture_warning(tctx, "talloc failed\n");
733 ret = false;
734 goto done;
738 * Lock a byte range from posix
741 fd = open(localname, O_RDWR);
742 if (fd == -1) {
743 torture_warning(tctx, "open(%s) failed: %s\n",
744 localname, strerror(errno));
745 goto done;
748 posix_lock.l_type = F_WRLCK;
749 posix_lock.l_whence = SEEK_SET;
750 posix_lock.l_start = 0;
751 posix_lock.l_len = 1;
753 if (fcntl(fd, F_SETLK, &posix_lock) == -1) {
754 torture_warning(tctx, "fcntl failed: %s\n", strerror(errno));
755 ret = false;
756 goto done;
760 * Try a cifs brlock without timeout to see if posix locking = yes
763 io.lockx.in.ulock_cnt = 0;
764 io.lockx.in.lock_cnt = 1;
766 lock_entry.count = 1;
767 lock_entry.offset = 0;
768 lock_entry.pid = cli->tree->session->pid;
770 io.lockx.level = RAW_LOCK_LOCKX;
771 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
772 io.lockx.in.timeout = 0;
773 io.lockx.in.locks = &lock_entry;
774 io.lockx.in.file.fnum = fnum;
776 status = smb_raw_lock(cli->tree, &io);
778 ret = true;
779 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
781 if (!ret) {
782 goto done;
786 * Now fire off a timed brlock, unlock the posix lock and see if the
787 * timed lock gets through.
790 io.lockx.in.timeout = 5000;
792 req = smb_raw_lock_send(cli->tree, &io);
793 if (req == NULL) {
794 torture_warning(tctx, "smb_raw_lock_send failed\n");
795 ret = false;
796 goto done;
800 * Ship the async timed request to the server
802 event_loop_once(req->transport->socket->event.ctx);
803 msleep(500);
805 close(fd);
807 status = smbcli_request_simple_recv(req);
809 CHECK_STATUS(status, NT_STATUS_OK);
811 done:
812 if (fnum != -1) {
813 smbcli_close(cli->tree, fnum);
815 if (fd != -1) {
816 close(fd);
818 smbcli_deltree(cli->tree, dirname);
819 return ret;
822 bool torture_samba3_rootdirfid(struct torture_context *tctx)
824 struct smbcli_state *cli;
825 NTSTATUS status;
826 uint16_t dnum;
827 union smb_open io;
828 const char *fname = "testfile";
829 bool ret = false;
831 if (!torture_open_connection(&cli, tctx, 0)) {
832 ret = false;
833 goto done;
836 smbcli_unlink(cli->tree, fname);
838 ZERO_STRUCT(io);
839 io.generic.level = RAW_OPEN_NTCREATEX;
840 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
841 io.ntcreatex.in.root_fid = 0;
842 io.ntcreatex.in.security_flags = 0;
843 io.ntcreatex.in.access_mask =
844 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
845 io.ntcreatex.in.alloc_size = 0;
846 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
847 io.ntcreatex.in.share_access =
848 NTCREATEX_SHARE_ACCESS_READ
849 | NTCREATEX_SHARE_ACCESS_READ;
850 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
851 io.ntcreatex.in.create_options = 0;
852 io.ntcreatex.in.fname = "\\";
853 status = smb_raw_open(cli->tree, tctx, &io);
854 if (!NT_STATUS_IS_OK(status)) {
855 d_printf("smb_open on the directory failed: %s\n",
856 nt_errstr(status));
857 ret = false;
858 goto done;
860 dnum = io.ntcreatex.out.file.fnum;
862 io.ntcreatex.in.flags =
863 NTCREATEX_FLAGS_REQUEST_OPLOCK
864 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
865 io.ntcreatex.in.root_fid = dnum;
866 io.ntcreatex.in.security_flags = 0;
867 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
868 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
869 io.ntcreatex.in.alloc_size = 0;
870 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
871 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
872 io.ntcreatex.in.create_options = 0;
873 io.ntcreatex.in.fname = fname;
875 status = smb_raw_open(cli->tree, tctx, &io);
876 if (!NT_STATUS_IS_OK(status)) {
877 d_printf("smb_open on the file %s failed: %s\n",
878 fname, nt_errstr(status));
879 ret = false;
880 goto done;
883 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
884 smbcli_close(cli->tree, dnum);
885 smbcli_unlink(cli->tree, fname);
887 ret = true;
888 done:
889 return ret;