source: trunk/server/source4/torture/basic/base.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: 61.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22#include "torture/smbtorture.h"
23#include "torture/basic/proto.h"
24#include "libcli/libcli.h"
25#include "libcli/raw/raw_proto.h"
26#include "torture/util.h"
27#include "system/filesys.h"
28#include "system/time.h"
29#include "libcli/resolve/resolve.h"
30#include "lib/events/events.h"
31#include "param/param.h"
32
33
34#define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
35
36
37static struct smbcli_state *open_nbt_connection(struct torture_context *tctx)
38{
39 struct nbt_name called, calling;
40 struct smbcli_state *cli;
41 const char *host = torture_setting_string(tctx, "host", NULL);
42 struct smbcli_options options;
43
44 make_nbt_name_client(&calling, lpcfg_netbios_name(tctx->lp_ctx));
45
46 nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
47
48 cli = smbcli_state_init(NULL);
49 if (!cli) {
50 torture_comment(tctx, "Failed initialize smbcli_struct to connect with %s\n", host);
51 goto failed;
52 }
53
54 lpcfg_smbcli_options(tctx->lp_ctx, &options);
55
56 if (!smbcli_socket_connect(cli, host, lpcfg_smb_ports(tctx->lp_ctx), tctx->ev,
57 lpcfg_resolve_context(tctx->lp_ctx), &options,
58 lpcfg_socket_options(tctx->lp_ctx))) {
59 torture_comment(tctx, "Failed to connect with %s\n", host);
60 goto failed;
61 }
62
63 if (!smbcli_transport_establish(cli, &calling, &called)) {
64 torture_comment(tctx, "%s rejected the session\n",host);
65 goto failed;
66 }
67
68 return cli;
69
70failed:
71 talloc_free(cli);
72 return NULL;
73}
74
75static bool tcon_devtest(struct torture_context *tctx,
76 struct smbcli_state *cli,
77 const char *myshare, const char *devtype,
78 NTSTATUS expected_error)
79{
80 bool status;
81 const char *password = torture_setting_string(tctx, "password", NULL);
82
83 status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype,
84 password));
85
86 torture_comment(tctx, "Trying share %s with devtype %s\n", myshare, devtype);
87
88 if (NT_STATUS_IS_OK(expected_error)) {
89 if (!status) {
90 torture_fail(tctx, talloc_asprintf(tctx,
91 "tconX to share %s with type %s "
92 "should have succeeded but failed",
93 myshare, devtype));
94 }
95 smbcli_tdis(cli);
96 } else {
97 if (status) {
98 torture_fail(tctx, talloc_asprintf(tctx,
99 "tconx to share %s with type %s "
100 "should have failed but succeeded",
101 myshare, devtype));
102 } else {
103 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
104 expected_error)) {
105 } else {
106 torture_fail(tctx, "Returned unexpected error");
107 }
108 }
109 }
110 return true;
111}
112
113
114
115/**
116test whether fnums and tids open on one VC are available on another (a major
117security hole)
118*/
119static bool run_fdpasstest(struct torture_context *tctx,
120 struct smbcli_state *cli1,
121 struct smbcli_state *cli2)
122{
123 const char *fname = "\\fdpass.tst";
124 int fnum1, oldtid;
125 uint8_t buf[1024];
126
127 smbcli_unlink(cli1->tree, fname);
128
129 torture_comment(tctx, "Opening a file on connection 1\n");
130
131 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
132 torture_assert(tctx, fnum1 != -1,
133 talloc_asprintf(tctx,
134 "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree)));
135
136 torture_comment(tctx, "writing to file on connection 1\n");
137
138 torture_assert(tctx,
139 smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) == 13,
140 talloc_asprintf(tctx,
141 "write failed (%s)\n", smbcli_errstr(cli1->tree)));
142
143 oldtid = cli2->tree->tid;
144 cli2->session->vuid = cli1->session->vuid;
145 cli2->tree->tid = cli1->tree->tid;
146 cli2->session->pid = cli1->session->pid;
147
148 torture_comment(tctx, "reading from file on connection 2\n");
149
150 torture_assert(tctx, smbcli_read(cli2->tree, fnum1, buf, 0, 13) != 13,
151 talloc_asprintf(tctx,
152 "read succeeded! nasty security hole [%s]\n", buf));
153
154 smbcli_close(cli1->tree, fnum1);
155 smbcli_unlink(cli1->tree, fname);
156
157 cli2->tree->tid = oldtid;
158
159 return true;
160}
161
162/**
163 This checks how the getatr calls works
164*/
165static bool run_attrtest(struct torture_context *tctx,
166 struct smbcli_state *cli)
167{
168 int fnum;
169 time_t t, t2;
170 const char *fname = "\\attrib123456789.tst";
171 bool correct = true;
172
173 smbcli_unlink(cli->tree, fname);
174 fnum = smbcli_open(cli->tree, fname,
175 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
176 smbcli_close(cli->tree, fnum);
177
178 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
179 torture_comment(tctx, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
180 correct = false;
181 }
182
183 torture_comment(tctx, "New file time is %s", ctime(&t));
184
185 if (abs(t - time(NULL)) > 60*60*24*10) {
186 torture_comment(tctx, "ERROR: SMBgetatr bug. time is %s",
187 ctime(&t));
188 t = time(NULL);
189 correct = false;
190 }
191
192 t2 = t-60*60*24; /* 1 day ago */
193
194 torture_comment(tctx, "Setting file time to %s", ctime(&t2));
195
196 if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
197 torture_comment(tctx, "setatr failed (%s)\n", smbcli_errstr(cli->tree));
198 correct = true;
199 }
200
201 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
202 torture_comment(tctx, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
203 correct = true;
204 }
205
206 torture_comment(tctx, "Retrieved file time as %s", ctime(&t));
207
208 if (t != t2) {
209 torture_comment(tctx, "ERROR: getatr/setatr bug. times are\n%s",
210 ctime(&t));
211 torture_comment(tctx, "%s", ctime(&t2));
212 correct = true;
213 }
214
215 smbcli_unlink(cli->tree, fname);
216
217 return correct;
218}
219
220/**
221 This checks a couple of trans2 calls
222*/
223static bool run_trans2test(struct torture_context *tctx,
224 struct smbcli_state *cli)
225{
226 int fnum;
227 size_t size;
228 time_t c_time, a_time, m_time, w_time, m_time2;
229 const char *fname = "\\trans2.tst";
230 const char *dname = "\\trans2";
231 const char *fname2 = "\\trans2\\trans2.tst";
232 const char *pname;
233 bool correct = true;
234
235 smbcli_unlink(cli->tree, fname);
236
237 torture_comment(tctx, "Testing qfileinfo\n");
238
239 fnum = smbcli_open(cli->tree, fname,
240 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
241 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
242 NULL, NULL))) {
243 torture_comment(tctx, "ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
244 correct = false;
245 }
246
247 torture_comment(tctx, "Testing NAME_INFO\n");
248
249 if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
250 torture_comment(tctx, "ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
251 correct = false;
252 }
253
254 if (!pname || strcmp(pname, fname)) {
255 torture_comment(tctx, "qfilename gave different name? [%s] [%s]\n",
256 fname, pname);
257 correct = false;
258 }
259
260 smbcli_close(cli->tree, fnum);
261 smbcli_unlink(cli->tree, fname);
262
263 fnum = smbcli_open(cli->tree, fname,
264 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
265 if (fnum == -1) {
266 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
267 return false;
268 }
269 smbcli_close(cli->tree, fnum);
270
271 torture_comment(tctx, "Checking for sticky create times\n");
272
273 if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
274 torture_comment(tctx, "ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
275 correct = false;
276 } else {
277 if (c_time != m_time) {
278 torture_comment(tctx, "create time=%s", ctime(&c_time));
279 torture_comment(tctx, "modify time=%s", ctime(&m_time));
280 torture_comment(tctx, "This system appears to have sticky create times\n");
281 }
282 if (a_time % (60*60) == 0) {
283 torture_comment(tctx, "access time=%s", ctime(&a_time));
284 torture_comment(tctx, "This system appears to set a midnight access time\n");
285 correct = false;
286 }
287
288 if (abs(m_time - time(NULL)) > 60*60*24*7) {
289 torture_comment(tctx, "ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
290 correct = false;
291 }
292 }
293
294
295 smbcli_unlink(cli->tree, fname);
296 fnum = smbcli_open(cli->tree, fname,
297 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
298 smbcli_close(cli->tree, fnum);
299 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
300 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
301 correct = false;
302 } else {
303 if (w_time < 60*60*24*2) {
304 torture_comment(tctx, "write time=%s", ctime(&w_time));
305 torture_comment(tctx, "This system appears to set a initial 0 write time\n");
306 correct = false;
307 }
308 }
309
310 smbcli_unlink(cli->tree, fname);
311
312
313 /* check if the server updates the directory modification time
314 when creating a new file */
315 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
316 torture_comment(tctx, "ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
317 correct = false;
318 }
319 sleep(3);
320 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
321 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
322 correct = false;
323 }
324
325 fnum = smbcli_open(cli->tree, fname2,
326 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
327 smbcli_write(cli->tree, fnum, 0, &fnum, 0, sizeof(fnum));
328 smbcli_close(cli->tree, fnum);
329 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
330 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
331 correct = false;
332 } else {
333 if (m_time2 == m_time) {
334 torture_comment(tctx, "This system does not update directory modification times\n");
335 correct = false;
336 }
337 }
338 smbcli_unlink(cli->tree, fname2);
339 smbcli_rmdir(cli->tree, dname);
340
341 return correct;
342}
343
344/* send smb negprot commands, not reading the response */
345static bool run_negprot_nowait(struct torture_context *tctx)
346{
347 int i;
348 struct smbcli_state *cli, *cli2;
349 bool correct = true;
350
351 torture_comment(tctx, "starting negprot nowait test\n");
352
353 cli = open_nbt_connection(tctx);
354 if (!cli) {
355 return false;
356 }
357
358 torture_comment(tctx, "Filling send buffer\n");
359
360 for (i=0;i<100;i++) {
361 struct smbcli_request *req;
362 req = smb_raw_negotiate_send(cli->transport, lpcfg_unicode(tctx->lp_ctx), PROTOCOL_NT1);
363 event_loop_once(cli->transport->socket->event.ctx);
364 if (req->state == SMBCLI_REQUEST_ERROR) {
365 if (i > 0) {
366 torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n", i+1, nt_errstr(req->status));
367 break;
368 } else {
369 torture_comment(tctx, "Failed to fill pipe - %s \n", nt_errstr(req->status));
370 torture_close_connection(cli);
371 return false;
372 }
373 }
374 }
375
376 torture_comment(tctx, "Opening secondary connection\n");
377 if (!torture_open_connection(&cli2, tctx, 1)) {
378 torture_comment(tctx, "Failed to open secondary connection\n");
379 correct = false;
380 }
381
382 if (!torture_close_connection(cli2)) {
383 torture_comment(tctx, "Failed to close secondary connection\n");
384 correct = false;
385 }
386
387 torture_close_connection(cli);
388
389 return correct;
390}
391
392/**
393 this checks to see if a secondary tconx can use open files from an
394 earlier tconx
395 */
396static bool run_tcon_test(struct torture_context *tctx, struct smbcli_state *cli)
397{
398 const char *fname = "\\tcontest.tmp";
399 int fnum1;
400 uint16_t cnum1, cnum2, cnum3;
401 uint16_t vuid1, vuid2;
402 uint8_t buf[4];
403 bool ret = true;
404 struct smbcli_tree *tree1;
405 const char *host = torture_setting_string(tctx, "host", NULL);
406 const char *share = torture_setting_string(tctx, "share", NULL);
407 const char *password = torture_setting_string(tctx, "password", NULL);
408
409 if (smbcli_deltree(cli->tree, fname) == -1) {
410 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
411 }
412
413 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
414 if (fnum1 == -1) {
415 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
416 return false;
417 }
418
419 cnum1 = cli->tree->tid;
420 vuid1 = cli->session->vuid;
421
422 memset(buf, 0, 4); /* init buf so valgrind won't complain */
423 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
424 torture_comment(tctx, "initial write failed (%s)\n", smbcli_errstr(cli->tree));
425 return false;
426 }
427
428 tree1 = cli->tree; /* save old tree connection */
429 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
430 torture_comment(tctx, "%s refused 2nd tree connect (%s)\n", host,
431 smbcli_errstr(cli->tree));
432 talloc_free(cli);
433 return false;
434 }
435
436 cnum2 = cli->tree->tid;
437 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
438 vuid2 = cli->session->vuid + 1;
439
440 /* try a write with the wrong tid */
441 cli->tree->tid = cnum2;
442
443 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
444 torture_comment(tctx, "* server allows write with wrong TID\n");
445 ret = false;
446 } else {
447 torture_comment(tctx, "server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
448 }
449
450
451 /* try a write with an invalid tid */
452 cli->tree->tid = cnum3;
453
454 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
455 torture_comment(tctx, "* server allows write with invalid TID\n");
456 ret = false;
457 } else {
458 torture_comment(tctx, "server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
459 }
460
461 /* try a write with an invalid vuid */
462 cli->session->vuid = vuid2;
463 cli->tree->tid = cnum1;
464
465 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
466 torture_comment(tctx, "* server allows write with invalid VUID\n");
467 ret = false;
468 } else {
469 torture_comment(tctx, "server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
470 }
471
472 cli->session->vuid = vuid1;
473 cli->tree->tid = cnum1;
474
475 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
476 torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(cli->tree));
477 return false;
478 }
479
480 cli->tree->tid = cnum2;
481
482 if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
483 torture_comment(tctx, "secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
484 return false;
485 }
486
487 cli->tree = tree1; /* restore initial tree */
488 cli->tree->tid = cnum1;
489
490 smbcli_unlink(tree1, fname);
491
492 return ret;
493}
494
495/**
496 checks for correct tconX support
497 */
498static bool run_tcon_devtype_test(struct torture_context *tctx,
499 struct smbcli_state *cli1)
500{
501 const char *share = torture_setting_string(tctx, "share", NULL);
502
503 if (!tcon_devtest(tctx, cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
504 return false;
505
506 if (!tcon_devtest(tctx, cli1, "IPC$", "?????", NT_STATUS_OK))
507 return false;
508
509 if (!tcon_devtest(tctx, cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
510 return false;
511
512 if (!tcon_devtest(tctx, cli1, "IPC$", "IPC", NT_STATUS_OK))
513 return false;
514
515 if (!tcon_devtest(tctx, cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
516 return false;
517
518 if (!tcon_devtest(tctx, cli1, share, "A:", NT_STATUS_OK))
519 return false;
520
521 if (!tcon_devtest(tctx, cli1, share, "?????", NT_STATUS_OK))
522 return false;
523
524 if (!tcon_devtest(tctx, cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
525 return false;
526
527 if (!tcon_devtest(tctx, cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
528 return false;
529
530 if (!tcon_devtest(tctx, cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
531 return false;
532
533 return true;
534}
535
536static bool rw_torture2(struct torture_context *tctx,
537 struct smbcli_state *c1, struct smbcli_state *c2)
538{
539 const char *lockfname = "\\torture2.lck";
540 int fnum1;
541 int fnum2;
542 int i;
543 uint8_t buf[131072];
544 uint8_t buf_rd[131072];
545 bool correct = true;
546 ssize_t bytes_read, bytes_written;
547
548 torture_assert(tctx, smbcli_deltree(c1->tree, lockfname) != -1,
549 talloc_asprintf(tctx,
550 "unlink failed (%s)", smbcli_errstr(c1->tree)));
551
552 fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
553 DENY_NONE);
554 torture_assert(tctx, fnum1 != -1,
555 talloc_asprintf(tctx,
556 "first open read/write of %s failed (%s)",
557 lockfname, smbcli_errstr(c1->tree)));
558 fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY,
559 DENY_NONE);
560 torture_assert(tctx, fnum2 != -1,
561 talloc_asprintf(tctx,
562 "second open read-only of %s failed (%s)",
563 lockfname, smbcli_errstr(c2->tree)));
564
565 torture_comment(tctx, "Checking data integrity over %d ops\n",
566 torture_numops);
567
568 for (i=0;i<torture_numops;i++)
569 {
570 size_t buf_size = ((unsigned int)random()%(sizeof(buf)-1))+ 1;
571 if (i % 10 == 0) {
572 if (torture_setting_bool(tctx, "progress", true)) {
573 torture_comment(tctx, "%d\r", i); fflush(stdout);
574 }
575 }
576
577 generate_random_buffer(buf, buf_size);
578
579 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
580 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c1->tree));
581 torture_comment(tctx, "wrote %d, expected %d\n", (int)bytes_written, (int)buf_size);
582 correct = false;
583 break;
584 }
585
586 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
587 torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c2->tree));
588 torture_comment(tctx, "read %d, expected %d\n", (int)bytes_read, (int)buf_size);
589 correct = false;
590 break;
591 }
592
593 torture_assert_mem_equal(tctx, buf_rd, buf, buf_size,
594 "read/write compare failed\n");
595 }
596
597 torture_assert_ntstatus_ok(tctx, smbcli_close(c2->tree, fnum2),
598 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c2->tree)));
599 torture_assert_ntstatus_ok(tctx, smbcli_close(c1->tree, fnum1),
600 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c1->tree)));
601
602 torture_assert_ntstatus_ok(tctx, smbcli_unlink(c1->tree, lockfname),
603 talloc_asprintf(tctx, "unlink failed (%s)", smbcli_errstr(c1->tree)));
604
605 torture_comment(tctx, "\n");
606
607 return correct;
608}
609
610
611
612static bool run_readwritetest(struct torture_context *tctx,
613 struct smbcli_state *cli1,
614 struct smbcli_state *cli2)
615{
616 torture_comment(tctx, "Running readwritetest v1\n");
617 if (!rw_torture2(tctx, cli1, cli2))
618 return false;
619
620 torture_comment(tctx, "Running readwritetest v2\n");
621
622 if (!rw_torture2(tctx, cli1, cli1))
623 return false;
624
625 return true;
626}
627
628/*
629test the timing of deferred open requests
630*/
631static bool run_deferopen(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
632{
633 const char *fname = "\\defer_open_test.dat";
634 int retries=4;
635 int i = 0;
636 bool correct = true;
637 int nsec;
638 int msec;
639 double sec;
640
641 nsec = torture_setting_int(tctx, "sharedelay", 1000000);
642 msec = nsec / 1000;
643 sec = ((double)nsec) / ((double) 1000000);
644
645 if (retries <= 0) {
646 torture_comment(tctx, "failed to connect\n");
647 return false;
648 }
649
650 torture_comment(tctx, "Testing deferred open requests.\n");
651
652 while (i < 4) {
653 int fnum = -1;
654
655 do {
656 struct timeval tv;
657 tv = timeval_current();
658 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
659 SEC_RIGHTS_FILE_ALL,
660 FILE_ATTRIBUTE_NORMAL,
661 NTCREATEX_SHARE_ACCESS_NONE,
662 NTCREATEX_DISP_OPEN_IF, 0, 0);
663 if (fnum != -1) {
664 break;
665 }
666 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
667 double e = timeval_elapsed(&tv);
668 if (e < (0.5 * sec) || e > ((1.5 * sec) + 1)) {
669 torture_comment(tctx,"Timing incorrect %.2f violation 1 sec == %.2f\n",
670 e, sec);
671 return false;
672 }
673 }
674 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
675
676 if (fnum == -1) {
677 torture_comment(tctx,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
678 return false;
679 }
680
681 torture_comment(tctx, "pid %u open %d\n", (unsigned)getpid(), i);
682
683 smb_msleep(10 * msec);
684 i++;
685 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
686 torture_comment(tctx,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
687 return false;
688 }
689 smb_msleep(2 * msec);
690 }
691
692 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
693 /* All until the last unlink will fail with sharing violation
694 but also the last request can fail since the file could have
695 been successfully deleted by another (test) process */
696 NTSTATUS status = smbcli_nt_error(cli->tree);
697 if ((!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))
698 && (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))) {
699 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
700 correct = false;
701 }
702 }
703
704 torture_comment(tctx, "deferred test finished\n");
705 return correct;
706}
707
708/**
709 Try with a wrong vuid and check error message.
710 */
711
712static bool run_vuidtest(struct torture_context *tctx,
713 struct smbcli_state *cli)
714{
715 const char *fname = "\\vuid.tst";
716 int fnum;
717 size_t size;
718 time_t c_time, a_time, m_time;
719
720 uint16_t orig_vuid;
721 NTSTATUS result;
722
723 smbcli_unlink(cli->tree, fname);
724
725 fnum = smbcli_open(cli->tree, fname,
726 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
727
728 orig_vuid = cli->session->vuid;
729
730 cli->session->vuid += 1234;
731
732 torture_comment(tctx, "Testing qfileinfo with wrong vuid\n");
733
734 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
735 &size, &c_time, &a_time,
736 &m_time, NULL, NULL))) {
737 torture_fail(tctx, "qfileinfo passed with wrong vuid");
738 }
739
740 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
741 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
742 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
743 NT_STATUS_INVALID_HANDLE)) {
744 torture_fail(tctx, talloc_asprintf(tctx,
745 "qfileinfo should have returned DOS error "
746 "ERRSRV:ERRbaduid\n but returned %s",
747 smbcli_errstr(cli->tree)));
748 }
749
750 cli->session->vuid -= 1234;
751
752 torture_assert_ntstatus_ok(tctx, smbcli_close(cli->tree, fnum),
753 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli->tree)));
754
755 smbcli_unlink(cli->tree, fname);
756
757 return true;
758}
759
760/*
761 Test open mode returns on read-only files.
762 */
763 static bool run_opentest(struct torture_context *tctx, struct smbcli_state *cli1,
764 struct smbcli_state *cli2)
765{
766 const char *fname = "\\readonly.file";
767 char *control_char_fname;
768 int fnum1, fnum2;
769 uint8_t buf[20];
770 size_t fsize;
771 bool correct = true;
772 char *tmp_path;
773 int failures = 0;
774 int i;
775
776 asprintf(&control_char_fname, "\\readonly.afile");
777 for (i = 1; i <= 0x1f; i++) {
778 control_char_fname[10] = i;
779 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
780 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
781
782 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
783 NT_STATUS_OBJECT_NAME_INVALID)) {
784 torture_comment(tctx, "Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
785 smbcli_errstr(cli1->tree), i);
786 failures++;
787 }
788
789 if (fnum1 != -1) {
790 smbcli_close(cli1->tree, fnum1);
791 }
792 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
793 smbcli_unlink(cli1->tree, control_char_fname);
794 }
795 free(control_char_fname);
796
797 if (!failures)
798 torture_comment(tctx, "Create file with control char names passed.\n");
799
800 smbcli_setatr(cli1->tree, fname, 0, 0);
801 smbcli_unlink(cli1->tree, fname);
802
803 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
804 if (fnum1 == -1) {
805 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
806 return false;
807 }
808
809 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
810 torture_comment(tctx, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
811 return false;
812 }
813
814 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
815 torture_result(tctx, TORTURE_FAIL,
816 __location__ ": smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
817 CHECK_MAX_FAILURES(error_test1);
818 return false;
819 }
820
821 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
822 if (fnum1 == -1) {
823 torture_result(tctx, TORTURE_FAIL,
824 __location__ ": open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
825 CHECK_MAX_FAILURES(error_test1);
826 return false;
827 }
828
829 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
830 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
831
832 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
833 NT_STATUS_ACCESS_DENIED)) {
834 torture_comment(tctx, "correct error code ERRDOS/ERRnoaccess returned\n");
835 }
836
837 torture_comment(tctx, "finished open test 1\n");
838
839error_test1:
840 smbcli_close(cli1->tree, fnum1);
841
842 /* Now try not readonly and ensure ERRbadshare is returned. */
843
844 smbcli_setatr(cli1->tree, fname, 0, 0);
845
846 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
847 if (fnum1 == -1) {
848 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
849 return false;
850 }
851
852 /* This will fail - but the error should be ERRshare. */
853 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
854
855 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
856 NT_STATUS_SHARING_VIOLATION)) {
857 torture_comment(tctx, "correct error code ERRDOS/ERRbadshare returned\n");
858 }
859
860 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
861 torture_comment(tctx, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
862 return false;
863 }
864
865 smbcli_unlink(cli1->tree, fname);
866
867 torture_comment(tctx, "finished open test 2\n");
868
869 /* Test truncate open disposition on file opened for read. */
870
871 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
872 if (fnum1 == -1) {
873 torture_comment(tctx, "(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
874 return false;
875 }
876
877 /* write 20 bytes. */
878
879 memset(buf, '\0', 20);
880
881 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
882 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(cli1->tree));
883 correct = false;
884 }
885
886 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
887 torture_comment(tctx, "(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
888 return false;
889 }
890
891 /* Ensure size == 20. */
892 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
893 torture_result(tctx, TORTURE_FAIL,
894 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
895 CHECK_MAX_FAILURES(error_test3);
896 return false;
897 }
898
899 if (fsize != 20) {
900 torture_result(tctx, TORTURE_FAIL,
901 __location__ ": (3) file size != 20\n");
902 CHECK_MAX_FAILURES(error_test3);
903 return false;
904 }
905
906 /* Now test if we can truncate a file opened for readonly. */
907
908 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
909 if (fnum1 == -1) {
910 torture_result(tctx, TORTURE_FAIL,
911 __location__ ": (3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
912 CHECK_MAX_FAILURES(error_test3);
913 return false;
914 }
915
916 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
917 torture_result(tctx, TORTURE_FAIL,
918 __location__ ": close2 failed (%s)\n", smbcli_errstr(cli1->tree));
919 return false;
920 }
921
922 /* Ensure size == 0. */
923 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
924 torture_result(tctx, TORTURE_FAIL,
925 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
926 CHECK_MAX_FAILURES(error_test3);
927 return false;
928 }
929
930 if (fsize != 0) {
931 torture_result(tctx, TORTURE_FAIL,
932 __location__ ": (3) file size != 0\n");
933 CHECK_MAX_FAILURES(error_test3);
934 return false;
935 }
936 torture_comment(tctx, "finished open test 3\n");
937error_test3:
938
939 fnum1 = fnum2 = -1;
940 smbcli_unlink(cli1->tree, fname);
941
942
943 torture_comment(tctx, "Testing ctemp\n");
944 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
945 if (fnum1 == -1) {
946 torture_result(tctx, TORTURE_FAIL,
947 __location__ ": ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
948 CHECK_MAX_FAILURES(error_test4);
949 return false;
950 }
951 torture_comment(tctx, "ctemp gave path %s\n", tmp_path);
952
953error_test4:
954 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
955 torture_comment(tctx, "close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
956 }
957 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
958 torture_comment(tctx, "unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
959 }
960
961 /* Test the non-io opens... */
962
963 torture_comment(tctx, "Test #1 testing 2 non-io opens (no delete)\n");
964 fnum1 = fnum2 = -1;
965 smbcli_setatr(cli2->tree, fname, 0, 0);
966 smbcli_unlink(cli2->tree, fname);
967
968 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
969 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
970
971 if (fnum1 == -1) {
972 torture_result(tctx, TORTURE_FAIL,
973 __location__ ": Test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
974 CHECK_MAX_FAILURES(error_test10);
975 return false;
976 }
977
978 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
979 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
980 if (fnum2 == -1) {
981 torture_result(tctx, TORTURE_FAIL,
982 __location__ ": Test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
983 CHECK_MAX_FAILURES(error_test10);
984 return false;
985 }
986
987 torture_comment(tctx, "non-io open test #1 passed.\n");
988error_test10:
989
990 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
991 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
992 }
993 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
994 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
995 }
996
997 torture_comment(tctx, "Test #2 testing 2 non-io opens (first with delete)\n");
998 fnum1 = fnum2 = -1;
999 smbcli_unlink(cli1->tree, fname);
1000
1001 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1002 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1003
1004 if (fnum1 == -1) {
1005 torture_result(tctx, TORTURE_FAIL,
1006 __location__ ": Test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1007 CHECK_MAX_FAILURES(error_test20);
1008 return false;
1009 }
1010
1011 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1012 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1013
1014 if (fnum2 == -1) {
1015 torture_result(tctx, TORTURE_FAIL,
1016 __location__ ": Test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1017 CHECK_MAX_FAILURES(error_test20);
1018 return false;
1019 }
1020
1021 torture_comment(tctx, "non-io open test #2 passed.\n");
1022error_test20:
1023
1024 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1025 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1026 }
1027 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1028 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1029 }
1030
1031 fnum1 = fnum2 = -1;
1032 smbcli_unlink(cli1->tree, fname);
1033
1034 torture_comment(tctx, "Test #3 testing 2 non-io opens (second with delete)\n");
1035
1036 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1037 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1038
1039 if (fnum1 == -1) {
1040 torture_result(tctx, TORTURE_FAIL,
1041 __location__ ": Test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1042 CHECK_MAX_FAILURES(error_test30);
1043 return false;
1044 }
1045
1046 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1047 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1048
1049 if (fnum2 == -1) {
1050 torture_result(tctx, TORTURE_FAIL,
1051 __location__ ": Test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1052 CHECK_MAX_FAILURES(error_test30);
1053 return false;
1054 }
1055
1056 torture_comment(tctx, "non-io open test #3 passed.\n");
1057error_test30:
1058
1059 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1060 torture_comment(tctx, "Test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1061 }
1062 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1063 torture_comment(tctx, "Test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1064 }
1065
1066 torture_comment(tctx, "Test #4 testing 2 non-io opens (both with delete)\n");
1067 fnum1 = fnum2 = -1;
1068 smbcli_unlink(cli1->tree, fname);
1069
1070 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1071 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1072
1073 if (fnum1 == -1) {
1074 torture_result(tctx, TORTURE_FAIL,
1075 __location__ ": Test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1076 CHECK_MAX_FAILURES(error_test40);
1077 return false;
1078 }
1079
1080 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1081 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1082
1083 if (fnum2 != -1) {
1084 torture_result(tctx, TORTURE_FAIL,
1085 __location__ ": Test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1086 CHECK_MAX_FAILURES(error_test40);
1087 return false;
1088 }
1089
1090 torture_comment(tctx, "Test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1091
1092 torture_comment(tctx, "non-io open test #4 passed.\n");
1093error_test40:
1094
1095 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1096 torture_comment(tctx, "Test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1097 }
1098 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1099 torture_comment(tctx, "Test 4 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1100 }
1101
1102 torture_comment(tctx, "Test #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1103 fnum1 = fnum2 = -1;
1104 smbcli_unlink(cli1->tree, fname);
1105
1106 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1107 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1108
1109 if (fnum1 == -1) {
1110 torture_result(tctx, TORTURE_FAIL,
1111 __location__ ": Test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1112 CHECK_MAX_FAILURES(error_test50);
1113 return false;
1114 }
1115
1116 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1117 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1118
1119 if (fnum2 == -1) {
1120 torture_result(tctx, TORTURE_FAIL,
1121 __location__ ": Test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1122 CHECK_MAX_FAILURES(error_test50);
1123 return false;
1124 }
1125
1126 torture_comment(tctx, "non-io open test #5 passed.\n");
1127error_test50:
1128
1129 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1130 torture_comment(tctx, "Test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1131 }
1132
1133 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1134 torture_comment(tctx, "Test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1135 }
1136
1137 torture_comment(tctx, "Test #6 testing 1 non-io open, one io open\n");
1138 fnum1 = fnum2 = -1;
1139 smbcli_unlink(cli1->tree, fname);
1140
1141 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1142 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1143
1144 if (fnum1 == -1) {
1145 torture_result(tctx, TORTURE_FAIL,
1146 __location__ ": Test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1147 CHECK_MAX_FAILURES(error_test60);
1148 return false;
1149 }
1150
1151 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1152 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1153
1154 if (fnum2 == -1) {
1155 torture_result(tctx, TORTURE_FAIL,
1156 __location__ ": Test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1157 CHECK_MAX_FAILURES(error_test60);
1158 return false;
1159 }
1160
1161 torture_comment(tctx, "non-io open test #6 passed.\n");
1162error_test60:
1163
1164 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1165 torture_comment(tctx, "Test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1166 }
1167
1168 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1169 torture_comment(tctx, "Test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1170 }
1171
1172 torture_comment(tctx, "Test #7 testing 1 non-io open, one io open with delete\n");
1173 fnum1 = fnum2 = -1;
1174 smbcli_unlink(cli1->tree, fname);
1175
1176 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1177 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1178
1179 if (fnum1 == -1) {
1180 torture_result(tctx, TORTURE_FAIL,
1181 __location__ ": Test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1182 CHECK_MAX_FAILURES(error_test70);
1183 return false;
1184 }
1185
1186 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1187 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1188
1189 if (fnum2 != -1) {
1190 torture_result(tctx, TORTURE_FAIL,
1191 __location__ ": Test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1192 CHECK_MAX_FAILURES(error_test70);
1193 return false;
1194 }
1195
1196 torture_comment(tctx, "Test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1197
1198 torture_comment(tctx, "non-io open test #7 passed.\n");
1199error_test70:
1200
1201 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1202 torture_comment(tctx, "Test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1203 }
1204 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1205 torture_comment(tctx, "Test 7 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1206 }
1207
1208 torture_comment(tctx, "Test #8 testing one normal open, followed by lock, followed by open with truncate\n");
1209 fnum1 = fnum2 = -1;
1210 smbcli_unlink(cli1->tree, fname);
1211
1212 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1213 if (fnum1 == -1) {
1214 torture_comment(tctx, "(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1215 return false;
1216 }
1217
1218 /* write 20 bytes. */
1219
1220 memset(buf, '\0', 20);
1221
1222 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1223 torture_comment(tctx, "(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1224 correct = false;
1225 }
1226
1227 /* Ensure size == 20. */
1228 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1229 torture_result(tctx, TORTURE_FAIL,
1230 __location__ ": (8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1231 CHECK_MAX_FAILURES(error_test80);
1232 return false;
1233 }
1234
1235 if (fsize != 20) {
1236 torture_result(tctx, TORTURE_FAIL,
1237 __location__ ": (8) file size %lu != 20\n", (unsigned long)fsize);
1238 CHECK_MAX_FAILURES(error_test80);
1239 return false;
1240 }
1241
1242 /* Get an exclusive lock on the open file. */
1243 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1244 torture_result(tctx, TORTURE_FAIL,
1245 __location__ ": (8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1246 CHECK_MAX_FAILURES(error_test80);
1247 return false;
1248 }
1249
1250 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1251 if (fnum1 == -1) {
1252 torture_comment(tctx, "(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1253 return false;
1254 }
1255
1256 /* Ensure size == 0. */
1257 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1258 torture_result(tctx, TORTURE_FAIL,
1259 __location__ ": (8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1260 CHECK_MAX_FAILURES(error_test80);
1261 return false;
1262 }
1263
1264 if (fsize != 0) {
1265 torture_result(tctx, TORTURE_FAIL,
1266 __location__ ": (8) file size %lu != 0\n", (unsigned long)fsize);
1267 CHECK_MAX_FAILURES(error_test80);
1268 return false;
1269 }
1270
1271 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1272 torture_comment(tctx, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1273 return false;
1274 }
1275
1276 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1277 torture_comment(tctx, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1278 return false;
1279 }
1280
1281error_test80:
1282
1283 torture_comment(tctx, "open test #8 passed.\n");
1284
1285 smbcli_unlink(cli1->tree, fname);
1286
1287 return failures > 0 ? false : correct;
1288}
1289
1290/* FIRST_DESIRED_ACCESS 0xf019f */
1291#define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1292 SEC_FILE_READ_EA| /* 0xf */ \
1293 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1294 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1295 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1296 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1297/* SECOND_DESIRED_ACCESS 0xe0080 */
1298#define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1299 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1300 SEC_STD_WRITE_OWNER /* 0xe0000 */
1301
1302#if 0
1303#define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1304 READ_CONTROL|WRITE_DAC|\
1305 SEC_FILE_READ_DATA|\
1306 WRITE_OWNER /* */
1307#endif
1308
1309
1310
1311/**
1312 Test ntcreate calls made by xcopy
1313 */
1314static bool run_xcopy(struct torture_context *tctx,
1315 struct smbcli_state *cli1)
1316{
1317 const char *fname = "\\test.txt";
1318 int fnum1, fnum2;
1319
1320 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1321 FIRST_DESIRED_ACCESS,
1322 FILE_ATTRIBUTE_ARCHIVE,
1323 NTCREATEX_SHARE_ACCESS_NONE,
1324 NTCREATEX_DISP_OVERWRITE_IF,
1325 0x4044, 0);
1326
1327 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx,
1328 "First open failed - %s", smbcli_errstr(cli1->tree)));
1329
1330 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1331 SECOND_DESIRED_ACCESS, 0,
1332 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1333 0x200000, 0);
1334 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
1335 "second open failed - %s", smbcli_errstr(cli1->tree)));
1336
1337 return true;
1338}
1339
1340static bool run_iometer(struct torture_context *tctx,
1341 struct smbcli_state *cli)
1342{
1343 const char *fname = "\\iobw.tst";
1344 int fnum;
1345 size_t filesize;
1346 NTSTATUS status;
1347 char buf[2048];
1348 int ops;
1349
1350 memset(buf, 0, sizeof(buf));
1351
1352 status = smbcli_getatr(cli->tree, fname, NULL, &filesize, NULL);
1353 torture_assert_ntstatus_ok(tctx, status,
1354 talloc_asprintf(tctx, "smbcli_getatr failed: %s", nt_errstr(status)));
1355
1356 torture_comment(tctx, "size: %d\n", (int)filesize);
1357
1358 filesize -= (sizeof(buf) - 1);
1359
1360 fnum = smbcli_nt_create_full(cli->tree, fname, 0x16,
1361 0x2019f, 0, 0x3, 3, 0x42, 0x3);
1362 torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open failed: %s",
1363 smbcli_errstr(cli->tree)));
1364
1365 ops = 0;
1366
1367 while (true) {
1368 int i, num_reads, num_writes;
1369
1370 num_reads = random() % 10;
1371 num_writes = random() % 3;
1372
1373 for (i=0; i<num_reads; i++) {
1374 ssize_t res;
1375 if (ops++ > torture_numops) {
1376 return true;
1377 }
1378 res = smbcli_read(cli->tree, fnum, buf,
1379 random() % filesize, sizeof(buf));
1380 torture_assert(tctx, res == sizeof(buf),
1381 talloc_asprintf(tctx, "read failed: %s",
1382 smbcli_errstr(cli->tree)));
1383 }
1384 for (i=0; i<num_writes; i++) {
1385 ssize_t res;
1386 if (ops++ > torture_numops) {
1387 return true;
1388 }
1389 res = smbcli_write(cli->tree, fnum, 0, buf,
1390 random() % filesize, sizeof(buf));
1391 torture_assert(tctx, res == sizeof(buf),
1392 talloc_asprintf(tctx, "read failed: %s",
1393 smbcli_errstr(cli->tree)));
1394 }
1395 }
1396}
1397
1398/**
1399 tries variants of chkpath
1400 */
1401static bool torture_chkpath_test(struct torture_context *tctx,
1402 struct smbcli_state *cli)
1403{
1404 int fnum;
1405 bool ret;
1406
1407 torture_comment(tctx, "Testing valid and invalid paths\n");
1408
1409 /* cleanup from an old run */
1410 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1411 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1412 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1413
1414 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1415 torture_comment(tctx, "mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1416 return false;
1417 }
1418
1419 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1420 torture_comment(tctx, "mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1421 return false;
1422 }
1423
1424 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1425 if (fnum == -1) {
1426 torture_comment(tctx, "open1 failed (%s)\n", smbcli_errstr(cli->tree));
1427 return false;
1428 }
1429 smbcli_close(cli->tree, fnum);
1430
1431 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1432 torture_comment(tctx, "chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1433 ret = false;
1434 }
1435
1436 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1437 torture_comment(tctx, "chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1438 ret = false;
1439 }
1440
1441 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1442 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1443 NT_STATUS_NOT_A_DIRECTORY);
1444 } else {
1445 torture_comment(tctx, "* chkpath on a file should fail\n");
1446 ret = false;
1447 }
1448
1449 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1450 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1451 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1452 } else {
1453 torture_comment(tctx, "* chkpath on a non existent file should fail\n");
1454 ret = false;
1455 }
1456
1457 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1458 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1459 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1460 } else {
1461 torture_comment(tctx, "* chkpath on a non existent component should fail\n");
1462 ret = false;
1463 }
1464
1465 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1466 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1467 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1468
1469 return ret;
1470}
1471
1472/*
1473 * This is a test to excercise some weird Samba3 error paths.
1474 */
1475
1476static bool torture_samba3_errorpaths(struct torture_context *tctx)
1477{
1478 bool nt_status_support;
1479 bool client_ntlmv2_auth;
1480 struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
1481 bool result = false;
1482 int fnum;
1483 const char *os2_fname = ".+,;=[].";
1484 const char *dname = "samba3_errordir";
1485 union smb_open io;
1486 NTSTATUS status;
1487
1488 nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx);
1489 client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(tctx->lp_ctx);
1490
1491 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
1492 torture_comment(tctx, "Could not set 'nt status support = yes'\n");
1493 goto fail;
1494 }
1495 if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "yes")) {
1496 torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = yes'\n");
1497 goto fail;
1498 }
1499
1500 if (!torture_open_connection(&cli_nt, tctx, 0)) {
1501 goto fail;
1502 }
1503
1504 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
1505 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = no'\n");
1506 goto fail;
1507 }
1508 if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "no")) {
1509 torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = no'\n");
1510 goto fail;
1511 }
1512
1513 if (!torture_open_connection(&cli_dos, tctx, 1)) {
1514 goto fail;
1515 }
1516
1517 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support",
1518 nt_status_support ? "yes":"no")) {
1519 torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support'");
1520 goto fail;
1521 }
1522 if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth",
1523 client_ntlmv2_auth ? "yes":"no")) {
1524 torture_result(tctx, TORTURE_FAIL, "Could not reset 'client ntlmv2 auth'");
1525 goto fail;
1526 }
1527
1528 smbcli_unlink(cli_nt->tree, os2_fname);
1529 smbcli_rmdir(cli_nt->tree, dname);
1530
1531 if (!NT_STATUS_IS_OK(smbcli_mkdir(cli_nt->tree, dname))) {
1532 torture_comment(tctx, "smbcli_mkdir(%s) failed: %s\n", dname,
1533 smbcli_errstr(cli_nt->tree));
1534 goto fail;
1535 }
1536
1537 io.generic.level = RAW_OPEN_NTCREATEX;
1538 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1539 io.ntcreatex.in.root_fid.fnum = 0;
1540 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1541 io.ntcreatex.in.alloc_size = 1024*1024;
1542 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1543 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1544 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1545 io.ntcreatex.in.create_options = 0;
1546 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1547 io.ntcreatex.in.security_flags = 0;
1548 io.ntcreatex.in.fname = dname;
1549
1550 status = smb_raw_open(cli_nt->tree, tctx, &io);
1551 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1552 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1553 __location__, nt_errstr(status),
1554 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1555 goto fail;
1556 }
1557 status = smb_raw_open(cli_dos->tree, tctx, &io);
1558 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1559 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1560 __location__, nt_errstr(status),
1561 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1562 goto fail;
1563 }
1564
1565 status = smbcli_mkdir(cli_nt->tree, dname);
1566 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1567 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1568 __location__, nt_errstr(status),
1569 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1570 goto fail;
1571 }
1572 status = smbcli_mkdir(cli_dos->tree, dname);
1573 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnoaccess))) {
1574 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1575 __location__, nt_errstr(status),
1576 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRnoaccess)));
1577 goto fail;
1578 }
1579
1580 {
1581 union smb_mkdir md;
1582 md.t2mkdir.level = RAW_MKDIR_T2MKDIR;
1583 md.t2mkdir.in.path = dname;
1584 md.t2mkdir.in.num_eas = 0;
1585 md.t2mkdir.in.eas = NULL;
1586
1587 status = smb_raw_mkdir(cli_nt->tree, &md);
1588 if (!NT_STATUS_EQUAL(status,
1589 NT_STATUS_OBJECT_NAME_COLLISION)) {
1590 torture_comment(
1591 tctx, "(%s) incorrect status %s should be "
1592 "NT_STATUS_OBJECT_NAME_COLLISION\n",
1593 __location__, nt_errstr(status));
1594 goto fail;
1595 }
1596 status = smb_raw_mkdir(cli_dos->tree, &md);
1597 if (!NT_STATUS_EQUAL(status,
1598 NT_STATUS_DOS(ERRDOS, ERRrename))) {
1599 torture_comment(tctx, "(%s) incorrect status %s "
1600 "should be ERRDOS:ERRrename\n",
1601 __location__, nt_errstr(status));
1602 goto fail;
1603 }
1604 }
1605
1606 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1607 status = smb_raw_open(cli_nt->tree, tctx, &io);
1608 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1609 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1610 __location__, nt_errstr(status),
1611 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1612 goto fail;
1613 }
1614
1615 status = smb_raw_open(cli_dos->tree, tctx, &io);
1616 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1617 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1618 __location__, nt_errstr(status),
1619 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1620 goto fail;
1621 }
1622
1623 {
1624 /* Test an invalid DOS deny mode */
1625 const char *fname = "test.txt";
1626
1627 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR | O_CREAT, 5);
1628 if (fnum != -1) {
1629 torture_comment(tctx, "Open(%s) with invalid deny mode succeeded -- "
1630 "expected failure\n", fname);
1631 smbcli_close(cli_nt->tree, fnum);
1632 goto fail;
1633 }
1634 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1635 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1636 torture_comment(tctx, "Expected DOS error ERRDOS/ERRbadaccess, "
1637 "got %s\n", smbcli_errstr(cli_nt->tree));
1638 goto fail;
1639 }
1640
1641 fnum = smbcli_open(cli_dos->tree, fname, O_RDWR | O_CREAT, 5);
1642 if (fnum != -1) {
1643 torture_comment(tctx, "Open(%s) with invalid deny mode succeeded -- "
1644 "expected failure\n", fname);
1645 smbcli_close(cli_nt->tree, fnum);
1646 goto fail;
1647 }
1648 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1649 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1650 torture_comment(tctx, "Expected DOS error ERRDOS:ERRbadaccess, "
1651 "got %s\n", smbcli_errstr(cli_nt->tree));
1652 goto fail;
1653 }
1654 }
1655
1656 {
1657 /*
1658 * Samba 3.0.23 has a bug that an existing file can be opened
1659 * as a directory using ntcreate&x. Test this.
1660 */
1661
1662 const char *fname = "\\test_dir.txt";
1663
1664 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR|O_CREAT,
1665 DENY_NONE);
1666 if (fnum == -1) {
1667 d_printf("(%s) smbcli_open failed: %s\n", __location__,
1668 smbcli_errstr(cli_nt->tree));
1669 }
1670 smbcli_close(cli_nt->tree, fnum);
1671
1672 io.generic.level = RAW_OPEN_NTCREATEX;
1673 io.ntcreatex.in.root_fid.fnum = 0;
1674 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1675 io.ntcreatex.in.alloc_size = 0;
1676 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1677 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1678 NTCREATEX_SHARE_ACCESS_WRITE|
1679 NTCREATEX_SHARE_ACCESS_DELETE;
1680 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1681 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1682 io.ntcreatex.in.impersonation =
1683 NTCREATEX_IMPERSONATION_ANONYMOUS;
1684 io.ntcreatex.in.security_flags = 0;
1685 io.ntcreatex.in.fname = fname;
1686 io.ntcreatex.in.flags = 0;
1687
1688 status = smb_raw_open(cli_nt->tree, tctx, &io);
1689 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1690 torture_comment(tctx, "ntcreate as dir gave %s, "
1691 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1692 nt_errstr(status));
1693 result = false;
1694 }
1695
1696 if (NT_STATUS_IS_OK(status)) {
1697 smbcli_close(cli_nt->tree, io.ntcreatex.out.file.fnum);
1698 }
1699
1700 status = smb_raw_open(cli_dos->tree, tctx, &io);
1701 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,
1702 ERRbaddirectory))) {
1703 torture_comment(tctx, "ntcreate as dir gave %s, "
1704 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1705 nt_errstr(status));
1706 result = false;
1707 }
1708
1709 if (NT_STATUS_IS_OK(status)) {
1710 smbcli_close(cli_dos->tree,
1711 io.ntcreatex.out.file.fnum);
1712 }
1713
1714 smbcli_unlink(cli_nt->tree, fname);
1715 }
1716
1717 if (!torture_setting_bool(tctx, "samba3", false)) {
1718 goto done;
1719 }
1720
1721 fnum = smbcli_open(cli_dos->tree, os2_fname,
1722 O_RDWR | O_CREAT | O_TRUNC,
1723 DENY_NONE);
1724 if (fnum != -1) {
1725 torture_comment(tctx, "Open(%s) succeeded -- expected failure\n",
1726 os2_fname);
1727 smbcli_close(cli_dos->tree, fnum);
1728 goto fail;
1729 }
1730
1731 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_dos->tree),
1732 NT_STATUS_DOS(ERRDOS, ERRcannotopen))) {
1733 torture_comment(tctx, "Expected DOS error ERRDOS/ERRcannotopen, got %s\n",
1734 smbcli_errstr(cli_dos->tree));
1735 goto fail;
1736 }
1737
1738 fnum = smbcli_open(cli_nt->tree, os2_fname,
1739 O_RDWR | O_CREAT | O_TRUNC,
1740 DENY_NONE);
1741 if (fnum != -1) {
1742 torture_comment(tctx, "Open(%s) succeeded -- expected failure\n",
1743 os2_fname);
1744 smbcli_close(cli_nt->tree, fnum);
1745 goto fail;
1746 }
1747
1748 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1749 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1750 torture_comment(tctx, "Expected error NT_STATUS_OBJECT_NAME_NOT_FOUND, "
1751 "got %s\n", smbcli_errstr(cli_nt->tree));
1752 goto fail;
1753 }
1754
1755 done:
1756 result = true;
1757
1758 fail:
1759 if (cli_dos != NULL) {
1760 torture_close_connection(cli_dos);
1761 }
1762 if (cli_nt != NULL) {
1763 torture_close_connection(cli_nt);
1764 }
1765
1766 return result;
1767}
1768
1769/**
1770 This checks file/dir birthtime
1771*/
1772static void list_fn(struct clilist_file_info *finfo, const char *name,
1773 void *state){
1774
1775 /* Just to change dir access time*/
1776 sleep(5);
1777
1778}
1779
1780static bool run_birthtimetest(struct torture_context *tctx,
1781 struct smbcli_state *cli)
1782{
1783 int fnum;
1784 size_t size;
1785 time_t c_time, a_time, m_time, w_time, c_time1;
1786 const char *fname = "\\birthtime.tst";
1787 const char *dname = "\\birthtime";
1788 const char *fname2 = "\\birthtime\\birthtime.tst";
1789 bool correct = true;
1790 uint8_t buf[16];
1791
1792
1793 smbcli_unlink(cli->tree, fname);
1794
1795 torture_comment(tctx, "Testing Birthtime for File\n");
1796
1797 /* Save File birthtime/creationtime */
1798 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
1799 DENY_NONE);
1800 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size,
1801 &c_time, &a_time, &m_time, NULL, NULL))) {
1802 torture_comment(tctx, "ERROR: qfileinfo failed (%s)\n",
1803 smbcli_errstr(cli->tree));
1804 correct = false;
1805 }
1806 smbcli_close(cli->tree, fnum);
1807
1808 sleep(10);
1809
1810 /* Change in File attribute changes file change time*/
1811 smbcli_setatr(cli->tree, fname, FILE_ATTRIBUTE_SYSTEM, 0);
1812
1813 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT , DENY_NONE);
1814 /* Writing updates modification time*/
1815 smbcli_smbwrite(cli->tree, fnum, &fname, 0, sizeof(fname));
1816 /*Reading updates access time */
1817 smbcli_read(cli->tree, fnum, buf, 0, 13);
1818 smbcli_close(cli->tree, fnum);
1819
1820 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time1,
1821 &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1822 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n",
1823 smbcli_errstr(cli->tree));
1824 correct = false;
1825 } else {
1826 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1827 (long) c_time, (long) c_time1);
1828 if (c_time1 != c_time) {
1829 torture_comment(tctx, "This system updated file \
1830 birth times! Not expected!\n");
1831 correct = false;
1832 }
1833 }
1834 smbcli_unlink(cli->tree, fname);
1835
1836 torture_comment(tctx, "Testing Birthtime for Directory\n");
1837
1838 /* check if the server does not update the directory birth time
1839 when creating a new file */
1840 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1841 torture_comment(tctx, "ERROR: mkdir failed (%s)\n",
1842 smbcli_errstr(cli->tree));
1843 correct = false;
1844 }
1845 sleep(3);
1846 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1847 &c_time,&a_time,&m_time,&w_time, &size, NULL, NULL))){
1848 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n",
1849 smbcli_errstr(cli->tree));
1850 correct = false;
1851 }
1852
1853 /* Creating a new file changes dir modification time and change time*/
1854 smbcli_unlink(cli->tree, fname2);
1855 fnum = smbcli_open(cli->tree, fname2, O_RDWR | O_CREAT | O_TRUNC,
1856 DENY_NONE);
1857 smbcli_smbwrite(cli->tree, fnum, &fnum, 0, sizeof(fnum));
1858 smbcli_read(cli->tree, fnum, buf, 0, 13);
1859 smbcli_close(cli->tree, fnum);
1860
1861 /* dir listing changes dir access time*/
1862 smbcli_list(cli->tree, "\\birthtime\\*", 0, list_fn, cli );
1863
1864 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1865 &c_time1, &a_time, &m_time,&w_time,&size,NULL,NULL))){
1866 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n",
1867 smbcli_errstr(cli->tree));
1868 correct = false;
1869 } else {
1870 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1871 (long) c_time, (long) c_time1);
1872 if (c_time1 != c_time) {
1873 torture_comment(tctx, "This system updated directory \
1874 birth times! Not Expected!\n");
1875 correct = false;
1876 }
1877 }
1878 smbcli_unlink(cli->tree, fname2);
1879 smbcli_rmdir(cli->tree, dname);
1880
1881 return correct;
1882}
1883
1884
1885NTSTATUS torture_base_init(void)
1886{
1887 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "base");
1888
1889 torture_suite_add_2smb_test(suite, "fdpass", run_fdpasstest);
1890 torture_suite_add_suite(suite, torture_base_locktest(suite));
1891 torture_suite_add_1smb_test(suite, "unlink", torture_unlinktest);
1892 torture_suite_add_1smb_test(suite, "attr", run_attrtest);
1893 torture_suite_add_1smb_test(suite, "trans2", run_trans2test);
1894 torture_suite_add_1smb_test(suite, "birthtime", run_birthtimetest);
1895 torture_suite_add_simple_test(suite, "negnowait", run_negprot_nowait);
1896 torture_suite_add_1smb_test(suite, "dir1", torture_dirtest1);
1897 torture_suite_add_1smb_test(suite, "dir2", torture_dirtest2);
1898 torture_suite_add_1smb_test(suite, "deny1", torture_denytest1);
1899 torture_suite_add_2smb_test(suite, "deny2", torture_denytest2);
1900 torture_suite_add_2smb_test(suite, "deny3", torture_denytest3);
1901 torture_suite_add_1smb_test(suite, "denydos", torture_denydos_sharing);
1902 torture_suite_add_smb_multi_test(suite, "ntdeny1", torture_ntdenytest1);
1903 torture_suite_add_2smb_test(suite, "ntdeny2", torture_ntdenytest2);
1904 torture_suite_add_1smb_test(suite, "tcon", run_tcon_test);
1905 torture_suite_add_1smb_test(suite, "tcondev", run_tcon_devtype_test);
1906 torture_suite_add_1smb_test(suite, "vuid", run_vuidtest);
1907 torture_suite_add_2smb_test(suite, "rw1", run_readwritetest);
1908 torture_suite_add_2smb_test(suite, "open", run_opentest);
1909 torture_suite_add_smb_multi_test(suite, "defer_open", run_deferopen);
1910 torture_suite_add_1smb_test(suite, "xcopy", run_xcopy);
1911 torture_suite_add_1smb_test(suite, "iometer", run_iometer);
1912 torture_suite_add_1smb_test(suite, "rename", torture_test_rename);
1913 torture_suite_add_suite(suite, torture_test_delete());
1914 torture_suite_add_1smb_test(suite, "properties", torture_test_properties);
1915 torture_suite_add_1smb_test(suite, "mangle", torture_mangle);
1916 torture_suite_add_1smb_test(suite, "openattr", torture_openattrtest);
1917 torture_suite_add_1smb_test(suite, "winattr", torture_winattrtest);
1918 torture_suite_add_suite(suite, torture_charset(suite));
1919 torture_suite_add_1smb_test(suite, "chkpath", torture_chkpath_test);
1920 torture_suite_add_1smb_test(suite, "secleak", torture_sec_leak);
1921 torture_suite_add_simple_test(suite, "disconnect", torture_disconnect);
1922 torture_suite_add_suite(suite, torture_delay_write());
1923 torture_suite_add_simple_test(suite, "samba3error", torture_samba3_errorpaths);
1924 torture_suite_add_1smb_test(suite, "casetable", torture_casetable);
1925 torture_suite_add_1smb_test(suite, "utable", torture_utable);
1926 torture_suite_add_simple_test(suite, "smb", torture_smb_scan);
1927 torture_suite_add_suite(suite, torture_trans2_aliases(suite));
1928 torture_suite_add_1smb_test(suite, "trans2-scan", torture_trans2_scan);
1929 torture_suite_add_1smb_test(suite, "nttrans", torture_nttrans_scan);
1930 torture_suite_add_1smb_test(suite, "createx_access", torture_createx_access);
1931 torture_suite_add_2smb_test(suite, "createx_sharemodes_file", torture_createx_sharemodes_file);
1932 torture_suite_add_2smb_test(suite, "createx_sharemodes_dir", torture_createx_sharemodes_dir);
1933 torture_suite_add_1smb_test(suite, "maximum_allowed", torture_maximum_allowed);
1934
1935 torture_suite_add_simple_test(suite, "bench-holdcon", torture_holdcon);
1936 torture_suite_add_1smb_test(suite, "bench-holdopen", torture_holdopen);
1937 torture_suite_add_simple_test(suite, "bench-readwrite", run_benchrw);
1938 torture_suite_add_smb_multi_test(suite, "bench-torture", run_torture);
1939 torture_suite_add_1smb_test(suite, "scan-pipe_number", run_pipe_number);
1940 torture_suite_add_1smb_test(suite, "scan-ioctl", torture_ioctl_test);
1941 torture_suite_add_smb_multi_test(suite, "scan-maxfid", run_maxfidtest);
1942
1943 suite->description = talloc_strdup(suite,
1944 "Basic SMB tests (imported from the original smbtorture)");
1945
1946 torture_register_suite(suite);
1947
1948 return NT_STATUS_OK;
1949}
Note: See TracBrowser for help on using the repository browser.