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