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