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