s3:torture pass flags to torture_open_connection_share()
[samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
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 "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "../lib/util/memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
46
47 extern char *optarg;
48 extern int optind;
49
50 fstring host, workgroup, share, password, username, myname;
51 struct cli_credentials *torture_creds;
52 static const char *sockops="TCP_NODELAY";
53 int torture_nprocs=1;
54 static int port_to_use=0;
55 int torture_numops=100;
56 int torture_blocksize=1024*1024;
57 static int procnum; /* records process count number when forking */
58 static struct cli_state *current_cli;
59 static fstring randomfname;
60 static bool use_oplocks;
61 static bool use_level_II_oplocks;
62 static const char *client_txt = "client_oplocks.txt";
63 static bool disable_spnego;
64 static bool use_kerberos;
65 static bool force_dos_errors;
66 static fstring multishare_conn_fname;
67 static bool use_multishare_conn = False;
68 static bool do_encrypt;
69 static const char *local_path = NULL;
70 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
71 char *test_filename;
72
73 bool torture_showall = False;
74
75 static double create_procs(bool (*fn)(int), bool *result);
76
77 /********************************************************************
78  Ensure a connection is encrypted.
79 ********************************************************************/
80
81 static bool force_cli_encryption(struct cli_state *c,
82                         const char *sharename)
83 {
84         uint16_t major, minor;
85         uint32_t caplow, caphigh;
86         NTSTATUS status;
87
88         if (!SERVER_HAS_UNIX_CIFS(c)) {
89                 d_printf("Encryption required and "
90                         "server that doesn't support "
91                         "UNIX extensions - failing connect\n");
92                         return false;
93         }
94
95         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
96                                              &caphigh);
97         if (!NT_STATUS_IS_OK(status)) {
98                 d_printf("Encryption required and "
99                         "can't get UNIX CIFS extensions "
100                         "version from server: %s\n", nt_errstr(status));
101                 return false;
102         }
103
104         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
105                 d_printf("Encryption required and "
106                         "share %s doesn't support "
107                         "encryption.\n", sharename);
108                 return false;
109         }
110
111         status = cli_smb1_setup_encryption(c, torture_creds);
112         if (!NT_STATUS_IS_OK(status)) {
113                 d_printf("Encryption required and "
114                         "setup failed with error %s.\n",
115                         nt_errstr(status));
116                 return false;
117         }
118
119         return true;
120 }
121
122
123 static struct cli_state *open_nbt_connection(void)
124 {
125         struct cli_state *c;
126         NTSTATUS status;
127         int flags = 0;
128
129         if (disable_spnego) {
130                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
131         }
132
133         if (use_oplocks) {
134                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
135         }
136
137         if (use_level_II_oplocks) {
138                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
139         }
140
141         if (use_kerberos) {
142                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
143         }
144
145         if (force_dos_errors) {
146                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
147         }
148
149         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
150                                 signing_state, flags, &c);
151         if (!NT_STATUS_IS_OK(status)) {
152                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
153                 return NULL;
154         }
155
156         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
157
158         return c;
159 }
160
161 /****************************************************************************
162  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
163 ****************************************************************************/
164
165 static bool cli_bad_session_request(int fd,
166                          struct nmb_name *calling, struct nmb_name *called)
167 {
168         TALLOC_CTX *frame;
169         uint8_t len_buf[4];
170         struct iovec iov[3];
171         ssize_t len;
172         uint8_t *inbuf;
173         int err;
174         bool ret = false;
175         uint8_t message_type;
176         uint8_t error;
177         struct tevent_context *ev;
178         struct tevent_req *req;
179
180         frame = talloc_stackframe();
181
182         iov[0].iov_base = len_buf;
183         iov[0].iov_len  = sizeof(len_buf);
184
185         /* put in the destination name */
186
187         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
188                                       called->name_type);
189         if (iov[1].iov_base == NULL) {
190                 goto fail;
191         }
192         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
193                                   talloc_get_size(iov[1].iov_base));
194
195         /* and my name */
196
197         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
198                                       calling->name_type);
199         if (iov[2].iov_base == NULL) {
200                 goto fail;
201         }
202         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
203                                   talloc_get_size(iov[2].iov_base));
204
205         /* Deliberately corrupt the name len (first byte) */
206         *((uint8_t *)iov[2].iov_base) = 100;
207
208         /* send a session request (RFC 1002) */
209         /* setup the packet length
210          * Remove four bytes from the length count, since the length
211          * field in the NBT Session Service header counts the number
212          * of bytes which follow.  The cli_send_smb() function knows
213          * about this and accounts for those four bytes.
214          * CRH.
215          */
216
217         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
218         SCVAL(len_buf,0,0x81);
219
220         len = write_data_iov(fd, iov, 3);
221         if (len == -1) {
222                 goto fail;
223         }
224
225         ev = samba_tevent_context_init(frame);
226         if (ev == NULL) {
227                 goto fail;
228         }
229         req = read_smb_send(frame, ev, fd);
230         if (req == NULL) {
231                 goto fail;
232         }
233         if (!tevent_req_poll(req, ev)) {
234                 goto fail;
235         }
236         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
237         if (len == -1) {
238                 errno = err;
239                 goto fail;
240         }
241         TALLOC_FREE(ev);
242
243         message_type = CVAL(inbuf, 0);
244         if (message_type != 0x83) {
245                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
246                           message_type);
247                 goto fail;
248         }
249
250         if (smb_len(inbuf) != 1) {
251                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
252                           (int)smb_len(inbuf));
253                 goto fail;
254         }
255
256         error = CVAL(inbuf, 4);
257         if (error !=  0x82) {
258                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
259                           (int)error);
260                 goto fail;
261         }
262
263         ret = true;
264 fail:
265         TALLOC_FREE(frame);
266         return ret;
267 }
268
269 /* Insert a NULL at the first separator of the given path and return a pointer
270  * to the remainder of the string.
271  */
272 static char *
273 terminate_path_at_separator(char * path)
274 {
275         char * p;
276
277         if (!path) {
278                 return NULL;
279         }
280
281         if ((p = strchr_m(path, '/'))) {
282                 *p = '\0';
283                 return p + 1;
284         }
285
286         if ((p = strchr_m(path, '\\'))) {
287                 *p = '\0';
288                 return p + 1;
289         }
290
291         /* No separator. */
292         return NULL;
293 }
294
295 /*
296   parse a //server/share type UNC name
297 */
298 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
299                       char **hostname, char **sharename)
300 {
301         char *p;
302
303         *hostname = *sharename = NULL;
304
305         if (strncmp(unc_name, "\\\\", 2) &&
306             strncmp(unc_name, "//", 2)) {
307                 return False;
308         }
309
310         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
311         p = terminate_path_at_separator(*hostname);
312
313         if (p && *p) {
314                 *sharename = talloc_strdup(mem_ctx, p);
315                 terminate_path_at_separator(*sharename);
316         }
317
318         if (*hostname && *sharename) {
319                 return True;
320         }
321
322         TALLOC_FREE(*hostname);
323         TALLOC_FREE(*sharename);
324         return False;
325 }
326
327 static bool torture_open_connection_share(struct cli_state **c,
328                                    const char *hostname, 
329                                    const char *sharename,
330                                    int flags)
331 {
332         NTSTATUS status;
333
334         status = cli_full_connection_creds(c,
335                                            myname,
336                                            hostname,
337                                            NULL, /* dest_ss */
338                                            port_to_use,
339                                            sharename,
340                                            "?????",
341                                            torture_creds,
342                                            flags,
343                                            signing_state);
344         if (!NT_STATUS_IS_OK(status)) {
345                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
346                         hostname, sharename, port_to_use, nt_errstr(status));
347                 return False;
348         }
349
350         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
351
352         if (do_encrypt) {
353                 return force_cli_encryption(*c,
354                                         sharename);
355         }
356         return True;
357 }
358
359 bool torture_open_connection(struct cli_state **c, int conn_index)
360 {
361         char **unc_list = NULL;
362         int num_unc_names = 0;
363         bool result;
364         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
365
366         if (use_oplocks) {
367                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
368         }
369         if (use_level_II_oplocks) {
370                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
371         }
372
373         if (use_multishare_conn==True) {
374                 char *h, *s;
375                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
376                 if (!unc_list || num_unc_names <= 0) {
377                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
378                         exit(1);
379                 }
380
381                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382                                       NULL, &h, &s)) {
383                         printf("Failed to parse UNC name %s\n",
384                                unc_list[conn_index % num_unc_names]);
385                         TALLOC_FREE(unc_list);
386                         exit(1);
387                 }
388
389                 result = torture_open_connection_share(c, h, s, flags);
390
391                 /* h, s were copied earlier */
392                 TALLOC_FREE(unc_list);
393                 return result;
394         }
395
396         return torture_open_connection_share(c, host, share, flags);
397 }
398
399 bool torture_init_connection(struct cli_state **pcli)
400 {
401         struct cli_state *cli;
402
403         cli = open_nbt_connection();
404         if (cli == NULL) {
405                 return false;
406         }
407
408         *pcli = cli;
409         return true;
410 }
411
412 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
413 {
414         uint16_t old_vuid = cli_state_get_uid(cli);
415         NTSTATUS status;
416         bool ret;
417
418         cli_state_set_uid(cli, 0);
419         status = cli_session_setup_creds(cli, torture_creds);
420         ret = NT_STATUS_IS_OK(status);
421         *new_vuid = cli_state_get_uid(cli);
422         cli_state_set_uid(cli, old_vuid);
423         return ret;
424 }
425
426
427 bool torture_close_connection(struct cli_state *c)
428 {
429         bool ret = True;
430         NTSTATUS status;
431
432         status = cli_tdis(c);
433         if (!NT_STATUS_IS_OK(status)) {
434                 printf("tdis failed (%s)\n", nt_errstr(status));
435                 ret = False;
436         }
437
438         cli_shutdown(c);
439
440         return ret;
441 }
442
443
444 /* check if the server produced the expected dos or nt error code */
445 static bool check_both_error(int line, NTSTATUS status,
446                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
447 {
448         if (NT_STATUS_IS_DOS(status)) {
449                 uint8_t cclass;
450                 uint32_t num;
451
452                 /* Check DOS error */
453                 cclass = NT_STATUS_DOS_CLASS(status);
454                 num = NT_STATUS_DOS_CODE(status);
455
456                 if (eclass != cclass || ecode != num) {
457                         printf("unexpected error code class=%d code=%d\n",
458                                (int)cclass, (int)num);
459                         printf(" expected %d/%d %s (line=%d)\n",
460                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
461                         return false;
462                 }
463         } else {
464                 /* Check NT error */
465                 if (!NT_STATUS_EQUAL(nterr, status)) {
466                         printf("unexpected error code %s\n",
467                                 nt_errstr(status));
468                         printf(" expected %s (line=%d)\n",
469                                 nt_errstr(nterr), line);
470                         return false;
471                 }
472         }
473
474         return true;
475 }
476
477
478 /* check if the server produced the expected error code */
479 static bool check_error(int line, NTSTATUS status,
480                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
481 {
482         if (NT_STATUS_IS_DOS(status)) {
483                 uint8_t cclass;
484                 uint32_t num;
485
486                 /* Check DOS error */
487
488                 cclass = NT_STATUS_DOS_CLASS(status);
489                 num = NT_STATUS_DOS_CODE(status);
490
491                 if (eclass != cclass || ecode != num) {
492                         printf("unexpected error code class=%d code=%d\n", 
493                                (int)cclass, (int)num);
494                         printf(" expected %d/%d %s (line=%d)\n", 
495                                (int)eclass, (int)ecode, nt_errstr(nterr),
496                                line);
497                         return False;
498                 }
499
500         } else {
501                 /* Check NT error */
502
503                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
504                         printf("unexpected error code %s\n",
505                                nt_errstr(status));
506                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
507                                line);
508                         return False;
509                 }
510         }
511
512         return True;
513 }
514
515
516 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
517 {
518         NTSTATUS status;
519
520         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
521
522         while (!NT_STATUS_IS_OK(status)) {
523                 if (!check_both_error(__LINE__, status, ERRDOS,
524                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
525                         return false;
526                 }
527
528                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
529         }
530
531         return true;
532 }
533
534
535 static bool rw_torture(struct cli_state *c)
536 {
537         const char *lockfname = "\\torture.lck";
538         fstring fname;
539         uint16_t fnum;
540         uint16_t fnum2;
541         pid_t pid2, pid = getpid();
542         int i, j;
543         char buf[1024];
544         bool correct = True;
545         size_t nread = 0;
546         NTSTATUS status;
547
548         memset(buf, '\0', sizeof(buf));
549
550         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
551                          DENY_NONE, &fnum2);
552         if (!NT_STATUS_IS_OK(status)) {
553                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
554         }
555         if (!NT_STATUS_IS_OK(status)) {
556                 printf("open of %s failed (%s)\n",
557                        lockfname, nt_errstr(status));
558                 return False;
559         }
560
561         for (i=0;i<torture_numops;i++) {
562                 unsigned n = (unsigned)sys_random()%10;
563
564                 if (i % 10 == 0) {
565                         printf("%d\r", i); fflush(stdout);
566                 }
567                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
568
569                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
570                         return False;
571                 }
572
573                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
574                                   DENY_ALL, &fnum);
575                 if (!NT_STATUS_IS_OK(status)) {
576                         printf("open failed (%s)\n", nt_errstr(status));
577                         correct = False;
578                         break;
579                 }
580
581                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
582                                       sizeof(pid), NULL);
583                 if (!NT_STATUS_IS_OK(status)) {
584                         printf("write failed (%s)\n", nt_errstr(status));
585                         correct = False;
586                 }
587
588                 for (j=0;j<50;j++) {
589                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
590                                               sizeof(pid)+(j*sizeof(buf)),
591                                               sizeof(buf), NULL);
592                         if (!NT_STATUS_IS_OK(status)) {
593                                 printf("write failed (%s)\n",
594                                        nt_errstr(status));
595                                 correct = False;
596                         }
597                 }
598
599                 pid2 = 0;
600
601                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
602                                   &nread);
603                 if (!NT_STATUS_IS_OK(status)) {
604                         printf("read failed (%s)\n", nt_errstr(status));
605                         correct = false;
606                 } else if (nread != sizeof(pid)) {
607                         printf("read/write compare failed: "
608                                "recv %ld req %ld\n", (unsigned long)nread,
609                                (unsigned long)sizeof(pid));
610                         correct = false;
611                 }
612
613                 if (pid2 != pid) {
614                         printf("data corruption!\n");
615                         correct = False;
616                 }
617
618                 status = cli_close(c, fnum);
619                 if (!NT_STATUS_IS_OK(status)) {
620                         printf("close failed (%s)\n", nt_errstr(status));
621                         correct = False;
622                 }
623
624                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
625                 if (!NT_STATUS_IS_OK(status)) {
626                         printf("unlink failed (%s)\n", nt_errstr(status));
627                         correct = False;
628                 }
629
630                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
631                 if (!NT_STATUS_IS_OK(status)) {
632                         printf("unlock failed (%s)\n", nt_errstr(status));
633                         correct = False;
634                 }
635         }
636
637         cli_close(c, fnum2);
638         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
639
640         printf("%d\n", i);
641
642         return correct;
643 }
644
645 static bool run_torture(int dummy)
646 {
647         struct cli_state *cli;
648         bool ret;
649
650         cli = current_cli;
651
652         smbXcli_conn_set_sockopt(cli->conn, sockops);
653
654         ret = rw_torture(cli);
655
656         if (!torture_close_connection(cli)) {
657                 ret = False;
658         }
659
660         return ret;
661 }
662
663 static bool rw_torture3(struct cli_state *c, char *lockfname)
664 {
665         uint16_t fnum = (uint16_t)-1;
666         unsigned int i = 0;
667         char buf[131072];
668         char buf_rd[131072];
669         unsigned count;
670         unsigned countprev = 0;
671         size_t sent = 0;
672         bool correct = True;
673         NTSTATUS status = NT_STATUS_OK;
674
675         srandom(1);
676         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
677         {
678                 SIVAL(buf, i, sys_random());
679         }
680
681         if (procnum == 0)
682         {
683                 status = cli_unlink(
684                         c, lockfname,
685                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
686                 if (!NT_STATUS_IS_OK(status)) {
687                         printf("unlink failed (%s) (normal, this file should "
688                                "not exist)\n", nt_errstr(status));
689                 }
690
691                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
692                                   DENY_NONE, &fnum);
693                 if (!NT_STATUS_IS_OK(status)) {
694                         printf("first open read/write of %s failed (%s)\n",
695                                         lockfname, nt_errstr(status));
696                         return False;
697                 }
698         }
699         else
700         {
701                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
702                 {
703                         status = cli_openx(c, lockfname, O_RDONLY, 
704                                          DENY_NONE, &fnum);
705                         if (NT_STATUS_IS_OK(status)) {
706                                 break;
707                         }
708                         smb_msleep(10);
709                 }
710                 if (!NT_STATUS_IS_OK(status)) {
711                         printf("second open read-only of %s failed (%s)\n",
712                                         lockfname, nt_errstr(status));
713                         return False;
714                 }
715         }
716
717         i = 0;
718         for (count = 0; count < sizeof(buf); count += sent)
719         {
720                 if (count >= countprev) {
721                         printf("%d %8d\r", i, count);
722                         fflush(stdout);
723                         i++;
724                         countprev += (sizeof(buf) / 20);
725                 }
726
727                 if (procnum == 0)
728                 {
729                         sent = ((unsigned)sys_random()%(20))+ 1;
730                         if (sent > sizeof(buf) - count)
731                         {
732                                 sent = sizeof(buf) - count;
733                         }
734
735                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
736                                               count, sent, NULL);
737                         if (!NT_STATUS_IS_OK(status)) {
738                                 printf("write failed (%s)\n",
739                                        nt_errstr(status));
740                                 correct = False;
741                         }
742                 }
743                 else
744                 {
745                         status = cli_read(c, fnum, buf_rd+count, count,
746                                           sizeof(buf)-count, &sent);
747                         if(!NT_STATUS_IS_OK(status)) {
748                                 printf("read failed offset:%d size:%ld (%s)\n",
749                                        count, (unsigned long)sizeof(buf)-count,
750                                        nt_errstr(status));
751                                 correct = False;
752                                 sent = 0;
753                         } else if (sent > 0) {
754                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
755                                 {
756                                         printf("read/write compare failed\n");
757                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
758                                         correct = False;
759                                         break;
760                                 }
761                         }
762                 }
763
764         }
765
766         status = cli_close(c, fnum);
767         if (!NT_STATUS_IS_OK(status)) {
768                 printf("close failed (%s)\n", nt_errstr(status));
769                 correct = False;
770         }
771
772         return correct;
773 }
774
775 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
776 {
777         const char *lockfname = "\\torture2.lck";
778         uint16_t fnum1;
779         uint16_t fnum2;
780         int i;
781         char buf[131072];
782         char buf_rd[131072];
783         bool correct = True;
784         size_t bytes_read;
785         NTSTATUS status;
786
787         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
788         if (!NT_STATUS_IS_OK(status)) {
789                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
790         }
791
792         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
793                           DENY_NONE, &fnum1);
794         if (!NT_STATUS_IS_OK(status)) {
795                 printf("first open read/write of %s failed (%s)\n",
796                                 lockfname, nt_errstr(status));
797                 return False;
798         }
799
800         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
801         if (!NT_STATUS_IS_OK(status)) {
802                 printf("second open read-only of %s failed (%s)\n",
803                                 lockfname, nt_errstr(status));
804                 cli_close(c1, fnum1);
805                 return False;
806         }
807
808         for (i = 0; i < torture_numops; i++)
809         {
810                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
811                 if (i % 10 == 0) {
812                         printf("%d\r", i); fflush(stdout);
813                 }
814
815                 generate_random_buffer((unsigned char *)buf, buf_size);
816
817                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
818                                       buf_size, NULL);
819                 if (!NT_STATUS_IS_OK(status)) {
820                         printf("write failed (%s)\n", nt_errstr(status));
821                         correct = False;
822                         break;
823                 }
824
825                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
826                 if(!NT_STATUS_IS_OK(status)) {
827                         printf("read failed (%s)\n", nt_errstr(status));
828                         correct = false;
829                         break;
830                 } else if (bytes_read != buf_size) {
831                         printf("read failed\n");
832                         printf("read %ld, expected %ld\n",
833                                (unsigned long)bytes_read,
834                                (unsigned long)buf_size); 
835                         correct = False;
836                         break;
837                 }
838
839                 if (memcmp(buf_rd, buf, buf_size) != 0)
840                 {
841                         printf("read/write compare failed\n");
842                         correct = False;
843                         break;
844                 }
845         }
846
847         status = cli_close(c2, fnum2);
848         if (!NT_STATUS_IS_OK(status)) {
849                 printf("close failed (%s)\n", nt_errstr(status));
850                 correct = False;
851         }
852
853         status = cli_close(c1, fnum1);
854         if (!NT_STATUS_IS_OK(status)) {
855                 printf("close failed (%s)\n", nt_errstr(status));
856                 correct = False;
857         }
858
859         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
860         if (!NT_STATUS_IS_OK(status)) {
861                 printf("unlink failed (%s)\n", nt_errstr(status));
862                 correct = False;
863         }
864
865         return correct;
866 }
867
868 static bool run_readwritetest(int dummy)
869 {
870         struct cli_state *cli1, *cli2;
871         bool test1, test2 = False;
872
873         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
874                 return False;
875         }
876         smbXcli_conn_set_sockopt(cli1->conn, sockops);
877         smbXcli_conn_set_sockopt(cli2->conn, sockops);
878
879         printf("starting readwritetest\n");
880
881         test1 = rw_torture2(cli1, cli2);
882         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
883
884         if (test1) {
885                 test2 = rw_torture2(cli1, cli1);
886                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
887         }
888
889         if (!torture_close_connection(cli1)) {
890                 test1 = False;
891         }
892
893         if (!torture_close_connection(cli2)) {
894                 test2 = False;
895         }
896
897         return (test1 && test2);
898 }
899
900 static bool run_readwritemulti(int dummy)
901 {
902         struct cli_state *cli;
903         bool test;
904
905         cli = current_cli;
906
907         smbXcli_conn_set_sockopt(cli->conn, sockops);
908
909         printf("run_readwritemulti: fname %s\n", randomfname);
910         test = rw_torture3(cli, randomfname);
911
912         if (!torture_close_connection(cli)) {
913                 test = False;
914         }
915
916         return test;
917 }
918
919 static bool run_readwritelarge_internal(void)
920 {
921         static struct cli_state *cli1;
922         uint16_t fnum1;
923         const char *lockfname = "\\large.dat";
924         off_t fsize;
925         char buf[126*1024];
926         bool correct = True;
927         NTSTATUS status;
928
929         if (!torture_open_connection(&cli1, 0)) {
930                 return False;
931         }
932         smbXcli_conn_set_sockopt(cli1->conn, sockops);
933         memset(buf,'\0',sizeof(buf));
934
935         printf("starting readwritelarge_internal\n");
936
937         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
938
939         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
940                           DENY_NONE, &fnum1);
941         if (!NT_STATUS_IS_OK(status)) {
942                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
943                 return False;
944         }
945
946         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
947
948         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
949                                      NULL, NULL, NULL);
950         if (!NT_STATUS_IS_OK(status)) {
951                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
952                 correct = False;
953         }
954
955         if (fsize == sizeof(buf))
956                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
957                        (unsigned long)fsize);
958         else {
959                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
960                        (unsigned long)fsize);
961                 correct = False;
962         }
963
964         status = cli_close(cli1, fnum1);
965         if (!NT_STATUS_IS_OK(status)) {
966                 printf("close failed (%s)\n", nt_errstr(status));
967                 correct = False;
968         }
969
970         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
971         if (!NT_STATUS_IS_OK(status)) {
972                 printf("unlink failed (%s)\n", nt_errstr(status));
973                 correct = False;
974         }
975
976         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
977                           DENY_NONE, &fnum1);
978         if (!NT_STATUS_IS_OK(status)) {
979                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
980                 return False;
981         }
982
983         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
984
985         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
986                                      NULL, NULL, NULL);
987         if (!NT_STATUS_IS_OK(status)) {
988                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
989                 correct = False;
990         }
991
992         if (fsize == sizeof(buf))
993                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
994                        (unsigned long)fsize);
995         else {
996                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
997                        (unsigned long)fsize);
998                 correct = False;
999         }
1000
1001 #if 0
1002         /* ToDo - set allocation. JRA */
1003         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1004                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1005                 return False;
1006         }
1007         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1008                                  NULL, NULL)) {
1009                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1010                 correct = False;
1011         }
1012         if (fsize != 0)
1013                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1014 #endif
1015
1016         status = cli_close(cli1, fnum1);
1017         if (!NT_STATUS_IS_OK(status)) {
1018                 printf("close failed (%s)\n", nt_errstr(status));
1019                 correct = False;
1020         }
1021
1022         if (!torture_close_connection(cli1)) {
1023                 correct = False;
1024         }
1025         return correct;
1026 }
1027
1028 static bool run_readwritelarge(int dummy)
1029 {
1030         return run_readwritelarge_internal();
1031 }
1032
1033 static bool run_readwritelarge_signtest(int dummy)
1034 {
1035         bool ret;
1036         signing_state = SMB_SIGNING_REQUIRED;
1037         ret = run_readwritelarge_internal();
1038         signing_state = SMB_SIGNING_DEFAULT;
1039         return ret;
1040 }
1041
1042 int line_count = 0;
1043 int nbio_id;
1044
1045 #define ival(s) strtol(s, NULL, 0)
1046
1047 /* run a test that simulates an approximate netbench client load */
1048 static bool run_netbench(int client)
1049 {
1050         struct cli_state *cli;
1051         int i;
1052         char line[1024];
1053         char cname[20];
1054         FILE *f;
1055         const char *params[20];
1056         bool correct = True;
1057
1058         cli = current_cli;
1059
1060         nbio_id = client;
1061
1062         smbXcli_conn_set_sockopt(cli->conn, sockops);
1063
1064         nb_setup(cli);
1065
1066         slprintf(cname,sizeof(cname)-1, "client%d", client);
1067
1068         f = fopen(client_txt, "r");
1069
1070         if (!f) {
1071                 perror(client_txt);
1072                 return False;
1073         }
1074
1075         while (fgets(line, sizeof(line)-1, f)) {
1076                 char *saveptr;
1077                 line_count++;
1078
1079                 line[strlen(line)-1] = 0;
1080
1081                 /* printf("[%d] %s\n", line_count, line); */
1082
1083                 all_string_sub(line,"client1", cname, sizeof(line));
1084
1085                 /* parse the command parameters */
1086                 params[0] = strtok_r(line, " ", &saveptr);
1087                 i = 0;
1088                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1089
1090                 params[i] = "";
1091
1092                 if (i < 2) continue;
1093
1094                 if (!strncmp(params[0],"SMB", 3)) {
1095                         printf("ERROR: You are using a dbench 1 load file\n");
1096                         exit(1);
1097                 }
1098
1099                 if (!strcmp(params[0],"NTCreateX")) {
1100                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1101                                    ival(params[4]));
1102                 } else if (!strcmp(params[0],"Close")) {
1103                         nb_close(ival(params[1]));
1104                 } else if (!strcmp(params[0],"Rename")) {
1105                         nb_rename(params[1], params[2]);
1106                 } else if (!strcmp(params[0],"Unlink")) {
1107                         nb_unlink(params[1]);
1108                 } else if (!strcmp(params[0],"Deltree")) {
1109                         nb_deltree(params[1]);
1110                 } else if (!strcmp(params[0],"Rmdir")) {
1111                         nb_rmdir(params[1]);
1112                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1113                         nb_qpathinfo(params[1]);
1114                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1115                         nb_qfileinfo(ival(params[1]));
1116                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1117                         nb_qfsinfo(ival(params[1]));
1118                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1119                         nb_findfirst(params[1]);
1120                 } else if (!strcmp(params[0],"WriteX")) {
1121                         nb_writex(ival(params[1]), 
1122                                   ival(params[2]), ival(params[3]), ival(params[4]));
1123                 } else if (!strcmp(params[0],"ReadX")) {
1124                         nb_readx(ival(params[1]), 
1125                                   ival(params[2]), ival(params[3]), ival(params[4]));
1126                 } else if (!strcmp(params[0],"Flush")) {
1127                         nb_flush(ival(params[1]));
1128                 } else {
1129                         printf("Unknown operation %s\n", params[0]);
1130                         exit(1);
1131                 }
1132         }
1133         fclose(f);
1134
1135         nb_cleanup();
1136
1137         if (!torture_close_connection(cli)) {
1138                 correct = False;
1139         }
1140
1141         return correct;
1142 }
1143
1144
1145 /* run a test that simulates an approximate netbench client load */
1146 static bool run_nbench(int dummy)
1147 {
1148         double t;
1149         bool correct = True;
1150
1151         nbio_shmem(torture_nprocs);
1152
1153         nbio_id = -1;
1154
1155         signal(SIGALRM, nb_alarm);
1156         alarm(1);
1157         t = create_procs(run_netbench, &correct);
1158         alarm(0);
1159
1160         printf("\nThroughput %g MB/sec\n", 
1161                1.0e-6 * nbio_total() / t);
1162         return correct;
1163 }
1164
1165
1166 /*
1167   This test checks for two things:
1168
1169   1) correct support for retaining locks over a close (ie. the server
1170      must not use posix semantics)
1171   2) support for lock timeouts
1172  */
1173 static bool run_locktest1(int dummy)
1174 {
1175         struct cli_state *cli1, *cli2;
1176         const char *fname = "\\lockt1.lck";
1177         uint16_t fnum1, fnum2, fnum3;
1178         time_t t1, t2;
1179         unsigned lock_timeout;
1180         NTSTATUS status;
1181
1182         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1183                 return False;
1184         }
1185         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1186         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1187
1188         printf("starting locktest1\n");
1189
1190         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1191
1192         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1193                           &fnum1);
1194         if (!NT_STATUS_IS_OK(status)) {
1195                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1196                 return False;
1197         }
1198
1199         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1200         if (!NT_STATUS_IS_OK(status)) {
1201                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1202                 return False;
1203         }
1204
1205         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1206         if (!NT_STATUS_IS_OK(status)) {
1207                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1208                 return False;
1209         }
1210
1211         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1212         if (!NT_STATUS_IS_OK(status)) {
1213                 printf("lock1 failed (%s)\n", nt_errstr(status));
1214                 return false;
1215         }
1216
1217         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1218         if (NT_STATUS_IS_OK(status)) {
1219                 printf("lock2 succeeded! This is a locking bug\n");
1220                 return false;
1221         } else {
1222                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1223                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1224                         return false;
1225                 }
1226         }
1227
1228         lock_timeout = (1 + (random() % 20));
1229         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1230         t1 = time(NULL);
1231         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1232         if (NT_STATUS_IS_OK(status)) {
1233                 printf("lock3 succeeded! This is a locking bug\n");
1234                 return false;
1235         } else {
1236                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1237                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1238                         return false;
1239                 }
1240         }
1241         t2 = time(NULL);
1242
1243         if (ABS(t2 - t1) < lock_timeout-1) {
1244                 printf("error: This server appears not to support timed lock requests\n");
1245         }
1246
1247         printf("server slept for %u seconds for a %u second timeout\n",
1248                (unsigned int)(t2-t1), lock_timeout);
1249
1250         status = cli_close(cli1, fnum2);
1251         if (!NT_STATUS_IS_OK(status)) {
1252                 printf("close1 failed (%s)\n", nt_errstr(status));
1253                 return False;
1254         }
1255
1256         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1257         if (NT_STATUS_IS_OK(status)) {
1258                 printf("lock4 succeeded! This is a locking bug\n");
1259                 return false;
1260         } else {
1261                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1262                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1263                         return false;
1264                 }
1265         }
1266
1267         status = cli_close(cli1, fnum1);
1268         if (!NT_STATUS_IS_OK(status)) {
1269                 printf("close2 failed (%s)\n", nt_errstr(status));
1270                 return False;
1271         }
1272
1273         status = cli_close(cli2, fnum3);
1274         if (!NT_STATUS_IS_OK(status)) {
1275                 printf("close3 failed (%s)\n", nt_errstr(status));
1276                 return False;
1277         }
1278
1279         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1280         if (!NT_STATUS_IS_OK(status)) {
1281                 printf("unlink failed (%s)\n", nt_errstr(status));
1282                 return False;
1283         }
1284
1285
1286         if (!torture_close_connection(cli1)) {
1287                 return False;
1288         }
1289
1290         if (!torture_close_connection(cli2)) {
1291                 return False;
1292         }
1293
1294         printf("Passed locktest1\n");
1295         return True;
1296 }
1297
1298 /*
1299   this checks to see if a secondary tconx can use open files from an
1300   earlier tconx
1301  */
1302 static bool run_tcon_test(int dummy)
1303 {
1304         static struct cli_state *cli;
1305         const char *fname = "\\tcontest.tmp";
1306         uint16_t fnum1;
1307         uint32_t cnum1, cnum2, cnum3;
1308         struct smbXcli_tcon *orig_tcon = NULL;
1309         uint16_t vuid1, vuid2;
1310         char buf[4];
1311         bool ret = True;
1312         NTSTATUS status;
1313
1314         memset(buf, '\0', sizeof(buf));
1315
1316         if (!torture_open_connection(&cli, 0)) {
1317                 return False;
1318         }
1319         smbXcli_conn_set_sockopt(cli->conn, sockops);
1320
1321         printf("starting tcontest\n");
1322
1323         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1324
1325         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1326         if (!NT_STATUS_IS_OK(status)) {
1327                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1328                 return False;
1329         }
1330
1331         cnum1 = cli_state_get_tid(cli);
1332         vuid1 = cli_state_get_uid(cli);
1333
1334         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1335         if (!NT_STATUS_IS_OK(status)) {
1336                 printf("initial write failed (%s)", nt_errstr(status));
1337                 return False;
1338         }
1339
1340         orig_tcon = cli_state_save_tcon(cli);
1341         if (orig_tcon == NULL) {
1342                 return false;
1343         }
1344
1345         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1346         if (!NT_STATUS_IS_OK(status)) {
1347                 printf("%s refused 2nd tree connect (%s)\n", host,
1348                        nt_errstr(status));
1349                 cli_shutdown(cli);
1350                 return False;
1351         }
1352
1353         cnum2 = cli_state_get_tid(cli);
1354         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1355         vuid2 = cli_state_get_uid(cli) + 1;
1356
1357         /* try a write with the wrong tid */
1358         cli_state_set_tid(cli, cnum2);
1359
1360         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1361         if (NT_STATUS_IS_OK(status)) {
1362                 printf("* server allows write with wrong TID\n");
1363                 ret = False;
1364         } else {
1365                 printf("server fails write with wrong TID : %s\n",
1366                        nt_errstr(status));
1367         }
1368
1369
1370         /* try a write with an invalid tid */
1371         cli_state_set_tid(cli, cnum3);
1372
1373         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1374         if (NT_STATUS_IS_OK(status)) {
1375                 printf("* server allows write with invalid TID\n");
1376                 ret = False;
1377         } else {
1378                 printf("server fails write with invalid TID : %s\n",
1379                        nt_errstr(status));
1380         }
1381
1382         /* try a write with an invalid vuid */
1383         cli_state_set_uid(cli, vuid2);
1384         cli_state_set_tid(cli, cnum1);
1385
1386         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1387         if (NT_STATUS_IS_OK(status)) {
1388                 printf("* server allows write with invalid VUID\n");
1389                 ret = False;
1390         } else {
1391                 printf("server fails write with invalid VUID : %s\n",
1392                        nt_errstr(status));
1393         }
1394
1395         cli_state_set_tid(cli, cnum1);
1396         cli_state_set_uid(cli, vuid1);
1397
1398         status = cli_close(cli, fnum1);
1399         if (!NT_STATUS_IS_OK(status)) {
1400                 printf("close failed (%s)\n", nt_errstr(status));
1401                 return False;
1402         }
1403
1404         cli_state_set_tid(cli, cnum2);
1405
1406         status = cli_tdis(cli);
1407         if (!NT_STATUS_IS_OK(status)) {
1408                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1409                 return False;
1410         }
1411
1412         cli_state_restore_tcon(cli, orig_tcon);
1413
1414         cli_state_set_tid(cli, cnum1);
1415
1416         if (!torture_close_connection(cli)) {
1417                 return False;
1418         }
1419
1420         return ret;
1421 }
1422
1423
1424 /*
1425  checks for old style tcon support
1426  */
1427 static bool run_tcon2_test(int dummy)
1428 {
1429         static struct cli_state *cli;
1430         uint16_t cnum, max_xmit;
1431         char *service;
1432         NTSTATUS status;
1433
1434         if (!torture_open_connection(&cli, 0)) {
1435                 return False;
1436         }
1437         smbXcli_conn_set_sockopt(cli->conn, sockops);
1438
1439         printf("starting tcon2 test\n");
1440
1441         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1442                 return false;
1443         }
1444
1445         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1446
1447         SAFE_FREE(service);
1448
1449         if (!NT_STATUS_IS_OK(status)) {
1450                 printf("tcon2 failed : %s\n", nt_errstr(status));
1451         } else {
1452                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1453                        (int)max_xmit, (int)cnum);
1454         }
1455
1456         if (!torture_close_connection(cli)) {
1457                 return False;
1458         }
1459
1460         printf("Passed tcon2 test\n");
1461         return True;
1462 }
1463
1464 static bool tcon_devtest(struct cli_state *cli,
1465                          const char *myshare, const char *devtype,
1466                          const char *return_devtype,
1467                          NTSTATUS expected_error)
1468 {
1469         NTSTATUS status;
1470         bool ret;
1471
1472         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1473
1474         if (NT_STATUS_IS_OK(expected_error)) {
1475                 if (NT_STATUS_IS_OK(status)) {
1476                         if (strcmp(cli->dev, return_devtype) == 0) {
1477                                 ret = True;
1478                         } else { 
1479                                 printf("tconX to share %s with type %s "
1480                                        "succeeded but returned the wrong "
1481                                        "device type (got [%s] but should have got [%s])\n",
1482                                        myshare, devtype, cli->dev, return_devtype);
1483                                 ret = False;
1484                         }
1485                 } else {
1486                         printf("tconX to share %s with type %s "
1487                                "should have succeeded but failed\n",
1488                                myshare, devtype);
1489                         ret = False;
1490                 }
1491                 cli_tdis(cli);
1492         } else {
1493                 if (NT_STATUS_IS_OK(status)) {
1494                         printf("tconx to share %s with type %s "
1495                                "should have failed but succeeded\n",
1496                                myshare, devtype);
1497                         ret = False;
1498                 } else {
1499                         if (NT_STATUS_EQUAL(status, expected_error)) {
1500                                 ret = True;
1501                         } else {
1502                                 printf("Returned unexpected error\n");
1503                                 ret = False;
1504                         }
1505                 }
1506         }
1507         return ret;
1508 }
1509
1510 /*
1511  checks for correct tconX support
1512  */
1513 static bool run_tcon_devtype_test(int dummy)
1514 {
1515         static struct cli_state *cli1 = NULL;
1516         int flags = 0;
1517         NTSTATUS status;
1518         bool ret = True;
1519
1520         status = cli_full_connection_creds(&cli1,
1521                                            myname,
1522                                            host,
1523                                            NULL, /* dest_ss */
1524                                            port_to_use,
1525                                            NULL, /* service */
1526                                            NULL, /* service_type */
1527                                            torture_creds,
1528                                            flags,
1529                                            signing_state);
1530
1531         if (!NT_STATUS_IS_OK(status)) {
1532                 printf("could not open connection\n");
1533                 return False;
1534         }
1535
1536         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1537                 ret = False;
1538
1539         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1540                 ret = False;
1541
1542         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543                 ret = False;
1544
1545         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1546                 ret = False;
1547
1548         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1549                 ret = False;
1550
1551         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1552                 ret = False;
1553
1554         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1555                 ret = False;
1556
1557         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1558                 ret = False;
1559
1560         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1561                 ret = False;
1562
1563         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1564                 ret = False;
1565
1566         cli_shutdown(cli1);
1567
1568         if (ret)
1569                 printf("Passed tcondevtest\n");
1570
1571         return ret;
1572 }
1573
1574
1575 /*
1576   This test checks that 
1577
1578   1) the server supports multiple locking contexts on the one SMB
1579   connection, distinguished by PID.  
1580
1581   2) the server correctly fails overlapping locks made by the same PID (this
1582      goes against POSIX behaviour, which is why it is tricky to implement)
1583
1584   3) the server denies unlock requests by an incorrect client PID
1585 */
1586 static bool run_locktest2(int dummy)
1587 {
1588         static struct cli_state *cli;
1589         const char *fname = "\\lockt2.lck";
1590         uint16_t fnum1, fnum2, fnum3;
1591         bool correct = True;
1592         NTSTATUS status;
1593
1594         if (!torture_open_connection(&cli, 0)) {
1595                 return False;
1596         }
1597
1598         smbXcli_conn_set_sockopt(cli->conn, sockops);
1599
1600         printf("starting locktest2\n");
1601
1602         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1603
1604         cli_setpid(cli, 1);
1605
1606         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1607         if (!NT_STATUS_IS_OK(status)) {
1608                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1609                 return False;
1610         }
1611
1612         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1613         if (!NT_STATUS_IS_OK(status)) {
1614                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1615                 return False;
1616         }
1617
1618         cli_setpid(cli, 2);
1619
1620         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1621         if (!NT_STATUS_IS_OK(status)) {
1622                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1623                 return False;
1624         }
1625
1626         cli_setpid(cli, 1);
1627
1628         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1629         if (!NT_STATUS_IS_OK(status)) {
1630                 printf("lock1 failed (%s)\n", nt_errstr(status));
1631                 return false;
1632         }
1633
1634         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1635         if (NT_STATUS_IS_OK(status)) {
1636                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1637                 correct = false;
1638         } else {
1639                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1640                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1641                         return false;
1642                 }
1643         }
1644
1645         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1646         if (NT_STATUS_IS_OK(status)) {
1647                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1648                 correct = false;
1649         } else {
1650                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1651                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1652                         return false;
1653                 }
1654         }
1655
1656         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1657         if (NT_STATUS_IS_OK(status)) {
1658                 printf("READ lock2 succeeded! This is a locking bug\n");
1659                 correct = false;
1660         } else {
1661                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1662                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1663                         return false;
1664                 }
1665         }
1666
1667         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1668         if (!NT_STATUS_IS_OK(status)) {
1669                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1670         }
1671         cli_setpid(cli, 2);
1672         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1673                 printf("unlock at 100 succeeded! This is a locking bug\n");
1674                 correct = False;
1675         }
1676
1677         status = cli_unlock(cli, fnum1, 0, 4);
1678         if (NT_STATUS_IS_OK(status)) {
1679                 printf("unlock1 succeeded! This is a locking bug\n");
1680                 correct = false;
1681         } else {
1682                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1683                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1684                         return false;
1685                 }
1686         }
1687
1688         status = cli_unlock(cli, fnum1, 0, 8);
1689         if (NT_STATUS_IS_OK(status)) {
1690                 printf("unlock2 succeeded! This is a locking bug\n");
1691                 correct = false;
1692         } else {
1693                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1694                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1695                         return false;
1696                 }
1697         }
1698
1699         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1700         if (NT_STATUS_IS_OK(status)) {
1701                 printf("lock3 succeeded! This is a locking bug\n");
1702                 correct = false;
1703         } else {
1704                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1705                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1706                         return false;
1707                 }
1708         }
1709
1710         cli_setpid(cli, 1);
1711
1712         status = cli_close(cli, fnum1);
1713         if (!NT_STATUS_IS_OK(status)) {
1714                 printf("close1 failed (%s)\n", nt_errstr(status));
1715                 return False;
1716         }
1717
1718         status = cli_close(cli, fnum2);
1719         if (!NT_STATUS_IS_OK(status)) {
1720                 printf("close2 failed (%s)\n", nt_errstr(status));
1721                 return False;
1722         }
1723
1724         status = cli_close(cli, fnum3);
1725         if (!NT_STATUS_IS_OK(status)) {
1726                 printf("close3 failed (%s)\n", nt_errstr(status));
1727                 return False;
1728         }
1729
1730         if (!torture_close_connection(cli)) {
1731                 correct = False;
1732         }
1733
1734         printf("locktest2 finished\n");
1735
1736         return correct;
1737 }
1738
1739
1740 /*
1741   This test checks that 
1742
1743   1) the server supports the full offset range in lock requests
1744 */
1745 static bool run_locktest3(int dummy)
1746 {
1747         static struct cli_state *cli1, *cli2;
1748         const char *fname = "\\lockt3.lck";
1749         uint16_t fnum1, fnum2;
1750         int i;
1751         uint32_t offset;
1752         bool correct = True;
1753         NTSTATUS status;
1754
1755 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1756
1757         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1758                 return False;
1759         }
1760         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1761         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1762
1763         printf("starting locktest3\n");
1764
1765         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1766
1767         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1768                          &fnum1);
1769         if (!NT_STATUS_IS_OK(status)) {
1770                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1771                 return False;
1772         }
1773
1774         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1777                 return False;
1778         }
1779
1780         for (offset=i=0;i<torture_numops;i++) {
1781                 NEXT_OFFSET;
1782
1783                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1784                 if (!NT_STATUS_IS_OK(status)) {
1785                         printf("lock1 %d failed (%s)\n", 
1786                                i,
1787                                nt_errstr(status));
1788                         return False;
1789                 }
1790
1791                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1792                 if (!NT_STATUS_IS_OK(status)) {
1793                         printf("lock2 %d failed (%s)\n", 
1794                                i,
1795                                nt_errstr(status));
1796                         return False;
1797                 }
1798         }
1799
1800         for (offset=i=0;i<torture_numops;i++) {
1801                 NEXT_OFFSET;
1802
1803                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1804                 if (NT_STATUS_IS_OK(status)) {
1805                         printf("error: lock1 %d succeeded!\n", i);
1806                         return False;
1807                 }
1808
1809                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1810                 if (NT_STATUS_IS_OK(status)) {
1811                         printf("error: lock2 %d succeeded!\n", i);
1812                         return False;
1813                 }
1814
1815                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1816                 if (NT_STATUS_IS_OK(status)) {
1817                         printf("error: lock3 %d succeeded!\n", i);
1818                         return False;
1819                 }
1820
1821                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1822                 if (NT_STATUS_IS_OK(status)) {
1823                         printf("error: lock4 %d succeeded!\n", i);
1824                         return False;
1825                 }
1826         }
1827
1828         for (offset=i=0;i<torture_numops;i++) {
1829                 NEXT_OFFSET;
1830
1831                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1832                 if (!NT_STATUS_IS_OK(status)) {
1833                         printf("unlock1 %d failed (%s)\n", 
1834                                i,
1835                                nt_errstr(status));
1836                         return False;
1837                 }
1838
1839                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1840                 if (!NT_STATUS_IS_OK(status)) {
1841                         printf("unlock2 %d failed (%s)\n", 
1842                                i,
1843                                nt_errstr(status));
1844                         return False;
1845                 }
1846         }
1847
1848         status = cli_close(cli1, fnum1);
1849         if (!NT_STATUS_IS_OK(status)) {
1850                 printf("close1 failed (%s)\n", nt_errstr(status));
1851                 return False;
1852         }
1853
1854         status = cli_close(cli2, fnum2);
1855         if (!NT_STATUS_IS_OK(status)) {
1856                 printf("close2 failed (%s)\n", nt_errstr(status));
1857                 return False;
1858         }
1859
1860         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1861         if (!NT_STATUS_IS_OK(status)) {
1862                 printf("unlink failed (%s)\n", nt_errstr(status));
1863                 return False;
1864         }
1865
1866         if (!torture_close_connection(cli1)) {
1867                 correct = False;
1868         }
1869
1870         if (!torture_close_connection(cli2)) {
1871                 correct = False;
1872         }
1873
1874         printf("finished locktest3\n");
1875
1876         return correct;
1877 }
1878
1879 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1880                            char *buf, off_t offset, size_t size,
1881                            size_t *nread, size_t expect)
1882 {
1883         NTSTATUS status;
1884         size_t l_nread;
1885
1886         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1887
1888         if(!NT_STATUS_IS_OK(status)) {
1889                 return false;
1890         } else if (l_nread != expect) {
1891                 return false;
1892         }
1893
1894         if (nread) {
1895                 *nread = l_nread;
1896         }
1897
1898         return true;
1899 }
1900
1901 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1902         printf("** "); correct = False; \
1903         }
1904
1905 /*
1906   looks at overlapping locks
1907 */
1908 static bool run_locktest4(int dummy)
1909 {
1910         static struct cli_state *cli1, *cli2;
1911         const char *fname = "\\lockt4.lck";
1912         uint16_t fnum1, fnum2, f;
1913         bool ret;
1914         char buf[1000];
1915         bool correct = True;
1916         NTSTATUS status;
1917
1918         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1919                 return False;
1920         }
1921
1922         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1923         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1924
1925         printf("starting locktest4\n");
1926
1927         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1928
1929         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1930         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1931
1932         memset(buf, 0, sizeof(buf));
1933
1934         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1935                               NULL);
1936         if (!NT_STATUS_IS_OK(status)) {
1937                 printf("Failed to create file: %s\n", nt_errstr(status));
1938                 correct = False;
1939                 goto fail;
1940         }
1941
1942         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1943               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1944         EXPECTED(ret, False);
1945         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1946
1947         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1948               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1949         EXPECTED(ret, True);
1950         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1951
1952         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1953               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1954         EXPECTED(ret, False);
1955         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1956
1957         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1958               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1959         EXPECTED(ret, True);
1960         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1961
1962         ret = (cli_setpid(cli1, 1),
1963               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1964               (cli_setpid(cli1, 2),
1965               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1966         EXPECTED(ret, False);
1967         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1968
1969         ret = (cli_setpid(cli1, 1),
1970               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1971               (cli_setpid(cli1, 2),
1972               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1973         EXPECTED(ret, True);
1974         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1975
1976         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1977               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1978         EXPECTED(ret, True);
1979         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1980
1981         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1982               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1983         EXPECTED(ret, False);
1984         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1985
1986         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1987               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1988         EXPECTED(ret, False);
1989         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1990
1991         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1992               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1993         EXPECTED(ret, True);
1994         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1995
1996         ret = (cli_setpid(cli1, 1),
1997              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1998              (cli_setpid(cli1, 2),
1999              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2000         EXPECTED(ret, False);
2001         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2002
2003         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2004               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2005               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2006         EXPECTED(ret, False);
2007         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2008
2009
2010         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2011               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2012         EXPECTED(ret, False);
2013         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2014
2015         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2016         ret = NT_STATUS_IS_OK(status);
2017         if (ret) {
2018                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2019                                       NULL);
2020                 ret = NT_STATUS_IS_OK(status);
2021         }
2022         EXPECTED(ret, False);
2023         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2024
2025
2026         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2027               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2028               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2029               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2030         EXPECTED(ret, True);
2031         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2032
2033
2034         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2035               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2036               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2037               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2038               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2039                                              150, 4, NULL))) &&
2040               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2041         EXPECTED(ret, True);
2042         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2043
2044         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2045               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2046               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2047                                            160, 4, NULL)) &&
2048               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2049         EXPECTED(ret, True);
2050         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2051
2052         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2053               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2054               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2055                                            170, 4, NULL)) &&
2056               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2057         EXPECTED(ret, True);
2058         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2059
2060         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2061               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2062               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2063               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2064                                             190, 4, NULL)) &&
2065               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2066         EXPECTED(ret, True);
2067         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2068
2069         cli_close(cli1, fnum1);
2070         cli_close(cli2, fnum2);
2071         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2072         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2073         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2074               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2075               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2076               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2077               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2078         cli_close(cli1, f);
2079         cli_close(cli1, fnum1);
2080         EXPECTED(ret, True);
2081         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2082
2083  fail:
2084         cli_close(cli1, fnum1);
2085         cli_close(cli2, fnum2);
2086         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2087         torture_close_connection(cli1);
2088         torture_close_connection(cli2);
2089
2090         printf("finished locktest4\n");
2091         return correct;
2092 }
2093
2094 /*
2095   looks at lock upgrade/downgrade.
2096 */
2097 static bool run_locktest5(int dummy)
2098 {
2099         static struct cli_state *cli1, *cli2;
2100         const char *fname = "\\lockt5.lck";
2101         uint16_t fnum1, fnum2, fnum3;
2102         bool ret;
2103         char buf[1000];
2104         bool correct = True;
2105         NTSTATUS status;
2106
2107         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2108                 return False;
2109         }
2110
2111         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2112         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2113
2114         printf("starting locktest5\n");
2115
2116         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2117
2118         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2119         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2120         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2121
2122         memset(buf, 0, sizeof(buf));
2123
2124         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2125                               NULL);
2126         if (!NT_STATUS_IS_OK(status)) {
2127                 printf("Failed to create file: %s\n", nt_errstr(status));
2128                 correct = False;
2129                 goto fail;
2130         }
2131
2132         /* Check for NT bug... */
2133         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2134               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2135         cli_close(cli1, fnum1);
2136         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2137         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2138         ret = NT_STATUS_IS_OK(status);
2139         EXPECTED(ret, True);
2140         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2141         cli_close(cli1, fnum1);
2142         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2143         cli_unlock(cli1, fnum3, 0, 1);
2144
2145         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2146               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2147         EXPECTED(ret, True);
2148         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2149
2150         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2151         ret = NT_STATUS_IS_OK(status);
2152         EXPECTED(ret, False);
2153
2154         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2155
2156         /* Unlock the process 2 lock. */
2157         cli_unlock(cli2, fnum2, 0, 4);
2158
2159         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2160         ret = NT_STATUS_IS_OK(status);
2161         EXPECTED(ret, False);
2162
2163         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2164
2165         /* Unlock the process 1 fnum3 lock. */
2166         cli_unlock(cli1, fnum3, 0, 4);
2167
2168         /* Stack 2 more locks here. */
2169         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2170               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2171
2172         EXPECTED(ret, True);
2173         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2174
2175         /* Unlock the first process lock, then check this was the WRITE lock that was
2176                 removed. */
2177
2178         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2179               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2180
2181         EXPECTED(ret, True);
2182         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2183
2184         /* Unlock the process 2 lock. */
2185         cli_unlock(cli2, fnum2, 0, 4);
2186
2187         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2188
2189         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2190                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2191                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2192
2193         EXPECTED(ret, True);
2194         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2195
2196         /* Ensure the next unlock fails. */
2197         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2198         EXPECTED(ret, False);
2199         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2200
2201         /* Ensure connection 2 can get a write lock. */
2202         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2203         ret = NT_STATUS_IS_OK(status);
2204         EXPECTED(ret, True);
2205
2206         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2207
2208
2209  fail:
2210         cli_close(cli1, fnum1);
2211         cli_close(cli2, fnum2);
2212         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2213         if (!torture_close_connection(cli1)) {
2214                 correct = False;
2215         }
2216         if (!torture_close_connection(cli2)) {
2217                 correct = False;
2218         }
2219
2220         printf("finished locktest5\n");
2221
2222         return correct;
2223 }
2224
2225 /*
2226   tries the unusual lockingX locktype bits
2227 */
2228 static bool run_locktest6(int dummy)
2229 {
2230         static struct cli_state *cli;
2231         const char *fname[1] = { "\\lock6.txt" };
2232         int i;
2233         uint16_t fnum;
2234         NTSTATUS status;
2235
2236         if (!torture_open_connection(&cli, 0)) {
2237                 return False;
2238         }
2239
2240         smbXcli_conn_set_sockopt(cli->conn, sockops);
2241
2242         printf("starting locktest6\n");
2243
2244         for (i=0;i<1;i++) {
2245                 printf("Testing %s\n", fname[i]);
2246
2247                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2248
2249                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2250                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2251                 cli_close(cli, fnum);
2252                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2253
2254                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2255                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2256                 cli_close(cli, fnum);
2257                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2258
2259                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2260         }
2261
2262         torture_close_connection(cli);
2263
2264         printf("finished locktest6\n");
2265         return True;
2266 }
2267
2268 static bool run_locktest7(int dummy)
2269 {
2270         struct cli_state *cli1;
2271         const char *fname = "\\lockt7.lck";
2272         uint16_t fnum1;
2273         char buf[200];
2274         bool correct = False;
2275         size_t nread;
2276         NTSTATUS status;
2277
2278         if (!torture_open_connection(&cli1, 0)) {
2279                 return False;
2280         }
2281
2282         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2283
2284         printf("starting locktest7\n");
2285
2286         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2287
2288         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2289
2290         memset(buf, 0, sizeof(buf));
2291
2292         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2293                               NULL);
2294         if (!NT_STATUS_IS_OK(status)) {
2295                 printf("Failed to create file: %s\n", nt_errstr(status));
2296                 goto fail;
2297         }
2298
2299         cli_setpid(cli1, 1);
2300
2301         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2302         if (!NT_STATUS_IS_OK(status)) {
2303                 printf("Unable to apply read lock on range 130:4, "
2304                        "error was %s\n", nt_errstr(status));
2305                 goto fail;
2306         } else {
2307                 printf("pid1 successfully locked range 130:4 for READ\n");
2308         }
2309
2310         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2311         if (!NT_STATUS_IS_OK(status)) {
2312                 printf("pid1 unable to read the range 130:4, error was %s\n",
2313                       nt_errstr(status));
2314                 goto fail;
2315         } else if (nread != 4) {
2316                 printf("pid1 unable to read the range 130:4, "
2317                        "recv %ld req %d\n", (unsigned long)nread, 4);
2318                 goto fail;
2319         } else {
2320                 printf("pid1 successfully read the range 130:4\n");
2321         }
2322
2323         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2324         if (!NT_STATUS_IS_OK(status)) {
2325                 printf("pid1 unable to write to the range 130:4, error was "
2326                        "%s\n", nt_errstr(status));
2327                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2328                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2329                         goto fail;
2330                 }
2331         } else {
2332                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2333                 goto fail;
2334         }
2335
2336         cli_setpid(cli1, 2);
2337
2338         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2339         if (!NT_STATUS_IS_OK(status)) {
2340                 printf("pid2 unable to read the range 130:4, error was %s\n",
2341                       nt_errstr(status));
2342                 goto fail;
2343         } else if (nread != 4) {
2344                 printf("pid2 unable to read the range 130:4, "
2345                        "recv %ld req %d\n", (unsigned long)nread, 4);
2346                 goto fail;
2347         } else {
2348                 printf("pid2 successfully read the range 130:4\n");
2349         }
2350
2351         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2352         if (!NT_STATUS_IS_OK(status)) {
2353                 printf("pid2 unable to write to the range 130:4, error was "
2354                        "%s\n", nt_errstr(status));
2355                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2356                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2357                         goto fail;
2358                 }
2359         } else {
2360                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2361                 goto fail;
2362         }
2363
2364         cli_setpid(cli1, 1);
2365         cli_unlock(cli1, fnum1, 130, 4);
2366
2367         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2368         if (!NT_STATUS_IS_OK(status)) {
2369                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2370                 goto fail;
2371         } else {
2372                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2373         }
2374
2375         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2376         if (!NT_STATUS_IS_OK(status)) {
2377                 printf("pid1 unable to read the range 130:4, error was %s\n",
2378                       nt_errstr(status));
2379                 goto fail;
2380         } else if (nread != 4) {
2381                 printf("pid1 unable to read the range 130:4, "
2382                        "recv %ld req %d\n", (unsigned long)nread, 4);
2383                 goto fail;
2384         } else {
2385                 printf("pid1 successfully read the range 130:4\n");
2386         }
2387
2388         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2389         if (!NT_STATUS_IS_OK(status)) {
2390                 printf("pid1 unable to write to the range 130:4, error was "
2391                        "%s\n", nt_errstr(status));
2392                 goto fail;
2393         } else {
2394                 printf("pid1 successfully wrote to the range 130:4\n");
2395         }
2396
2397         cli_setpid(cli1, 2);
2398
2399         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2400         if (!NT_STATUS_IS_OK(status)) {
2401                 printf("pid2 unable to read the range 130:4, error was "
2402                        "%s\n", nt_errstr(status));
2403                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2404                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2405                         goto fail;
2406                 }
2407         } else {
2408                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2409                        (unsigned long)nread);
2410                 goto fail;
2411         }
2412
2413         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2414         if (!NT_STATUS_IS_OK(status)) {
2415                 printf("pid2 unable to write to the range 130:4, error was "
2416                        "%s\n", nt_errstr(status));
2417                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2418                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2419                         goto fail;
2420                 }
2421         } else {
2422                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2423                 goto fail;
2424         }
2425
2426         cli_unlock(cli1, fnum1, 130, 0);
2427         correct = True;
2428
2429 fail:
2430         cli_close(cli1, fnum1);
2431         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2432         torture_close_connection(cli1);
2433
2434         printf("finished locktest7\n");
2435         return correct;
2436 }
2437
2438 /*
2439  * This demonstrates a problem with our use of GPFS share modes: A file
2440  * descriptor sitting in the pending close queue holding a GPFS share mode
2441  * blocks opening a file another time. Happens with Word 2007 temp files.
2442  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2443  * open is denied with NT_STATUS_SHARING_VIOLATION.
2444  */
2445
2446 static bool run_locktest8(int dummy)
2447 {
2448         struct cli_state *cli1;
2449         const char *fname = "\\lockt8.lck";
2450         uint16_t fnum1, fnum2;
2451         char buf[200];
2452         bool correct = False;
2453         NTSTATUS status;
2454
2455         if (!torture_open_connection(&cli1, 0)) {
2456                 return False;
2457         }
2458
2459         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2460
2461         printf("starting locktest8\n");
2462
2463         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2464
2465         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2466                           &fnum1);
2467         if (!NT_STATUS_IS_OK(status)) {
2468                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2469                 return false;
2470         }
2471
2472         memset(buf, 0, sizeof(buf));
2473
2474         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2475         if (!NT_STATUS_IS_OK(status)) {
2476                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2477                           nt_errstr(status));
2478                 goto fail;
2479         }
2480
2481         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2482         if (!NT_STATUS_IS_OK(status)) {
2483                 printf("Unable to apply read lock on range 1:1, error was "
2484                        "%s\n", nt_errstr(status));
2485                 goto fail;
2486         }
2487
2488         status = cli_close(cli1, fnum1);
2489         if (!NT_STATUS_IS_OK(status)) {
2490                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2491                 goto fail;
2492         }
2493
2494         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2495         if (!NT_STATUS_IS_OK(status)) {
2496                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2497                           nt_errstr(status));
2498                 goto fail;
2499         }
2500
2501         correct = true;
2502
2503 fail:
2504         cli_close(cli1, fnum1);
2505         cli_close(cli1, fnum2);
2506         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2507         torture_close_connection(cli1);
2508
2509         printf("finished locktest8\n");
2510         return correct;
2511 }
2512
2513 /*
2514  * This test is designed to be run in conjunction with
2515  * external NFS or POSIX locks taken in the filesystem.
2516  * It checks that the smbd server will block until the
2517  * lock is released and then acquire it. JRA.
2518  */
2519
2520 static bool got_alarm;
2521 static struct cli_state *alarm_cli;
2522
2523 static void alarm_handler(int dummy)
2524 {
2525         got_alarm = True;
2526 }
2527
2528 static void alarm_handler_parent(int dummy)
2529 {
2530         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2531 }
2532
2533 static void do_local_lock(int read_fd, int write_fd)
2534 {
2535         int fd;
2536         char c = '\0';
2537         struct flock lock;
2538         const char *local_pathname = NULL;
2539         int ret;
2540
2541         local_pathname = talloc_asprintf(talloc_tos(),
2542                         "%s/lockt9.lck", local_path);
2543         if (!local_pathname) {
2544                 printf("child: alloc fail\n");
2545                 exit(1);
2546         }
2547
2548         unlink(local_pathname);
2549         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2550         if (fd == -1) {
2551                 printf("child: open of %s failed %s.\n",
2552                         local_pathname, strerror(errno));
2553                 exit(1);
2554         }
2555
2556         /* Now take a fcntl lock. */
2557         lock.l_type = F_WRLCK;
2558         lock.l_whence = SEEK_SET;
2559         lock.l_start = 0;
2560         lock.l_len = 4;
2561         lock.l_pid = getpid();
2562
2563         ret = fcntl(fd,F_SETLK,&lock);
2564         if (ret == -1) {
2565                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2566                         local_pathname, strerror(errno));
2567                 exit(1);
2568         } else {
2569                 printf("child: got lock 0:4 on file %s.\n",
2570                         local_pathname );
2571                 fflush(stdout);
2572         }
2573
2574         CatchSignal(SIGALRM, alarm_handler);
2575         alarm(5);
2576         /* Signal the parent. */
2577         if (write(write_fd, &c, 1) != 1) {
2578                 printf("child: start signal fail %s.\n",
2579                         strerror(errno));
2580                 exit(1);
2581         }
2582         alarm(0);
2583
2584         alarm(10);
2585         /* Wait for the parent to be ready. */
2586         if (read(read_fd, &c, 1) != 1) {
2587                 printf("child: reply signal fail %s.\n",
2588                         strerror(errno));
2589                 exit(1);
2590         }
2591         alarm(0);
2592
2593         sleep(5);
2594         close(fd);
2595         printf("child: released lock 0:4 on file %s.\n",
2596                 local_pathname );
2597         fflush(stdout);
2598         exit(0);
2599 }
2600
2601 static bool run_locktest9(int dummy)
2602 {
2603         struct cli_state *cli1;
2604         const char *fname = "\\lockt9.lck";
2605         uint16_t fnum;
2606         bool correct = False;
2607         int pipe_in[2], pipe_out[2];
2608         pid_t child_pid;
2609         char c = '\0';
2610         int ret;
2611         struct timeval start;
2612         double seconds;
2613         NTSTATUS status;
2614
2615         printf("starting locktest9\n");
2616
2617         if (local_path == NULL) {
2618                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2619                 return false;
2620         }
2621
2622         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2623                 return false;
2624         }
2625
2626         child_pid = fork();
2627         if (child_pid == -1) {
2628                 return false;
2629         }
2630
2631         if (child_pid == 0) {
2632                 /* Child. */
2633                 do_local_lock(pipe_out[0], pipe_in[1]);
2634                 exit(0);
2635         }
2636
2637         close(pipe_out[0]);
2638         close(pipe_in[1]);
2639         pipe_out[0] = -1;
2640         pipe_in[1] = -1;
2641
2642         /* Parent. */
2643         ret = read(pipe_in[0], &c, 1);
2644         if (ret != 1) {
2645                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2646                         strerror(errno));
2647                 return false;
2648         }
2649
2650         if (!torture_open_connection(&cli1, 0)) {
2651                 return false;
2652         }
2653
2654         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2655
2656         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2657                           &fnum);
2658         if (!NT_STATUS_IS_OK(status)) {
2659                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2660                 return false;
2661         }
2662
2663         /* Ensure the child has the lock. */
2664         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2665         if (NT_STATUS_IS_OK(status)) {
2666                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2667                 goto fail;
2668         } else {
2669                 d_printf("Child has the lock.\n");
2670         }
2671
2672         /* Tell the child to wait 5 seconds then exit. */
2673         ret = write(pipe_out[1], &c, 1);
2674         if (ret != 1) {
2675                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2676                         strerror(errno));
2677                 goto fail;
2678         }
2679
2680         /* Wait 20 seconds for the lock. */
2681         alarm_cli = cli1;
2682         CatchSignal(SIGALRM, alarm_handler_parent);
2683         alarm(20);
2684
2685         start = timeval_current();
2686
2687         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2688         if (!NT_STATUS_IS_OK(status)) {
2689                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2690                        "%s\n", nt_errstr(status));
2691                 goto fail_nofd;
2692         }
2693         alarm(0);
2694
2695         seconds = timeval_elapsed(&start);
2696
2697         printf("Parent got the lock after %.2f seconds.\n",
2698                 seconds);
2699
2700         status = cli_close(cli1, fnum);
2701         if (!NT_STATUS_IS_OK(status)) {
2702                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2703                 goto fail;
2704         }
2705
2706         correct = true;
2707
2708 fail:
2709         cli_close(cli1, fnum);
2710         torture_close_connection(cli1);
2711
2712 fail_nofd:
2713
2714         printf("finished locktest9\n");
2715         return correct;
2716 }
2717
2718 /*
2719 test whether fnums and tids open on one VC are available on another (a major
2720 security hole)
2721 */
2722 static bool run_fdpasstest(int dummy)
2723 {
2724         struct cli_state *cli1, *cli2;
2725         const char *fname = "\\fdpass.tst";
2726         uint16_t fnum1;
2727         char buf[1024];
2728         NTSTATUS status;
2729
2730         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2731                 return False;
2732         }
2733         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2734         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2735
2736         printf("starting fdpasstest\n");
2737
2738         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2739
2740         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2741                           &fnum1);
2742         if (!NT_STATUS_IS_OK(status)) {
2743                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2744                 return False;
2745         }
2746
2747         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2748                               13, NULL);
2749         if (!NT_STATUS_IS_OK(status)) {
2750                 printf("write failed (%s)\n", nt_errstr(status));
2751                 return False;
2752         }
2753
2754         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2755         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2756         cli_setpid(cli2, cli_getpid(cli1));
2757
2758         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2759                 printf("read succeeded! nasty security hole [%s]\n", buf);
2760                 return false;
2761         }
2762
2763         cli_close(cli1, fnum1);
2764         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2765
2766         torture_close_connection(cli1);
2767         torture_close_connection(cli2);
2768
2769         printf("finished fdpasstest\n");
2770         return True;
2771 }
2772
2773 static bool run_fdsesstest(int dummy)
2774 {
2775         struct cli_state *cli;
2776         uint16_t new_vuid;
2777         uint16_t saved_vuid;
2778         uint32_t new_cnum;
2779         uint32_t saved_cnum;
2780         const char *fname = "\\fdsess.tst";
2781         const char *fname1 = "\\fdsess1.tst";
2782         uint16_t fnum1;
2783         uint16_t fnum2;
2784         char buf[1024];
2785         bool ret = True;
2786         NTSTATUS status;
2787
2788         if (!torture_open_connection(&cli, 0))
2789                 return False;
2790         smbXcli_conn_set_sockopt(cli->conn, sockops);
2791
2792         if (!torture_cli_session_setup2(cli, &new_vuid))
2793                 return False;
2794
2795         saved_cnum = cli_state_get_tid(cli);
2796         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2797                 return False;
2798         new_cnum = cli_state_get_tid(cli);
2799         cli_state_set_tid(cli, saved_cnum);
2800
2801         printf("starting fdsesstest\n");
2802
2803         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2804         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2805
2806         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2807         if (!NT_STATUS_IS_OK(status)) {
2808                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2809                 return False;
2810         }
2811
2812         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2813                               NULL);
2814         if (!NT_STATUS_IS_OK(status)) {
2815                 printf("write failed (%s)\n", nt_errstr(status));
2816                 return False;
2817         }
2818
2819         saved_vuid = cli_state_get_uid(cli);
2820         cli_state_set_uid(cli, new_vuid);
2821
2822         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2823                 printf("read succeeded with different vuid! "
2824                        "nasty security hole [%s]\n", buf);
2825                 ret = false;
2826         }
2827         /* Try to open a file with different vuid, samba cnum. */
2828         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2829                 printf("create with different vuid, same cnum succeeded.\n");
2830                 cli_close(cli, fnum2);
2831                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2832         } else {
2833                 printf("create with different vuid, same cnum failed.\n");
2834                 printf("This will cause problems with service clients.\n");
2835                 ret = False;
2836         }
2837
2838         cli_state_set_uid(cli, saved_vuid);
2839
2840         /* Try with same vuid, different cnum. */
2841         cli_state_set_tid(cli, new_cnum);
2842
2843         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2844                 printf("read succeeded with different cnum![%s]\n", buf);
2845                 ret = false;
2846         }
2847
2848         cli_state_set_tid(cli, saved_cnum);
2849         cli_close(cli, fnum1);
2850         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2851
2852         torture_close_connection(cli);
2853
2854         printf("finished fdsesstest\n");
2855         return ret;
2856 }
2857
2858 /*
2859   This test checks that 
2860
2861   1) the server does not allow an unlink on a file that is open
2862 */
2863 static bool run_unlinktest(int dummy)
2864 {
2865         struct cli_state *cli;
2866         const char *fname = "\\unlink.tst";
2867         uint16_t fnum;
2868         bool correct = True;
2869         NTSTATUS status;
2870
2871         if (!torture_open_connection(&cli, 0)) {
2872                 return False;
2873         }
2874
2875         smbXcli_conn_set_sockopt(cli->conn, sockops);
2876
2877         printf("starting unlink test\n");
2878
2879         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2880
2881         cli_setpid(cli, 1);
2882
2883         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2884         if (!NT_STATUS_IS_OK(status)) {
2885                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2886                 return False;
2887         }
2888
2889         status = cli_unlink(cli, fname,
2890                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2891         if (NT_STATUS_IS_OK(status)) {
2892                 printf("error: server allowed unlink on an open file\n");
2893                 correct = False;
2894         } else {
2895                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2896                                       NT_STATUS_SHARING_VIOLATION);
2897         }
2898
2899         cli_close(cli, fnum);
2900         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2901
2902         if (!torture_close_connection(cli)) {
2903                 correct = False;
2904         }
2905
2906         printf("unlink test finished\n");
2907
2908         return correct;
2909 }
2910
2911
2912 /*
2913 test how many open files this server supports on the one socket
2914 */
2915 static bool run_maxfidtest(int dummy)
2916 {
2917         struct cli_state *cli;
2918         fstring fname;
2919         uint16_t fnums[0x11000];
2920         int i;
2921         int retries=4;
2922         bool correct = True;
2923         NTSTATUS status;
2924
2925         cli = current_cli;
2926
2927         if (retries <= 0) {
2928                 printf("failed to connect\n");
2929                 return False;
2930         }
2931
2932         smbXcli_conn_set_sockopt(cli->conn, sockops);
2933
2934         for (i=0; i<0x11000; i++) {
2935                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2936                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2937                                   &fnums[i]);
2938                 if (!NT_STATUS_IS_OK(status)) {
2939                         printf("open of %s failed (%s)\n", 
2940                                fname, nt_errstr(status));
2941                         printf("maximum fnum is %d\n", i);
2942                         break;
2943                 }
2944                 printf("%6d\r", i);
2945         }
2946         printf("%6d\n", i);
2947         i--;
2948
2949         printf("cleaning up\n");
2950         for (;i>=0;i--) {
2951                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2952                 cli_close(cli, fnums[i]);
2953
2954                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2955                 if (!NT_STATUS_IS_OK(status)) {
2956                         printf("unlink of %s failed (%s)\n", 
2957                                fname, nt_errstr(status));
2958                         correct = False;
2959                 }
2960                 printf("%6d\r", i);
2961         }
2962         printf("%6d\n", 0);
2963
2964         printf("maxfid test finished\n");
2965         if (!torture_close_connection(cli)) {
2966                 correct = False;
2967         }
2968         return correct;
2969 }
2970
2971 /* generate a random buffer */
2972 static void rand_buf(char *buf, int len)
2973 {
2974         while (len--) {
2975                 *buf = (char)sys_random();
2976                 buf++;
2977         }
2978 }
2979
2980 /* send smb negprot commands, not reading the response */
2981 static bool run_negprot_nowait(int dummy)
2982 {
2983         struct tevent_context *ev;
2984         int i;
2985         struct cli_state *cli;
2986         bool correct = True;
2987
2988         printf("starting negprot nowait test\n");
2989
2990         ev = samba_tevent_context_init(talloc_tos());
2991         if (ev == NULL) {
2992                 return false;
2993         }
2994
2995         if (!(cli = open_nbt_connection())) {
2996                 TALLOC_FREE(ev);
2997                 return False;
2998         }
2999
3000         for (i=0;i<50000;i++) {
3001                 struct tevent_req *req;
3002
3003                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3004                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3005                 if (req == NULL) {
3006                         TALLOC_FREE(ev);
3007                         return false;
3008                 }
3009                 if (!tevent_req_poll(req, ev)) {
3010                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3011                                   strerror(errno));
3012                         TALLOC_FREE(ev);
3013                         return false;
3014                 }
3015                 TALLOC_FREE(req);
3016         }
3017
3018         if (torture_close_connection(cli)) {
3019                 correct = False;
3020         }
3021
3022         printf("finished negprot nowait test\n");
3023
3024         return correct;
3025 }
3026
3027 /* send smb negprot commands, not reading the response */
3028 static bool run_bad_nbt_session(int dummy)
3029 {
3030         struct nmb_name called, calling;
3031         struct sockaddr_storage ss;
3032         NTSTATUS status;
3033         int fd;
3034         bool ret;
3035
3036         printf("starting bad nbt session test\n");
3037
3038         make_nmb_name(&calling, myname, 0x0);
3039         make_nmb_name(&called , host, 0x20);
3040
3041         if (!resolve_name(host, &ss, 0x20, true)) {
3042                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3043                 return false;
3044         }
3045
3046         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3047         if (!NT_STATUS_IS_OK(status)) {
3048                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3049                           nt_errstr(status));
3050                 return false;
3051         }
3052
3053         ret = cli_bad_session_request(fd, &calling, &called);
3054         close(fd);
3055         if (!ret) {
3056                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3057                           nt_errstr(status));
3058                 return false;
3059         }
3060
3061         printf("finished bad nbt session test\n");
3062         return true;
3063 }
3064
3065 /* send random IPC commands */
3066 static bool run_randomipc(int dummy)
3067 {
3068         char *rparam = NULL;
3069         char *rdata = NULL;
3070         unsigned int rdrcnt,rprcnt;
3071         char param[1024];
3072         int api, param_len, i;
3073         struct cli_state *cli;
3074         bool correct = True;
3075         int count = 50000;
3076
3077         printf("starting random ipc test\n");
3078
3079         if (!torture_open_connection(&cli, 0)) {
3080                 return False;
3081         }
3082
3083         for (i=0;i<count;i++) {
3084                 api = sys_random() % 500;
3085                 param_len = (sys_random() % 64);
3086
3087                 rand_buf(param, param_len);
3088
3089                 SSVAL(param,0,api); 
3090
3091                 cli_api(cli, 
3092                         param, param_len, 8,  
3093                         NULL, 0, CLI_BUFFER_SIZE,
3094                         &rparam, &rprcnt,     
3095                         &rdata, &rdrcnt);
3096                 if (i % 100 == 0) {
3097                         printf("%d/%d\r", i,count);
3098                 }
3099         }
3100         printf("%d/%d\n", i, count);
3101
3102         if (!torture_close_connection(cli)) {
3103                 correct = False;
3104         }
3105
3106         SAFE_FREE(rparam);
3107         SAFE_FREE(rdata);
3108
3109         printf("finished random ipc test\n");
3110
3111         return correct;
3112 }
3113
3114
3115
3116 static void browse_callback(const char *sname, uint32_t stype,
3117                             const char *comment, void *state)
3118 {
3119         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3120 }
3121
3122
3123
3124 /*
3125   This test checks the browse list code
3126
3127 */
3128 static bool run_browsetest(int dummy)
3129 {
3130         static struct cli_state *cli;
3131         bool correct = True;
3132
3133         printf("starting browse test\n");
3134
3135         if (!torture_open_connection(&cli, 0)) {
3136                 return False;
3137         }
3138
3139         printf("domain list:\n");
3140         cli_NetServerEnum(cli, cli->server_domain, 
3141                           SV_TYPE_DOMAIN_ENUM,
3142                           browse_callback, NULL);
3143
3144         printf("machine list:\n");
3145         cli_NetServerEnum(cli, cli->server_domain, 
3146                           SV_TYPE_ALL,
3147                           browse_callback, NULL);
3148
3149         if (!torture_close_connection(cli)) {
3150                 correct = False;
3151         }
3152
3153         printf("browse test finished\n");
3154
3155         return correct;
3156
3157 }
3158
3159
3160 /*
3161   This checks how the getatr calls works
3162 */
3163 static bool run_attrtest(int dummy)
3164 {
3165         struct cli_state *cli;
3166         uint16_t fnum;
3167         time_t t, t2;
3168         const char *fname = "\\attrib123456789.tst";
3169         bool correct = True;
3170         NTSTATUS status;
3171
3172         printf("starting attrib test\n");
3173
3174         if (!torture_open_connection(&cli, 0)) {
3175                 return False;
3176         }
3177
3178         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3179         cli_openx(cli, fname, 
3180                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3181         cli_close(cli, fnum);
3182
3183         status = cli_getatr(cli, fname, NULL, NULL, &t);
3184         if (!NT_STATUS_IS_OK(status)) {
3185                 printf("getatr failed (%s)\n", nt_errstr(status));
3186                 correct = False;
3187         }
3188
3189         if (abs(t - time(NULL)) > 60*60*24*10) {
3190                 printf("ERROR: SMBgetatr bug. time is %s",
3191                        ctime(&t));
3192                 t = time(NULL);
3193                 correct = True;
3194         }
3195
3196         t2 = t-60*60*24; /* 1 day ago */
3197
3198         status = cli_setatr(cli, fname, 0, t2);
3199         if (!NT_STATUS_IS_OK(status)) {
3200                 printf("setatr failed (%s)\n", nt_errstr(status));
3201                 correct = True;
3202         }
3203
3204         status = cli_getatr(cli, fname, NULL, NULL, &t);
3205         if (!NT_STATUS_IS_OK(status)) {
3206                 printf("getatr failed (%s)\n", nt_errstr(status));
3207                 correct = True;
3208         }
3209
3210         if (t != t2) {
3211                 printf("ERROR: getatr/setatr bug. times are\n%s",
3212                        ctime(&t));
3213                 printf("%s", ctime(&t2));
3214                 correct = True;
3215         }
3216
3217         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3218
3219         if (!torture_close_connection(cli)) {
3220                 correct = False;
3221         }
3222
3223         printf("attrib test finished\n");
3224
3225         return correct;
3226 }
3227
3228
3229 /*
3230   This checks a couple of trans2 calls
3231 */
3232 static bool run_trans2test(int dummy)
3233 {
3234         struct cli_state *cli;
3235         uint16_t fnum;
3236         off_t size;
3237         time_t c_time, a_time, m_time;
3238         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3239         const char *fname = "\\trans2.tst";
3240         const char *dname = "\\trans2";
3241         const char *fname2 = "\\trans2\\trans2.tst";
3242         char *pname;
3243         bool correct = True;
3244         NTSTATUS status;
3245         uint32_t fs_attr;
3246
3247         printf("starting trans2 test\n");
3248
3249         if (!torture_open_connection(&cli, 0)) {
3250                 return False;
3251         }
3252
3253         status = cli_get_fs_attr_info(cli, &fs_attr);
3254         if (!NT_STATUS_IS_OK(status)) {
3255                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3256                        nt_errstr(status));
3257                 correct = false;
3258         }
3259
3260         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3261         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3262         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3263                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3264         if (!NT_STATUS_IS_OK(status)) {
3265                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3266                 correct = False;
3267         }
3268
3269         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3270         if (!NT_STATUS_IS_OK(status)) {
3271                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3272                 correct = False;
3273         }
3274         else if (strcmp(pname, fname)) {
3275                 printf("qfilename gave different name? [%s] [%s]\n",
3276                        fname, pname);
3277                 correct = False;
3278         }
3279
3280         cli_close(cli, fnum);
3281
3282         sleep(2);
3283
3284         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3285         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3286                           &fnum);
3287         if (!NT_STATUS_IS_OK(status)) {
3288                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3289                 return False;
3290         }
3291         cli_close(cli, fnum);
3292
3293         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3294                                 NULL);
3295         if (!NT_STATUS_IS_OK(status)) {
3296                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3297                 correct = False;
3298         } else {
3299                 time_t t = time(NULL);
3300
3301                 if (c_time != m_time) {
3302                         printf("create time=%s", ctime(&c_time));
3303                         printf("modify time=%s", ctime(&m_time));
3304                         printf("This system appears to have sticky create times\n");
3305                 }
3306                 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3307                         printf("access time=%s", ctime(&a_time));
3308                         printf("This system appears to set a midnight access time\n");
3309                         correct = False;
3310                 }
3311
3312                 if (abs(m_time - t) > 60*60*24*7) {
3313                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3314                         correct = False;
3315                 }
3316         }
3317
3318
3319         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3320         cli_openx(cli, fname, 
3321                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3322         cli_close(cli, fnum);
3323         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3324                                 &m_time_ts, &size, NULL, NULL);
3325         if (!NT_STATUS_IS_OK(status)) {
3326                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3327                 correct = False;
3328         } else {
3329                 if (w_time_ts.tv_sec < 60*60*24*2) {
3330                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3331                         printf("This system appears to set a initial 0 write time\n");
3332                         correct = False;
3333                 }
3334         }
3335
3336         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3337
3338
3339         /* check if the server updates the directory modification time
3340            when creating a new file */
3341         status = cli_mkdir(cli, dname);
3342         if (!NT_STATUS_IS_OK(status)) {
3343                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3344                 correct = False;
3345         }
3346         sleep(3);
3347         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3348                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3349         if (!NT_STATUS_IS_OK(status)) {
3350                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3351                 correct = False;
3352         }
3353
3354         cli_openx(cli, fname2, 
3355                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3356         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3357         cli_close(cli, fnum);
3358         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3359                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3360         if (!NT_STATUS_IS_OK(status)) {
3361                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3362                 correct = False;
3363         } else {
3364                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3365                     == 0) {
3366                         printf("This system does not update directory modification times\n");
3367                         correct = False;
3368                 }
3369         }
3370         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3371         cli_rmdir(cli, dname);
3372
3373         if (!torture_close_connection(cli)) {
3374                 correct = False;
3375         }
3376
3377         printf("trans2 test finished\n");
3378
3379         return correct;
3380 }
3381
3382 /*
3383   This checks new W2K calls.
3384 */
3385
3386 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3387 {
3388         uint8_t *buf = NULL;
3389         uint32_t len;
3390         NTSTATUS status;
3391
3392         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3393                                CLI_BUFFER_SIZE, NULL, &buf, &len);
3394         if (!NT_STATUS_IS_OK(status)) {
3395                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3396                        nt_errstr(status));
3397         } else {
3398                 printf("qfileinfo: level %d, len = %u\n", level, len);
3399                 dump_data(0, (uint8_t *)buf, len);
3400                 printf("\n");
3401         }
3402         TALLOC_FREE(buf);
3403         return status;
3404 }
3405
3406 static bool run_w2ktest(int dummy)
3407 {
3408         struct cli_state *cli;
3409         uint16_t fnum;
3410         const char *fname = "\\w2ktest\\w2k.tst";
3411         int level;
3412         bool correct = True;
3413
3414         printf("starting w2k test\n");
3415
3416         if (!torture_open_connection(&cli, 0)) {
3417                 return False;
3418         }
3419
3420         cli_openx(cli, fname, 
3421                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3422
3423         for (level = 1004; level < 1040; level++) {
3424                 new_trans(cli, fnum, level);
3425         }
3426
3427         cli_close(cli, fnum);
3428
3429         if (!torture_close_connection(cli)) {
3430                 correct = False;
3431         }
3432
3433         printf("w2k test finished\n");
3434
3435         return correct;
3436 }
3437
3438
3439 /*
3440   this is a harness for some oplock tests
3441  */
3442 static bool run_oplock1(int dummy)
3443 {
3444         struct cli_state *cli1;
3445         const char *fname = "\\lockt1.lck";
3446         uint16_t fnum1;
3447         bool correct = True;
3448         NTSTATUS status;
3449
3450         printf("starting oplock test 1\n");
3451
3452         if (!torture_open_connection(&cli1, 0)) {
3453                 return False;
3454         }
3455
3456         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3457
3458         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3459
3460         cli1->use_oplocks = True;
3461
3462         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3463                           &fnum1);
3464         if (!NT_STATUS_IS_OK(status)) {
3465                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3466                 return False;
3467         }
3468
3469         cli1->use_oplocks = False;
3470
3471         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3472         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3473
3474         status = cli_close(cli1, fnum1);
3475         if (!NT_STATUS_IS_OK(status)) {
3476                 printf("close2 failed (%s)\n", nt_errstr(status));
3477                 return False;
3478         }
3479
3480         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3481         if (!NT_STATUS_IS_OK(status)) {
3482                 printf("unlink failed (%s)\n", nt_errstr(status));
3483                 return False;
3484         }
3485
3486         if (!torture_close_connection(cli1)) {
3487                 correct = False;
3488         }
3489
3490         printf("finished oplock test 1\n");
3491
3492         return correct;
3493 }
3494
3495 static bool run_oplock2(int dummy)
3496 {
3497         struct cli_state *cli1, *cli2;
3498         const char *fname = "\\lockt2.lck";
3499         uint16_t fnum1, fnum2;
3500         int saved_use_oplocks = use_oplocks;
3501         char buf[4];
3502         bool correct = True;
3503         volatile bool *shared_correct;
3504         size_t nread;
3505         NTSTATUS status;
3506
3507         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3508         *shared_correct = True;
3509
3510         use_level_II_oplocks = True;
3511         use_oplocks = True;
3512
3513         printf("starting oplock test 2\n");
3514
3515         if (!torture_open_connection(&cli1, 0)) {
3516                 use_level_II_oplocks = False;
3517                 use_oplocks = saved_use_oplocks;
3518                 return False;
3519         }
3520
3521         if (!torture_open_connection(&cli2, 1)) {
3522                 use_level_II_oplocks = False;
3523                 use_oplocks = saved_use_oplocks;
3524                 return False;
3525         }
3526
3527         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3528
3529         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3530         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3531
3532         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3533                           &fnum1);
3534         if (!NT_STATUS_IS_OK(status)) {
3535                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3536                 return False;
3537         }
3538
3539         /* Don't need the globals any more. */
3540         use_level_II_oplocks = False;
3541         use_oplocks = saved_use_oplocks;
3542
3543         if (fork() == 0) {
3544                 /* Child code */
3545                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3546                 if (!NT_STATUS_IS_OK(status)) {
3547                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3548                         *shared_correct = False;
3549                         exit(0);
3550                 }
3551
3552                 sleep(2);
3553
3554                 status = cli_close(cli2, fnum2);
3555                 if (!NT_STATUS_IS_OK(status)) {
3556                         printf("close2 failed (%s)\n", nt_errstr(status));
3557                         *shared_correct = False;
3558                 }
3559
3560                 exit(0);
3561         }
3562
3563         sleep(2);
3564
3565         /* Ensure cli1 processes the break. Empty file should always return 0
3566          * bytes.  */
3567         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3568         if (!NT_STATUS_IS_OK(status)) {
3569                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3570                 correct = false;
3571         } else if (nread != 0) {
3572                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3573                       (unsigned long)nread, 0);
3574                 correct = false;
3575         }
3576
3577         /* Should now be at level II. */
3578         /* Test if sending a write locks causes a break to none. */
3579         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3580         if (!NT_STATUS_IS_OK(status)) {
3581                 printf("lock failed (%s)\n", nt_errstr(status));
3582                 correct = False;
3583         }
3584
3585         cli_unlock(cli1, fnum1, 0, 4);
3586
3587         sleep(2);
3588
3589         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3590         if (!NT_STATUS_IS_OK(status)) {
3591                 printf("lock failed (%s)\n", nt_errstr(status));
3592                 correct = False;
3593         }
3594
3595         cli_unlock(cli1, fnum1, 0, 4);
3596
3597         sleep(2);
3598
3599         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3600
3601         status = cli_close(cli1, fnum1);
3602         if (!NT_STATUS_IS_OK(status)) {
3603                 printf("close1 failed (%s)\n", nt_errstr(status));
3604                 correct = False;
3605         }
3606
3607         sleep(4);
3608
3609         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3610         if (!NT_STATUS_IS_OK(status)) {
3611                 printf("unlink failed (%s)\n", nt_errstr(status));
3612                 correct = False;
3613         }
3614
3615         if (!torture_close_connection(cli1)) {
3616                 correct = False;
3617         }
3618
3619         if (!*shared_correct) {
3620                 correct = False;
3621         }
3622
3623         printf("finished oplock test 2\n");
3624
3625         return correct;
3626 }
3627
3628 struct oplock4_state {
3629         struct tevent_context *ev;
3630         struct cli_state *cli;
3631         bool *got_break;
3632         uint16_t *fnum2;
3633 };
3634
3635 static void oplock4_got_break(struct tevent_req *req);
3636 static void oplock4_got_open(struct tevent_req *req);
3637
3638 static bool run_oplock4(int dummy)
3639 {
3640         struct tevent_context *ev;
3641         struct cli_state *cli1, *cli2;
3642         struct tevent_req *oplock_req, *open_req;
3643         const char *fname = "\\lockt4.lck";
3644         const char *fname_ln = "\\lockt4_ln.lck";
3645         uint16_t fnum1, fnum2;
3646         int saved_use_oplocks = use_oplocks;
3647         NTSTATUS status;
3648         bool correct = true;
3649
3650         bool got_break;
3651
3652         struct oplock4_state *state;
3653
3654         printf("starting oplock test 4\n");
3655
3656         if (!torture_open_connection(&cli1, 0)) {
3657                 use_level_II_oplocks = false;
3658                 use_oplocks = saved_use_oplocks;
3659                 return false;
3660         }
3661
3662         if (!torture_open_connection(&cli2, 1)) {
3663                 use_level_II_oplocks = false;
3664                 use_oplocks = saved_use_oplocks;
3665                 return false;
3666         }
3667
3668         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3669         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3670
3671         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3672         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3673
3674         /* Create the file. */
3675         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3676                           &fnum1);
3677         if (!NT_STATUS_IS_OK(status)) {
3678                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3679                 return false;
3680         }
3681
3682         status = cli_close(cli1, fnum1);
3683         if (!NT_STATUS_IS_OK(status)) {
3684                 printf("close1 failed (%s)\n", nt_errstr(status));
3685                 return false;
3686         }
3687
3688         /* Now create a hardlink. */
3689         status = cli_nt_hardlink(cli1, fname, fname_ln);
3690         if (!NT_STATUS_IS_OK(status)) {
3691                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3692                 return false;
3693         }
3694
3695         /* Prove that opening hardlinks cause deny modes to conflict. */
3696         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3697         if (!NT_STATUS_IS_OK(status)) {
3698                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3699                 return false;
3700         }
3701
3702         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3703         if (NT_STATUS_IS_OK(status)) {
3704                 printf("open of %s succeeded - should fail with sharing violation.\n",
3705                         fname_ln);
3706                 return false;
3707         }
3708
3709         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3710                 printf("open of %s should fail with sharing violation. Got %s\n",
3711                         fname_ln, nt_errstr(status));
3712                 return false;
3713         }
3714
3715         status = cli_close(cli1, fnum1);
3716         if (!NT_STATUS_IS_OK(status)) {
3717                 printf("close1 failed (%s)\n", nt_errstr(status));
3718                 return false;
3719         }
3720
3721         cli1->use_oplocks = true;
3722         cli2->use_oplocks = true;
3723
3724         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3725         if (!NT_STATUS_IS_OK(status)) {
3726                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3727                 return false;
3728         }
3729
3730         ev = samba_tevent_context_init(talloc_tos());
3731         if (ev == NULL) {
3732                 printf("tevent_context_init failed\n");
3733                 return false;
3734         }
3735
3736         state = talloc(ev, struct oplock4_state);
3737         if (state == NULL) {
3738                 printf("talloc failed\n");
3739                 return false;
3740         }
3741         state->ev = ev;
3742         state->cli = cli1;
3743         state->got_break = &got_break;
3744         state->fnum2 = &fnum2;
3745
3746         oplock_req = cli_smb_oplock_break_waiter_send(
3747                 talloc_tos(), ev, cli1);
3748         if (oplock_req == NULL) {
3749                 printf("cli_smb_oplock_break_waiter_send failed\n");
3750                 return false;
3751         }
3752         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3753
3754         open_req = cli_openx_send(
3755                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3756         if (open_req == NULL) {
3757                 printf("cli_openx_send failed\n");
3758                 return false;
3759         }
3760         tevent_req_set_callback(open_req, oplock4_got_open, state);
3761
3762         got_break = false;
3763         fnum2 = 0xffff;
3764
3765         while (!got_break || fnum2 == 0xffff) {
3766                 int ret;
3767                 ret = tevent_loop_once(ev);
3768                 if (ret == -1) {
3769                         printf("tevent_loop_once failed: %s\n",
3770                                strerror(errno));
3771                         return false;
3772                 }
3773         }
3774
3775         status = cli_close(cli2, fnum2);
3776         if (!NT_STATUS_IS_OK(status)) {
3777                 printf("close2 failed (%s)\n", nt_errstr(status));
3778                 correct = false;
3779         }
3780
3781         status = cli_close(cli1, fnum1);
3782         if (!NT_STATUS_IS_OK(status)) {
3783                 printf("close1 failed (%s)\n", nt_errstr(status));
3784                 correct = false;
3785         }
3786
3787         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3788         if (!NT_STATUS_IS_OK(status)) {
3789                 printf("unlink failed (%s)\n", nt_errstr(status));
3790                 correct = false;
3791         }
3792
3793         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3794         if (!NT_STATUS_IS_OK(status)) {
3795                 printf("unlink failed (%s)\n", nt_errstr(status));
3796                 correct = false;
3797         }
3798
3799         if (!torture_close_connection(cli1)) {
3800                 correct = false;
3801         }
3802
3803         if (!got_break) {
3804                 correct = false;
3805         }
3806
3807         printf("finished oplock test 4\n");
3808
3809         return correct;
3810 }
3811
3812 static void oplock4_got_break(struct tevent_req *req)
3813 {
3814         struct oplock4_state *state = tevent_req_callback_data(
3815                 req, struct oplock4_state);
3816         uint16_t fnum;
3817         uint8_t level;
3818         NTSTATUS status;
3819
3820         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3821         TALLOC_FREE(req);
3822         if (!NT_STATUS_IS_OK(status)) {
3823                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3824                        nt_errstr(status));
3825                 return;
3826         }
3827         *state->got_break = true;
3828
3829         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3830                                   NO_OPLOCK);
3831         if (req == NULL) {
3832                 printf("cli_oplock_ack_send failed\n");
3833                 return;
3834         }
3835 }
3836
3837 static void oplock4_got_open(struct tevent_req *req)
3838 {
3839         struct oplock4_state *state = tevent_req_callback_data(
3840                 req, struct oplock4_state);
3841         NTSTATUS status;
3842
3843         status = cli_openx_recv(req, state->fnum2);
3844         if (!NT_STATUS_IS_OK(status)) {
3845                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3846                 *state->fnum2 = 0xffff;
3847         }
3848 }
3849
3850 /*
3851   Test delete on close semantics.
3852  */
3853 static bool run_deletetest(int dummy)
3854 {
3855         struct cli_state *cli1 = NULL;
3856         struct cli_state *cli2 = NULL;
3857         const char *fname = "\\delete.file";
3858         uint16_t fnum1 = (uint16_t)-1;
3859         uint16_t fnum2 = (uint16_t)-1;
3860         bool correct = false;
3861         NTSTATUS status;
3862
3863         printf("starting delete test\n");
3864
3865         if (!torture_open_connection(&cli1, 0)) {
3866                 return False;
3867         }
3868
3869         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3870
3871         /* Test 1 - this should delete the file on close. */
3872
3873         cli_setatr(cli1, fname, 0, 0);
3874         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3875
3876         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3877                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3878                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
3879         if (!NT_STATUS_IS_OK(status)) {
3880                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3881                 goto fail;
3882         }
3883
3884         status = cli_close(cli1, fnum1);
3885         if (!NT_STATUS_IS_OK(status)) {
3886                 printf("[1] close failed (%s)\n", nt_errstr(status));
3887                 goto fail;
3888         }
3889
3890         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3891         if (NT_STATUS_IS_OK(status)) {
3892                 printf("[1] open of %s succeeded (should fail)\n", fname);
3893                 goto fail;
3894         }
3895
3896         printf("first delete on close test succeeded.\n");
3897
3898         /* Test 2 - this should delete the file on close. */
3899
3900         cli_setatr(cli1, fname, 0, 0);
3901         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3902
3903         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3904                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3905                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3906         if (!NT_STATUS_IS_OK(status)) {
3907                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3908                 goto fail;
3909         }
3910
3911         status = cli_nt_delete_on_close(cli1, fnum1, true);
3912         if (!NT_STATUS_IS_OK(status)) {
3913                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3914                 goto fail;
3915         }
3916
3917         status = cli_close(cli1, fnum1);
3918         if (!NT_STATUS_IS_OK(status)) {
3919                 printf("[2] close failed (%s)\n", nt_errstr(status));
3920                 goto fail;
3921         }
3922
3923         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3924         if (NT_STATUS_IS_OK(status)) {
3925                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3926                 status = cli_close(cli1, fnum1);
3927                 if (!NT_STATUS_IS_OK(status)) {
3928                         printf("[2] close failed (%s)\n", nt_errstr(status));
3929                 }
3930                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3931                 goto fail;
3932         }
3933
3934         printf("second delete on close test succeeded.\n");
3935
3936         /* Test 3 - ... */
3937         cli_setatr(cli1, fname, 0, 0);
3938         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3939
3940         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3941                               FILE_ATTRIBUTE_NORMAL,
3942                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3943                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
3944         if (!NT_STATUS_IS_OK(status)) {
3945                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3946                 goto fail;
3947         }
3948
3949         /* This should fail with a sharing violation - open for delete is only compatible
3950            with SHARE_DELETE. */
3951
3952         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3953                               FILE_ATTRIBUTE_NORMAL,
3954                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3955                               FILE_OPEN, 0, 0, &fnum2, NULL);
3956         if (NT_STATUS_IS_OK(status)) {
3957                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3958                 goto fail;
3959         }
3960
3961         /* This should succeed. */
3962         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3963                              FILE_ATTRIBUTE_NORMAL,
3964                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3965                              FILE_OPEN, 0, 0, &fnum2, NULL);
3966         if (!NT_STATUS_IS_OK(status)) {
3967                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
3968                 goto fail;
3969         }
3970
3971         status = cli_nt_delete_on_close(cli1, fnum1, true);
3972         if (!NT_STATUS_IS_OK(status)) {
3973                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3974                 goto fail;
3975         }
3976
3977         status = cli_close(cli1, fnum1);
3978         if (!NT_STATUS_IS_OK(status)) {
3979                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3980                 goto fail;
3981         }
3982
3983         status = cli_close(cli1, fnum2);
3984         if (!NT_STATUS_IS_OK(status)) {
3985                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3986                 goto fail;
3987         }
3988
3989         /* This should fail - file should no longer be there. */
3990
3991         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
3992         if (NT_STATUS_IS_OK(status)) {
3993                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3994                 status = cli_close(cli1, fnum1);
3995                 if (!NT_STATUS_IS_OK(status)) {
3996                         printf("[3] close failed (%s)\n", nt_errstr(status));
3997                 }
3998                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3999                 goto fail;
4000         }
4001
4002         printf("third delete on close test succeeded.\n");
4003
4004         /* Test 4 ... */
4005         cli_setatr(cli1, fname, 0, 0);
4006         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4007
4008         status = cli_ntcreate(cli1, fname, 0,
4009                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4010                               FILE_ATTRIBUTE_NORMAL,
4011                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4012                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4013         if (!NT_STATUS_IS_OK(status)) {
4014                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4015                 goto fail;
4016         }
4017
4018         /* This should succeed. */
4019         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4020                              FILE_ATTRIBUTE_NORMAL,
4021                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4022                              FILE_OPEN, 0, 0, &fnum2, NULL);
4023         if (!NT_STATUS_IS_OK(status)) {
4024                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4025                 goto fail;
4026         }
4027
4028         status = cli_close(cli1, fnum2);
4029         if (!NT_STATUS_IS_OK(status)) {
4030                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4031                 goto fail;
4032         }
4033
4034         status = cli_nt_delete_on_close(cli1, fnum1, true);
4035         if (!NT_STATUS_IS_OK(status)) {
4036                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4037                 goto fail;
4038         }
4039
4040         /* This should fail - no more opens once delete on close set. */
4041         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4042                               FILE_ATTRIBUTE_NORMAL,
4043                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4044                               FILE_OPEN, 0, 0, &fnum2, NULL);
4045         if (NT_STATUS_IS_OK(status)) {
4046                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4047                 goto fail;
4048         }
4049
4050         status = cli_close(cli1, fnum1);
4051         if (!NT_STATUS_IS_OK(status)) {
4052                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4053                 goto fail;
4054         }
4055
4056         printf("fourth delete on close test succeeded.\n");
4057
4058         /* Test 5 ... */
4059         cli_setatr(cli1, fname, 0, 0);
4060         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4061
4062         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4063         if (!NT_STATUS_IS_OK(status)) {
4064                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4065                 goto fail;
4066         }
4067
4068         /* This should fail - only allowed on NT opens with DELETE access. */
4069
4070         status = cli_nt_delete_on_close(cli1, fnum1, true);
4071         if (NT_STATUS_IS_OK(status)) {
4072                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4073                 goto fail;
4074         }
4075
4076         status = cli_close(cli1, fnum1);
4077         if (!NT_STATUS_IS_OK(status)) {
4078                 printf("[5] close failed (%s)\n", nt_errstr(status));
4079                 goto fail;
4080         }
4081
4082         printf("fifth delete on close test succeeded.\n");
4083
4084         /* Test 6 ... */
4085         cli_setatr(cli1, fname, 0, 0);
4086         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4087
4088         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4089                              FILE_ATTRIBUTE_NORMAL,
4090                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4091                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4092         if (!NT_STATUS_IS_OK(status)) {
4093                 printf("[6] open of %s failed (%s)\n", fname,
4094                        nt_errstr(status));
4095                 goto fail;
4096         }
4097
4098         /* This should fail - only allowed on NT opens with DELETE access. */
4099
4100         status = cli_nt_delete_on_close(cli1, fnum1, true);
4101         if (NT_STATUS_IS_OK(status)) {
4102                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4103                 goto fail;
4104         }
4105
4106         status = cli_close(cli1, fnum1);
4107         if (!NT_STATUS_IS_OK(status)) {
4108                 printf("[6] close failed (%s)\n", nt_errstr(status));
4109                 goto fail;
4110         }
4111
4112         printf("sixth delete on close test succeeded.\n");
4113
4114         /* Test 7 ... */
4115         cli_setatr(cli1, fname, 0, 0);
4116         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4117
4118         status = cli_ntcreate(cli1, fname, 0,
4119                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4120                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4121                               0, 0, &fnum1, NULL);
4122         if (!NT_STATUS_IS_OK(status)) {
4123                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4124                 goto fail;
4125         }
4126
4127         status = cli_nt_delete_on_close(cli1, fnum1, true);
4128         if (!NT_STATUS_IS_OK(status)) {
4129                 printf("[7] setting delete_on_close on file failed !\n");
4130                 goto fail;
4131         }
4132
4133         status = cli_nt_delete_on_close(cli1, fnum1, false);
4134         if (!NT_STATUS_IS_OK(status)) {
4135                 printf("[7] unsetting delete_on_close on file failed !\n");
4136                 goto fail;
4137         }
4138
4139         status = cli_close(cli1, fnum1);
4140         if (!NT_STATUS_IS_OK(status)) {
4141                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4142                 goto fail;
4143         }
4144
4145         /* This next open should succeed - we reset the flag. */
4146         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4147         if (!NT_STATUS_IS_OK(status)) {
4148                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4149                 goto fail;
4150         }
4151
4152         status = cli_close(cli1, fnum1);
4153         if (!NT_STATUS_IS_OK(status)) {
4154                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4155                 goto fail;
4156         }
4157
4158         printf("seventh delete on close test succeeded.\n");
4159
4160         /* Test 8 ... */
4161         cli_setatr(cli1, fname, 0, 0);
4162         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4163
4164         if (!torture_open_connection(&cli2, 1)) {
4165                 printf("[8] failed to open second connection.\n");
4166                 goto fail;
4167         }
4168
4169         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4170
4171         status = cli_ntcreate(cli1, fname, 0,
4172                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4173                              FILE_ATTRIBUTE_NORMAL,
4174                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4175                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4176         if (!NT_STATUS_IS_OK(status)) {
4177                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4178                 goto fail;
4179         }
4180
4181         status = cli_ntcreate(cli2, fname, 0,
4182                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4183                              FILE_ATTRIBUTE_NORMAL,
4184                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4185                              FILE_OPEN, 0, 0, &fnum2, NULL);
4186         if (!NT_STATUS_IS_OK(status)) {
4187                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4188                 goto fail;
4189         }
4190
4191         status = cli_nt_delete_on_close(cli1, fnum1, true);
4192         if (!NT_STATUS_IS_OK(status)) {
4193                 printf("[8] setting delete_on_close on file failed !\n");
4194                 goto fail;
4195         }
4196
4197         status = cli_close(cli1, fnum1);
4198         if (!NT_STATUS_IS_OK(status)) {
4199                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4200                 goto fail;
4201         }
4202
4203         status = cli_close(cli2, fnum2);
4204         if (!NT_STATUS_IS_OK(status)) {
4205                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4206                 goto fail;
4207         }
4208
4209         /* This should fail.. */
4210         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4211         if (NT_STATUS_IS_OK(status)) {
4212                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4213                 goto fail;
4214         }
4215
4216         printf("eighth delete on close test succeeded.\n");
4217
4218         /* Test 9 ... */
4219
4220         /* This should fail - we need to set DELETE_ACCESS. */
4221         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4222                               FILE_ATTRIBUTE_NORMAL,
4223                               FILE_SHARE_NONE,
4224                               FILE_OVERWRITE_IF,
4225                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4226         if (NT_STATUS_IS_OK(status)) {
4227                 printf("[9] open of %s succeeded should have failed!\n", fname);
4228                 goto fail;
4229         }
4230
4231         printf("ninth delete on close test succeeded.\n");
4232
4233         /* Test 10 ... */
4234
4235         status = cli_ntcreate(cli1, fname, 0,
4236                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4237                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4238                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4239                              0, &fnum1, NULL);
4240         if (!NT_STATUS_IS_OK(status)) {
4241                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4242                 goto fail;
4243         }
4244
4245         /* This should delete the file. */
4246         status = cli_close(cli1, fnum1);
4247         if (!NT_STATUS_IS_OK(status)) {
4248                 printf("[10] close failed (%s)\n", nt_errstr(status));
4249                 goto fail;
4250         }
4251
4252         /* This should fail.. */
4253         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4254         if (NT_STATUS_IS_OK(status)) {
4255                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4256                 goto fail;
4257         }
4258
4259         printf("tenth delete on close test succeeded.\n");
4260
4261         /* Test 11 ... */
4262
4263         cli_setatr(cli1, fname, 0, 0);
4264         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4265
4266         /* Can we open a read-only file with delete access? */
4267
4268         /* Create a readonly file. */
4269         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4270                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4271                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4272         if (!NT_STATUS_IS_OK(status)) {
4273                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4274                 goto fail;
4275         }
4276
4277         status = cli_close(cli1, fnum1);
4278         if (!NT_STATUS_IS_OK(status)) {
4279                 printf("[11] close failed (%s)\n", nt_errstr(status));
4280                 goto fail;
4281         }
4282
4283         /* Now try open for delete access. */
4284         status = cli_ntcreate(cli1, fname, 0,
4285                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4286                              0,
4287                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4288                              FILE_OPEN, 0, 0, &fnum1, NULL);
4289         if (!NT_STATUS_IS_OK(status)) {
4290                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4291                 goto fail;
4292         }
4293
4294         cli_close(cli1, fnum1);
4295
4296         printf("eleventh delete on close test succeeded.\n");
4297
4298         /*
4299          * Test 12
4300          * like test 4 but with initial delete on close
4301          */
4302
4303         cli_setatr(cli1, fname, 0, 0);
4304         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4305
4306         status = cli_ntcreate(cli1, fname, 0,
4307                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4308                               FILE_ATTRIBUTE_NORMAL,
4309                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4310                               FILE_OVERWRITE_IF,
4311                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4312         if (!NT_STATUS_IS_OK(status)) {
4313                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4314                 goto fail;
4315         }
4316
4317         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4318                               FILE_ATTRIBUTE_NORMAL,
4319                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4320                               FILE_OPEN, 0, 0, &fnum2, NULL);
4321         if (!NT_STATUS_IS_OK(status)) {
4322                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4323                 goto fail;
4324         }
4325
4326         status = cli_close(cli1, fnum2);
4327         if (!NT_STATUS_IS_OK(status)) {
4328                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4329                 goto fail;
4330         }
4331
4332         status = cli_nt_delete_on_close(cli1, fnum1, true);
4333         if (!NT_STATUS_IS_OK(status)) {
4334                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4335                 goto fail;
4336         }
4337
4338         /* This should fail - no more opens once delete on close set. */
4339         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4340                               FILE_ATTRIBUTE_NORMAL,
4341                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4342                               FILE_OPEN, 0, 0, &fnum2, NULL);
4343         if (NT_STATUS_IS_OK(status)) {
4344                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4345                 goto fail;
4346         }
4347
4348         status = cli_nt_delete_on_close(cli1, fnum1, false);
4349         if (!NT_STATUS_IS_OK(status)) {
4350                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4351                 goto fail;
4352         }
4353
4354         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4355                               FILE_ATTRIBUTE_NORMAL,
4356                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4357                               FILE_OPEN, 0, 0, &fnum2, NULL);
4358         if (!NT_STATUS_IS_OK(status)) {
4359                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4360                 goto fail;
4361         }
4362
4363         status = cli_close(cli1, fnum2);
4364         if (!NT_STATUS_IS_OK(status)) {
4365                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4366                 goto fail;
4367         }
4368
4369         status = cli_close(cli1, fnum1);
4370         if (!NT_STATUS_IS_OK(status)) {
4371                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4372                 goto fail;
4373         }
4374
4375         /*
4376          * setting delete on close on the handle does
4377          * not unset the initial delete on close...
4378          */
4379         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4380                               FILE_ATTRIBUTE_NORMAL,
4381                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4382                               FILE_OPEN, 0, 0, &fnum2, NULL);
4383         if (NT_STATUS_IS_OK(status)) {
4384                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4385                 goto fail;
4386         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4387                 printf("ntcreate returned %s, expected "
4388                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4389                        nt_errstr(status));
4390                 goto fail;
4391         }
4392
4393         printf("twelfth delete on close test succeeded.\n");
4394
4395
4396         printf("finished delete test\n");
4397
4398         correct = true;
4399
4400   fail:
4401         /* FIXME: This will crash if we aborted before cli2 got
4402          * intialized, because these functions don't handle
4403          * uninitialized connections. */
4404
4405         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4406         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4407         cli_setatr(cli1, fname, 0, 0);
4408         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4409
4410         if (cli1 && !torture_close_connection(cli1)) {
4411                 correct = False;
4412         }
4413         if (cli2 && !torture_close_connection(cli2)) {
4414                 correct = False;
4415         }
4416         return correct;
4417 }
4418
4419
4420 /*
4421   Test wildcard delete.
4422  */
4423 static bool run_wild_deletetest(int dummy)
4424 {
4425         struct cli_state *cli = NULL;
4426         const char *dname = "\\WTEST";
4427         const char *fname = "\\WTEST\\A";
4428         const char *wunlink_name = "\\WTEST\\*";
4429         uint16_t fnum1 = (uint16_t)-1;
4430         bool correct = false;
4431         NTSTATUS status;
4432
4433         printf("starting wildcard delete test\n");
4434
4435         if (!torture_open_connection(&cli, 0)) {
4436                 return false;
4437         }
4438
4439         smbXcli_conn_set_sockopt(cli->conn, sockops);
4440
4441         cli_unlink(cli, fname, 0);
4442         cli_rmdir(cli, dname);
4443         status = cli_mkdir(cli, dname);
4444         if (!NT_STATUS_IS_OK(status)) {
4445                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4446                 goto fail;
4447         }
4448         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4449         if (!NT_STATUS_IS_OK(status)) {
4450                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4451                 goto fail;
4452         }
4453         status = cli_close(cli, fnum1);
4454         fnum1 = -1;
4455
4456         /*
4457          * Note the unlink attribute-type of zero. This should
4458          * map into FILE_ATTRIBUTE_NORMAL at the server even
4459          * on a wildcard delete.
4460          */
4461
4462         status = cli_unlink(cli, wunlink_name, 0);
4463         if (!NT_STATUS_IS_OK(status)) {
4464                 printf("unlink of %s failed %s!\n",
4465                         wunlink_name, nt_errstr(status));
4466                 goto fail;
4467         }
4468
4469         printf("finished wildcard delete test\n");
4470
4471         correct = true;
4472
4473   fail:
4474
4475         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4476         cli_unlink(cli, fname, 0);
4477         cli_rmdir(cli, dname);
4478
4479         if (cli && !torture_close_connection(cli)) {
4480                 correct = false;
4481         }
4482         return correct;
4483 }
4484
4485 static bool run_deletetest_ln(int dummy)
4486 {
4487         struct cli_state *cli;
4488         const char *fname = "\\delete1";
4489         const char *fname_ln = "\\delete1_ln";
4490         uint16_t fnum;
4491         uint16_t fnum1;
4492         NTSTATUS status;
4493         bool correct = true;
4494         time_t t;
4495
4496         printf("starting deletetest-ln\n");
4497
4498         if (!torture_open_connection(&cli, 0)) {
4499                 return false;
4500         }
4501
4502         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4503         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4504
4505         smbXcli_conn_set_sockopt(cli->conn, sockops);
4506
4507         /* Create the file. */
4508         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4509         if (!NT_STATUS_IS_OK(status)) {
4510                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4511                 return false;
4512         }
4513
4514         status = cli_close(cli, fnum);
4515         if (!NT_STATUS_IS_OK(status)) {
4516                 printf("close1 failed (%s)\n", nt_errstr(status));
4517                 return false;
4518         }
4519
4520         /* Now create a hardlink. */
4521         status = cli_nt_hardlink(cli, fname, fname_ln);
4522         if (!NT_STATUS_IS_OK(status)) {
4523                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4524                 return false;
4525         }
4526
4527         /* Open the original file. */
4528         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4529                         FILE_ATTRIBUTE_NORMAL,
4530                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4531                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
4532         if (!NT_STATUS_IS_OK(status)) {
4533                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4534                 return false;
4535         }
4536
4537         /* Unlink the hard link path. */
4538         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4539                         FILE_ATTRIBUTE_NORMAL,
4540                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4541                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4542         if (!NT_STATUS_IS_OK(status)) {
4543                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4544                 return false;
4545         }
4546         status = cli_nt_delete_on_close(cli, fnum1, true);
4547         if (!NT_STATUS_IS_OK(status)) {
4548                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4549                         __location__, fname_ln, nt_errstr(status));
4550                 return false;
4551         }
4552
4553         status = cli_close(cli, fnum1);
4554         if (!NT_STATUS_IS_OK(status)) {
4555                 printf("close %s failed (%s)\n",
4556                         fname_ln, nt_errstr(status));
4557                 return false;
4558         }
4559
4560         status = cli_close(cli, fnum);
4561         if (!NT_STATUS_IS_OK(status)) {
4562                 printf("close %s failed (%s)\n",
4563                         fname, nt_errstr(status));
4564                 return false;
4565         }
4566
4567         /* Ensure the original file is still there. */
4568         status = cli_getatr(cli, fname, NULL, NULL, &t);
4569         if (!NT_STATUS_IS_OK(status)) {
4570                 printf("%s getatr on file %s failed (%s)\n",
4571                         __location__,
4572                         fname,
4573                         nt_errstr(status));
4574                 correct = False;
4575         }
4576
4577         /* Ensure the link path is gone. */
4578         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4579         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4580                 printf("%s, getatr for file %s returned wrong error code %s "
4581                         "- should have been deleted\n",
4582                         __location__,
4583                         fname_ln, nt_errstr(status));
4584                 correct = False;
4585         }
4586
4587         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4588         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4589
4590         if (!torture_close_connection(cli)) {
4591                 correct = false;
4592         }
4593
4594         printf("finished deletetest-ln\n");
4595
4596         return correct;
4597 }
4598
4599 /*
4600   print out server properties
4601  */
4602 static bool run_properties(int dummy)
4603 {
4604         struct cli_state *cli;
4605         bool correct = True;
4606
4607         printf("starting properties test\n");
4608
4609         ZERO_STRUCT(cli);
4610
4611         if (!torture_open_connection(&cli, 0)) {
4612                 return False;
4613         }
4614
4615         smbXcli_conn_set_sockopt(cli->conn, sockops);
4616
4617         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4618
4619         if (!torture_close_connection(cli)) {
4620                 correct = False;
4621         }
4622
4623         return correct;
4624 }
4625
4626
4627
4628 /* FIRST_DESIRED_ACCESS   0xf019f */
4629 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4630                                FILE_READ_EA|                           /* 0xf */ \
4631                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4632                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4633                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4634                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4635 /* SECOND_DESIRED_ACCESS  0xe0080 */
4636 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4637                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4638                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4639
4640 #if 0
4641 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4642                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4643                                FILE_READ_DATA|\
4644                                WRITE_OWNER_ACCESS                      /* */
4645 #endif
4646
4647 /*
4648   Test ntcreate calls made by xcopy
4649  */
4650 static bool run_xcopy(int dummy)
4651 {
4652         static struct cli_state *cli1;
4653         const char *fname = "\\test.txt";
4654         bool correct = True;
4655         uint16_t fnum1, fnum2;
4656         NTSTATUS status;
4657
4658         printf("starting xcopy test\n");
4659
4660         if (!torture_open_connection(&cli1, 0)) {
4661                 return False;
4662         }
4663
4664         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4665                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4666                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4667         if (!NT_STATUS_IS_OK(status)) {
4668                 printf("First open failed - %s\n", nt_errstr(status));
4669                 return False;
4670         }
4671
4672         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4673                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4674                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4675         if (!NT_STATUS_IS_OK(status)) {
4676                 printf("second open failed - %s\n", nt_errstr(status));
4677                 return False;
4678         }
4679
4680         if (!torture_close_connection(cli1)) {
4681                 correct = False;
4682         }
4683
4684         return correct;
4685 }
4686
4687 /*
4688   Test rename on files open with share delete and no share delete.
4689  */
4690 static bool run_rename(int dummy)
4691 {
4692         static struct cli_state *cli1;
4693         const char *fname = "\\test.txt";
4694         const char *fname1 = "\\test1.txt";
4695         bool correct = True;
4696         uint16_t fnum1;
4697         uint16_t attr;
4698         NTSTATUS status;
4699
4700         printf("starting rename test\n");
4701
4702         if (!torture_open_connection(&cli1, 0)) {
4703                 return False;
4704         }
4705
4706         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4707         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4708
4709         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4710                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4711                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4712         if (!NT_STATUS_IS_OK(status)) {
4713                 printf("First open failed - %s\n", nt_errstr(status));
4714                 return False;
4715         }
4716
4717         status = cli_rename(cli1, fname, fname1, false);
4718         if (!NT_STATUS_IS_OK(status)) {
4719                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4720         } else {
4721                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4722                 correct = False;
4723         }
4724
4725         status = cli_close(cli1, fnum1);
4726         if (!NT_STATUS_IS_OK(status)) {
4727                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4728                 return False;
4729         }
4730
4731         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4733         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4734 #if 0
4735                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4736 #else
4737                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4738 #endif
4739                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4740         if (!NT_STATUS_IS_OK(status)) {
4741                 printf("Second open failed - %s\n", nt_errstr(status));
4742                 return False;
4743         }
4744
4745         status = cli_rename(cli1, fname, fname1, false);
4746         if (!NT_STATUS_IS_OK(status)) {
4747                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4748                 correct = False;
4749         } else {
4750                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4751         }
4752
4753         status = cli_close(cli1, fnum1);
4754         if (!NT_STATUS_IS_OK(status)) {
4755                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4756                 return False;
4757         }
4758
4759         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4760         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4761
4762         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4763                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4764                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4765         if (!NT_STATUS_IS_OK(status)) {
4766                 printf("Third open failed - %s\n", nt_errstr(status));
4767                 return False;
4768         }
4769
4770
4771 #if 0
4772   {
4773         uint16_t fnum2;
4774
4775         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4776                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4777                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4778                 return False;
4779         }
4780         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4781                 printf("[8] setting delete_on_close on file failed !\n");
4782                 return False;
4783         }
4784
4785         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4786                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4787                 return False;
4788         }
4789   }
4790 #endif
4791
4792         status = cli_rename(cli1, fname, fname1, false);
4793         if (!NT_STATUS_IS_OK(status)) {
4794                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4795                 correct = False;
4796         } else {
4797                 printf("Third rename succeeded (SHARE_NONE)\n");
4798         }
4799
4800         status = cli_close(cli1, fnum1);
4801         if (!NT_STATUS_IS_OK(status)) {
4802                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4803                 return False;
4804         }
4805
4806         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4807         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4808
4809         /*----*/
4810
4811         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4812                               FILE_ATTRIBUTE_NORMAL,
4813                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4814                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4815         if (!NT_STATUS_IS_OK(status)) {
4816                 printf("Fourth open failed - %s\n", nt_errstr(status));
4817                 return False;
4818         }
4819
4820         status = cli_rename(cli1, fname, fname1, false);
4821         if (!NT_STATUS_IS_OK(status)) {
4822                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4823         } else {
4824                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4825                 correct = False;
4826         }
4827
4828         status = cli_close(cli1, fnum1);
4829         if (!NT_STATUS_IS_OK(status)) {
4830                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4831                 return False;
4832         }
4833
4834         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4835         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4836
4837         /*--*/
4838
4839         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4840                          FILE_ATTRIBUTE_NORMAL,
4841                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4842                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4843         if (!NT_STATUS_IS_OK(status)) {
4844                 printf("Fifth open failed - %s\n", nt_errstr(status));
4845                 return False;
4846         }
4847
4848         status = cli_rename(cli1, fname, fname1, false);
4849         if (!NT_STATUS_IS_OK(status)) {
4850                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4851                 correct = False;
4852         } else {
4853                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4854         }
4855
4856         /*
4857          * Now check if the first name still exists ...
4858          */
4859
4860         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4861                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4862                                    FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4863           printf("Opening original file after rename of open file fails: %s\n",
4864               cli_errstr(cli1));
4865         }
4866         else {
4867           printf("Opening original file after rename of open file works ...\n");
4868           (void)cli_close(cli1, fnum2);
4869           } */
4870
4871         /*--*/
4872         status = cli_close(cli1, fnum1);
4873         if (!NT_STATUS_IS_OK(status)) {
4874                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4875                 return False;
4876         }
4877
4878         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4879         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4880         if (!NT_STATUS_IS_OK(status)) {
4881                 printf("getatr on file %s failed - %s ! \n",
4882                         fname1, nt_errstr(status));
4883                 correct = False;
4884         } else {
4885                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4886                         printf("Renamed file %s has wrong attr 0x%x "
4887                                 "(should be 0x%x)\n",
4888                                 fname1,
4889                                 attr,
4890                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4891                         correct = False;
4892                 } else {
4893                         printf("Renamed file %s has archive bit set\n", fname1);
4894                 }
4895         }
4896
4897         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4898         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4899
4900         if (!torture_close_connection(cli1)) {
4901                 correct = False;
4902         }
4903
4904         return correct;
4905 }
4906
4907 /*
4908   Test rename into a directory with an ACL denying it.
4909  */
4910 static bool run_rename_access(int dummy)
4911 {
4912         static struct cli_state *cli = NULL;
4913         static struct cli_state *posix_cli = NULL;
4914         const char *src = "test.txt";
4915         const char *dname = "dir";
4916         const char *dst = "dir\\test.txt";
4917         const char *dsrc = "test.dir";
4918         const char *ddst = "dir\\test.dir";
4919         uint16_t fnum = (uint16_t)-1;
4920         struct security_descriptor *sd = NULL;
4921         struct security_descriptor *newsd = NULL;
4922         NTSTATUS status;
4923         TALLOC_CTX *frame = NULL;
4924
4925         frame = talloc_stackframe();
4926         printf("starting rename access test\n");
4927
4928         /* Windows connection. */
4929         if (!torture_open_connection(&cli, 0)) {
4930                 goto fail;
4931         }
4932
4933         smbXcli_conn_set_sockopt(cli->conn, sockops);
4934
4935         /* Posix connection. */
4936         if (!torture_open_connection(&posix_cli, 0)) {
4937                 goto fail;
4938         }
4939
4940         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
4941
4942         status = torture_setup_unix_extensions(posix_cli);
4943         if (!NT_STATUS_IS_OK(status)) {
4944                 goto fail;
4945         }
4946
4947         /* Start with a clean slate. */
4948         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4949         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4950         cli_rmdir(cli, dsrc);
4951         cli_rmdir(cli, ddst);
4952         cli_rmdir(cli, dname);
4953
4954         /*
4955          * Setup the destination directory with a DENY ACE to
4956          * prevent new files within it.
4957          */
4958         status = cli_ntcreate(cli,
4959                                 dname,
4960                                 0,
4961                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
4962                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
4963                                         WRITE_OWNER_ACCESS,
4964                                 FILE_ATTRIBUTE_DIRECTORY,
4965                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
4966                                 FILE_CREATE,
4967                                 FILE_DIRECTORY_FILE,
4968                                 0,
4969                                 &fnum,
4970                                 NULL);
4971         if (!NT_STATUS_IS_OK(status)) {
4972                 printf("Create of %s - %s\n", dname, nt_errstr(status));
4973                 goto fail;
4974         }
4975
4976         status = cli_query_secdesc(cli,
4977                                 fnum,
4978                                 frame,
4979                                 &sd);
4980         if (!NT_STATUS_IS_OK(status)) {
4981                 printf("cli_query_secdesc failed for %s (%s)\n",
4982                         dname, nt_errstr(status));
4983                 goto fail;
4984         }
4985
4986         newsd = security_descriptor_dacl_create(frame,
4987                                         0,
4988                                         NULL,
4989                                         NULL,
4990                                         SID_WORLD,
4991                                         SEC_ACE_TYPE_ACCESS_DENIED,
4992                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
4993                                         0,
4994                                         NULL);
4995         if (newsd == NULL) {
4996                 goto fail;
4997         }
4998         sd->dacl = security_acl_concatenate(frame,
4999                                         newsd->dacl,
5000                                         sd->dacl);
5001         if (sd->dacl == NULL) {
5002                 goto fail;
5003         }
5004         status = cli_set_secdesc(cli, fnum, sd);
5005         if (!NT_STATUS_IS_OK(status)) {
5006                 printf("cli_set_secdesc failed for %s (%s)\n",
5007                         dname, nt_errstr(status));
5008                 goto fail;
5009         }
5010         status = cli_close(cli, fnum);
5011         if (!NT_STATUS_IS_OK(status)) {
5012                 printf("close failed for %s (%s)\n",
5013                         dname, nt_errstr(status));
5014                 goto fail;
5015         }
5016         /* Now go around the back and chmod to 777 via POSIX. */
5017         status = cli_posix_chmod(posix_cli, dname, 0777);
5018         if (!NT_STATUS_IS_OK(status)) {
5019                 printf("cli_posix_chmod failed for %s (%s)\n",
5020                         dname, nt_errstr(status));
5021                 goto fail;
5022         }
5023
5024         /* Check we can't create a file within dname via Windows. */
5025         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5026         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5027                 cli_close(posix_cli, fnum);
5028                 printf("Create of %s should be ACCESS denied, was %s\n",
5029                         dst, nt_errstr(status));
5030                 goto fail;
5031         }
5032
5033         /* Make the sample file/directory. */
5034         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5035         if (!NT_STATUS_IS_OK(status)) {
5036                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5037                 goto fail;
5038         }
5039         status = cli_close(cli, fnum);
5040         if (!NT_STATUS_IS_OK(status)) {
5041                 printf("cli_close failed (%s)\n", nt_errstr(status));
5042                 goto fail;
5043         }
5044
5045         status = cli_mkdir(cli, dsrc);
5046         if (!NT_STATUS_IS_OK(status)) {
5047                 printf("cli_mkdir of %s failed (%s)\n",
5048                         dsrc, nt_errstr(status));
5049                 goto fail;
5050         }
5051
5052         /*
5053          * OK - renames of the new file and directory into the
5054          * dst directory should fail.
5055          */
5056
5057         status = cli_rename(cli, src, dst, false);
5058         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5059                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5060                         src, dst, nt_errstr(status));
5061                 goto fail;
5062         }
5063         status = cli_rename(cli, dsrc, ddst, false);
5064         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5065                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5066                         src, dst, nt_errstr(status));
5067                 goto fail;
5068         }
5069
5070         TALLOC_FREE(frame);
5071         return true;
5072
5073   fail:
5074
5075         if (posix_cli) {
5076                 torture_close_connection(posix_cli);
5077         }
5078
5079         if (cli) {
5080                 if (fnum != (uint64_t)-1) {
5081                         cli_close(cli, fnum);
5082                 }
5083                 cli_unlink(cli, src,
5084                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5085                 cli_unlink(cli, dst,
5086                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5087                 cli_rmdir(cli, dsrc);
5088                 cli_rmdir(cli, ddst);
5089                 cli_rmdir(cli, dname);
5090
5091                 torture_close_connection(cli);
5092         }
5093
5094         TALLOC_FREE(frame);
5095         return false;
5096 }
5097
5098 /*
5099   Test owner rights ACE.
5100  */
5101 static bool run_owner_rights(int dummy)
5102 {
5103         static struct cli_state *cli = NULL;
5104         const char *fname = "owner_rights.txt";
5105         uint16_t fnum = (uint16_t)-1;
5106         struct security_descriptor *sd = NULL;
5107         struct security_descriptor *newsd = NULL;
5108         NTSTATUS status;
5109         TALLOC_CTX *frame = NULL;
5110
5111         frame = talloc_stackframe();
5112         printf("starting owner rights test\n");
5113
5114         /* Windows connection. */
5115         if (!torture_open_connection(&cli, 0)) {
5116                 goto fail;
5117         }
5118
5119         smbXcli_conn_set_sockopt(cli->conn, sockops);
5120
5121         /* Start with a clean slate. */
5122         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5123
5124         /* Create the test file. */
5125         /* Now try and open for read and write-dac. */
5126         status = cli_ntcreate(cli,
5127                                 fname,
5128                                 0,
5129                                 GENERIC_ALL_ACCESS,
5130                                 FILE_ATTRIBUTE_NORMAL,
5131                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5132                                         FILE_SHARE_DELETE,
5133                                 FILE_CREATE,
5134                                 0,
5135                                 0,
5136                                 &fnum,
5137                                 NULL);
5138         if (!NT_STATUS_IS_OK(status)) {
5139                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5140                 goto fail;
5141         }
5142
5143         /* Get the original SD. */
5144         status = cli_query_secdesc(cli,
5145                                 fnum,
5146                                 frame,
5147                                 &sd);
5148         if (!NT_STATUS_IS_OK(status)) {
5149                 printf("cli_query_secdesc failed for %s (%s)\n",
5150                         fname, nt_errstr(status));
5151                 goto fail;
5152         }
5153
5154         /*
5155          * Add an "owner-rights" ACE denying WRITE_DATA,
5156          * and an "owner-rights" ACE allowing READ_DATA.
5157          */
5158
5159         newsd = security_descriptor_dacl_create(frame,
5160                                         0,
5161                                         NULL,
5162                                         NULL,
5163                                         SID_OWNER_RIGHTS,
5164                                         SEC_ACE_TYPE_ACCESS_DENIED,
5165                                         FILE_WRITE_DATA,
5166                                         0,
5167                                         SID_OWNER_RIGHTS,
5168                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5169                                         FILE_READ_DATA,
5170                                         0,
5171                                         NULL);
5172         if (newsd == NULL) {
5173                 goto fail;
5174         }
5175         sd->dacl = security_acl_concatenate(frame,
5176                                         newsd->dacl,
5177                                         sd->dacl);
5178         if (sd->dacl == NULL) {
5179                 goto fail;
5180         }
5181         status = cli_set_secdesc(cli, fnum, sd);
5182         if (!NT_STATUS_IS_OK(status)) {
5183                 printf("cli_set_secdesc failed for %s (%s)\n",
5184                         fname, nt_errstr(status));
5185                 goto fail;
5186         }
5187         status = cli_close(cli, fnum);
5188         if (!NT_STATUS_IS_OK(status)) {
5189                 printf("close failed for %s (%s)\n",
5190                         fname, nt_errstr(status));
5191                 goto fail;
5192         }
5193         fnum = (uint16_t)-1;
5194
5195         /* Try and open for FILE_WRITE_DATA */
5196         status = cli_ntcreate(cli,
5197                                 fname,
5198                                 0,
5199                                 FILE_WRITE_DATA,
5200                                 FILE_ATTRIBUTE_NORMAL,
5201                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5202                                         FILE_SHARE_DELETE,
5203                                 FILE_OPEN,
5204                                 0,
5205                                 0,
5206                                 &fnum,
5207                                 NULL);
5208         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5209                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5210                 goto fail;
5211         }
5212
5213         /* Now try and open for FILE_READ_DATA */
5214         status = cli_ntcreate(cli,
5215                                 fname,
5216                                 0,
5217                                 FILE_READ_DATA,
5218                                 FILE_ATTRIBUTE_NORMAL,
5219                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5220                                         FILE_SHARE_DELETE,
5221                                 FILE_OPEN,
5222                                 0,
5223                                 0,
5224                                 &fnum,
5225                                 NULL);
5226         if (!NT_STATUS_IS_OK(status)) {
5227                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5228                 goto fail;
5229         }
5230
5231         status = cli_close(cli, fnum);
5232         if (!NT_STATUS_IS_OK(status)) {
5233                 printf("close failed for %s (%s)\n",
5234                         fname, nt_errstr(status));
5235                 goto fail;
5236         }
5237
5238         /* Restore clean slate. */
5239         TALLOC_FREE(sd);
5240         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5241
5242         /* Create the test file. */
5243         status = cli_ntcreate(cli,
5244                                 fname,
5245                                 0,
5246                                 GENERIC_ALL_ACCESS,
5247                                 FILE_ATTRIBUTE_NORMAL,
5248                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5249                                         FILE_SHARE_DELETE,
5250                                 FILE_CREATE,
5251                                 0,
5252                                 0,
5253                                 &fnum,
5254                                 NULL);
5255         if (!NT_STATUS_IS_OK(status)) {
5256                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5257                 goto fail;
5258         }
5259
5260         /* Get the original SD. */
5261         status = cli_query_secdesc(cli,
5262                                 fnum,
5263                                 frame,
5264                                 &sd);
5265         if (!NT_STATUS_IS_OK(status)) {
5266                 printf("cli_query_secdesc failed for %s (%s)\n",
5267                         fname, nt_errstr(status));
5268                 goto fail;
5269         }
5270
5271         /*
5272          * Add an "owner-rights ACE denying WRITE_DATA,
5273          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5274          */
5275
5276         newsd = security_descriptor_dacl_create(frame,
5277                                         0,
5278                                         NULL,
5279                                         NULL,
5280                                         SID_OWNER_RIGHTS,
5281                                         SEC_ACE_TYPE_ACCESS_DENIED,
5282                                         FILE_WRITE_DATA,
5283                                         0,
5284                                         SID_OWNER_RIGHTS,
5285                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5286                                         FILE_READ_DATA|FILE_WRITE_DATA,
5287                                         0,
5288                                         NULL);
5289         if (newsd == NULL) {
5290                 goto fail;
5291         }
5292         sd->dacl = security_acl_concatenate(frame,
5293                                         newsd->dacl,
5294                                         sd->dacl);
5295         if (sd->dacl == NULL) {
5296                 goto fail;
5297         }
5298         status = cli_set_secdesc(cli, fnum, sd);
5299         if (!NT_STATUS_IS_OK(status)) {
5300                 printf("cli_set_secdesc failed for %s (%s)\n",
5301                         fname, nt_errstr(status));
5302                 goto fail;
5303         }
5304         status = cli_close(cli, fnum);
5305         if (!NT_STATUS_IS_OK(status)) {
5306                 printf("close failed for %s (%s)\n",
5307                         fname, nt_errstr(status));
5308                 goto fail;
5309         }
5310         fnum = (uint16_t)-1;
5311
5312         /* Try and open for FILE_WRITE_DATA */
5313         status = cli_ntcreate(cli,
5314                                 fname,
5315                                 0,
5316                                 FILE_WRITE_DATA,
5317                                 FILE_ATTRIBUTE_NORMAL,
5318                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5319                                         FILE_SHARE_DELETE,
5320                                 FILE_OPEN,
5321                                 0,
5322                                 0,
5323                                 &fnum,
5324                                 NULL);
5325         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5326                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5327                 goto fail;
5328         }
5329
5330         /* Now try and open for FILE_READ_DATA */
5331         status = cli_ntcreate(cli,
5332                                 fname,
5333                                 0,
5334                                 FILE_READ_DATA,
5335                                 FILE_ATTRIBUTE_NORMAL,
5336                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5337                                         FILE_SHARE_DELETE,
5338                                 FILE_OPEN,
5339                                 0,
5340                                 0,
5341                                 &fnum,
5342                                 NULL);
5343         if (!NT_STATUS_IS_OK(status)) {
5344                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5345                 goto fail;
5346         }
5347
5348         status = cli_close(cli, fnum);
5349         if (!NT_STATUS_IS_OK(status)) {
5350                 printf("close failed for %s (%s)\n",
5351                         fname, nt_errstr(status));
5352                 goto fail;
5353         }
5354
5355         /* Restore clean slate. */
5356         TALLOC_FREE(sd);
5357         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5358
5359
5360         /* Create the test file. */
5361         status = cli_ntcreate(cli,
5362                                 fname,
5363                                 0,
5364                                 GENERIC_ALL_ACCESS,
5365                                 FILE_ATTRIBUTE_NORMAL,
5366                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5367                                         FILE_SHARE_DELETE,
5368                                 FILE_CREATE,
5369                                 0,
5370                                 0,
5371                                 &fnum,
5372                                 NULL);
5373         if (!NT_STATUS_IS_OK(status)) {
5374                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5375                 goto fail;
5376         }
5377
5378         /* Get the original SD. */
5379         status = cli_query_secdesc(cli,
5380                                 fnum,
5381                                 frame,
5382                                 &sd);
5383         if (!NT_STATUS_IS_OK(status)) {
5384                 printf("cli_query_secdesc failed for %s (%s)\n",
5385                         fname, nt_errstr(status));
5386                 goto fail;
5387         }
5388
5389         /*
5390          * Add an "authenticated users" ACE allowing READ_DATA,
5391          * add an "owner-rights" denying READ_DATA,
5392          * and an "authenticated users" ACE allowing WRITE_DATA.
5393          */
5394
5395         newsd = security_descriptor_dacl_create(frame,
5396                                         0,
5397                                         NULL,
5398                                         NULL,
5399                                         SID_NT_AUTHENTICATED_USERS,
5400                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5401                                         FILE_READ_DATA,
5402                                         0,
5403                                         SID_OWNER_RIGHTS,
5404                                         SEC_ACE_TYPE_ACCESS_DENIED,
5405                                         FILE_READ_DATA,
5406                                         0,
5407                                         SID_NT_AUTHENTICATED_USERS,
5408                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5409                                         FILE_WRITE_DATA,
5410                                         0,
5411                                         NULL);
5412         if (newsd == NULL) {
5413                 printf("newsd == NULL\n");
5414                 goto fail;
5415         }
5416         sd->dacl = security_acl_concatenate(frame,
5417                                         newsd->dacl,
5418                                         sd->dacl);
5419         if (sd->dacl == NULL) {
5420                 printf("sd->dacl == NULL\n");
5421                 goto fail;
5422         }
5423         status = cli_set_secdesc(cli, fnum, sd);
5424         if (!NT_STATUS_IS_OK(status)) {
5425                 printf("cli_set_secdesc failed for %s (%s)\n",
5426                         fname, nt_errstr(status));
5427                 goto fail;
5428         }
5429         status = cli_close(cli, fnum);
5430         if (!NT_STATUS_IS_OK(status)) {
5431                 printf("close failed for %s (%s)\n",
5432                         fname, nt_errstr(status));
5433                 goto fail;
5434         }
5435         fnum = (uint16_t)-1;
5436
5437         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5438         status = cli_ntcreate(cli,
5439                                 fname,
5440                                 0,
5441                                 FILE_READ_DATA|FILE_WRITE_DATA,
5442                                 FILE_ATTRIBUTE_NORMAL,
5443                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5444                                         FILE_SHARE_DELETE,
5445                                 FILE_OPEN,
5446                                 0,
5447                                 0,
5448                                 &fnum,
5449                                 NULL);
5450         if (!NT_STATUS_IS_OK(status)) {
5451                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5452                 goto fail;
5453         }
5454
5455         status = cli_close(cli, fnum);
5456         if (!NT_STATUS_IS_OK(status)) {
5457                 printf("close failed for %s (%s)\n",
5458                         fname, nt_errstr(status));
5459                 goto fail;
5460         }
5461
5462         cli_unlink(cli, fname,
5463                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5464
5465         TALLOC_FREE(frame);
5466         return true;
5467
5468   fail:
5469
5470         if (cli) {
5471                 if (fnum != (uint16_t)-1) {
5472                         cli_close(cli, fnum);
5473                 }
5474                 cli_unlink(cli, fname,
5475                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5476                 torture_close_connection(cli);
5477         }
5478
5479         TALLOC_FREE(frame);
5480         return false;
5481 }
5482
5483 static bool run_pipe_number(int dummy)
5484 {
5485         struct cli_state *cli1;
5486         const char *pipe_name = "\\SPOOLSS";
5487         uint16_t fnum;
5488         int num_pipes = 0;
5489         NTSTATUS status;
5490
5491         printf("starting pipenumber test\n");
5492         if (!torture_open_connection(&cli1, 0)) {
5493                 return False;
5494         }
5495
5496         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5497         while(1) {
5498                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5499                                       FILE_ATTRIBUTE_NORMAL,
5500                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
5501                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
5502                 if (!NT_STATUS_IS_OK(status)) {
5503                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5504                         break;
5505                 }
5506                 num_pipes++;
5507                 printf("\r%6d", num_pipes);
5508         }
5509
5510         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5511         torture_close_connection(cli1);
5512         return True;
5513 }
5514
5515 /*
5516   Test open mode returns on read-only files.
5517  */
5518 static bool run_opentest(int dummy)
5519 {
5520         static struct cli_state *cli1;
5521         static struct cli_state *cli2;
5522         const char *fname = "\\readonly.file";
5523         uint16_t fnum1, fnum2;
5524         char buf[20];
5525         off_t fsize;
5526         bool correct = True;
5527         char *tmp_path;
5528         NTSTATUS status;
5529
5530         printf("starting open test\n");
5531
5532         if (!torture_open_connection(&cli1, 0)) {
5533                 return False;
5534         }
5535
5536         cli_setatr(cli1, fname, 0, 0);
5537         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5538
5539         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5540
5541         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5542         if (!NT_STATUS_IS_OK(status)) {
5543                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5544                 return False;
5545         }
5546
5547         status = cli_close(cli1, fnum1);
5548         if (!NT_STATUS_IS_OK(status)) {
5549                 printf("close2 failed (%s)\n", nt_errstr(status));
5550                 return False;
5551         }
5552
5553         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5556                 return False;
5557         }
5558
5559         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5560         if (!NT_STATUS_IS_OK(status)) {
5561                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5562                 return False;
5563         }
5564
5565         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5566         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5567
5568         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5569                         NT_STATUS_ACCESS_DENIED)) {
5570                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5571         }
5572
5573         printf("finished open test 1\n");
5574
5575         cli_close(cli1, fnum1);
5576
5577         /* Now try not readonly and ensure ERRbadshare is returned. */
5578
5579         cli_setatr(cli1, fname, 0, 0);
5580
5581         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5582         if (!NT_STATUS_IS_OK(status)) {
5583                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5584                 return False;
5585         }
5586
5587         /* This will fail - but the error should be ERRshare. */
5588         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5589
5590         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5591                         NT_STATUS_SHARING_VIOLATION)) {
5592                 printf("correct error code ERRDOS/ERRbadshare returned\n");
5593         }
5594
5595         status = cli_close(cli1, fnum1);
5596         if (!NT_STATUS_IS_OK(status)) {
5597                 printf("close2 failed (%s)\n", nt_errstr(status));
5598                 return False;
5599         }
5600
5601         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5602
5603         printf("finished open test 2\n");
5604
5605         /* Test truncate open disposition on file opened for read. */
5606         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5607         if (!NT_STATUS_IS_OK(status)) {
5608                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5609                 return False;
5610         }
5611
5612         /* write 20 bytes. */
5613
5614         memset(buf, '\0', 20);
5615
5616         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5617         if (!NT_STATUS_IS_OK(status)) {
5618                 printf("write failed (%s)\n", nt_errstr(status));
5619                 correct = False;
5620         }
5621
5622         status = cli_close(cli1, fnum1);
5623         if (!NT_STATUS_IS_OK(status)) {
5624                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5625                 return False;
5626         }
5627
5628         /* Ensure size == 20. */
5629         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5630         if (!NT_STATUS_IS_OK(status)) {
5631                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5632                 return False;
5633         }
5634
5635         if (fsize != 20) {
5636                 printf("(3) file size != 20\n");
5637                 return False;
5638         }
5639
5640         /* Now test if we can truncate a file opened for readonly. */
5641         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5642         if (!NT_STATUS_IS_OK(status)) {
5643                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5644                 return False;
5645         }
5646
5647         status = cli_close(cli1, fnum1);
5648         if (!NT_STATUS_IS_OK(status)) {
5649                 printf("close2 failed (%s)\n", nt_errstr(status));
5650                 return False;
5651         }
5652
5653         /* Ensure size == 0. */
5654         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5655         if (!NT_STATUS_IS_OK(status)) {
5656                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5657                 return False;
5658         }
5659
5660         if (fsize != 0) {
5661                 printf("(3) file size != 0\n");
5662                 return False;
5663         }
5664         printf("finished open test 3\n");
5665
5666         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5667
5668         printf("Do ctemp tests\n");
5669         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5670         if (!NT_STATUS_IS_OK(status)) {
5671                 printf("ctemp failed (%s)\n", nt_errstr(status));
5672                 return False;
5673         }
5674
5675         printf("ctemp gave path %s\n", tmp_path);
5676         status = cli_close(cli1, fnum1);
5677         if (!NT_STATUS_IS_OK(status)) {
5678                 printf("close of temp failed (%s)\n", nt_errstr(status));
5679         }
5680
5681         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5682         if (!NT_STATUS_IS_OK(status)) {
5683                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5684         }
5685
5686         /* Test the non-io opens... */
5687
5688         if (!torture_open_connection(&cli2, 1)) {
5689                 return False;
5690         }
5691
5692         cli_setatr(cli2, fname, 0, 0);
5693         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5694
5695         smbXcli_conn_set_sockopt(cli2->conn, sockops);
5696
5697         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5698         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5699                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5700                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5701         if (!NT_STATUS_IS_OK(status)) {
5702                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5703                 return False;
5704         }
5705
5706         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5707                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5708                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5709         if (!NT_STATUS_IS_OK(status)) {
5710                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5711                 return False;
5712         }
5713
5714         status = cli_close(cli1, fnum1);
5715         if (!NT_STATUS_IS_OK(status)) {
5716                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5717                 return False;
5718         }
5719
5720         status = cli_close(cli2, fnum2);
5721         if (!NT_STATUS_IS_OK(status)) {
5722                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5723                 return False;
5724         }
5725
5726         printf("non-io open test #1 passed.\n");
5727
5728         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5729
5730         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5731
5732         status = cli_ntcreate(cli1, fname, 0,
5733                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5734                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5735                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5736         if (!NT_STATUS_IS_OK(status)) {
5737                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5738                 return False;
5739         }
5740
5741         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5742                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5743                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5744         if (!NT_STATUS_IS_OK(status)) {
5745                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5746                 return False;
5747         }
5748
5749         status = cli_close(cli1, fnum1);
5750         if (!NT_STATUS_IS_OK(status)) {
5751                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5752                 return False;
5753         }
5754
5755         status = cli_close(cli2, fnum2);
5756         if (!NT_STATUS_IS_OK(status)) {
5757                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5758                 return False;
5759         }
5760
5761         printf("non-io open test #2 passed.\n");
5762
5763         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5764
5765         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5766
5767         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5768                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5769                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5770         if (!NT_STATUS_IS_OK(status)) {
5771                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5772                 return False;
5773         }
5774
5775         status = cli_ntcreate(cli2, fname, 0,
5776                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5777                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5778                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5779         if (!NT_STATUS_IS_OK(status)) {
5780                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5781                 return False;
5782         }
5783
5784         status = cli_close(cli1, fnum1);
5785         if (!NT_STATUS_IS_OK(status)) {
5786                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5787                 return False;
5788         }
5789
5790         status = cli_close(cli2, fnum2);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5793                 return False;
5794         }
5795
5796         printf("non-io open test #3 passed.\n");
5797
5798         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5799
5800         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5801
5802         status = cli_ntcreate(cli1, fname, 0,
5803                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5804                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5805                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5806         if (!NT_STATUS_IS_OK(status)) {
5807                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5808                 return False;
5809         }
5810
5811         status = cli_ntcreate(cli2, fname, 0,
5812                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5813                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5814                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5815         if (NT_STATUS_IS_OK(status)) {
5816                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5817                 return False;
5818         }
5819
5820         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5821
5822         status = cli_close(cli1, fnum1);
5823         if (!NT_STATUS_IS_OK(status)) {
5824                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5825                 return False;
5826         }
5827
5828         printf("non-io open test #4 passed.\n");
5829
5830         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5831
5832         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5833
5834         status = cli_ntcreate(cli1, fname, 0,
5835                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5836                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5837                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5838         if (!NT_STATUS_IS_OK(status)) {
5839                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5840                 return False;
5841         }
5842
5843         status = cli_ntcreate(cli2, fname, 0,
5844                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5845                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5846                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5847         if (!NT_STATUS_IS_OK(status)) {
5848                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5849                 return False;
5850         }
5851
5852         status = cli_close(cli1, fnum1);
5853         if (!NT_STATUS_IS_OK(status)) {
5854                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5855                 return False;
5856         }
5857
5858         status = cli_close(cli2, fnum2);
5859         if (!NT_STATUS_IS_OK(status)) {
5860                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5861                 return False;
5862         }
5863
5864         printf("non-io open test #5 passed.\n");
5865
5866         printf("TEST #6 testing 1 non-io open, one io open\n");
5867
5868         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5869
5870         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5871                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5872                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5873         if (!NT_STATUS_IS_OK(status)) {
5874                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5875                 return False;
5876         }
5877
5878         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5879                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5880                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5881         if (!NT_STATUS_IS_OK(status)) {
5882                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5883                 return False;
5884         }
5885
5886         status = cli_close(cli1, fnum1);
5887         if (!NT_STATUS_IS_OK(status)) {
5888                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5889                 return False;
5890         }
5891
5892         status = cli_close(cli2, fnum2);
5893         if (!NT_STATUS_IS_OK(status)) {
5894                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5895                 return False;
5896         }
5897
5898         printf("non-io open test #6 passed.\n");
5899
5900         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5901
5902         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5903
5904         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5905                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5906                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5907         if (!NT_STATUS_IS_OK(status)) {
5908                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5909                 return False;
5910         }
5911
5912         status = cli_ntcreate(cli2, fname, 0,
5913                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5914                               FILE_ATTRIBUTE_NORMAL,
5915                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5916                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5917         if (NT_STATUS_IS_OK(status)) {
5918                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5919                 return False;
5920         }
5921
5922         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5923
5924         status = cli_close(cli1, fnum1);
5925         if (!NT_STATUS_IS_OK(status)) {
5926                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5927                 return False;
5928         }
5929
5930         printf("non-io open test #7 passed.\n");
5931
5932         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5933
5934         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5935         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5936                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5937                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5938         if (!NT_STATUS_IS_OK(status)) {
5939                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5940                 correct = false;
5941                 goto out;
5942         }
5943
5944         /* Write to ensure we have to update the file time. */
5945         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5946                               NULL);
5947         if (!NT_STATUS_IS_OK(status)) {
5948                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5949                 correct = false;
5950                 goto out;
5951         }
5952
5953         status = cli_close(cli1, fnum1);
5954         if (!NT_STATUS_IS_OK(status)) {
5955                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5956                 correct = false;
5957         }
5958
5959   out:
5960
5961         if (!torture_close_connection(cli1)) {
5962                 correct = False;
5963         }
5964         if (!torture_close_connection(cli2)) {
5965                 correct = False;
5966         }
5967
5968         return correct;
5969 }
5970
5971 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5972 {
5973         uint16_t major, minor;
5974         uint32_t caplow, caphigh;
5975         NTSTATUS status;
5976
5977         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5978                 printf("Server doesn't support UNIX CIFS extensions.\n");
5979                 return NT_STATUS_NOT_SUPPORTED;
5980         }
5981
5982         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5983                                              &caphigh);
5984         if (!NT_STATUS_IS_OK(status)) {
5985                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5986                        nt_errstr(status));
5987                 return status;
5988         }
5989
5990         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5991                                                       caplow, caphigh);
5992         if (!NT_STATUS_IS_OK(status)) {
5993                 printf("Server doesn't support setting UNIX CIFS extensions: "
5994                        "%s.\n", nt_errstr(status));
5995                 return status;
5996         }
5997
5998         return NT_STATUS_OK;
5999 }
6000
6001 /*
6002   Test POSIX open /mkdir calls.
6003  */
6004 static bool run_simple_posix_open_test(int dummy)
6005 {
6006         static struct cli_state *cli1;
6007         const char *fname = "posix:file";
6008         const char *hname = "posix:hlink";
6009         const char *sname = "posix:symlink";
6010         const char *dname = "posix:dir";
6011         char buf[10];
6012         char namebuf[11];
6013         uint16_t fnum1 = (uint16_t)-1;
6014         SMB_STRUCT_STAT sbuf;
6015         bool correct = false;
6016         NTSTATUS status;
6017         size_t nread;
6018         const char *fname_windows = "windows_file";
6019         uint16_t fnum2 = (uint16_t)-1;
6020
6021         printf("Starting simple POSIX open test\n");
6022
6023         if (!torture_open_connection(&cli1, 0)) {
6024                 return false;
6025         }
6026
6027         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6028
6029         status = torture_setup_unix_extensions(cli1);
6030         if (!NT_STATUS_IS_OK(status)) {
6031                 return false;
6032         }
6033
6034         cli_setatr(cli1, fname, 0, 0);
6035         cli_posix_unlink(cli1, fname);
6036         cli_setatr(cli1, dname, 0, 0);
6037         cli_posix_rmdir(cli1, dname);
6038         cli_setatr(cli1, hname, 0, 0);
6039         cli_posix_unlink(cli1, hname);
6040         cli_setatr(cli1, sname, 0, 0);
6041         cli_posix_unlink(cli1, sname);
6042         cli_setatr(cli1, fname_windows, 0, 0);
6043         cli_posix_unlink(cli1, fname_windows);
6044
6045         /* Create a directory. */
6046         status = cli_posix_mkdir(cli1, dname, 0777);
6047         if (!NT_STATUS_IS_OK(status)) {
6048                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6049                 goto out;
6050         }
6051
6052         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6053                                 0600, &fnum1);
6054         if (!NT_STATUS_IS_OK(status)) {
6055                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6056                 goto out;
6057         }
6058
6059         /* Test ftruncate - set file size. */
6060         status = cli_ftruncate(cli1, fnum1, 1000);
6061         if (!NT_STATUS_IS_OK(status)) {
6062                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6063                 goto out;
6064         }
6065
6066         /* Ensure st_size == 1000 */
6067         status = cli_posix_stat(cli1, fname, &sbuf);
6068         if (!NT_STATUS_IS_OK(status)) {
6069                 printf("stat failed (%s)\n", nt_errstr(status));
6070                 goto out;
6071         }
6072
6073         if (sbuf.st_ex_size != 1000) {
6074                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6075                 goto out;
6076         }
6077
6078         /* Ensure st_mode == 0600 */
6079         if ((sbuf.st_ex_mode & 07777) != 0600) {
6080                 printf("posix_open - bad permissions 0%o != 0600\n",
6081                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6082                 goto out;
6083         }
6084
6085         /* Test ftruncate - set file size back to zero. */
6086         status = cli_ftruncate(cli1, fnum1, 0);
6087         if (!NT_STATUS_IS_OK(status)) {
6088                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6089                 goto out;
6090         }
6091
6092         status = cli_close(cli1, fnum1);
6093         if (!NT_STATUS_IS_OK(status)) {
6094                 printf("close failed (%s)\n", nt_errstr(status));
6095                 goto out;
6096         }
6097
6098         /* Now open the file again for read only. */
6099         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6100         if (!NT_STATUS_IS_OK(status)) {
6101                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6102                 goto out;
6103         }
6104
6105         /* Now unlink while open. */
6106         status = cli_posix_unlink(cli1, fname);
6107         if (!NT_STATUS_IS_OK(status)) {
6108                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6109                 goto out;
6110         }
6111
6112         status = cli_close(cli1, fnum1);
6113         if (!NT_STATUS_IS_OK(status)) {
6114                 printf("close(2) failed (%s)\n", nt_errstr(status));
6115                 goto out;
6116         }
6117
6118         /* Ensure the file has gone. */
6119         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6120         if (NT_STATUS_IS_OK(status)) {
6121                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6122                 goto out;
6123         }
6124
6125         /* Create again to test open with O_TRUNC. */
6126         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6127         if (!NT_STATUS_IS_OK(status)) {
6128                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6129                 goto out;
6130         }
6131
6132         /* Test ftruncate - set file size. */
6133         status = cli_ftruncate(cli1, fnum1, 1000);
6134         if (!NT_STATUS_IS_OK(status)) {
6135                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6136                 goto out;
6137         }
6138
6139         /* Ensure st_size == 1000 */
6140         status = cli_posix_stat(cli1, fname, &sbuf);
6141         if (!NT_STATUS_IS_OK(status)) {
6142                 printf("stat failed (%s)\n", nt_errstr(status));
6143                 goto out;
6144         }
6145
6146         if (sbuf.st_ex_size != 1000) {
6147                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6148                 goto out;
6149         }
6150
6151         status = cli_close(cli1, fnum1);
6152         if (!NT_STATUS_IS_OK(status)) {
6153                 printf("close(2) failed (%s)\n", nt_errstr(status));
6154                 goto out;
6155         }
6156
6157         /* Re-open with O_TRUNC. */
6158         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6159         if (!NT_STATUS_IS_OK(status)) {
6160                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6161                 goto out;
6162         }
6163
6164         /* Ensure st_size == 0 */
6165         status = cli_posix_stat(cli1, fname, &sbuf);
6166         if (!NT_STATUS_IS_OK(status)) {
6167                 printf("stat failed (%s)\n", nt_errstr(status));
6168                 goto out;
6169         }
6170
6171         if (sbuf.st_ex_size != 0) {
6172                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6173                 goto out;
6174         }
6175
6176         status = cli_close(cli1, fnum1);
6177         if (!NT_STATUS_IS_OK(status)) {
6178                 printf("close failed (%s)\n", nt_errstr(status));
6179                 goto out;
6180         }
6181
6182         status = cli_posix_unlink(cli1, fname);
6183         if (!NT_STATUS_IS_OK(status)) {
6184                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6185                 goto out;
6186         }
6187
6188         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6189         if (!NT_STATUS_IS_OK(status)) {
6190                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6191                         dname, nt_errstr(status));
6192                 goto out;
6193         }
6194
6195         cli_close(cli1, fnum1);
6196
6197         /* What happens when we try and POSIX open a directory for write ? */
6198         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6199         if (NT_STATUS_IS_OK(status)) {
6200                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6201                 goto out;
6202         } else {
6203                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6204                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6205                         goto out;
6206                 }
6207         }
6208
6209         /* Create the file. */
6210         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6211                                 0600, &fnum1);
6212         if (!NT_STATUS_IS_OK(status)) {
6213                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6214                 goto out;
6215         }
6216
6217         /* Write some data into it. */
6218         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6219                               NULL);
6220         if (!NT_STATUS_IS_OK(status)) {
6221                 printf("cli_write failed: %s\n", nt_errstr(status));
6222                 goto out;
6223         }
6224
6225         cli_close(cli1, fnum1);
6226
6227         /* Now create a hardlink. */
6228         status = cli_posix_hardlink(cli1, fname, hname);
6229         if (!NT_STATUS_IS_OK(status)) {
6230                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6231                 goto out;
6232         }
6233
6234         /* Now create a symlink. */
6235         status = cli_posix_symlink(cli1, fname, sname);
6236         if (!NT_STATUS_IS_OK(status)) {
6237                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6238                 goto out;
6239         }
6240
6241         /* Open the hardlink for read. */
6242         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6243         if (!NT_STATUS_IS_OK(status)) {
6244                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6245                 goto out;
6246         }
6247
6248         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6249         if (!NT_STATUS_IS_OK(status)) {
6250                 printf("POSIX read of %s failed (%s)\n", hname,
6251                        nt_errstr(status));
6252                 goto out;
6253         } else if (nread != 10) {
6254                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6255                        hname, (unsigned long)nread, 10);
6256                 goto out;
6257         }
6258
6259         if (memcmp(buf, "TEST DATA\n", 10)) {
6260                 printf("invalid data read from hardlink\n");
6261                 goto out;
6262         }
6263
6264         /* Do a POSIX lock/unlock. */
6265         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6266         if (!NT_STATUS_IS_OK(status)) {
6267                 printf("POSIX lock failed %s\n", nt_errstr(status));
6268                 goto out;
6269         }
6270
6271         /* Punch a hole in the locked area. */
6272         status = cli_posix_unlock(cli1, fnum1, 10, 80);
6273         if (!NT_STATUS_IS_OK(status)) {
6274                 printf("POSIX unlock failed %s\n", nt_errstr(status));
6275                 goto out;
6276         }
6277
6278         cli_close(cli1, fnum1);
6279
6280         /* Open the symlink for read - this should fail. A POSIX
6281            client should not be doing opens on a symlink. */
6282         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6283         if (NT_STATUS_IS_OK(status)) {
6284                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6285                 goto out;
6286         } else {
6287                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6288                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6289                         printf("POSIX open of %s should have failed "
6290                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6291                                 "failed with %s instead.\n",
6292                                 sname, nt_errstr(status));
6293                         goto out;
6294                 }
6295         }
6296
6297         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6298         if (!NT_STATUS_IS_OK(status)) {
6299                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6300                 goto out;
6301         }
6302
6303         if (strcmp(namebuf, fname) != 0) {
6304                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6305                         sname, fname, namebuf);
6306                 goto out;
6307         }
6308
6309         status = cli_posix_rmdir(cli1, dname);
6310         if (!NT_STATUS_IS_OK(status)) {
6311                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6312                 goto out;
6313         }
6314
6315         /* Check directory opens with a specific permission. */
6316         status = cli_posix_mkdir(cli1, dname, 0700);
6317         if (!NT_STATUS_IS_OK(status)) {
6318                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6319                 goto out;
6320         }
6321
6322         /* Ensure st_mode == 0700 */
6323         status = cli_posix_stat(cli1, dname, &sbuf);
6324         if (!NT_STATUS_IS_OK(status)) {
6325                 printf("stat failed (%s)\n", nt_errstr(status));
6326                 goto out;
6327         }
6328
6329         if ((sbuf.st_ex_mode & 07777) != 0700) {
6330                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6331                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6332                 goto out;
6333         }
6334
6335         /*
6336          * Now create a Windows file, and attempt a POSIX unlink.
6337          * This should fail with a sharing violation but due to:
6338          *
6339          * [Bug 9571] Unlink after open causes smbd to panic
6340          *
6341          * ensure we've fixed the lock ordering violation.
6342          */
6343
6344         status = cli_ntcreate(cli1, fname_windows, 0,
6345                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
6346                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6347                         FILE_CREATE,
6348                         0x0, 0x0, &fnum2, NULL);
6349         if (!NT_STATUS_IS_OK(status)) {
6350                 printf("Windows create of %s failed (%s)\n", fname_windows,
6351                         nt_errstr(status));
6352                 goto out;
6353         }
6354
6355         /* Now try posix_unlink. */
6356         status = cli_posix_unlink(cli1, fname_windows);
6357         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6358                 printf("POSIX unlink of %s should fail "
6359                         "with NT_STATUS_SHARING_VIOLATION "
6360                         "got %s instead !\n",
6361                         fname_windows,
6362                         nt_errstr(status));
6363                 goto out;
6364         }
6365
6366         cli_close(cli1, fnum2);
6367
6368         printf("Simple POSIX open test passed\n");
6369         correct = true;
6370
6371   out:
6372
6373         if (fnum1 != (uint16_t)-1) {
6374                 cli_close(cli1, fnum1);
6375                 fnum1 = (uint16_t)-1;
6376         }
6377
6378         if (fnum2 != (uint16_t)-1) {
6379                 cli_close(cli1, fnum2);
6380                 fnum2 = (uint16_t)-1;
6381         }
6382
6383         cli_setatr(cli1, sname, 0, 0);
6384         cli_posix_unlink(cli1, sname);
6385         cli_setatr(cli1, hname, 0, 0);
6386         cli_posix_unlink(cli1, hname);
6387         cli_setatr(cli1, fname, 0, 0);
6388         cli_posix_unlink(cli1, fname);
6389         cli_setatr(cli1, dname, 0, 0);
6390         cli_posix_rmdir(cli1, dname);
6391         cli_setatr(cli1, fname_windows, 0, 0);
6392         cli_posix_unlink(cli1, fname_windows);
6393
6394         if (!torture_close_connection(cli1)) {
6395                 correct = false;
6396         }
6397
6398         return correct;
6399 }
6400
6401 /*
6402   Test POSIX and Windows ACLs are rejected on symlinks.
6403  */
6404 static bool run_acl_symlink_test(int dummy)
6405 {
6406         static struct cli_state *cli;
6407         const char *fname = "posix_file";
6408         const char *sname = "posix_symlink";
6409         uint16_t fnum = (uint16_t)-1;
6410         bool correct = false;
6411         NTSTATUS status;
6412         char *posix_acl = NULL;
6413         size_t posix_acl_len = 0;
6414         char *posix_acl_sym = NULL;
6415         size_t posix_acl_len_sym = 0;
6416         struct security_descriptor *sd = NULL;
6417         struct security_descriptor *sd_sym = NULL;
6418         TALLOC_CTX *frame = NULL;
6419
6420         frame = talloc_stackframe();
6421
6422         printf("Starting acl symlink test\n");
6423
6424         if (!torture_open_connection(&cli, 0)) {
6425                 TALLOC_FREE(frame);
6426                 return false;
6427         }
6428
6429         smbXcli_conn_set_sockopt(cli->conn, sockops);
6430
6431         status = torture_setup_unix_extensions(cli);
6432         if (!NT_STATUS_IS_OK(status)) {
6433                 TALLOC_FREE(frame);
6434                 return false;
6435         }
6436
6437         cli_setatr(cli, fname, 0, 0);
6438         cli_posix_unlink(cli, fname);
6439         cli_setatr(cli, sname, 0, 0);
6440         cli_posix_unlink(cli, sname);
6441
6442         status = cli_ntcreate(cli,
6443                         fname,
6444                         0,
6445                         READ_CONTROL_ACCESS,
6446                         0,
6447                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6448                         FILE_CREATE,
6449                         0x0,
6450                         0x0,
6451                         &fnum,
6452                         NULL);
6453
6454         if (!NT_STATUS_IS_OK(status)) {
6455                 printf("cli_ntcreate of %s failed (%s)\n",
6456                         fname,
6457                         nt_errstr(status));
6458                 goto out;
6459         }
6460
6461         /* Get the Windows ACL on the file. */
6462         status = cli_query_secdesc(cli,
6463                                 fnum,
6464                                 frame,
6465                                 &sd);
6466         if (!NT_STATUS_IS_OK(status)) {
6467                 printf("cli_query_secdesc failed (%s)\n",
6468                         nt_errstr(status));
6469                 goto out;
6470         }
6471
6472         /* Get the POSIX ACL on the file. */
6473         status = cli_posix_getacl(cli,
6474                                 fname,
6475                                 frame,
6476                                 &posix_acl_len,
6477                                 &posix_acl);
6478
6479         if (!NT_STATUS_IS_OK(status)) {
6480                 printf("cli_posix_getacl failed (%s)\n",
6481                         nt_errstr(status));
6482                 goto out;
6483         }
6484
6485         status = cli_close(cli, fnum);
6486         if (!NT_STATUS_IS_OK(status)) {
6487                 printf("close failed (%s)\n", nt_errstr(status));
6488                 goto out;
6489         }
6490         fnum = (uint16_t)-1;
6491
6492         /* Now create a symlink. */
6493         status = cli_posix_symlink(cli, fname, sname);
6494         if (!NT_STATUS_IS_OK(status)) {
6495                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6496                         sname,
6497                         fname,
6498                         nt_errstr(status));
6499                 goto out;
6500         }
6501
6502         /* Open a handle on the symlink. */
6503         status = cli_ntcreate(cli,
6504                         sname,
6505                         0,
6506                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6507                         0,
6508                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6509                         FILE_OPEN,
6510                         0x0,
6511                         0x0,
6512                         &fnum,
6513                         NULL);
6514
6515         if (!NT_STATUS_IS_OK(status)) {
6516                 printf("cli_posix_open of %s failed (%s)\n",
6517                         sname,
6518                         nt_errstr(status));
6519                 goto out;
6520         }
6521
6522         /* Get the Windows ACL on the symlink handle. Should fail */
6523         status = cli_query_secdesc(cli,
6524                                 fnum,
6525                                 frame,
6526                                 &sd_sym);
6527
6528         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6529                 printf("cli_query_secdesc on a symlink gave %s. "
6530                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6531                         nt_errstr(status));
6532                 goto out;
6533         }
6534
6535         /* Get the POSIX ACL on the symlink pathname. Should fail. */
6536         status = cli_posix_getacl(cli,
6537                                 sname,
6538                                 frame,
6539                                 &posix_acl_len_sym,
6540                                 &posix_acl_sym);
6541
6542         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6543                 printf("cli_posix_getacl on a symlink gave %s. "
6544                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6545                         nt_errstr(status));
6546                 goto out;
6547         }
6548
6549         /* Set the Windows ACL on the symlink handle. Should fail */
6550         status = cli_set_security_descriptor(cli,
6551                                 fnum,
6552                                 SECINFO_DACL,
6553                                 sd);
6554
6555         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6556                 printf("cli_query_secdesc on a symlink gave %s. "
6557                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6558                         nt_errstr(status));
6559                 goto out;
6560         }
6561
6562         /* Set the POSIX ACL on the symlink pathname. Should fail. */
6563         status = cli_posix_setacl(cli,
6564                                 sname,
6565                                 posix_acl,
6566                                 posix_acl_len);
6567
6568         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6569                 printf("cli_posix_getacl on a symlink gave %s. "
6570                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6571                         nt_errstr(status));
6572                 goto out;
6573         }
6574
6575         printf("ACL symlink test passed\n");
6576         correct = true;
6577
6578   out:
6579
6580         if (fnum != (uint16_t)-1) {
6581                 cli_close(cli, fnum);
6582                 fnum = (uint16_t)-1;
6583         }
6584
6585         cli_setatr(cli, sname, 0, 0);
6586         cli_posix_unlink(cli, sname);
6587         cli_setatr(cli, fname, 0, 0);
6588         cli_posix_unlink(cli, fname);
6589
6590         if (!torture_close_connection(cli)) {
6591                 correct = false;
6592         }
6593
6594         TALLOC_FREE(frame);
6595         return correct;
6596 }
6597
6598 /*
6599   Test POSIX can delete a file containing streams.
6600  */
6601 static bool run_posix_stream_delete(int dummy)
6602 {
6603         struct cli_state *cli1 = NULL;
6604         struct cli_state *cli2 = NULL;
6605         const char *fname = "streamfile";
6606         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6607         uint16_t fnum1 = (uint16_t)-1;
6608         bool correct = false;
6609         NTSTATUS status;
6610         TALLOC_CTX *frame = NULL;
6611
6612         frame = talloc_stackframe();
6613
6614         printf("Starting POSIX stream delete test\n");
6615
6616         if (!torture_open_connection(&cli1, 0) ||
6617                         !torture_open_connection(&cli2, 1)) {
6618                 TALLOC_FREE(frame);
6619                 return false;
6620         }
6621
6622         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6623         smbXcli_conn_set_sockopt(cli2->conn, sockops);
6624
6625         status = torture_setup_unix_extensions(cli2);
6626         if (!NT_STATUS_IS_OK(status)) {
6627                 goto out;
6628         }
6629
6630         cli_setatr(cli1, fname, 0, 0);
6631         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6632
6633         /* Create the file. */
6634         status = cli_ntcreate(cli1,
6635                         fname,
6636                         0,
6637                         READ_CONTROL_ACCESS,
6638                         0,
6639                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6640                         FILE_CREATE,
6641                         0x0,
6642                         0x0,
6643                         &fnum1,
6644                         NULL);
6645
6646         if (!NT_STATUS_IS_OK(status)) {
6647                 printf("cli_ntcreate of %s failed (%s)\n",
6648                         fname,
6649                         nt_errstr(status));
6650                 goto out;
6651         }
6652
6653         status = cli_close(cli1, fnum1);
6654         if (!NT_STATUS_IS_OK(status)) {
6655                 printf("cli_close of %s failed (%s)\n",
6656                         fname,
6657                         nt_errstr(status));
6658                 goto out;
6659         }
6660         fnum1 = (uint16_t)-1;
6661
6662         /* Now create the stream. */
6663         status = cli_ntcreate(cli1,
6664                         stream_fname,
6665                         0,
6666                         FILE_WRITE_DATA,
6667                         0,
6668                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6669                         FILE_CREATE,
6670                         0x0,
6671                         0x0,
6672                         &fnum1,
6673                         NULL);
6674
6675         if (!NT_STATUS_IS_OK(status)) {
6676                 printf("cli_ntcreate of %s failed (%s)\n",
6677                         stream_fname,
6678                         nt_errstr(status));
6679                 goto out;
6680         }
6681
6682         /* Leave the stream handle open... */
6683
6684         /* POSIX unlink should fail. */
6685         status = cli_posix_unlink(cli2, fname);
6686         if (NT_STATUS_IS_OK(status)) {
6687                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6688                         fname);
6689                 goto out;
6690         }
6691
6692         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6693                 printf("cli_posix_unlink of %s failed with (%s) "
6694                         "should have been NT_STATUS_SHARING_VIOLATION\n",
6695                         fname,
6696                         nt_errstr(status));
6697                 goto out;
6698         }
6699
6700         /* Close the stream handle. */
6701         status = cli_close(cli1, fnum1);
6702         if (!NT_STATUS_IS_OK(status)) {
6703                 printf("cli_close of %s failed (%s)\n",
6704                         stream_fname,
6705                         nt_errstr(status));
6706                 goto out;
6707         }
6708         fnum1 = (uint16_t)-1;
6709
6710         /* POSIX unlink after stream handle closed should succeed. */
6711         status = cli_posix_unlink(cli2, fname);
6712         if (!NT_STATUS_IS_OK(status)) {
6713                 printf("cli_posix_unlink of %s failed (%s)\n",
6714                         fname,
6715                         nt_errstr(status));
6716                 goto out;
6717         }
6718
6719         printf("POSIX stream delete test passed\n");
6720         correct = true;
6721
6722   out:
6723
6724         if (fnum1 != (uint16_t)-1) {
6725                 cli_close(cli1, fnum1);
6726                 fnum1 = (uint16_t)-1;
6727         }
6728
6729         cli_setatr(cli1, fname, 0, 0);
6730         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6731
6732         if (!torture_close_connection(cli1)) {
6733                 correct = false;
6734         }
6735         if (!torture_close_connection(cli2)) {
6736                 correct = false;
6737         }
6738
6739         TALLOC_FREE(frame);
6740         return correct;
6741 }
6742
6743 /*
6744   Test setting EA's are rejected on symlinks.
6745  */
6746 static bool run_ea_symlink_test(int dummy)
6747 {
6748         static struct cli_state *cli;
6749         const char *fname = "posix_file_ea";
6750         const char *sname = "posix_symlink_ea";
6751         const char *ea_name = "testea_name";
6752         const char *ea_value = "testea_value";
6753         uint16_t fnum = (uint16_t)-1;
6754         bool correct = false;
6755         NTSTATUS status;
6756         size_t i, num_eas;
6757         struct ea_struct *eas = NULL;
6758         TALLOC_CTX *frame = NULL;
6759
6760         frame = talloc_stackframe();
6761
6762         printf("Starting EA symlink test\n");
6763
6764         if (!torture_open_connection(&cli, 0)) {
6765                 TALLOC_FREE(frame);
6766                 return false;
6767         }
6768
6769         smbXcli_conn_set_sockopt(cli->conn, sockops);
6770
6771         status = torture_setup_unix_extensions(cli);
6772         if (!NT_STATUS_IS_OK(status)) {
6773                 TALLOC_FREE(frame);
6774                 return false;
6775         }
6776
6777         cli_setatr(cli, fname, 0, 0);
6778         cli_posix_unlink(cli, fname);
6779         cli_setatr(cli, sname, 0, 0);
6780         cli_posix_unlink(cli, sname);
6781
6782         status = cli_ntcreate(cli,
6783                         fname,
6784                         0,
6785                         READ_CONTROL_ACCESS,
6786                         0,
6787                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6788                         FILE_CREATE,
6789                         0x0,
6790                         0x0,
6791                         &fnum,
6792                         NULL);
6793
6794         if (!NT_STATUS_IS_OK(status)) {
6795                 printf("cli_ntcreate of %s failed (%s)\n",
6796                         fname,
6797                         nt_errstr(status));
6798                 goto out;
6799         }
6800
6801         status = cli_close(cli, fnum);
6802         if (!NT_STATUS_IS_OK(status)) {
6803                 printf("close failed (%s)\n",
6804                         nt_errstr(status));
6805                 goto out;
6806         }
6807         fnum = (uint16_t)-1;
6808
6809         /* Set an EA on the path. */
6810         status = cli_set_ea_path(cli,
6811                                 fname,
6812                                 ea_name,
6813                                 ea_value,
6814                                 strlen(ea_value)+1);
6815
6816         if (!NT_STATUS_IS_OK(status)) {
6817                 printf("cli_set_ea_path failed (%s)\n",
6818                         nt_errstr(status));
6819                 goto out;
6820         }
6821
6822         /* Now create a symlink. */
6823         status = cli_posix_symlink(cli, fname, sname);
6824         if (!NT_STATUS_IS_OK(status)) {
6825                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6826                         sname,
6827                         fname,
6828                         nt_errstr(status));
6829                 goto out;
6830         }
6831
6832         /* Get the EA list on the path. Should return value set. */
6833         status = cli_get_ea_list_path(cli,
6834                                 fname,
6835                                 frame,
6836                                 &num_eas,
6837                                 &eas);
6838
6839         if (!NT_STATUS_IS_OK(status)) {
6840                 printf("cli_get_ea_list_path failed (%s)\n",
6841                         nt_errstr(status));
6842                 goto out;
6843         }
6844
6845         /* Ensure the EA we set is there. */
6846         for (i=0; i<num_eas; i++) {
6847                 if (strcmp(eas[i].name, ea_name) == 0 &&
6848                                 eas[i].value.length == strlen(ea_value)+1 &&
6849                                 memcmp(eas[i].value.data,
6850                                         ea_value,
6851                                         eas[i].value.length) == 0) {
6852                         break;
6853                 }
6854         }
6855
6856         if (i == num_eas) {
6857                 printf("Didn't find EA on pathname %s\n",
6858                         fname);
6859                 goto out;
6860         }
6861
6862         num_eas = 0;
6863         TALLOC_FREE(eas);
6864
6865         /* Get the EA list on the symlink. Should return empty list. */
6866         status = cli_get_ea_list_path(cli,
6867                                 sname,
6868                                 frame,
6869                                 &num_eas,
6870                                 &eas);
6871
6872         if (!NT_STATUS_IS_OK(status)) {
6873                 printf("cli_get_ea_list_path failed (%s)\n",
6874                         nt_errstr(status));
6875                 goto out;
6876         }
6877
6878         if (num_eas != 0) {
6879                 printf("cli_get_ea_list_path failed (%s)\n",
6880                         nt_errstr(status));
6881                 goto out;
6882         }
6883
6884         /* Set an EA on the symlink. Should fail. */
6885         status = cli_set_ea_path(cli,
6886                                 sname,
6887                                 ea_name,
6888                                 ea_value,
6889                                 strlen(ea_value)+1);
6890
6891         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6892                 printf("cli_set_ea_path on a symlink gave %s. "
6893                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6894                         nt_errstr(status));
6895                 goto out;
6896         }
6897
6898         printf("EA symlink test passed\n");
6899         correct = true;
6900
6901   out:
6902
6903         if (fnum != (uint16_t)-1) {
6904                 cli_close(cli, fnum);
6905                 fnum = (uint16_t)-1;
6906         }
6907
6908         cli_setatr(cli, sname, 0, 0);
6909         cli_posix_unlink(cli, sname);
6910         cli_setatr(cli, fname, 0, 0);
6911         cli_posix_unlink(cli, fname);
6912
6913         if (!torture_close_connection(cli)) {
6914                 correct = false;
6915         }
6916
6917         TALLOC_FREE(frame);
6918         return correct;
6919 }
6920
6921 /*
6922   Test POSIX locks are OFD-locks.
6923  */
6924 static bool run_posix_ofd_lock_test(int dummy)
6925 {
6926         static struct cli_state *cli;
6927         const char *fname = "posix_file";
6928         uint16_t fnum1 = (uint16_t)-1;
6929         uint16_t fnum2 = (uint16_t)-1;
6930         bool correct = false;
6931         NTSTATUS status;
6932         TALLOC_CTX *frame = NULL;
6933
6934         frame = talloc_stackframe();
6935
6936         printf("Starting POSIX ofd-lock test\n");
6937
6938         if (!torture_open_connection(&cli, 0)) {
6939                 TALLOC_FREE(frame);
6940                 return false;
6941         }
6942
6943         smbXcli_conn_set_sockopt(cli->conn, sockops);
6944
6945         status = torture_setup_unix_extensions(cli);
6946         if (!NT_STATUS_IS_OK(status)) {
6947                 TALLOC_FREE(frame);
6948                 return false;
6949         }
6950
6951         cli_setatr(cli, fname, 0, 0);
6952         cli_posix_unlink(cli, fname);
6953
6954         /* Open the file twice. */
6955         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
6956                                 0600, &fnum1);
6957         if (!NT_STATUS_IS_OK(status)) {
6958                 printf("First POSIX open of %s failed\n", fname);
6959                 goto out;
6960         }
6961
6962         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
6963         if (!NT_STATUS_IS_OK(status)) {
6964                 printf("First POSIX open of %s failed\n", fname);
6965                 goto out;
6966         }
6967
6968         /* Set a 0-50 lock on fnum1. */
6969         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
6970         if (!NT_STATUS_IS_OK(status)) {
6971                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
6972                 goto out;
6973         }
6974
6975         /* Set a 60-100 lock on fnum2. */
6976         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
6977         if (!NT_STATUS_IS_OK(status)) {
6978                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
6979                 goto out;
6980         }
6981
6982         /* close fnum1 - 0-50 lock should go away. */
6983         status = cli_close(cli, fnum1);
6984         if (!NT_STATUS_IS_OK(status)) {
6985                 printf("close failed (%s)\n",
6986                         nt_errstr(status));
6987                 goto out;
6988         }
6989         fnum1 = (uint16_t)-1;
6990
6991         /* Change the lock context. */
6992         cli_setpid(cli, cli_getpid(cli) + 1);
6993
6994         /* Re-open fnum1. */
6995         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
6996         if (!NT_STATUS_IS_OK(status)) {
6997                 printf("Third POSIX open of %s failed\n", fname);
6998                 goto out;
6999         }
7000
7001         /* 60-100 lock should still be there. */
7002         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7003         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7004                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7005                 goto out;
7006         }
7007
7008         /* 0-50 lock should be gone. */
7009         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7010         if (!NT_STATUS_IS_OK(status)) {
7011                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7012                 goto out;
7013         }
7014
7015         printf("POSIX OFD lock test passed\n");
7016         correct = true;
7017
7018   out:
7019
7020         if (fnum1 != (uint16_t)-1) {
7021                 cli_close(cli, fnum1);
7022                 fnum1 = (uint16_t)-1;
7023         }
7024         if (fnum2 != (uint16_t)-1) {
7025                 cli_close(cli, fnum2);
7026                 fnum2 = (uint16_t)-1;
7027         }
7028
7029         cli_setatr(cli, fname, 0, 0);
7030         cli_posix_unlink(cli, fname);
7031
7032         if (!torture_close_connection(cli)) {
7033                 correct = false;
7034         }
7035
7036         TALLOC_FREE(frame);
7037         return correct;
7038 }
7039
7040 static uint32_t open_attrs_table[] = {
7041                 FILE_ATTRIBUTE_NORMAL,
7042                 FILE_ATTRIBUTE_ARCHIVE,
7043                 FILE_ATTRIBUTE_READONLY,
7044                 FILE_ATTRIBUTE_HIDDEN,
7045                 FILE_ATTRIBUTE_SYSTEM,
7046
7047                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7048                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7049                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7050                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7051                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7052                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7053
7054                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7055                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7056                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7057                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7058 };
7059
7060 struct trunc_open_results {
7061         unsigned int num;
7062         uint32_t init_attr;
7063         uint32_t trunc_attr;
7064         uint32_t result_attr;
7065 };
7066
7067 static struct trunc_open_results attr_results[] = {
7068         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7069         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7070         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7071         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7072         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7073         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7074         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7075         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7076         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7077         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7078         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7079         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7080         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7081         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7082         { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7083         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7084         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7085         { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7086         { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
7087         { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
7088         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7089         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7090         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7091         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7092         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7093         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7094 };
7095
7096 static bool run_openattrtest(int dummy)
7097 {
7098         static struct cli_state *cli1;
7099         const char *fname = "\\openattr.file";
7100         uint16_t fnum1;
7101         bool correct = True;
7102         uint16_t attr;
7103         unsigned int i, j, k, l;
7104         NTSTATUS status;
7105
7106         printf("starting open attr test\n");
7107
7108         if (!torture_open_connection(&cli1, 0)) {
7109                 return False;
7110         }
7111
7112         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7113
7114         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7115                 cli_setatr(cli1, fname, 0, 0);
7116                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7117
7118                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7119                                        open_attrs_table[i], FILE_SHARE_NONE,
7120                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7121                 if (!NT_STATUS_IS_OK(status)) {
7122                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7123                         return False;
7124                 }
7125
7126                 status = cli_close(cli1, fnum1);
7127                 if (!NT_STATUS_IS_OK(status)) {
7128                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7129                         return False;
7130                 }
7131
7132                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7133                         status = cli_ntcreate(cli1, fname, 0,
7134                                               FILE_READ_DATA|FILE_WRITE_DATA,
7135                                               open_attrs_table[j],
7136                                               FILE_SHARE_NONE, FILE_OVERWRITE,
7137                                               0, 0, &fnum1, NULL);
7138                         if (!NT_STATUS_IS_OK(status)) {
7139                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7140                                         if (attr_results[l].num == k) {
7141                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7142                                                                 k, open_attrs_table[i],
7143                                                                 open_attrs_table[j],
7144                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
7145                                                 correct = False;
7146                                         }
7147                                 }
7148
7149                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7150                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7151                                                         k, open_attrs_table[i], open_attrs_table[j],
7152                                                         nt_errstr(status));
7153                                         correct = False;
7154                                 }
7155 #if 0
7156                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7157 #endif
7158                                 k++;
7159                                 continue;
7160                         }
7161
7162                         status = cli_close(cli1, fnum1);
7163                         if (!NT_STATUS_IS_OK(status)) {
7164                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7165                                 return False;
7166                         }
7167
7168                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7169                         if (!NT_STATUS_IS_OK(status)) {
7170                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7171                                 return False;
7172                         }
7173
7174 #if 0
7175                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7176                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
7177 #endif
7178
7179                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7180                                 if (attr_results[l].num == k) {
7181                                         if (attr != attr_results[l].result_attr ||
7182                                                         open_attrs_table[i] != attr_results[l].init_attr ||
7183                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
7184                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7185                                                 open_attrs_table[i],
7186                                                 open_attrs_table[j],
7187                                                 (unsigned int)attr,
7188                                                 attr_results[l].result_attr);
7189                                                 correct = False;
7190                                         }
7191                                         break;
7192                                 }
7193                         }
7194                         k++;
7195                 }
7196         }
7197
7198         cli_setatr(cli1, fname, 0, 0);
7199         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7200
7201         printf("open attr test %s.\n", correct ? "passed" : "failed");
7202
7203         if (!torture_close_connection(cli1)) {
7204                 correct = False;
7205         }
7206         return correct;
7207 }
7208
7209 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7210                     const char *name, void *state)
7211 {
7212         int *matched = (int *)state;
7213         if (matched != NULL) {
7214                 *matched += 1;
7215         }
7216         return NT_STATUS_OK;
7217 }
7218
7219 /*
7220   test directory listing speed
7221  */
7222 static bool run_dirtest(int dummy)
7223 {
7224         int i;
7225         static struct cli_state *cli;
7226         uint16_t fnum;
7227         struct timeval core_start;
7228         bool correct = True;
7229         int matched;
7230
7231         printf("starting directory test\n");
7232
7233         if (!torture_open_connection(&cli, 0)) {
7234                 return False;
7235         }
7236
7237         smbXcli_conn_set_sockopt(cli->conn, sockops);
7238
7239         srandom(0);
7240         for (i=0;i<torture_numops;i++) {
7241                 fstring fname;
7242                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7243                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7244                         fprintf(stderr,"Failed to open %s\n", fname);
7245                         return False;
7246                 }
7247                 cli_close(cli, fnum);
7248         }
7249
7250         core_start = timeval_current();
7251
7252         matched = 0;
7253         cli_list(cli, "a*.*", 0, list_fn, &matched);
7254         printf("Matched %d\n", matched);
7255
7256         matched = 0;
7257         cli_list(cli, "b*.*", 0, list_fn, &matched);
7258         printf("Matched %d\n", matched);
7259
7260         matched = 0;
7261         cli_list(cli, "xyzabc", 0, list_fn, &matched);
7262         printf("Matched %d\n", matched);
7263
7264         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7265
7266         srandom(0);
7267         for (i=0;i<torture_numops;i++) {
7268                 fstring fname;
7269                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7270                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7271         }
7272
7273         if (!torture_close_connection(cli)) {
7274                 correct = False;
7275         }
7276
7277         printf("finished dirtest\n");
7278
7279         return correct;
7280 }
7281
7282 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7283                    void *state)
7284 {
7285         struct cli_state *pcli = (struct cli_state *)state;
7286         fstring fname;
7287         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7288
7289         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7290                 return NT_STATUS_OK;
7291
7292         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7293                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7294                         printf("del_fn: failed to rmdir %s\n,", fname );
7295         } else {
7296                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7297                         printf("del_fn: failed to unlink %s\n,", fname );
7298         }
7299         return NT_STATUS_OK;
7300 }
7301
7302
7303 /*
7304   sees what IOCTLs are supported
7305  */
7306 bool torture_ioctl_test(int dummy)
7307 {
7308         static struct cli_state *cli;
7309         uint16_t device, function;
7310         uint16_t fnum;
7311         const char *fname = "\\ioctl.dat";
7312         DATA_BLOB blob;
7313         NTSTATUS status;
7314
7315         if (!torture_open_connection(&cli, 0)) {
7316                 return False;
7317         }
7318
7319         printf("starting ioctl test\n");
7320
7321         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7322
7323         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7324         if (!NT_STATUS_IS_OK(status)) {
7325                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7326                 return False;
7327         }
7328
7329         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7330         printf("ioctl device info: %s\n", nt_errstr(status));
7331
7332         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7333         printf("ioctl job info: %s\n", nt_errstr(status));
7334
7335         for (device=0;device<0x100;device++) {
7336                 printf("ioctl test with device = 0x%x\n", device);
7337                 for (function=0;function<0x100;function++) {
7338                         uint32_t code = (device<<16) | function;
7339
7340                         status = cli_raw_ioctl(cli, fnum, code, &blob);
7341
7342                         if (NT_STATUS_IS_OK(status)) {
7343                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7344                                        (int)blob.length);
7345                                 data_blob_free(&blob);
7346                         }
7347                 }
7348         }
7349
7350         if (!torture_close_connection(cli)) {
7351                 return False;
7352         }
7353
7354         return True;
7355 }
7356
7357
7358 /*
7359   tries varients of chkpath
7360  */
7361 bool torture_chkpath_test(int dummy)
7362 {
7363         static struct cli_state *cli;
7364         uint16_t fnum;
7365         bool ret;
7366         NTSTATUS status;
7367
7368         if (!torture_open_connection(&cli, 0)) {
7369                 return False;
7370         }
7371
7372         printf("starting chkpath test\n");
7373
7374         /* cleanup from an old run */
7375         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7376         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7377         cli_rmdir(cli, "\\chkpath.dir");
7378
7379         status = cli_mkdir(cli, "\\chkpath.dir");
7380         if (!NT_STATUS_IS_OK(status)) {
7381                 printf("mkdir1 failed : %s\n", nt_errstr(status));
7382                 return False;
7383         }
7384
7385         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7386         if (!NT_STATUS_IS_OK(status)) {
7387                 printf("mkdir2 failed : %s\n", nt_errstr(status));
7388                 return False;
7389         }
7390
7391         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7392                           DENY_NONE, &fnum);
7393         if (!NT_STATUS_IS_OK(status)) {
7394                 printf("open1 failed (%s)\n", nt_errstr(status));
7395                 return False;
7396         }
7397         cli_close(cli, fnum);
7398
7399         status = cli_chkpath(cli, "\\chkpath.dir");
7400         if (!NT_STATUS_IS_OK(status)) {
7401                 printf("chkpath1 failed: %s\n", nt_errstr(status));
7402                 ret = False;
7403         }
7404
7405         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7406         if (!NT_STATUS_IS_OK(status)) {
7407                 printf("chkpath2 failed: %s\n", nt_errstr(status));
7408                 ret = False;
7409         }
7410
7411         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7412         if (!NT_STATUS_IS_OK(status)) {
7413                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7414                                   NT_STATUS_NOT_A_DIRECTORY);
7415         } else {
7416                 printf("* chkpath on a file should fail\n");
7417                 ret = False;
7418         }
7419
7420         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7421         if (!NT_STATUS_IS_OK(status)) {
7422                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7423                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
7424         } else {
7425                 printf("* chkpath on a non existent file should fail\n");
7426                 ret = False;
7427         }
7428
7429         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7430         if (!NT_STATUS_IS_OK(status)) {
7431                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7432                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
7433         } else {
7434                 printf("* chkpath on a non existent component should fail\n");
7435                 ret = False;
7436         }
7437
7438         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7439         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7440         cli_rmdir(cli, "\\chkpath.dir");
7441
7442         if (!torture_close_connection(cli)) {
7443                 return False;
7444         }
7445
7446         return ret;
7447 }
7448
7449 static bool run_eatest(int dummy)
7450 {
7451         static struct cli_state *cli;
7452         const char *fname = "\\eatest.txt";
7453         bool correct = True;
7454         uint16_t fnum;
7455         int i;
7456         size_t num_eas;
7457         struct ea_struct *ea_list = NULL;
7458         TALLOC_CTX *mem_ctx = talloc_init("eatest");
7459         NTSTATUS status;
7460
7461         printf("starting eatest\n");
7462
7463         if (!torture_open_connection(&cli, 0)) {
7464                 talloc_destroy(mem_ctx);
7465                 return False;
7466         }
7467
7468         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7469
7470         status = cli_ntcreate(cli, fname, 0,
7471                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7472                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7473                               0x4044, 0, &fnum, NULL);
7474         if (!NT_STATUS_IS_OK(status)) {
7475                 printf("open failed - %s\n", nt_errstr(status));
7476                 talloc_destroy(mem_ctx);
7477                 return False;
7478         }
7479
7480         for (i = 0; i < 10; i++) {
7481                 fstring ea_name, ea_val;
7482
7483                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7484                 memset(ea_val, (char)i+1, i+1);
7485                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7486                 if (!NT_STATUS_IS_OK(status)) {
7487                         printf("ea_set of name %s failed - %s\n", ea_name,
7488                                nt_errstr(status));
7489                         talloc_destroy(mem_ctx);
7490                         return False;
7491                 }
7492         }
7493
7494         cli_close(cli, fnum);
7495         for (i = 0; i < 10; i++) {
7496                 fstring ea_name, ea_val;
7497
7498                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7499                 memset(ea_val, (char)i+1, i+1);
7500                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7501                 if (!NT_STATUS_IS_OK(status)) {
7502                         printf("ea_set of name %s failed - %s\n", ea_name,
7503                                nt_errstr(status));
7504                         talloc_destroy(mem_ctx);
7505                         return False;
7506                 }
7507         }
7508
7509         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7510         if (!NT_STATUS_IS_OK(status)) {
7511                 printf("ea_get list failed - %s\n", nt_errstr(status));
7512                 correct = False;
7513         }
7514
7515         printf("num_eas = %d\n", (int)num_eas);
7516
7517         if (num_eas != 20) {
7518                 printf("Should be 20 EA's stored... failing.\n");
7519                 correct = False;
7520         }
7521
7522         for (i = 0; i < num_eas; i++) {
7523                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7524                 dump_data(0, ea_list[i].value.data,
7525                           ea_list[i].value.length);
7526         }
7527
7528         /* Setting EA's to zero length deletes them. Test this */
7529         printf("Now deleting all EA's - case indepenent....\n");
7530
7531 #if 1
7532         cli_set_ea_path(cli, fname, "", "", 0);
7533 #else
7534         for (i = 0; i < 20; i++) {
7535                 fstring ea_name;
7536                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7537                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7538                 if (!NT_STATUS_IS_OK(status)) {
7539                         printf("ea_set of name %s failed - %s\n", ea_name,
7540                                nt_errstr(status));
7541                         talloc_destroy(mem_ctx);
7542                         return False;
7543                 }
7544         }
7545 #endif
7546
7547         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7548         if (!NT_STATUS_IS_OK(status)) {
7549                 printf("ea_get list failed - %s\n", nt_errstr(status));
7550                 correct = False;
7551         }
7552
7553         printf("num_eas = %d\n", (int)num_eas);
7554         for (i = 0; i < num_eas; i++) {
7555                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7556                 dump_data(0, ea_list[i].value.data,
7557                           ea_list[i].value.length);
7558         }
7559
7560         if (num_eas != 0) {
7561                 printf("deleting EA's failed.\n");
7562                 correct = False;
7563         }
7564
7565         /* Try and delete a non existent EA. */
7566         status = cli_set_ea_path(cli, fname, "foo", "", 0);
7567         if (!NT_STATUS_IS_OK(status)) {
7568                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7569                        nt_errstr(status));
7570                 correct = False;
7571         }
7572
7573         talloc_destroy(mem_ctx);
7574         if (!torture_close_connection(cli)) {
7575                 correct = False;
7576         }
7577
7578         return correct;
7579 }
7580
7581 static bool run_dirtest1(int dummy)
7582 {
7583         int i;
7584         static struct cli_state *cli;
7585         uint16_t fnum;
7586         int num_seen;
7587         bool correct = True;
7588
7589         printf("starting directory test\n");
7590
7591         if (!torture_open_connection(&cli, 0)) {
7592                 return False;
7593         }
7594
7595         smbXcli_conn_set_sockopt(cli->conn, sockops);
7596
7597         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7598         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7599         cli_rmdir(cli, "\\LISTDIR");
7600         cli_mkdir(cli, "\\LISTDIR");
7601
7602         /* Create 1000 files and 1000 directories. */
7603         for (i=0;i<1000;i++) {
7604                 fstring fname;
7605                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
7606                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7607                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
7608                                    0, 0, &fnum, NULL))) {
7609                         fprintf(stderr,"Failed to open %s\n", fname);
7610                         return False;
7611                 }
7612                 cli_close(cli, fnum);
7613         }
7614         for (i=0;i<1000;i++) {
7615                 fstring fname;
7616                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
7617                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
7618                         fprintf(stderr,"Failed to open %s\n", fname);
7619                         return False;
7620                 }
7621         }
7622
7623         /* Now ensure that doing an old list sees both files and directories. */
7624         num_seen = 0;
7625         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7626         printf("num_seen = %d\n", num_seen );
7627         /* We should see 100 files + 1000 directories + . and .. */
7628         if (num_seen != 2002)
7629                 correct = False;
7630
7631         /* Ensure if we have the "must have" bits we only see the
7632          * relevent entries.
7633          */
7634         num_seen = 0;
7635         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7636         printf("num_seen = %d\n", num_seen );
7637         if (num_seen != 1002)
7638                 correct = False;
7639
7640         num_seen = 0;
7641         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
7642         printf("num_seen = %d\n", num_seen );
7643         if (num_seen != 1000)
7644                 correct = False;
7645
7646         /* Delete everything. */
7647         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
7648         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
7649         cli_rmdir(cli, "\\LISTDIR");
7650
7651 #if 0
7652         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
7653         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
7654         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
7655 #endif
7656
7657         if (!torture_close_connection(cli)) {
7658                 correct = False;
7659         }
7660
7661         printf("finished dirtest1\n");
7662
7663         return correct;
7664 }
7665
7666 static bool run_error_map_extract(int dummy) {
7667
7668         static struct cli_state *c_dos;
7669         static struct cli_state *c_nt;
7670         NTSTATUS status;
7671
7672         uint32_t error;
7673
7674         uint32_t errnum;
7675         uint8_t errclass;
7676
7677         NTSTATUS nt_status;
7678
7679         fstring user;
7680
7681         /* NT-Error connection */
7682
7683         disable_spnego = true;
7684         if (!(c_nt = open_nbt_connection())) {
7685                 disable_spnego = false;
7686                 return False;
7687         }
7688         disable_spnego = false;
7689
7690         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
7691                                  PROTOCOL_NT1);
7692
7693         if (!NT_STATUS_IS_OK(status)) {
7694                 printf("%s rejected the NT-error negprot (%s)\n", host,
7695                        nt_errstr(status));
7696                 cli_shutdown(c_nt);
7697                 return False;
7698         }
7699
7700         status = cli_session_setup_anon(c_nt);
7701         if (!NT_STATUS_IS_OK(status)) {
7702                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
7703                 return False;
7704         }
7705
7706         /* DOS-Error connection */
7707
7708         disable_spnego = true;
7709         force_dos_errors = true;
7710         if (!(c_dos = open_nbt_connection())) {
7711                 disable_spnego = false;
7712                 force_dos_errors = false;
7713                 return False;
7714         }
7715         disable_spnego = false;
7716         force_dos_errors = false;
7717
7718         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
7719                                  PROTOCOL_NT1);
7720         if (!NT_STATUS_IS_OK(status)) {
7721                 printf("%s rejected the DOS-error negprot (%s)\n", host,
7722                        nt_errstr(status));
7723                 cli_shutdown(c_dos);
7724                 return False;
7725         }
7726
7727         status = cli_session_setup_anon(c_dos);
7728         if (!NT_STATUS_IS_OK(status)) {
7729                 printf("%s rejected the DOS-error initial session setup (%s)\n",
7730                         host, nt_errstr(status));
7731                 return False;
7732         }
7733
7734         c_nt->map_dos_errors = false;
7735         c_dos->map_dos_errors = false;
7736
7737         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
7738                 struct cli_credentials *user_creds = NULL;
7739
7740                 fstr_sprintf(user, "%X", error);
7741
7742                 user_creds = cli_session_creds_init(talloc_tos(),
7743                                                     user,
7744                                                     workgroup,
7745                                                     NULL, /* realm */
7746                                                     password,
7747                                                     false, /* use_kerberos */
7748                                                     false, /* fallback_after_kerberos */
7749                                                     false, /* use_ccache */
7750                                                     false); /* password_is_nt_hash */
7751                 if (user_creds == NULL) {
7752                         printf("cli_session_creds_init(%s) failed\n", user);
7753                         return false;
7754                 }
7755
7756                 status = cli_session_setup_creds(c_nt, user_creds);
7757                 if (NT_STATUS_IS_OK(status)) {
7758                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
7759                 }
7760
7761                 /* Case #1: 32-bit NT errors */
7762                 if (!NT_STATUS_IS_DOS(status)) {
7763                         nt_status = status;
7764                 } else {
7765                         printf("/** Dos error on NT connection! (%s) */\n", 
7766                                nt_errstr(status));
7767                         nt_status = NT_STATUS(0xc0000000);
7768                 }
7769
7770                 status = cli_session_setup_creds(c_dos, user_creds);
7771                 if (NT_STATUS_IS_OK(status)) {
7772                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
7773                 }
7774
7775                 /* Case #1: 32-bit NT errors */
7776                 if (NT_STATUS_IS_DOS(status)) {
7777                         printf("/** NT error on DOS connection! (%s) */\n", 
7778                                nt_errstr(status));
7779                         errnum = errclass = 0;
7780                 } else {
7781                         errclass = NT_STATUS_DOS_CLASS(status);
7782                         errnum = NT_STATUS_DOS_CODE(status);
7783                 }
7784
7785                 if (NT_STATUS_V(nt_status) != error) { 
7786                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
7787                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
7788                                get_nt_error_c_code(talloc_tos(), nt_status));
7789                 }
7790
7791                 printf("\t{%s,\t%s,\t%s},\n", 
7792                        smb_dos_err_class(errclass), 
7793                        smb_dos_err_name(errclass, errnum), 
7794                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
7795
7796                 TALLOC_FREE(user_creds);
7797         }
7798         return True;
7799 }
7800
7801 static bool run_sesssetup_bench(int dummy)
7802 {
7803         static struct cli_state *c;
7804         const char *fname = "\\file.dat";
7805         uint16_t fnum;
7806         NTSTATUS status;
7807         int i;
7808
7809         if (!torture_open_connection(&c, 0)) {
7810                 return false;
7811         }
7812
7813         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7814                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7815                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
7816         if (!NT_STATUS_IS_OK(status)) {
7817                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7818                 return false;
7819         }
7820
7821         for (i=0; i<torture_numops; i++) {
7822                 status = cli_session_setup_creds(c, torture_creds);
7823                 if (!NT_STATUS_IS_OK(status)) {
7824                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
7825                                  __location__, nt_errstr(status));
7826                         return false;
7827                 }
7828
7829                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
7830
7831                 status = cli_ulogoff(c);
7832                 if (!NT_STATUS_IS_OK(status)) {
7833                         d_printf("(%s) cli_ulogoff failed: %s\n",
7834                                  __location__, nt_errstr(status));
7835                         return false;
7836                 }
7837         }
7838
7839         return true;
7840 }
7841
7842 static bool subst_test(const char *str, const char *user, const char *domain,
7843                        uid_t uid, gid_t gid, const char *expected)
7844 {
7845         char *subst;
7846         bool result = true;
7847
7848         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
7849
7850         if (strcmp(subst, expected) != 0) {
7851                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
7852                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
7853                        expected);
7854                 result = false;
7855         }
7856
7857         TALLOC_FREE(subst);
7858         return result;
7859 }
7860
7861 static void chain1_open_completion(struct tevent_req *req)
7862 {
7863         uint16_t fnum;
7864         NTSTATUS status;
7865         status = cli_openx_recv(req, &fnum);
7866         TALLOC_FREE(req);
7867
7868         d_printf("cli_openx_recv returned %s: %d\n",
7869                  nt_errstr(status),
7870                  NT_STATUS_IS_OK(status) ? fnum : -1);
7871 }
7872
7873 static void chain1_write_completion(struct tevent_req *req)
7874 {
7875         size_t written;
7876         NTSTATUS status;
7877         status = cli_write_andx_recv(req, &written);
7878         TALLOC_FREE(req);
7879
7880         d_printf("cli_write_andx_recv returned %s: %d\n",
7881                  nt_errstr(status),
7882                  NT_STATUS_IS_OK(status) ? (int)written : -1);
7883 }
7884
7885 static void chain1_close_completion(struct tevent_req *req)
7886 {
7887         NTSTATUS status;
7888         bool *done = (bool *)tevent_req_callback_data_void(req);
7889
7890         status = cli_close_recv(req);
7891         *done = true;
7892
7893         TALLOC_FREE(req);
7894
7895         d_printf("cli_close returned %s\n", nt_errstr(status));
7896 }
7897
7898 static bool run_chain1(int dummy)
7899 {
7900         struct cli_state *cli1;
7901         struct tevent_context *evt = samba_tevent_context_init(NULL);
7902         struct tevent_req *reqs[3], *smbreqs[3];
7903         bool done = false;
7904         const char *str = "foobar";
7905         NTSTATUS status;
7906
7907         printf("starting chain1 test\n");
7908         if (!torture_open_connection(&cli1, 0)) {
7909                 return False;
7910         }
7911
7912         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7913
7914         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
7915                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
7916         if (reqs[0] == NULL) return false;
7917         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
7918
7919
7920         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
7921                                         (const uint8_t *)str, 0, strlen(str)+1,
7922                                         smbreqs, 1, &smbreqs[1]);
7923         if (reqs[1] == NULL) return false;
7924         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
7925
7926         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
7927         if (reqs[2] == NULL) return false;
7928         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
7929
7930         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7931         if (!NT_STATUS_IS_OK(status)) {
7932                 return false;
7933         }
7934
7935         while (!done) {
7936                 tevent_loop_once(evt);
7937         }
7938
7939         torture_close_connection(cli1);
7940         return True;
7941 }
7942
7943 static void chain2_sesssetup_completion(struct tevent_req *req)
7944 {
7945         NTSTATUS status;
7946         status = cli_session_setup_guest_recv(req);
7947         d_printf("sesssetup returned %s\n", nt_errstr(status));
7948 }
7949
7950 static void chain2_tcon_completion(struct tevent_req *req)
7951 {
7952         bool *done = (bool *)tevent_req_callback_data_void(req);
7953         NTSTATUS status;
7954         status = cli_tcon_andx_recv(req);
7955         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
7956         *done = true;
7957 }
7958
7959 static bool run_chain2(int dummy)
7960 {
7961         struct cli_state *cli1;
7962         struct tevent_context *evt = samba_tevent_context_init(NULL);
7963         struct tevent_req *reqs[2], *smbreqs[2];
7964         bool done = false;
7965         NTSTATUS status;
7966
7967         printf("starting chain2 test\n");
7968         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
7969                                       port_to_use, SMB_SIGNING_DEFAULT, 0);
7970         if (!NT_STATUS_IS_OK(status)) {
7971                 return False;
7972         }
7973
7974         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7975
7976         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
7977                                                  &smbreqs[0]);
7978         if (reqs[0] == NULL) return false;
7979         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
7980
7981         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
7982                                        "?????", NULL, 0, &smbreqs[1]);
7983         if (reqs[1] == NULL) return false;
7984         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
7985
7986         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
7987         if (!NT_STATUS_IS_OK(status)) {
7988                 return false;
7989         }
7990
7991         while (!done) {
7992                 tevent_loop_once(evt);
7993         }
7994
7995         torture_close_connection(cli1);
7996         return True;
7997 }
7998
7999
8000 struct torture_createdel_state {
8001         struct tevent_context *ev;
8002         struct cli_state *cli;
8003 };
8004
8005 static void torture_createdel_created(struct tevent_req *subreq);
8006 static void torture_createdel_closed(struct tevent_req *subreq);
8007
8008 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8009                                                  struct tevent_context *ev,
8010                                                  struct cli_state *cli,
8011                                                  const char *name)
8012 {
8013         struct tevent_req *req, *subreq;
8014         struct torture_createdel_state *state;
8015
8016         req = tevent_req_create(mem_ctx, &state,
8017                                 struct torture_createdel_state);
8018         if (req == NULL) {
8019                 return NULL;
8020         }
8021         state->ev = ev;
8022         state->cli = cli;
8023
8024         subreq = cli_ntcreate_send(
8025                 state, ev, cli, name, 0,
8026                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8027                 FILE_ATTRIBUTE_NORMAL,
8028                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8029                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
8030
8031         if (tevent_req_nomem(subreq, req)) {
8032                 return tevent_req_post(req, ev);
8033         }
8034         tevent_req_set_callback(subreq, torture_createdel_created, req);
8035         return req;
8036 }
8037
8038 static void torture_createdel_created(struct tevent_req *subreq)
8039 {
8040         struct tevent_req *req = tevent_req_callback_data(
8041                 subreq, struct tevent_req);
8042         struct torture_createdel_state *state = tevent_req_data(
8043                 req, struct torture_createdel_state);
8044         NTSTATUS status;
8045         uint16_t fnum;
8046
8047         status = cli_ntcreate_recv(subreq, &fnum, NULL);
8048         TALLOC_FREE(subreq);
8049         if (tevent_req_nterror(req, status)) {
8050                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8051                            nt_errstr(status)));
8052                 return;
8053         }
8054
8055         subreq = cli_close_send(state, state->ev, state->cli, fnum);
8056         if (tevent_req_nomem(subreq, req)) {
8057                 return;
8058         }
8059         tevent_req_set_callback(subreq, torture_createdel_closed, req);
8060 }
8061
8062 static void torture_createdel_closed(struct tevent_req *subreq)
8063 {
8064         struct tevent_req *req = tevent_req_callback_data(
8065                 subreq, struct tevent_req);
8066         NTSTATUS status;
8067
8068         status = cli_close_recv(subreq);
8069         if (tevent_req_nterror(req, status)) {
8070                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8071                 return;
8072         }
8073         tevent_req_done(req);
8074 }
8075
8076 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8077 {
8078         return tevent_req_simple_recv_ntstatus(req);
8079 }
8080
8081 struct torture_createdels_state {
8082         struct tevent_context *ev;
8083         struct cli_state *cli;
8084         const char *base_name;
8085         int sent;
8086         int received;
8087         int num_files;
8088         struct tevent_req **reqs;
8089 };
8090
8091 static void torture_createdels_done(struct tevent_req *subreq);
8092
8093 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8094                                                   struct tevent_context *ev,
8095                                                   struct cli_state *cli,
8096                                                   const char *base_name,
8097                                                   int num_parallel,
8098                                                   int num_files)
8099 {
8100         struct tevent_req *req;
8101         struct torture_createdels_state *state;
8102         int i;
8103
8104         req = tevent_req_create(mem_ctx, &state,
8105                                 struct torture_createdels_state);
8106         if (req == NULL) {
8107                 return NULL;
8108         }
8109         state->ev = ev;
8110         state->cli = cli;
8111         state->base_name = talloc_strdup(state, base_name);
8112         if (tevent_req_nomem(state->base_name, req)) {
8113                 return tevent_req_post(req, ev);
8114         }
8115         state->num_files = MAX(num_parallel, num_files);
8116         state->sent = 0;
8117         state->received = 0;
8118
8119         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8120         if (tevent_req_nomem(state->reqs, req)) {
8121                 return tevent_req_post(req, ev);
8122         }
8123
8124         for (i=0; i<num_parallel; i++) {
8125                 char *name;
8126
8127                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8128                                        state->sent);
8129                 if (tevent_req_nomem(name, req)) {
8130                         return tevent_req_post(req, ev);
8131                 }
8132                 state->reqs[i] = torture_createdel_send(
8133                         state->reqs, state->ev, state->cli, name);
8134                 if (tevent_req_nomem(state->reqs[i], req)) {
8135                         return tevent_req_post(req, ev);
8136                 }
8137                 name = talloc_move(state->reqs[i], &name);
8138                 tevent_req_set_callback(state->reqs[i],
8139                                         torture_createdels_done, req);
8140                 state->sent += 1;
8141         }
8142         return req;
8143 }
8144
8145 static void torture_createdels_done(struct tevent_req *subreq)
8146 {
8147         struct tevent_req *req = tevent_req_callback_data(
8148                 subreq, struct tevent_req);
8149         struct torture_createdels_state *state = tevent_req_data(
8150                 req, struct torture_createdels_state);
8151         size_t num_parallel = talloc_array_length(state->reqs);
8152         NTSTATUS status;
8153         char *name;
8154         int i;
8155
8156         status = torture_createdel_recv(subreq);
8157         if (!NT_STATUS_IS_OK(status)){
8158                 DEBUG(10, ("torture_createdel_recv returned %s\n",
8159                            nt_errstr(status)));
8160                 TALLOC_FREE(subreq);
8161                 tevent_req_nterror(req, status);
8162                 return;
8163         }
8164
8165         for (i=0; i<num_parallel; i++) {
8166                 if (subreq == state->reqs[i]) {
8167                         break;
8168                 }
8169         }
8170         if (i == num_parallel) {
8171                 DEBUG(10, ("received something we did not send\n"));
8172                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8173                 return;
8174         }
8175         TALLOC_FREE(state->reqs[i]);
8176
8177         if (state->sent >= state->num_files) {
8178                 tevent_req_done(req);
8179                 return;
8180         }
8181
8182         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8183                                state->sent);
8184         if (tevent_req_nomem(name, req)) {
8185                 return;
8186         }
8187         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8188                                                 state->cli, name);
8189         if (tevent_req_nomem(state->reqs[i], req)) {
8190                 return;
8191         }
8192         name = talloc_move(state->reqs[i], &name);
8193         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8194         state->sent += 1;
8195 }
8196
8197 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8198 {
8199         return tevent_req_simple_recv_ntstatus(req);
8200 }
8201
8202 struct swallow_notify_state {
8203         struct tevent_context *ev;
8204         struct cli_state *cli;
8205         uint16_t fnum;
8206         uint32_t completion_filter;
8207         bool recursive;
8208         bool (*fn)(uint32_t action, const char *name, void *priv);
8209         void *priv;
8210 };
8211
8212 static void swallow_notify_done(struct tevent_req *subreq);
8213
8214 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8215                                               struct tevent_context *ev,
8216                                               struct cli_state *cli,
8217                                               uint16_t fnum,
8218                                               uint32_t completion_filter,
8219                                               bool recursive,
8220                                               bool (*fn)(uint32_t action,
8221                                                          const char *name,
8222                                                          void *priv),
8223                                               void *priv)
8224 {
8225         struct tevent_req *req, *subreq;
8226         struct swallow_notify_state *state;
8227
8228         req = tevent_req_create(mem_ctx, &state,
8229                                 struct swallow_notify_state);
8230         if (req == NULL) {
8231                 return NULL;
8232         }
8233         state->ev = ev;
8234         state->cli = cli;
8235         state->fnum = fnum;
8236         state->completion_filter = completion_filter;
8237         state->recursive = recursive;
8238         state->fn = fn;
8239         state->priv = priv;
8240
8241         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8242                                  0xffff, state->completion_filter,
8243                                  state->recursive);
8244         if (tevent_req_nomem(subreq, req)) {
8245                 return tevent_req_post(req, ev);
8246         }
8247         tevent_req_set_callback(subreq, swallow_notify_done, req);
8248         return req;
8249 }
8250
8251 static void swallow_notify_done(struct tevent_req *subreq)
8252 {
8253         struct tevent_req *req = tevent_req_callback_data(
8254                 subreq, struct tevent_req);
8255         struct swallow_notify_state *state = tevent_req_data(
8256                 req, struct swallow_notify_state);
8257         NTSTATUS status;
8258         uint32_t i, num_changes;
8259         struct notify_change *changes;
8260
8261         status = cli_notify_recv(subreq, state, &num_changes, &changes);
8262         TALLOC_FREE(subreq);
8263         if (!NT_STATUS_IS_OK(status)) {
8264                 DEBUG(10, ("cli_notify_recv returned %s\n",
8265                            nt_errstr(status)));
8266                 tevent_req_nterror(req, status);
8267                 return;
8268         }
8269
8270         for (i=0; i<num_changes; i++) {
8271                 state->fn(changes[i].action, changes[i].name, state->priv);
8272         }
8273         TALLOC_FREE(changes);
8274
8275         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8276                                  0xffff, state->completion_filter,
8277                                  state->recursive);
8278         if (tevent_req_nomem(subreq, req)) {
8279                 return;
8280         }
8281         tevent_req_set_callback(subreq, swallow_notify_done, req);
8282 }
8283
8284 static bool print_notifies(uint32_t action, const char *name, void *priv)
8285 {
8286         if (DEBUGLEVEL > 5) {
8287                 d_printf("%d %s\n", (int)action, name);
8288         }
8289         return true;
8290 }
8291
8292 static void notify_bench_done(struct tevent_req *req)
8293 {
8294         int *num_finished = (int *)tevent_req_callback_data_void(req);
8295         *num_finished += 1;
8296 }
8297
8298 static bool run_notify_bench(int dummy)
8299 {
8300         const char *dname = "\\notify-bench";
8301         struct tevent_context *ev;
8302         NTSTATUS status;
8303         uint16_t dnum;
8304         struct tevent_req *req1;
8305         struct tevent_req *req2 = NULL;
8306         int i, num_unc_names;
8307         int num_finished = 0;
8308
8309         printf("starting notify-bench test\n");
8310
8311         if (use_multishare_conn) {
8312                 char **unc_list;
8313                 unc_list = file_lines_load(multishare_conn_fname,
8314                                            &num_unc_names, 0, NULL);
8315                 if (!unc_list || num_unc_names <= 0) {
8316                         d_printf("Failed to load unc names list from '%s'\n",
8317                                  multishare_conn_fname);
8318                         return false;
8319                 }
8320                 TALLOC_FREE(unc_list);
8321         } else {
8322                 num_unc_names = 1;
8323         }
8324
8325         ev = samba_tevent_context_init(talloc_tos());
8326         if (ev == NULL) {
8327                 d_printf("tevent_context_init failed\n");
8328                 return false;
8329         }
8330
8331         for (i=0; i<num_unc_names; i++) {
8332                 struct cli_state *cli;
8333                 char *base_fname;
8334
8335                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8336                                              dname, i);
8337                 if (base_fname == NULL) {
8338                         return false;
8339                 }
8340
8341                 if (!torture_open_connection(&cli, i)) {
8342                         return false;
8343                 }
8344
8345                 status = cli_ntcreate(cli, dname, 0,
8346                                       MAXIMUM_ALLOWED_ACCESS,
8347                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8348                                       FILE_SHARE_DELETE,
8349                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8350                                       &dnum, NULL);
8351
8352                 if (!NT_STATUS_IS_OK(status)) {
8353                         d_printf("Could not create %s: %s\n", dname,
8354                                  nt_errstr(status));
8355                         return false;
8356                 }
8357
8358                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8359                                            FILE_NOTIFY_CHANGE_FILE_NAME |
8360                                            FILE_NOTIFY_CHANGE_DIR_NAME |
8361                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
8362                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
8363                                            false, print_notifies, NULL);
8364                 if (req1 == NULL) {
8365                         d_printf("Could not create notify request\n");
8366                         return false;
8367                 }
8368
8369                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8370                                                base_fname, 10, torture_numops);
8371                 if (req2 == NULL) {
8372                         d_printf("Could not create createdels request\n");
8373                         return false;
8374                 }
8375                 TALLOC_FREE(base_fname);
8376
8377                 tevent_req_set_callback(req2, notify_bench_done,
8378                                         &num_finished);
8379         }
8380
8381         while (num_finished < num_unc_names) {
8382                 int ret;
8383                 ret = tevent_loop_once(ev);
8384                 if (ret != 0) {
8385                         d_printf("tevent_loop_once failed\n");
8386                         return false;
8387                 }
8388         }
8389
8390         if (!tevent_req_poll(req2, ev)) {
8391                 d_printf("tevent_req_poll failed\n");
8392         }
8393
8394         status = torture_createdels_recv(req2);
8395         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8396
8397         return true;
8398 }
8399
8400 static bool run_mangle1(int dummy)
8401 {
8402         struct cli_state *cli;
8403         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8404         uint16_t fnum;
8405         fstring alt_name;
8406         NTSTATUS status;
8407         time_t change_time, access_time, write_time;
8408         off_t size;
8409         uint16_t mode;
8410
8411         printf("starting mangle1 test\n");
8412         if (!torture_open_connection(&cli, 0)) {
8413                 return False;
8414         }
8415
8416         smbXcli_conn_set_sockopt(cli->conn, sockops);
8417
8418         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8419                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8420                               0, 0, &fnum, NULL);
8421         if (!NT_STATUS_IS_OK(status)) {
8422                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8423                 return false;
8424         }
8425         cli_close(cli, fnum);
8426
8427         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8428         if (!NT_STATUS_IS_OK(status)) {
8429                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8430                          nt_errstr(status));
8431                 return false;
8432         }
8433         d_printf("alt_name: %s\n", alt_name);
8434
8435         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8436         if (!NT_STATUS_IS_OK(status)) {
8437                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8438                          nt_errstr(status));
8439                 return false;
8440         }
8441         cli_close(cli, fnum);
8442
8443         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8444                                 &write_time, &size, &mode);
8445         if (!NT_STATUS_IS_OK(status)) {
8446                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8447                          nt_errstr(status));
8448                 return false;
8449         }
8450
8451         return true;
8452 }
8453
8454 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8455                                                  struct file_info *f,
8456                                                  const char *mask,
8457                                                  void *state)
8458 {
8459         if (f->short_name == NULL) {
8460                 return NT_STATUS_OK;
8461         }
8462
8463         if (strlen(f->short_name) == 0) {
8464                 return NT_STATUS_OK;
8465         }
8466
8467         printf("unexpected shortname: %s\n", f->short_name);
8468
8469         return NT_STATUS_OBJECT_NAME_INVALID;
8470 }
8471
8472 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8473                                             struct file_info *f,
8474                                             const char *mask,
8475                                             void *state)
8476 {
8477         char *name = state;
8478
8479         printf("name: %s\n", f->name);
8480         fstrcpy(name, f->name);
8481         return NT_STATUS_OK;
8482 }
8483
8484 static bool run_mangle_illegal(int dummy)
8485 {
8486         struct cli_state *cli = NULL;
8487         struct cli_state *cli_posix = NULL;
8488         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8489         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8490         char *mangled_path = NULL;
8491         uint16_t fnum;
8492         fstring name;
8493         fstring alt_name;
8494         NTSTATUS status;
8495
8496         printf("starting mangle-illegal test\n");
8497
8498         if (!torture_open_connection(&cli, 0)) {
8499                 return False;
8500         }
8501
8502         smbXcli_conn_set_sockopt(cli->conn, sockops);
8503
8504         if (!torture_open_connection(&cli_posix, 0)) {
8505                 return false;
8506         }
8507
8508         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8509
8510         status = torture_setup_unix_extensions(cli_posix);
8511         if (!NT_STATUS_IS_OK(status)) {
8512                 return false;
8513         }
8514
8515         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8516         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8517         if (!NT_STATUS_IS_OK(status)) {
8518                 printf("mkdir1 failed : %s\n", nt_errstr(status));
8519                 return False;
8520         }
8521
8522         /*
8523          * Create a file with illegal NTFS characters and test that we
8524          * get a usable mangled name
8525          */
8526
8527         cli_setatr(cli_posix, illegal_fname, 0, 0);
8528         cli_posix_unlink(cli_posix, illegal_fname);
8529
8530         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8531                                 0600, &fnum);
8532         if (!NT_STATUS_IS_OK(status)) {
8533                 printf("POSIX create of %s failed (%s)\n",
8534                        illegal_fname, nt_errstr(status));
8535                 return false;
8536         }
8537
8538         status = cli_close(cli_posix, fnum);
8539         if (!NT_STATUS_IS_OK(status)) {
8540                 printf("close failed (%s)\n", nt_errstr(status));
8541                 return false;
8542         }
8543
8544         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8545         if (!NT_STATUS_IS_OK(status)) {
8546                 d_printf("cli_list failed: %s\n", nt_errstr(status));
8547                 return false;
8548         }
8549
8550         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8551         if (mangled_path == NULL) {
8552                 return false;
8553         }
8554
8555         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8556         if (!NT_STATUS_IS_OK(status)) {
8557                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8558                 TALLOC_FREE(mangled_path);
8559                 return false;
8560         }
8561         TALLOC_FREE(mangled_path);
8562         cli_close(cli, fnum);
8563
8564         cli_setatr(cli_posix, illegal_fname, 0, 0);
8565         cli_posix_unlink(cli_posix, illegal_fname);
8566
8567         /*
8568          * Create a file with a long name and check that we got *no* short name.
8569          */
8570
8571         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8572                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8573                               0, 0, &fnum, NULL);
8574         if (!NT_STATUS_IS_OK(status)) {
8575                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8576                 return false;
8577         }
8578         cli_close(cli, fnum);
8579
8580         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
8581         if (!NT_STATUS_IS_OK(status)) {
8582                 d_printf("cli_list failed\n");
8583                 return false;
8584         }
8585
8586         cli_unlink(cli, fname, 0);
8587         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8588
8589         if (!torture_close_connection(cli_posix)) {
8590                 return false;
8591         }
8592
8593         if (!torture_close_connection(cli)) {
8594                 return false;
8595         }
8596
8597         return true;
8598 }
8599
8600 static size_t null_source(uint8_t *buf, size_t n, void *priv)
8601 {
8602         size_t *to_pull = (size_t *)priv;
8603         size_t thistime = *to_pull;
8604
8605         thistime = MIN(thistime, n);
8606         if (thistime == 0) {
8607                 return 0;
8608         }
8609
8610         memset(buf, 0, thistime);
8611         *to_pull -= thistime;
8612         return thistime;
8613 }
8614
8615 static bool run_windows_write(int dummy)
8616 {
8617         struct cli_state *cli1;
8618         uint16_t fnum;
8619         int i;
8620         bool ret = false;
8621         const char *fname = "\\writetest.txt";
8622         struct timeval start_time;
8623         double seconds;
8624         double kbytes;
8625         NTSTATUS status;
8626
8627         printf("starting windows_write test\n");
8628         if (!torture_open_connection(&cli1, 0)) {
8629                 return False;
8630         }
8631
8632         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
8633         if (!NT_STATUS_IS_OK(status)) {
8634                 printf("open failed (%s)\n", nt_errstr(status));
8635                 return False;
8636         }
8637
8638         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8639
8640         start_time = timeval_current();
8641
8642         for (i=0; i<torture_numops; i++) {
8643                 uint8_t c = 0;
8644                 off_t start = i * torture_blocksize;
8645                 size_t to_pull = torture_blocksize - 1;
8646
8647                 status = cli_writeall(cli1, fnum, 0, &c,
8648                                       start + torture_blocksize - 1, 1, NULL);
8649                 if (!NT_STATUS_IS_OK(status)) {
8650                         printf("cli_write failed: %s\n", nt_errstr(status));
8651                         goto fail;
8652                 }
8653
8654                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
8655                                   null_source, &to_pull);
8656                 if (!NT_STATUS_IS_OK(status)) {
8657                         printf("cli_push returned: %s\n", nt_errstr(status));
8658                         goto fail;
8659                 }
8660         }
8661
8662         seconds = timeval_elapsed(&start_time);
8663         kbytes = (double)torture_blocksize * torture_numops;
8664         kbytes /= 1024;
8665
8666         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
8667                (double)seconds, (int)(kbytes/seconds));
8668
8669         ret = true;
8670  fail:
8671         cli_close(cli1, fnum);
8672         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8673         torture_close_connection(cli1);
8674         return ret;
8675 }
8676
8677 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
8678 {
8679         size_t max_pdu = 0x1FFFF;
8680
8681         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
8682                 max_pdu = 0xFFFFFF;
8683         }
8684
8685         if (smb1cli_conn_signing_is_active(cli->conn)) {
8686                 max_pdu = 0x1FFFF;
8687         }
8688
8689         if (smb1cli_conn_encryption_on(cli->conn)) {
8690                 max_pdu = CLI_BUFFER_SIZE;
8691         }
8692
8693         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
8694                 len_requested &= 0xFFFF;
8695         }
8696
8697         return MIN(len_requested,
8698                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
8699 }
8700
8701 static bool check_read_call(struct cli_state *cli,
8702                             uint16_t fnum,
8703                             uint8_t *buf,
8704                             size_t len_requested)
8705 {
8706         NTSTATUS status;
8707         struct tevent_req *subreq = NULL;
8708         ssize_t len_read = 0;
8709         size_t len_expected = 0;
8710         struct tevent_context *ev = NULL;
8711
8712         ev = samba_tevent_context_init(talloc_tos());
8713         if (ev == NULL) {
8714                 return false;
8715         }
8716
8717         subreq = cli_read_andx_send(talloc_tos(),
8718                                     ev,
8719                                     cli,
8720                                     fnum,
8721                                     0,
8722                                     len_requested);
8723
8724         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
8725                 return false;
8726         }
8727
8728         status = cli_read_andx_recv(subreq, &len_read, &buf);
8729         if (!NT_STATUS_IS_OK(status)) {
8730                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
8731                 return false;
8732         }
8733
8734         TALLOC_FREE(subreq);
8735         TALLOC_FREE(ev);
8736
8737         len_expected = calc_expected_return(cli, len_requested);
8738
8739         if (len_expected > 0x10000 && len_read == 0x10000) {
8740                 /* Windows servers only return a max of 0x10000,
8741                    doesn't matter if you set CAP_LARGE_READX in
8742                    the client sessionsetupX call or not. */
8743                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
8744                         (unsigned int)len_requested);
8745         } else if (len_read != len_expected) {
8746                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
8747                         (unsigned int)len_requested,
8748                         (unsigned int)len_read,
8749                         (unsigned int)len_expected);
8750                 return false;
8751         } else {
8752                 d_printf("Correct read reply.\n");
8753         }
8754
8755         return true;
8756 }
8757
8758 /* Test large readX variants. */
8759 static bool large_readx_tests(struct cli_state *cli,
8760                                 uint16_t fnum,
8761                                 uint8_t *buf)
8762 {
8763         /* A read of 0xFFFF0001 should *always* return 1 byte. */
8764         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
8765                 return false;
8766         }
8767         /* A read of 0x10000 should return 0x10000 bytes. */
8768         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
8769                 return false;
8770         }
8771         /* A read of 0x10000 should return 0x10001 bytes. */
8772         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
8773                 return false;
8774         }
8775         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
8776            the requested number of bytes. */
8777         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
8778                 return false;
8779         }
8780         /* A read of 1MB should return 1MB bytes (on Samba). */
8781         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
8782                 return false;
8783         }
8784
8785         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
8786                 return false;
8787         }
8788         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
8789                 return false;
8790         }
8791         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
8792                 return false;
8793         }
8794         return true;
8795 }
8796
8797 static bool run_large_readx(int dummy)
8798 {
8799         uint8_t *buf = NULL;
8800         struct cli_state *cli1 = NULL;
8801         struct cli_state *cli2 = NULL;
8802         bool correct = false;
8803         const char *fname = "\\large_readx.dat";
8804         NTSTATUS status;
8805         uint16_t fnum1 = UINT16_MAX;
8806         uint32_t normal_caps = 0;
8807         size_t file_size = 20*1024*1024;
8808         TALLOC_CTX *frame = talloc_stackframe();
8809         size_t i;
8810         struct {
8811                 const char *name;
8812                 enum smb_signing_setting signing_setting;
8813                 enum protocol_types protocol;
8814         } runs[] = {
8815                 {
8816                         .name = "NT1",
8817                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
8818                         .protocol = PROTOCOL_NT1,
8819                 },{
8820                         .name = "NT1 - SIGNING_REQUIRED",
8821                         .signing_setting = SMB_SIGNING_REQUIRED,
8822                         .protocol = PROTOCOL_NT1,
8823                 },
8824         };
8825
8826         printf("starting large_readx test\n");
8827
8828         if (!torture_open_connection(&cli1, 0)) {
8829                 goto out;
8830         }
8831
8832         normal_caps = smb1cli_conn_capabilities(cli1->conn);
8833
8834         if (!(normal_caps & CAP_LARGE_READX)) {
8835                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8836                         (unsigned int)normal_caps);
8837                 goto out;
8838         }
8839
8840         /* Create a file of size 4MB. */
8841         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
8842                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8843                         0, 0, &fnum1, NULL);
8844
8845         if (!NT_STATUS_IS_OK(status)) {
8846                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8847                 goto out;
8848         }
8849
8850         /* Write file_size bytes. */
8851         buf = talloc_zero_array(frame, uint8_t, file_size);
8852         if (buf == NULL) {
8853                 goto out;
8854         }
8855
8856         status = cli_writeall(cli1,
8857                               fnum1,
8858                               0,
8859                               buf,
8860                               0,
8861                               file_size,
8862                               NULL);
8863         if (!NT_STATUS_IS_OK(status)) {
8864                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
8865                 goto out;
8866         }
8867
8868         status = cli_close(cli1, fnum1);
8869         if (!NT_STATUS_IS_OK(status)) {
8870                 d_printf("cli_close failed: %s\n", nt_errstr(status));
8871                 goto out;
8872         }
8873
8874         fnum1 = UINT16_MAX;
8875
8876         for (i=0; i < ARRAY_SIZE(runs); i++) {
8877                 enum smb_signing_setting saved_signing_setting = signing_state;
8878                 uint16_t fnum2 = -1;
8879
8880                 if (do_encrypt &&
8881                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
8882                 {
8883                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
8884                         continue;
8885                 }
8886
8887                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
8888
8889                 signing_state = runs[i].signing_setting;
8890                 cli2 = open_nbt_connection();
8891                 signing_state = saved_signing_setting;
8892                 if (cli2 == NULL) {
8893                         goto out;
8894                 }
8895
8896                 status = smbXcli_negprot(cli2->conn,
8897                                          cli2->timeout,
8898                                          runs[i].protocol,
8899                                          runs[i].protocol);
8900                 if (!NT_STATUS_IS_OK(status)) {
8901                         goto out;
8902                 }
8903
8904                 status = cli_session_setup_creds(cli2, torture_creds);
8905                 if (!NT_STATUS_IS_OK(status)) {
8906                         goto out;
8907                 }
8908
8909                 status = cli_tree_connect(cli2,
8910                                         share,
8911                                         "?????",
8912                                         password);
8913                 if (!NT_STATUS_IS_OK(status)) {
8914                         goto out;
8915                 }
8916
8917                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
8918
8919                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
8920
8921                 if (!(normal_caps & CAP_LARGE_READX)) {
8922                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
8923                                 (unsigned int)normal_caps);
8924                         goto out;
8925                 }
8926
8927                 if (do_encrypt) {
8928                         if (force_cli_encryption(cli2, share) == false) {
8929                                 goto out;
8930                         }
8931                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
8932                         uint16_t major, minor;
8933                         uint32_t caplow, caphigh;
8934
8935                         status = cli_unix_extensions_version(cli2,
8936                                                              &major, &minor,
8937                                                              &caplow, &caphigh);
8938                         if (!NT_STATUS_IS_OK(status)) {
8939                                 goto out;
8940                         }
8941                 }
8942
8943                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
8944                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
8945                                 0, 0, &fnum2, NULL);
8946                 if (!NT_STATUS_IS_OK(status)) {
8947                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
8948                         goto out;
8949                 }
8950
8951                 /* All reads must return less than file_size bytes. */
8952                 if (!large_readx_tests(cli2, fnum2, buf)) {
8953                         goto out;
8954                 }
8955
8956                 status = cli_close(cli2, fnum2);
8957                 if (!NT_STATUS_IS_OK(status)) {
8958                         d_printf("cli_close failed: %s\n", nt_errstr(status));
8959                         goto out;
8960                 }
8961                 fnum2 = -1;
8962
8963                 if (!torture_close_connection(cli2)) {
8964                         goto out;
8965                 }
8966                 cli2 = NULL;
8967         }
8968
8969         correct = true;
8970         printf("Success on large_readx test\n");
8971
8972   out:
8973
8974         if (cli2) {
8975                 if (!torture_close_connection(cli2)) {
8976                         correct = false;
8977                 }
8978         }
8979
8980         if (cli1) {
8981                 if (fnum1 != UINT16_MAX) {
8982                         status = cli_close(cli1, fnum1);
8983                         if (!NT_STATUS_IS_OK(status)) {
8984                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
8985                         }
8986                         fnum1 = UINT16_MAX;
8987                 }
8988
8989                 status = cli_unlink(cli1, fname,
8990                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8991                 if (!NT_STATUS_IS_OK(status)) {
8992                         printf("unlink failed (%s)\n", nt_errstr(status));
8993                 }
8994
8995                 if (!torture_close_connection(cli1)) {
8996                         correct = false;
8997                 }
8998         }
8999
9000         TALLOC_FREE(frame);
9001
9002         printf("finished large_readx test\n");
9003         return correct;
9004 }
9005
9006 static bool run_cli_echo(int dummy)
9007 {
9008         struct cli_state *cli;
9009         NTSTATUS status;
9010
9011         printf("starting cli_echo test\n");
9012         if (!torture_open_connection(&cli, 0)) {
9013                 return false;
9014         }
9015         smbXcli_conn_set_sockopt(cli->conn, sockops);
9016
9017         status = cli_echo(cli, 5, data_blob_const("hello", 5));
9018
9019         d_printf("cli_echo returned %s\n", nt_errstr(status));
9020
9021         torture_close_connection(cli);
9022         return NT_STATUS_IS_OK(status);
9023 }
9024
9025 static bool run_uid_regression_test(int dummy)
9026 {
9027         static struct cli_state *cli;
9028         int16_t old_vuid;
9029         int32_t old_cnum;
9030         bool correct = True;
9031         struct smbXcli_tcon *orig_tcon = NULL;
9032         NTSTATUS status;
9033
9034         printf("starting uid regression test\n");
9035
9036         if (!torture_open_connection(&cli, 0)) {
9037                 return False;
9038         }
9039
9040         smbXcli_conn_set_sockopt(cli->conn, sockops);
9041
9042         /* Ok - now save then logoff our current user. */
9043         old_vuid = cli_state_get_uid(cli);
9044
9045         status = cli_ulogoff(cli);
9046         if (!NT_STATUS_IS_OK(status)) {
9047                 d_printf("(%s) cli_ulogoff failed: %s\n",
9048                          __location__, nt_errstr(status));
9049                 correct = false;
9050                 goto out;
9051         }
9052
9053         cli_state_set_uid(cli, old_vuid);
9054
9055         /* Try an operation. */
9056         status = cli_mkdir(cli, "\\uid_reg_test");
9057         if (NT_STATUS_IS_OK(status)) {
9058                 d_printf("(%s) cli_mkdir succeeded\n",
9059                          __location__);
9060                 correct = false;
9061                 goto out;
9062         } else {
9063                 /* Should be bad uid. */
9064                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9065                                  NT_STATUS_USER_SESSION_DELETED)) {
9066                         correct = false;
9067                         goto out;
9068                 }
9069         }
9070
9071         old_cnum = cli_state_get_tid(cli);
9072         orig_tcon = cli_state_save_tcon(cli);
9073         if (orig_tcon == NULL) {
9074                 correct = false;
9075                 goto out;
9076         }
9077
9078         /* Now try a SMBtdis with the invald vuid set to zero. */
9079         cli_state_set_uid(cli, 0);
9080
9081         /* This should succeed. */
9082         status = cli_tdis(cli);
9083
9084         if (NT_STATUS_IS_OK(status)) {
9085                 d_printf("First tdis with invalid vuid should succeed.\n");
9086         } else {
9087                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9088                 correct = false;
9089                 cli_state_restore_tcon(cli, orig_tcon);
9090                 goto out;
9091         }
9092
9093         cli_state_restore_tcon(cli, orig_tcon);
9094         cli_state_set_uid(cli, old_vuid);
9095         cli_state_set_tid(cli, old_cnum);
9096
9097         /* This should fail. */
9098         status = cli_tdis(cli);
9099         if (NT_STATUS_IS_OK(status)) {
9100                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9101                 correct = false;
9102                 goto out;
9103         } else {
9104                 /* Should be bad tid. */
9105                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9106                                 NT_STATUS_NETWORK_NAME_DELETED)) {
9107                         correct = false;
9108                         goto out;
9109                 }
9110         }
9111
9112         cli_rmdir(cli, "\\uid_reg_test");
9113
9114   out:
9115
9116         cli_shutdown(cli);
9117         return correct;
9118 }
9119
9120
9121 static const char *illegal_chars = "*\\/?<>|\":";
9122 static char force_shortname_chars[] = " +,.[];=\177";
9123
9124 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9125                              const char *mask, void *state)
9126 {
9127         struct cli_state *pcli = (struct cli_state *)state;
9128         fstring fname;
9129         NTSTATUS status = NT_STATUS_OK;
9130
9131         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9132
9133         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9134                 return NT_STATUS_OK;
9135
9136         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9137                 status = cli_rmdir(pcli, fname);
9138                 if (!NT_STATUS_IS_OK(status)) {
9139                         printf("del_fn: failed to rmdir %s\n,", fname );
9140                 }
9141         } else {
9142                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9143                 if (!NT_STATUS_IS_OK(status)) {
9144                         printf("del_fn: failed to unlink %s\n,", fname );
9145                 }
9146         }
9147         return status;
9148 }
9149
9150 struct sn_state {
9151         int matched;
9152         int i;
9153         bool val;
9154 };
9155
9156 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9157                               const char *name, void *state)
9158 {
9159         struct sn_state *s = (struct sn_state  *)state;
9160         int i = s->i;
9161
9162 #if 0
9163         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9164                 i, finfo->name, finfo->short_name);
9165 #endif
9166
9167         if (strchr(force_shortname_chars, i)) {
9168                 if (!finfo->short_name) {
9169                         /* Shortname not created when it should be. */
9170                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9171                                 __location__, finfo->name, i);
9172                         s->val = true;
9173                 }
9174         } else if (finfo->short_name){
9175                 /* Shortname created when it should not be. */
9176                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9177                         __location__, finfo->short_name, finfo->name);
9178                 s->val = true;
9179         }
9180         s->matched += 1;
9181         return NT_STATUS_OK;
9182 }
9183
9184 static bool run_shortname_test(int dummy)
9185 {
9186         static struct cli_state *cli;
9187         bool correct = True;
9188         int i;
9189         struct sn_state s;
9190         char fname[40];
9191         NTSTATUS status;
9192
9193         printf("starting shortname test\n");
9194
9195         if (!torture_open_connection(&cli, 0)) {
9196                 return False;
9197         }
9198
9199         smbXcli_conn_set_sockopt(cli->conn, sockops);
9200
9201         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9202         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9203         cli_rmdir(cli, "\\shortname");
9204
9205         status = cli_mkdir(cli, "\\shortname");
9206         if (!NT_STATUS_IS_OK(status)) {
9207                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9208                         __location__, nt_errstr(status));
9209                 correct = false;
9210                 goto out;
9211         }
9212
9213         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9214                 correct = false;
9215                 goto out;
9216         }
9217         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9218                 correct = false;
9219                 goto out;
9220         }
9221
9222         s.val = false;
9223
9224         for (i = 32; i < 128; i++) {
9225                 uint16_t fnum = (uint16_t)-1;
9226
9227                 s.i = i;
9228
9229                 if (strchr(illegal_chars, i)) {
9230                         continue;
9231                 }
9232                 fname[15] = i;
9233
9234                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9235                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
9236                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9237                 if (!NT_STATUS_IS_OK(status)) {
9238                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
9239                                 __location__, fname, nt_errstr(status));
9240                         correct = false;
9241                         goto out;
9242                 }
9243                 cli_close(cli, fnum);
9244
9245                 s.matched = 0;
9246                 status = cli_list(cli, "\\shortname\\test*.*", 0,
9247                                   shortname_list_fn, &s);
9248                 if (s.matched != 1) {
9249                         d_printf("(%s) failed to list %s: %s\n",
9250                                 __location__, fname, nt_errstr(status));
9251                         correct = false;
9252                         goto out;
9253                 }
9254
9255                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9256                 if (!NT_STATUS_IS_OK(status)) {
9257                         d_printf("(%s) failed to delete %s: %s\n",
9258                                 __location__, fname, nt_errstr(status));
9259                         correct = false;
9260                         goto out;
9261                 }
9262
9263                 if (s.val) {
9264                         correct = false;
9265                         goto out;
9266                 }
9267         }
9268
9269   out:
9270
9271         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9272         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9273         cli_rmdir(cli, "\\shortname");
9274         torture_close_connection(cli);
9275         return correct;
9276 }
9277
9278 static void pagedsearch_cb(struct tevent_req *req)
9279 {
9280         TLDAPRC rc;
9281         struct tldap_message *msg;
9282         char *dn;
9283
9284         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9285         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9286                 d_printf("tldap_search_paged_recv failed: %s\n",
9287                          tldap_rc2string(rc));
9288                 return;
9289         }
9290         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9291                 TALLOC_FREE(msg);
9292                 return;
9293         }
9294         if (!tldap_entry_dn(msg, &dn)) {
9295                 d_printf("tldap_entry_dn failed\n");
9296                 return;
9297         }
9298         d_printf("%s\n", dn);
9299         TALLOC_FREE(msg);
9300 }
9301
9302 static bool run_tldap(int dummy)
9303 {
9304         struct tldap_context *ld;
9305         int fd;
9306         TLDAPRC rc;
9307         NTSTATUS status;
9308         struct sockaddr_storage addr;
9309         struct tevent_context *ev;
9310         struct tevent_req *req;
9311         char *basedn;
9312         const char *filter;
9313
9314         if (!resolve_name(host, &addr, 0, false)) {
9315                 d_printf("could not find host %s\n", host);
9316                 return false;
9317         }
9318         status = open_socket_out(&addr, 389, 9999, &fd);
9319         if (!NT_STATUS_IS_OK(status)) {
9320                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9321                 return false;
9322         }
9323
9324         ld = tldap_context_create(talloc_tos(), fd);
9325         if (ld == NULL) {
9326                 close(fd);
9327                 d_printf("tldap_context_create failed\n");
9328                 return false;
9329         }
9330
9331         rc = tldap_fetch_rootdse(ld);
9332         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9333                 d_printf("tldap_fetch_rootdse failed: %s\n",
9334                          tldap_errstr(talloc_tos(), ld, rc));
9335                 return false;
9336         }
9337
9338         basedn = tldap_talloc_single_attribute(
9339                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9340         if (basedn == NULL) {
9341                 d_printf("no defaultNamingContext\n");
9342                 return false;
9343         }
9344         d_printf("defaultNamingContext: %s\n", basedn);
9345
9346         ev = samba_tevent_context_init(talloc_tos());
9347         if (ev == NULL) {
9348                 d_printf("tevent_context_init failed\n");
9349                 return false;
9350         }
9351
9352         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9353                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
9354                                       NULL, 0, 0,
9355                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
9356         if (req == NULL) {
9357                 d_printf("tldap_search_paged_send failed\n");
9358                 return false;
9359         }
9360         tevent_req_set_callback(req, pagedsearch_cb, NULL);
9361
9362         tevent_req_poll(req, ev);
9363
9364         TALLOC_FREE(req);
9365
9366         /* test search filters against rootDSE */
9367         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9368                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9369
9370         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9371                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9372                           talloc_tos(), NULL);
9373         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9374                 d_printf("tldap_search with complex filter failed: %s\n",
9375                          tldap_errstr(talloc_tos(), ld, rc));
9376                 return false;
9377         }
9378
9379         TALLOC_FREE(ld);
9380         return true;
9381 }
9382
9383 /* Torture test to ensure no regression of :
9384 https://bugzilla.samba.org/show_bug.cgi?id=7084
9385 */
9386
9387 static bool run_dir_createtime(int dummy)
9388 {
9389         struct cli_state *cli;
9390         const char *dname = "\\testdir";
9391         const char *fname = "\\testdir\\testfile";
9392         NTSTATUS status;
9393         struct timespec create_time;
9394         struct timespec create_time1;
9395         uint16_t fnum;
9396         bool ret = false;
9397
9398         if (!torture_open_connection(&cli, 0)) {
9399                 return false;
9400         }
9401
9402         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9403         cli_rmdir(cli, dname);
9404
9405         status = cli_mkdir(cli, dname);
9406         if (!NT_STATUS_IS_OK(status)) {
9407                 printf("mkdir failed: %s\n", nt_errstr(status));
9408                 goto out;
9409         }
9410
9411         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9412                                 NULL, NULL, NULL);
9413         if (!NT_STATUS_IS_OK(status)) {
9414                 printf("cli_qpathinfo2 returned %s\n",
9415                        nt_errstr(status));
9416                 goto out;
9417         }
9418
9419         /* Sleep 3 seconds, then create a file. */
9420         sleep(3);
9421
9422         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9423                          DENY_NONE, &fnum);
9424         if (!NT_STATUS_IS_OK(status)) {
9425                 printf("cli_openx failed: %s\n", nt_errstr(status));
9426                 goto out;
9427         }
9428
9429         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
9430                                 NULL, NULL, NULL);
9431         if (!NT_STATUS_IS_OK(status)) {
9432                 printf("cli_qpathinfo2 (2) returned %s\n",
9433                        nt_errstr(status));
9434                 goto out;
9435         }
9436
9437         if (timespec_compare(&create_time1, &create_time)) {
9438                 printf("run_dir_createtime: create time was updated (error)\n");
9439         } else {
9440                 printf("run_dir_createtime: create time was not updated (correct)\n");
9441                 ret = true;
9442         }
9443
9444   out:
9445
9446         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9447         cli_rmdir(cli, dname);
9448         if (!torture_close_connection(cli)) {
9449                 ret = false;
9450         }
9451         return ret;
9452 }
9453
9454
9455 static bool run_streamerror(int dummy)
9456 {
9457         struct cli_state *cli;
9458         const char *dname = "\\testdir";
9459         const char *streamname =
9460                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
9461         NTSTATUS status;
9462         time_t change_time, access_time, write_time;
9463         off_t size;
9464         uint16_t mode, fnum;
9465         bool ret = true;
9466
9467         if (!torture_open_connection(&cli, 0)) {
9468                 return false;
9469         }
9470
9471         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9472         cli_rmdir(cli, dname);
9473
9474         status = cli_mkdir(cli, dname);
9475         if (!NT_STATUS_IS_OK(status)) {
9476                 printf("mkdir failed: %s\n", nt_errstr(status));
9477                 return false;
9478         }
9479
9480         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
9481                                 &write_time, &size, &mode);
9482         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9483                 printf("pathinfo returned %s, expected "
9484                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9485                        nt_errstr(status));
9486                 ret = false;
9487         }
9488
9489         status = cli_ntcreate(cli, streamname, 0x16,
9490                               FILE_READ_DATA|FILE_READ_EA|
9491                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
9492                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
9493                               FILE_OPEN, 0, 0, &fnum, NULL);
9494
9495         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
9496                 printf("ntcreate returned %s, expected "
9497                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
9498                        nt_errstr(status));
9499                 ret = false;
9500         }
9501
9502
9503         cli_rmdir(cli, dname);
9504         return ret;
9505 }
9506
9507 struct pidtest_state {
9508         bool success;
9509         uint16_t vwv[1];
9510         DATA_BLOB data;
9511 };
9512
9513 static void pid_echo_done(struct tevent_req *subreq);
9514
9515 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
9516                         struct tevent_context *ev,
9517                         struct cli_state *cli)
9518 {
9519         struct tevent_req *req, *subreq;
9520         struct pidtest_state *state;
9521
9522         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
9523         if (req == NULL) {
9524                 return NULL;
9525         }
9526
9527         SSVAL(state->vwv, 0, 1);
9528         state->data = data_blob_const("hello", 5);
9529
9530         subreq = smb1cli_req_send(state,
9531                                 ev,
9532                                 cli->conn,
9533                                 SMBecho,
9534                                 0, 0, /* *_flags */
9535                                 0, 0, /* *_flags2 */
9536                                 cli->timeout,
9537                                 0xDEADBEEF, /* pid */
9538                                 NULL, /* tcon */
9539                                 NULL, /* session */
9540                                 ARRAY_SIZE(state->vwv), state->vwv,
9541                                 state->data.length, state->data.data);
9542
9543         if (tevent_req_nomem(subreq, req)) {
9544                 return tevent_req_post(req, ev);
9545         }
9546         tevent_req_set_callback(subreq, pid_echo_done, req);
9547         return req;
9548 }
9549
9550 static void pid_echo_done(struct tevent_req *subreq)
9551 {
9552         struct tevent_req *req = tevent_req_callback_data(
9553                 subreq, struct tevent_req);
9554         struct pidtest_state *state = tevent_req_data(
9555                 req, struct pidtest_state);
9556         NTSTATUS status;
9557         uint32_t num_bytes;
9558         uint8_t *bytes = NULL;
9559         struct iovec *recv_iov = NULL;
9560         uint8_t *phdr = NULL;
9561         uint16_t pidlow = 0;
9562         uint16_t pidhigh = 0;
9563         struct smb1cli_req_expected_response expected[] = {
9564         {
9565                 .status = NT_STATUS_OK,
9566                 .wct    = 1,
9567         },
9568         };
9569
9570         status = smb1cli_req_recv(subreq, state,
9571                                 &recv_iov,
9572                                 &phdr,
9573                                 NULL, /* pwct */
9574                                 NULL, /* pvwv */
9575                                 NULL, /* pvwv_offset */
9576                                 &num_bytes,
9577                                 &bytes,
9578                                 NULL, /* pbytes_offset */
9579                                 NULL, /* pinbuf */
9580                                 expected, ARRAY_SIZE(expected));
9581
9582         TALLOC_FREE(subreq);
9583
9584         if (!NT_STATUS_IS_OK(status)) {
9585                 tevent_req_nterror(req, status);
9586                 return;
9587         }
9588
9589         if (num_bytes != state->data.length) {
9590                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9591                 return;
9592         }
9593
9594         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
9595                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9596                 return;
9597         }
9598
9599         /* Check pid low/high == DEADBEEF */
9600         pidlow = SVAL(phdr, HDR_PID);
9601         if (pidlow != 0xBEEF){
9602                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
9603                         (unsigned int)pidlow);
9604                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9605                 return;
9606         }
9607         pidhigh = SVAL(phdr, HDR_PIDHIGH);
9608         if (pidhigh != 0xDEAD){
9609                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
9610                         (unsigned int)pidhigh);
9611                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
9612                 return;
9613         }
9614
9615         tevent_req_done(req);
9616 }
9617
9618 static NTSTATUS pid_echo_recv(struct tevent_req *req)
9619 {
9620         return tevent_req_simple_recv_ntstatus(req);
9621 }
9622
9623 static bool run_pidhigh(int dummy)
9624 {
9625         bool success = false;
9626         struct cli_state *cli = NULL;
9627         NTSTATUS status;
9628         struct tevent_context *ev = NULL;
9629         struct tevent_req *req = NULL;
9630         TALLOC_CTX *frame = talloc_stackframe();
9631
9632         printf("starting pid high test\n");
9633         if (!torture_open_connection(&cli, 0)) {
9634                 return false;
9635         }
9636         smbXcli_conn_set_sockopt(cli->conn, sockops);
9637
9638         ev = samba_tevent_context_init(frame);
9639         if (ev == NULL) {
9640                 goto fail;
9641         }
9642
9643         req = pid_echo_send(frame, ev, cli);
9644         if (req == NULL) {
9645                 goto fail;
9646         }
9647
9648         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
9649                 goto fail;
9650         }
9651
9652         status = pid_echo_recv(req);
9653         if (NT_STATUS_IS_OK(status)) {
9654                 printf("pid high test ok\n");
9655                 success = true;
9656         }
9657
9658  fail:
9659
9660         TALLOC_FREE(frame);
9661         torture_close_connection(cli);
9662         return success;
9663 }
9664
9665 /*
9666   Test Windows open on a bad POSIX symlink.
9667  */
9668 static bool run_symlink_open_test(int dummy)
9669 {
9670         static struct cli_state *cli;
9671         const char *fname = "non_existant_file";
9672         const char *sname = "dangling_symlink";
9673         uint16_t fnum = (uint16_t)-1;
9674         bool correct = false;
9675         NTSTATUS status;
9676         TALLOC_CTX *frame = NULL;
9677
9678         frame = talloc_stackframe();
9679
9680         printf("Starting Windows bad symlink open test\n");
9681
9682         if (!torture_open_connection(&cli, 0)) {
9683                 TALLOC_FREE(frame);
9684                 return false;
9685         }
9686
9687         smbXcli_conn_set_sockopt(cli->conn, sockops);
9688
9689         status = torture_setup_unix_extensions(cli);
9690         if (!NT_STATUS_IS_OK(status)) {
9691                 TALLOC_FREE(frame);
9692                 return false;
9693         }
9694
9695         /* Ensure nothing exists. */
9696         cli_setatr(cli, fname, 0, 0);
9697         cli_posix_unlink(cli, fname);
9698         cli_setatr(cli, sname, 0, 0);
9699         cli_posix_unlink(cli, sname);
9700
9701         /* Create a symlink pointing nowhere. */
9702         status = cli_posix_symlink(cli, fname, sname);
9703         if (!NT_STATUS_IS_OK(status)) {
9704                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
9705                         sname,
9706                         fname,
9707                         nt_errstr(status));
9708                 goto out;
9709         }
9710
9711         /* Now ensure that a Windows open doesn't hang. */
9712         status = cli_ntcreate(cli,
9713                         sname,
9714                         0,
9715                         FILE_READ_DATA|FILE_WRITE_DATA,
9716                         0,
9717                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9718                         FILE_OPEN_IF,
9719                         0x0,
9720                         0x0,
9721                         &fnum,
9722                         NULL);
9723
9724         /*
9725          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
9726          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
9727          * we use O_NOFOLLOW on the server or not.
9728          */
9729         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
9730             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
9731         {
9732                 correct = true;
9733         } else {
9734                 printf("cli_ntcreate of %s returned %s - should return"
9735                                 " either (%s) or (%s)\n",
9736                         sname,
9737                         nt_errstr(status),
9738                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
9739                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
9740                 goto out;
9741         }
9742
9743         correct = true;
9744
9745   out:
9746
9747         if (fnum != (uint16_t)-1) {
9748                 cli_close(cli, fnum);
9749                 fnum = (uint16_t)-1;
9750         }
9751
9752         cli_setatr(cli, sname, 0, 0);
9753         cli_posix_unlink(cli, sname);
9754         cli_setatr(cli, fname, 0, 0);
9755         cli_posix_unlink(cli, fname);
9756
9757         if (!torture_close_connection(cli)) {
9758                 correct = false;
9759         }
9760
9761         TALLOC_FREE(frame);
9762         return correct;
9763 }
9764
9765 static bool run_local_substitute(int dummy)
9766 {
9767         bool ok = true;
9768
9769         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
9770         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
9771         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
9772         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
9773         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
9774         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
9775         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
9776         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
9777
9778         /* Different captialization rules in sub_basic... */
9779
9780         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
9781                        "blaDOM") == 0);
9782
9783         return ok;
9784 }
9785
9786 static bool run_local_base64(int dummy)
9787 {
9788         int i;
9789         bool ret = true;
9790
9791         for (i=1; i<2000; i++) {
9792                 DATA_BLOB blob1, blob2;
9793                 char *b64;
9794
9795                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
9796                 blob1.length = i;
9797                 generate_random_buffer(blob1.data, blob1.length);
9798
9799                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
9800                 if (b64 == NULL) {
9801                         d_fprintf(stderr, "base64_encode_data_blob failed "
9802                                   "for %d bytes\n", i);
9803                         ret = false;
9804                 }
9805                 blob2 = base64_decode_data_blob(b64);
9806                 TALLOC_FREE(b64);
9807
9808                 if (data_blob_cmp(&blob1, &blob2)) {
9809                         d_fprintf(stderr, "data_blob_cmp failed for %d "
9810                                   "bytes\n", i);
9811                         ret = false;
9812                 }
9813                 TALLOC_FREE(blob1.data);
9814                 data_blob_free(&blob2);
9815         }
9816         return ret;
9817 }
9818
9819 static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
9820 {
9821         return;
9822 }
9823
9824 static bool run_local_gencache(int dummy)
9825 {
9826         char *val;
9827         time_t tm;
9828         DATA_BLOB blob;
9829         char v;
9830         struct memcache *mem;
9831         int i;
9832
9833         mem = memcache_init(NULL, 0);
9834         if (mem == NULL) {
9835                 d_printf("%s: memcache_init failed\n", __location__);
9836                 return false;
9837         }
9838         memcache_set_global(mem);
9839
9840         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
9841                 d_printf("%s: gencache_set() failed\n", __location__);
9842                 return False;
9843         }
9844
9845         if (!gencache_get("foo", NULL, NULL, NULL)) {
9846                 d_printf("%s: gencache_get() failed\n", __location__);
9847                 return False;
9848         }
9849
9850         for (i=0; i<1000000; i++) {
9851                 gencache_parse("foo", parse_fn, NULL);
9852         }
9853
9854         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9855                 d_printf("%s: gencache_get() failed\n", __location__);
9856                 return False;
9857         }
9858         TALLOC_FREE(val);
9859
9860         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
9861                 d_printf("%s: gencache_get() failed\n", __location__);
9862                 return False;
9863         }
9864
9865         if (strcmp(val, "bar") != 0) {
9866                 d_printf("%s: gencache_get() returned %s, expected %s\n",
9867                          __location__, val, "bar");
9868                 TALLOC_FREE(val);
9869                 return False;
9870         }
9871
9872         TALLOC_FREE(val);
9873
9874         if (!gencache_del("foo")) {
9875                 d_printf("%s: gencache_del() failed\n", __location__);
9876                 return False;
9877         }
9878         if (gencache_del("foo")) {
9879                 d_printf("%s: second gencache_del() succeeded\n",
9880                          __location__);
9881                 return False;
9882         }
9883
9884         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
9885                 d_printf("%s: gencache_get() on deleted entry "
9886                          "succeeded\n", __location__);
9887                 return False;
9888         }
9889
9890         blob = data_blob_string_const_null("bar");
9891         tm = time(NULL) + 60;
9892
9893         if (!gencache_set_data_blob("foo", &blob, tm)) {
9894                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
9895                 return False;
9896         }
9897
9898         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9899                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
9900                 return False;
9901         }
9902
9903         if (strcmp((const char *)blob.data, "bar") != 0) {
9904                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
9905                          __location__, (const char *)blob.data, "bar");
9906                 data_blob_free(&blob);
9907                 return False;
9908         }
9909
9910         data_blob_free(&blob);
9911
9912         if (!gencache_del("foo")) {
9913                 d_printf("%s: gencache_del() failed\n", __location__);
9914                 return False;
9915         }
9916         if (gencache_del("foo")) {
9917                 d_printf("%s: second gencache_del() succeeded\n",
9918                          __location__);
9919                 return False;
9920         }
9921
9922         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
9923                 d_printf("%s: gencache_get_data_blob() on deleted entry "
9924                          "succeeded\n", __location__);
9925                 return False;
9926         }
9927
9928         v = 1;
9929         blob.data = (uint8_t *)&v;
9930         blob.length = sizeof(v);
9931
9932         if (!gencache_set_data_blob("blob", &blob, tm)) {
9933                 d_printf("%s: gencache_set_data_blob() failed\n",
9934                          __location__);
9935                 return false;
9936         }
9937         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
9938                 d_printf("%s: gencache_get succeeded\n", __location__);
9939                 return false;
9940         }
9941
9942         return True;
9943 }
9944
9945 static bool rbt_testval(struct db_context *db, const char *key,
9946                         const char *value)
9947 {
9948         struct db_record *rec;
9949         TDB_DATA data = string_tdb_data(value);
9950         bool ret = false;
9951         NTSTATUS status;
9952         TDB_DATA dbvalue;
9953
9954         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9955         if (rec == NULL) {
9956                 d_fprintf(stderr, "fetch_locked failed\n");
9957                 goto done;
9958         }
9959         status = dbwrap_record_store(rec, data, 0);
9960         if (!NT_STATUS_IS_OK(status)) {
9961                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
9962                 goto done;
9963         }
9964         TALLOC_FREE(rec);
9965
9966         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
9967         if (rec == NULL) {
9968                 d_fprintf(stderr, "second fetch_locked failed\n");
9969                 goto done;
9970         }
9971
9972         dbvalue = dbwrap_record_get_value(rec);
9973         if ((dbvalue.dsize != data.dsize)
9974             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
9975                 d_fprintf(stderr, "Got wrong data back\n");
9976                 goto done;
9977         }
9978
9979         ret = true;
9980  done:
9981         TALLOC_FREE(rec);
9982         return ret;
9983 }
9984
9985 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
9986 {
9987         int *count2 = (int *)private_data;
9988         (*count2)++;
9989         return 0;
9990 }
9991
9992 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
9993 {
9994         int *count2 = (int *)private_data;
9995         (*count2)++;
9996         dbwrap_record_delete(rec);
9997         return 0;
9998 }
9999
10000 static bool run_local_rbtree(int dummy)
10001 {
10002         struct db_context *db;
10003         bool ret = false;
10004         int i;
10005         NTSTATUS status;
10006         int count = 0;
10007         int count2 = 0;
10008
10009         db = db_open_rbt(NULL);
10010
10011         if (db == NULL) {
10012                 d_fprintf(stderr, "db_open_rbt failed\n");
10013                 return false;
10014         }
10015
10016         for (i=0; i<1000; i++) {
10017                 char *key, *value;
10018
10019                 if (asprintf(&key, "key%ld", random()) == -1) {
10020                         goto done;
10021                 }
10022                 if (asprintf(&value, "value%ld", random()) == -1) {
10023                         SAFE_FREE(key);
10024                         goto done;
10025                 }
10026
10027                 if (!rbt_testval(db, key, value)) {
10028                         SAFE_FREE(key);
10029                         SAFE_FREE(value);
10030                         goto done;
10031                 }
10032
10033                 SAFE_FREE(value);
10034                 if (asprintf(&value, "value%ld", random()) == -1) {
10035                         SAFE_FREE(key);
10036                         goto done;
10037                 }
10038
10039                 if (!rbt_testval(db, key, value)) {
10040                         SAFE_FREE(key);
10041                         SAFE_FREE(value);
10042                         goto done;
10043                 }
10044
10045                 SAFE_FREE(key);
10046                 SAFE_FREE(value);
10047         }
10048
10049         ret = true;
10050         count = 0; count2 = 0;
10051         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10052                                       &count2, &count);
10053         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10054         if ((count != count2) || (count != 1000)) {
10055                 ret = false;
10056         }
10057         count = 0; count2 = 0;
10058         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10059                                  &count2, &count);
10060         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10061         if ((count != count2) || (count != 1000)) {
10062                 ret = false;
10063         }
10064         count = 0; count2 = 0;
10065         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10066                                       &count2, &count);
10067         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10068         if ((count != count2) || (count != 0)) {
10069                 ret = false;
10070         }
10071
10072  done:
10073         TALLOC_FREE(db);
10074         return ret;
10075 }
10076
10077
10078 /*
10079   local test for character set functions
10080
10081   This is a very simple test for the functionality in convert_string_error()
10082  */
10083 static bool run_local_convert_string(int dummy)
10084 {
10085         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10086         const char *test_strings[2] = { "March", "M\303\244rz" };
10087         char dst[7];
10088         int i;
10089
10090         for (i=0; i<2; i++) {
10091                 const char *str = test_strings[i];
10092                 int len = strlen(str);
10093                 size_t converted_size;
10094                 bool ret;
10095
10096                 memset(dst, 'X', sizeof(dst));
10097
10098                 /* first try with real source length */
10099                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10100                                            str, len,
10101                                            dst, sizeof(dst),
10102                                            &converted_size);
10103                 if (ret != true) {
10104                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10105                         goto failed;
10106                 }
10107
10108                 if (converted_size != len) {
10109                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10110                                   str, len, (int)converted_size);
10111                         goto failed;
10112                 }
10113
10114                 if (strncmp(str, dst, converted_size) != 0) {
10115                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10116                         goto failed;
10117                 }
10118
10119                 if (strlen(str) != converted_size) {
10120                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10121                                   (int)strlen(str), (int)converted_size);
10122                         goto failed;
10123                 }
10124
10125                 if (dst[converted_size] != 'X') {
10126                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10127                         goto failed;
10128                 }
10129
10130                 /* now with srclen==-1, this causes the nul to be
10131                  * converted too */
10132                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10133                                            str, -1,
10134                                            dst, sizeof(dst),
10135                                            &converted_size);
10136                 if (ret != true) {
10137                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10138                         goto failed;
10139                 }
10140
10141                 if (converted_size != len+1) {
10142                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10143                                   str, len, (int)converted_size);
10144                         goto failed;
10145                 }
10146
10147                 if (strncmp(str, dst, converted_size) != 0) {
10148                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10149                         goto failed;
10150                 }
10151
10152                 if (len+1 != converted_size) {
10153                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10154                                   len+1, (int)converted_size);
10155                         goto failed;
10156                 }
10157
10158                 if (dst[converted_size] != 'X') {
10159                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10160                         goto failed;
10161                 }
10162
10163         }
10164
10165
10166         TALLOC_FREE(tmp_ctx);
10167         return true;
10168 failed:
10169         TALLOC_FREE(tmp_ctx);
10170         return false;
10171 }
10172
10173
10174 struct talloc_dict_test {
10175         int content;
10176 };
10177
10178 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
10179 {
10180         int *count = (int *)priv;
10181         *count += 1;
10182         return 0;
10183 }
10184
10185 static bool run_local_talloc_dict(int dummy)
10186 {
10187         struct talloc_dict *dict;
10188         struct talloc_dict_test *t;
10189         int key, count, res;
10190         bool ok;
10191
10192         dict = talloc_dict_init(talloc_tos());
10193         if (dict == NULL) {
10194                 return false;
10195         }
10196
10197         t = talloc(talloc_tos(), struct talloc_dict_test);
10198         if (t == NULL) {
10199                 return false;
10200         }
10201
10202         key = 1;
10203         t->content = 1;
10204         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
10205         if (!ok) {
10206                 return false;
10207         }
10208
10209         count = 0;
10210         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
10211         if (res == -1) {
10212                 return false;
10213         }
10214
10215         if (count != 1) {
10216                 return false;
10217         }
10218
10219         if (count != res) {
10220                 return false;
10221         }
10222
10223         TALLOC_FREE(dict);
10224
10225         return true;
10226 }
10227
10228 static bool run_local_string_to_sid(int dummy) {
10229         struct dom_sid sid;
10230
10231         if (string_to_sid(&sid, "S--1-5-32-545")) {
10232                 printf("allowing S--1-5-32-545\n");
10233                 return false;
10234         }
10235         if (string_to_sid(&sid, "S-1-5-32-+545")) {
10236                 printf("allowing S-1-5-32-+545\n");
10237                 return false;
10238         }
10239         if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
10240                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10241                 return false;
10242         }
10243         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10244                 printf("allowing S-1-5-32-545-abc\n");
10245                 return false;
10246         }
10247         if (string_to_sid(&sid, "S-300-5-32-545")) {
10248                 printf("allowing S-300-5-32-545\n");
10249                 return false;
10250         }
10251         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10252                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10253                 return false;
10254         }
10255         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10256                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10257                 return false;
10258         }
10259         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10260                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10261                 return false;
10262         }
10263         if (!string_to_sid(&sid, "S-1-5-32-545")) {
10264                 printf("could not parse S-1-5-32-545\n");
10265                 return false;
10266         }
10267         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10268                 printf("mis-parsed S-1-5-32-545 as %s\n",
10269                        sid_string_tos(&sid));
10270                 return false;
10271         }
10272         return true;
10273 }
10274
10275 static bool sid_to_string_test(const char *expected) {
10276         char *str;
10277         bool res = true;
10278         struct dom_sid sid;
10279
10280         if (!string_to_sid(&sid, expected)) {
10281                 printf("could not parse %s\n", expected);
10282                 return false;
10283         }
10284
10285         str = dom_sid_string(NULL, &sid);
10286         if (strcmp(str, expected)) {
10287                 printf("Comparison failed (%s != %s)\n", str, expected);
10288                 res = false;
10289         }
10290         TALLOC_FREE(str);
10291         return res;
10292 }
10293
10294 static bool run_local_sid_to_string(int dummy) {
10295         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10296                 return false;
10297         if (!sid_to_string_test("S-1-545"))
10298                 return false;
10299         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10300                 return false;
10301         return true;
10302 }
10303
10304 static bool run_local_binary_to_sid(int dummy) {
10305         struct dom_sid *sid = talloc(NULL, struct dom_sid);
10306         static const uint8_t good_binary_sid[] = {
10307                 0x1, /* revision number */
10308                 15, /* num auths */
10309                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10310                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10311                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10312                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10313                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10314                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10315                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10316                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10317                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10318                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10319                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10320                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10321                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10322                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10323                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10324                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10325         };
10326
10327         static const uint8_t long_binary_sid[] = {
10328                 0x1, /* revision number */
10329                 15, /* num auths */
10330                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10331                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10332                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10333                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10334                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10335                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10336                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10337                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10338                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10339                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10340                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10341                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10342                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10343                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10344                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10345                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10346                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10347                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10348                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10349         };
10350
10351         static const uint8_t long_binary_sid2[] = {
10352                 0x1, /* revision number */
10353                 32, /* num auths */
10354                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10355                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10356                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10357                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10358                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10359                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10360                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10361                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10362                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10363                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10364                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10365                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10366                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10367                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10368                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10369                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10370                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10371                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10372                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10373                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10374                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10375                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10376                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10377                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10378                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10379                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10380                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10381                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10382                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10383                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10384                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10385                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10386                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10387         };
10388
10389         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
10390                 return false;
10391         }
10392         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
10393                 return false;
10394         }
10395         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
10396                 return false;
10397         }
10398         return true;
10399 }
10400
10401 /* Split a path name into filename and stream name components. Canonicalise
10402  * such that an implicit $DATA token is always explicit.
10403  *
10404  * The "specification" of this function can be found in the
10405  * run_local_stream_name() function in torture.c, I've tried those
10406  * combinations against a W2k3 server.
10407  */
10408
10409 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10410                                        char **pbase, char **pstream)
10411 {
10412         char *base = NULL;
10413         char *stream = NULL;
10414         char *sname; /* stream name */
10415         const char *stype; /* stream type */
10416
10417         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10418
10419         sname = strchr_m(fname, ':');
10420
10421         if (sname == NULL) {
10422                 if (pbase != NULL) {
10423                         base = talloc_strdup(mem_ctx, fname);
10424                         NT_STATUS_HAVE_NO_MEMORY(base);
10425                 }
10426                 goto done;
10427         }
10428
10429         if (pbase != NULL) {
10430                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
10431                 NT_STATUS_HAVE_NO_MEMORY(base);
10432         }
10433
10434         sname += 1;
10435
10436         stype = strchr_m(sname, ':');
10437
10438         if (stype == NULL) {
10439                 sname = talloc_strdup(mem_ctx, sname);
10440                 stype = "$DATA";
10441         }
10442         else {
10443                 if (strcasecmp_m(stype, ":$DATA") != 0) {
10444                         /*
10445                          * If there is an explicit stream type, so far we only
10446                          * allow $DATA. Is there anything else allowed? -- vl
10447                          */
10448                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
10449                         TALLOC_FREE(base);
10450                         return NT_STATUS_OBJECT_NAME_INVALID;
10451                 }
10452                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
10453                 stype += 1;
10454         }
10455
10456         if (sname == NULL) {
10457                 TALLOC_FREE(base);
10458                 return NT_STATUS_NO_MEMORY;
10459         }
10460
10461         if (sname[0] == '\0') {
10462                 /*
10463                  * no stream name, so no stream
10464                  */
10465                 goto done;
10466         }
10467
10468         if (pstream != NULL) {
10469                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
10470                 if (stream == NULL) {
10471                         TALLOC_FREE(sname);
10472                         TALLOC_FREE(base);
10473                         return NT_STATUS_NO_MEMORY;
10474                 }
10475                 /*
10476                  * upper-case the type field
10477                  */
10478                 (void)strupper_m(strchr_m(stream, ':')+1);
10479         }
10480
10481  done:
10482         if (pbase != NULL) {
10483                 *pbase = base;
10484         }
10485         if (pstream != NULL) {
10486                 *pstream = stream;
10487         }
10488         return NT_STATUS_OK;
10489 }
10490
10491 static bool test_stream_name(const char *fname, const char *expected_base,
10492                              const char *expected_stream,
10493                              NTSTATUS expected_status)
10494 {
10495         NTSTATUS status;
10496         char *base = NULL;
10497         char *stream = NULL;
10498
10499         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
10500         if (!NT_STATUS_EQUAL(status, expected_status)) {
10501                 goto error;
10502         }
10503
10504         if (!NT_STATUS_IS_OK(status)) {
10505                 return true;
10506         }
10507
10508         if (base == NULL) goto error;
10509
10510         if (strcmp(expected_base, base) != 0) goto error;
10511
10512         if ((expected_stream != NULL) && (stream == NULL)) goto error;
10513         if ((expected_stream == NULL) && (stream != NULL)) goto error;
10514
10515         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
10516                 goto error;
10517
10518         TALLOC_FREE(base);
10519         TALLOC_FREE(stream);
10520         return true;
10521
10522  error:
10523         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
10524                   fname, expected_base ? expected_base : "<NULL>",
10525                   expected_stream ? expected_stream : "<NULL>",
10526                   nt_errstr(expected_status));
10527         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
10528                   base ? base : "<NULL>", stream ? stream : "<NULL>",
10529                   nt_errstr(status));
10530         TALLOC_FREE(base);
10531         TALLOC_FREE(stream);
10532         return false;
10533 }
10534
10535 static bool run_local_stream_name(int dummy)
10536 {
10537         bool ret = true;
10538
10539         ret &= test_stream_name(
10540                 "bla", "bla", NULL, NT_STATUS_OK);
10541         ret &= test_stream_name(
10542                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
10543         ret &= test_stream_name(
10544                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10545         ret &= test_stream_name(
10546                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
10547         ret &= test_stream_name(
10548                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
10549         ret &= test_stream_name(
10550                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
10551         ret &= test_stream_name(
10552                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
10553         ret &= test_stream_name(
10554                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
10555
10556         return ret;
10557 }
10558
10559 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
10560 {
10561         if (a.length != b.length) {
10562                 printf("a.length=%d != b.length=%d\n",
10563                        (int)a.length, (int)b.length);
10564                 return false;
10565         }
10566         if (memcmp(a.data, b.data, a.length) != 0) {
10567                 printf("a.data and b.data differ\n");
10568                 return false;
10569         }
10570         return true;
10571 }
10572
10573 static bool run_local_memcache(int dummy)
10574 {
10575         struct memcache *cache;
10576         DATA_BLOB k1, k2;
10577         DATA_BLOB d1, d2, d3;
10578         DATA_BLOB v1, v2, v3;
10579
10580         TALLOC_CTX *mem_ctx;
10581         char *str1, *str2;
10582         size_t size1, size2;
10583         bool ret = false;
10584
10585         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
10586
10587         if (cache == NULL) {
10588                 printf("memcache_init failed\n");
10589                 return false;
10590         }
10591
10592         d1 = data_blob_const("d1", 2);
10593         d2 = data_blob_const("d2", 2);
10594         d3 = data_blob_const("d3", 2);
10595
10596         k1 = data_blob_const("d1", 2);
10597         k2 = data_blob_const("d2", 2);
10598
10599         memcache_add(cache, STAT_CACHE, k1, d1);
10600         memcache_add(cache, GETWD_CACHE, k2, d2);
10601
10602         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
10603                 printf("could not find k1\n");
10604                 return false;
10605         }
10606         if (!data_blob_equal(d1, v1)) {
10607                 return false;
10608         }
10609
10610         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
10611                 printf("could not find k2\n");
10612                 return false;
10613         }
10614         if (!data_blob_equal(d2, v2)) {
10615                 return false;
10616         }
10617
10618         memcache_add(cache, STAT_CACHE, k1, d3);
10619
10620         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
10621                 printf("could not find replaced k1\n");
10622                 return false;
10623         }
10624         if (!data_blob_equal(d3, v3)) {
10625                 return false;
10626         }
10627
10628         memcache_add(cache, GETWD_CACHE, k1, d1);
10629
10630         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
10631                 printf("Did find k2, should have been purged\n");
10632                 return false;
10633         }
10634
10635         TALLOC_FREE(cache);
10636
10637         cache = memcache_init(NULL, 0);
10638
10639         mem_ctx = talloc_init("foo");
10640
10641         str1 = talloc_strdup(mem_ctx, "string1");
10642         str2 = talloc_strdup(mem_ctx, "string2");
10643
10644         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10645                             data_blob_string_const("torture"), &str1);
10646         size1 = talloc_total_size(cache);
10647
10648         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
10649                             data_blob_string_const("torture"), &str2);
10650         size2 = talloc_total_size(cache);
10651
10652         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
10653
10654         if (size2 > size1) {
10655                 printf("memcache leaks memory!\n");
10656                 goto fail;
10657         }
10658
10659         ret = true;
10660  fail:
10661         TALLOC_FREE(cache);
10662         return ret;
10663 }
10664
10665 static void wbclient_done(struct tevent_req *req)
10666 {
10667         wbcErr wbc_err;
10668         struct winbindd_response *wb_resp;
10669         int *i = (int *)tevent_req_callback_data_void(req);
10670
10671         wbc_err = wb_trans_recv(req, req, &wb_resp);
10672         TALLOC_FREE(req);
10673         *i += 1;
10674         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
10675 }
10676
10677 static bool run_wbclient_multi_ping(int dummy)
10678 {
10679         struct tevent_context *ev;
10680         struct wb_context **wb_ctx;
10681         struct winbindd_request wb_req;
10682         bool result = false;
10683         int i, j;
10684
10685         BlockSignals(True, SIGPIPE);
10686
10687         ev = tevent_context_init(talloc_tos());
10688         if (ev == NULL) {
10689                 goto fail;
10690         }
10691
10692         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
10693         if (wb_ctx == NULL) {
10694                 goto fail;
10695         }
10696
10697         ZERO_STRUCT(wb_req);
10698         wb_req.cmd = WINBINDD_PING;
10699
10700         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
10701
10702         for (i=0; i<torture_nprocs; i++) {
10703                 wb_ctx[i] = wb_context_init(ev, NULL);
10704                 if (wb_ctx[i] == NULL) {
10705                         goto fail;
10706                 }
10707                 for (j=0; j<torture_numops; j++) {
10708                         struct tevent_req *req;
10709                         req = wb_trans_send(ev, ev, wb_ctx[i],
10710                                             (j % 2) == 0, &wb_req);
10711                         if (req == NULL) {
10712                                 goto fail;
10713                         }
10714                         tevent_req_set_callback(req, wbclient_done, &i);
10715                 }
10716         }
10717
10718         i = 0;
10719
10720         while (i < torture_nprocs * torture_numops) {
10721                 tevent_loop_once(ev);
10722         }
10723
10724         result = true;
10725  fail:
10726         TALLOC_FREE(ev);
10727         return result;
10728 }
10729
10730 static void getaddrinfo_finished(struct tevent_req *req)
10731 {
10732         char *name = (char *)tevent_req_callback_data_void(req);
10733         struct addrinfo *ainfo;
10734         int res;
10735
10736         res = getaddrinfo_recv(req, &ainfo);
10737         if (res != 0) {
10738                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
10739                 return;
10740         }
10741         d_printf("gai(%s) succeeded\n", name);
10742         freeaddrinfo(ainfo);
10743 }
10744
10745 static bool run_getaddrinfo_send(int dummy)
10746 {
10747         TALLOC_CTX *frame = talloc_stackframe();
10748         struct fncall_context *ctx;
10749         struct tevent_context *ev;
10750         bool result = false;
10751         const char *names[4] = { "www.samba.org", "notfound.samba.org",
10752                                  "www.slashdot.org", "heise.de" };
10753         struct tevent_req *reqs[4];
10754         int i;
10755
10756         ev = samba_tevent_context_init(frame);
10757         if (ev == NULL) {
10758                 goto fail;
10759         }
10760
10761         ctx = fncall_context_init(frame, 4);
10762
10763         for (i=0; i<ARRAY_SIZE(names); i++) {
10764                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
10765                                            NULL);
10766                 if (reqs[i] == NULL) {
10767                         goto fail;
10768                 }
10769                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
10770                                         discard_const_p(void, names[i]));
10771         }
10772
10773         for (i=0; i<ARRAY_SIZE(reqs); i++) {
10774                 tevent_loop_once(ev);
10775         }
10776
10777         result = true;
10778 fail:
10779         TALLOC_FREE(frame);
10780         return result;
10781 }
10782
10783 static bool dbtrans_inc(struct db_context *db)
10784 {
10785         struct db_record *rec;
10786         uint32_t val;
10787         bool ret = false;
10788         NTSTATUS status;
10789         TDB_DATA value;
10790
10791         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10792         if (rec == NULL) {
10793                 printf(__location__ "fetch_lock failed\n");
10794                 return false;
10795         }
10796
10797         value = dbwrap_record_get_value(rec);
10798
10799         if (value.dsize != sizeof(uint32_t)) {
10800                 printf(__location__ "value.dsize = %d\n",
10801                        (int)value.dsize);
10802                 goto fail;
10803         }
10804
10805         memcpy(&val, value.dptr, sizeof(val));
10806         val += 1;
10807
10808         status = dbwrap_record_store(
10809                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
10810         if (!NT_STATUS_IS_OK(status)) {
10811                 printf(__location__ "store failed: %s\n",
10812                        nt_errstr(status));
10813                 goto fail;
10814         }
10815
10816         ret = true;
10817 fail:
10818         TALLOC_FREE(rec);
10819         return ret;
10820 }
10821
10822 static bool run_local_dbtrans(int dummy)
10823 {
10824         struct db_context *db;
10825         struct db_record *rec;
10826         NTSTATUS status;
10827         uint32_t initial;
10828         int res;
10829         TDB_DATA value;
10830
10831         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
10832                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
10833                      DBWRAP_FLAG_NONE);
10834         if (db == NULL) {
10835                 printf("Could not open transtest.db\n");
10836                 return false;
10837         }
10838
10839         res = dbwrap_transaction_start(db);
10840         if (res != 0) {
10841                 printf(__location__ "transaction_start failed\n");
10842                 return false;
10843         }
10844
10845         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
10846         if (rec == NULL) {
10847                 printf(__location__ "fetch_lock failed\n");
10848                 return false;
10849         }
10850
10851         value = dbwrap_record_get_value(rec);
10852
10853         if (value.dptr == NULL) {
10854                 initial = 0;
10855                 status = dbwrap_record_store(
10856                         rec, make_tdb_data((uint8_t *)&initial,
10857                                            sizeof(initial)),
10858                         0);
10859                 if (!NT_STATUS_IS_OK(status)) {
10860                         printf(__location__ "store returned %s\n",
10861                                nt_errstr(status));
10862                         return false;
10863                 }
10864         }
10865
10866         TALLOC_FREE(rec);
10867
10868         res = dbwrap_transaction_commit(db);
10869         if (res != 0) {
10870                 printf(__location__ "transaction_commit failed\n");
10871                 return false;
10872         }
10873
10874         while (true) {
10875                 uint32_t val, val2;
10876                 int i;
10877
10878                 res = dbwrap_transaction_start(db);
10879                 if (res != 0) {
10880                         printf(__location__ "transaction_start failed\n");
10881                         break;
10882                 }
10883
10884                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
10885                 if (!NT_STATUS_IS_OK(status)) {
10886                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10887                                nt_errstr(status));
10888                         break;
10889                 }
10890
10891                 for (i=0; i<10; i++) {
10892                         if (!dbtrans_inc(db)) {
10893                                 return false;
10894                         }
10895                 }
10896
10897                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
10898                 if (!NT_STATUS_IS_OK(status)) {
10899                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
10900                                nt_errstr(status));
10901                         break;
10902                 }
10903
10904                 if (val2 != val + 10) {
10905                         printf(__location__ "val=%d, val2=%d\n",
10906                                (int)val, (int)val2);
10907                         break;
10908                 }
10909
10910                 printf("val2=%d\r", val2);
10911
10912                 res = dbwrap_transaction_commit(db);
10913                 if (res != 0) {
10914                         printf(__location__ "transaction_commit failed\n");
10915                         break;
10916                 }
10917         }
10918
10919         TALLOC_FREE(db);
10920         return true;
10921 }
10922
10923 /*
10924  * Just a dummy test to be run under a debugger. There's no real way
10925  * to inspect the tevent_select specific function from outside of
10926  * tevent_select.c.
10927  */
10928
10929 static bool run_local_tevent_select(int dummy)
10930 {
10931         struct tevent_context *ev;
10932         struct tevent_fd *fd1, *fd2;
10933         bool result = false;
10934
10935         ev = tevent_context_init_byname(NULL, "select");
10936         if (ev == NULL) {
10937                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
10938                 goto fail;
10939         }
10940
10941         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
10942         if (fd1 == NULL) {
10943                 d_fprintf(stderr, "tevent_add_fd failed\n");
10944                 goto fail;
10945         }
10946         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
10947         if (fd2 == NULL) {
10948                 d_fprintf(stderr, "tevent_add_fd failed\n");
10949                 goto fail;
10950         }
10951         TALLOC_FREE(fd2);
10952
10953         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
10954         if (fd2 == NULL) {
10955                 d_fprintf(stderr, "tevent_add_fd failed\n");
10956                 goto fail;
10957         }
10958
10959         result = true;
10960 fail:
10961         TALLOC_FREE(ev);
10962         return result;
10963 }
10964
10965 static bool run_local_hex_encode_buf(int dummy)
10966 {
10967         char buf[17];
10968         uint8_t src[8];
10969         int i;
10970
10971         for (i=0; i<sizeof(src); i++) {
10972                 src[i] = i;
10973         }
10974         hex_encode_buf(buf, src, sizeof(src));
10975         if (strcmp(buf, "0001020304050607") != 0) {
10976                 return false;
10977         }
10978         hex_encode_buf(buf, NULL, 0);
10979         if (buf[0] != '\0') {
10980                 return false;
10981         }
10982         return true;
10983 }
10984
10985 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
10986         "0.0.0.0",
10987         "::0",
10988         "1.2.3.1",
10989         "0.0.0.0",
10990         "0.0.0.0",
10991         "1.2.3.2",
10992         "1.2.3.3",
10993         "1.2.3.4",
10994         "1.2.3.5",
10995         "::0",
10996         "1.2.3.6",
10997         "1.2.3.7",
10998         "::0",
10999         "::0",
11000         "::0",
11001         "1.2.3.8",
11002         "1.2.3.9",
11003         "1.2.3.10",
11004         "1.2.3.11",
11005         "1.2.3.12",
11006         "1.2.3.13",
11007         "1001:1111:1111:1000:0:1111:1111:1111",
11008         "1.2.3.1",
11009         "1.2.3.2",
11010         "1.2.3.3",
11011         "1.2.3.12",
11012         "::0",
11013         "::0"
11014 };
11015
11016 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11017         "1.2.3.1",
11018         "1.2.3.2",
11019         "1.2.3.3",
11020         "1.2.3.4",
11021         "1.2.3.5",
11022         "1.2.3.6",
11023         "1.2.3.7",
11024         "1.2.3.8",
11025         "1.2.3.9",
11026         "1.2.3.10",
11027         "1.2.3.11",
11028         "1.2.3.12",
11029         "1.2.3.13",
11030         "1001:1111:1111:1000:0:1111:1111:1111"
11031 };
11032
11033 static bool run_local_remove_duplicate_addrs2(int dummy)
11034 {
11035         struct ip_service test_vector[28];
11036         int count, i;
11037
11038         /* Construct the sockaddr_storage test vector. */
11039         for (i = 0; i < 28; i++) {
11040                 struct addrinfo hints;
11041                 struct addrinfo *res = NULL;
11042                 int ret;
11043
11044                 memset(&hints, '\0', sizeof(hints));
11045                 hints.ai_flags = AI_NUMERICHOST;
11046                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11047                                 NULL,
11048                                 &hints,
11049                                 &res);
11050                 if (ret) {
11051                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
11052                                 remove_duplicate_addrs2_test_strings_vector[i]);
11053                         return false;
11054                 }
11055                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11056                 memcpy(&test_vector[i].ss,
11057                         res->ai_addr,
11058                         res->ai_addrlen);
11059                 freeaddrinfo(res);
11060         }
11061
11062         count = remove_duplicate_addrs2(test_vector, i);
11063
11064         if (count != 14) {
11065                 fprintf(stderr, "count wrong (%d) should be 14\n",
11066                         count);
11067                 return false;
11068         }
11069
11070         for (i = 0; i < count; i++) {
11071                 char addr[INET6_ADDRSTRLEN];
11072
11073                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11074
11075                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11076                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11077                                 i,
11078                                 addr,
11079                                 remove_duplicate_addrs2_test_strings_result[i]);
11080                         return false;
11081                 }
11082         }
11083
11084         printf("run_local_remove_duplicate_addrs2: success\n");
11085         return true;
11086 }
11087
11088 static bool run_local_tdb_opener(int dummy)
11089 {
11090         TDB_CONTEXT *t;
11091         unsigned v = 0;
11092
11093         while (1) {
11094                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11095                              O_RDWR|O_CREAT, 0755);
11096                 if (t == NULL) {
11097                         perror("tdb_open failed");
11098                         return false;
11099                 }
11100                 tdb_close(t);
11101
11102                 v += 1;
11103                 printf("\r%u", v);
11104         }
11105         return true;
11106 }
11107
11108 static bool run_local_tdb_writer(int dummy)
11109 {
11110         TDB_CONTEXT *t;
11111         unsigned v = 0;
11112         TDB_DATA val;
11113
11114         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11115         if (t == 0) {
11116                 perror("tdb_open failed");
11117                 return 1;
11118         }
11119
11120         val.dptr = (uint8_t *)&v;
11121         val.dsize = sizeof(v);
11122
11123         while (1) {
11124                 TDB_DATA data;
11125                 int ret;
11126
11127                 ret = tdb_store(t, val, val, 0);
11128                 if (ret != 0) {
11129                         printf("%s\n", tdb_errorstr(t));
11130                 }
11131                 v += 1;
11132                 printf("\r%u", v);
11133
11134                 data = tdb_fetch(t, val);
11135                 if (data.dptr != NULL) {
11136                         SAFE_FREE(data.dptr);
11137                 }
11138         }
11139         return true;
11140 }
11141
11142 static bool run_local_canonicalize_path(int dummy)
11143 {
11144         const char *src[] = {
11145                         "/foo/..",
11146                         "/..",
11147                         "/foo/bar/../baz",
11148                         "/foo/././",
11149                         "/../foo",
11150                         ".././././",
11151                         ".././././../../../boo",
11152                         "./..",
11153                         NULL
11154                         };
11155         const char *dst[] = {
11156                         "/",
11157                         "/",
11158                         "/foo/baz",
11159                         "/foo",
11160                         "/foo",
11161                         "/",
11162                         "/boo",
11163                         "/",
11164                         NULL
11165                         };
11166         unsigned int i;
11167
11168         for (i = 0; src[i] != NULL; i++) {
11169                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11170                 if (d == NULL) {
11171                         perror("talloc fail\n");
11172                         return false;
11173                 }
11174                 if (strcmp(d, dst[i]) != 0) {
11175                         d_fprintf(stderr,
11176                                 "canonicalize missmatch %s -> %s != %s",
11177                                 src[i], d, dst[i]);
11178                         return false;
11179                 }
11180                 talloc_free(d);
11181         }
11182         return true;
11183 }
11184
11185 static bool run_ign_bad_negprot(int dummy)
11186 {
11187         struct tevent_context *ev;
11188         struct tevent_req *req;
11189         struct smbXcli_conn *conn;
11190         struct sockaddr_storage ss;
11191         NTSTATUS status;
11192         int fd;
11193         bool ok;
11194
11195         printf("starting ignore bad negprot\n");
11196
11197         ok = resolve_name(host, &ss, 0x20, true);
11198         if (!ok) {
11199                 d_fprintf(stderr, "Could not resolve name %s\n", host);
11200                 return false;
11201         }
11202
11203         status = open_socket_out(&ss, 445, 10000, &fd);
11204         if (!NT_STATUS_IS_OK(status)) {
11205                 d_fprintf(stderr, "open_socket_out failed: %s\n",
11206                           nt_errstr(status));
11207                 return false;
11208         }
11209
11210         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11211                                    NULL, 0);
11212         if (conn == NULL) {
11213                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11214                 return false;
11215         }
11216
11217         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11218         if (NT_STATUS_IS_OK(status)) {
11219                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11220                 return false;
11221         }
11222
11223         ev = samba_tevent_context_init(talloc_tos());
11224         if (ev == NULL) {
11225                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11226                 return false;
11227         }
11228
11229         req = smb1cli_session_setup_nt1_send(
11230                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11231                 data_blob_null, data_blob_null, 0x40,
11232                 "Windows 2000 2195", "Windows 2000 5.0");
11233         if (req == NULL) {
11234                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11235                 return false;
11236         }
11237
11238         ok = tevent_req_poll_ntstatus(req, ev, &status);
11239         if (!ok) {
11240                 d_fprintf(stderr, "tevent_req_poll failed\n");
11241                 return false;
11242         }
11243
11244         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11245                                                 NULL, NULL);
11246         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11247                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11248                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
11249                           nt_errstr(status));
11250                 return false;
11251         }
11252
11253         TALLOC_FREE(conn);
11254
11255         printf("starting ignore bad negprot\n");
11256
11257         return true;
11258 }
11259
11260 static double create_procs(bool (*fn)(int), bool *result)
11261 {
11262         int i, status;
11263         volatile pid_t *child_status;
11264         volatile bool *child_status_out;
11265         int synccount;
11266         int tries = 8;
11267         struct timeval start;
11268
11269         synccount = 0;
11270
11271         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11272         if (!child_status) {
11273                 printf("Failed to setup shared memory\n");
11274                 return -1;
11275         }
11276
11277         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11278         if (!child_status_out) {
11279                 printf("Failed to setup result status shared memory\n");
11280                 return -1;
11281         }
11282
11283         for (i = 0; i < torture_nprocs; i++) {
11284                 child_status[i] = 0;
11285                 child_status_out[i] = True;
11286         }
11287
11288         start = timeval_current();
11289
11290         for (i=0;i<torture_nprocs;i++) {
11291                 procnum = i;
11292                 if (fork() == 0) {
11293                         pid_t mypid = getpid();
11294                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11295
11296                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
11297
11298                         while (1) {
11299                                 if (torture_open_connection(&current_cli, i)) break;
11300                                 if (tries-- == 0) {
11301                                         printf("pid %d failed to start\n", (int)getpid());
11302                                         _exit(1);
11303                                 }
11304                                 smb_msleep(10); 
11305                         }
11306
11307                         child_status[i] = getpid();
11308
11309                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11310
11311                         child_status_out[i] = fn(i);
11312                         _exit(0);
11313                 }
11314         }
11315
11316         do {
11317                 synccount = 0;
11318                 for (i=0;i<torture_nprocs;i++) {
11319                         if (child_status[i]) synccount++;
11320                 }
11321                 if (synccount == torture_nprocs) break;
11322                 smb_msleep(10);
11323         } while (timeval_elapsed(&start) < 30);
11324
11325         if (synccount != torture_nprocs) {
11326                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11327                 *result = False;
11328                 return timeval_elapsed(&start);
11329         }
11330
11331         /* start the client load */
11332         start = timeval_current();
11333
11334         for (i=0;i<torture_nprocs;i++) {
11335                 child_status[i] = 0;
11336         }
11337
11338         printf("%d clients started\n", torture_nprocs);
11339
11340         for (i=0;i<torture_nprocs;i++) {
11341                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11342         }
11343
11344         printf("\n");
11345
11346         for (i=0;i<torture_nprocs;i++) {
11347                 if (!child_status_out[i]) {
11348                         *result = False;
11349                 }
11350         }
11351         return timeval_elapsed(&start);
11352 }
11353
11354 #define FLAG_MULTIPROC 1
11355
11356 static struct {
11357         const char *name;
11358         bool (*fn)(int);
11359         unsigned flags;
11360 } torture_ops[] = {
11361         {"FDPASS", run_fdpasstest, 0},
11362         {"LOCK1",  run_locktest1,  0},
11363         {"LOCK2",  run_locktest2,  0},
11364         {"LOCK3",  run_locktest3,  0},
11365         {"LOCK4",  run_locktest4,  0},
11366         {"LOCK5",  run_locktest5,  0},
11367         {"LOCK6",  run_locktest6,  0},
11368         {"LOCK7",  run_locktest7,  0},
11369         {"LOCK8",  run_locktest8,  0},
11370         {"LOCK9",  run_locktest9,  0},
11371         {"UNLINK", run_unlinktest, 0},
11372         {"BROWSE", run_browsetest, 0},
11373         {"ATTR",   run_attrtest,   0},
11374         {"TRANS2", run_trans2test, 0},
11375         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
11376         {"TORTURE",run_torture,    FLAG_MULTIPROC},
11377         {"RANDOMIPC", run_randomipc, 0},
11378         {"NEGNOWAIT", run_negprot_nowait, 0},
11379         {"NBENCH",  run_nbench, 0},
11380         {"NBENCH2", run_nbench2, 0},
11381         {"OPLOCK1",  run_oplock1, 0},
11382         {"OPLOCK2",  run_oplock2, 0},
11383         {"OPLOCK4",  run_oplock4, 0},
11384         {"DIR",  run_dirtest, 0},
11385         {"DIR1",  run_dirtest1, 0},
11386         {"DIR-CREATETIME",  run_dir_createtime, 0},
11387         {"DENY1",  torture_denytest1, 0},
11388         {"DENY2",  torture_denytest2, 0},
11389         {"TCON",  run_tcon_test, 0},
11390         {"TCONDEV",  run_tcon_devtype_test, 0},
11391         {"RW1",  run_readwritetest, 0},
11392         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
11393         {"RW3",  run_readwritelarge, 0},
11394         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
11395         {"OPEN", run_opentest, 0},
11396         {"POSIX", run_simple_posix_open_test, 0},
11397         {"POSIX-APPEND", run_posix_append, 0},
11398         {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
11399         {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
11400         {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
11401         {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
11402         {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
11403         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
11404         {"ASYNC-ECHO", run_async_echo, 0},
11405         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
11406         { "SHORTNAME-TEST", run_shortname_test, 0},
11407         { "ADDRCHANGE", run_addrchange, 0},
11408 #if 1
11409         {"OPENATTR", run_openattrtest, 0},
11410 #endif
11411         {"XCOPY", run_xcopy, 0},
11412         {"RENAME", run_rename, 0},
11413         {"RENAME-ACCESS", run_rename_access, 0},
11414         {"OWNER-RIGHTS", run_owner_rights, 0},
11415         {"DELETE", run_deletetest, 0},
11416         {"WILDDELETE", run_wild_deletetest, 0},
11417         {"DELETE-LN", run_deletetest_ln, 0},
11418         {"PROPERTIES", run_properties, 0},
11419         {"MANGLE", torture_mangle, 0},
11420         {"MANGLE1", run_mangle1, 0},
11421         {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
11422         {"W2K", run_w2ktest, 0},
11423         {"TRANS2SCAN", torture_trans2_scan, 0},
11424         {"NTTRANSSCAN", torture_nttrans_scan, 0},
11425         {"UTABLE", torture_utable, 0},
11426         {"CASETABLE", torture_casetable, 0},
11427         {"ERRMAPEXTRACT", run_error_map_extract, 0},
11428         {"PIPE_NUMBER", run_pipe_number, 0},
11429         {"TCON2",  run_tcon2_test, 0},
11430         {"IOCTL",  torture_ioctl_test, 0},
11431         {"CHKPATH",  torture_chkpath_test, 0},
11432         {"FDSESS", run_fdsesstest, 0},
11433         { "EATEST", run_eatest, 0},
11434         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
11435         { "CHAIN1", run_chain1, 0},
11436         { "CHAIN2", run_chain2, 0},
11437         { "CHAIN3", run_chain3, 0},
11438         { "WINDOWS-WRITE", run_windows_write, 0},
11439         { "LARGE_READX", run_large_readx, 0},
11440         { "NTTRANS-CREATE", run_nttrans_create, 0},
11441         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
11442         { "CLI_ECHO", run_cli_echo, 0},
11443         { "GETADDRINFO", run_getaddrinfo_send, 0},
11444         { "TLDAP", run_tldap },
11445         { "STREAMERROR", run_streamerror },
11446         { "NOTIFY-BENCH", run_notify_bench },
11447         { "NOTIFY-BENCH2", run_notify_bench2 },
11448         { "NOTIFY-BENCH3", run_notify_bench3 },
11449         { "BAD-NBT-SESSION", run_bad_nbt_session },
11450         { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
11451         { "SMB-ANY-CONNECT", run_smb_any_connect },
11452         { "NOTIFY-ONLINE", run_notify_online },
11453         { "SMB2-BASIC", run_smb2_basic },
11454         { "SMB2-NEGPROT", run_smb2_negprot },
11455         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
11456         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
11457         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
11458         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
11459         { "SMB2-FTRUNCATE", run_smb2_ftruncate },
11460         { "CLEANUP1", run_cleanup1 },
11461         { "CLEANUP2", run_cleanup2 },
11462         { "CLEANUP3", run_cleanup3 },
11463         { "CLEANUP4", run_cleanup4 },
11464         { "OPLOCK-CANCEL", run_oplock_cancel },
11465         { "PIDHIGH", run_pidhigh },
11466         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
11467         { "LOCAL-GENCACHE", run_local_gencache, 0},
11468         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
11469         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
11470         { "LOCAL-DBWRAP-WATCH2", run_dbwrap_watch2, 0 },
11471         { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
11472         { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
11473         { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
11474         { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
11475         { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
11476         { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
11477         { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
11478         { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
11479         { "LOCAL-BASE64", run_local_base64, 0},
11480         { "LOCAL-RBTREE", run_local_rbtree, 0},
11481         { "LOCAL-MEMCACHE", run_local_memcache, 0},
11482         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
11483         { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
11484         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
11485         { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
11486         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
11487         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
11488         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
11489         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
11490         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
11491         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
11492         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
11493         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
11494         { "local-tdb-opener", run_local_tdb_opener, 0 },
11495         { "local-tdb-writer", run_local_tdb_writer, 0 },
11496         { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
11497         { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
11498         { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
11499         { "LOCAL-G-LOCK1", run_g_lock1, 0 },
11500         { "LOCAL-G-LOCK2", run_g_lock2, 0 },
11501         { "LOCAL-G-LOCK3", run_g_lock3, 0 },
11502         { "LOCAL-G-LOCK4", run_g_lock4, 0 },
11503         { "LOCAL-G-LOCK5", run_g_lock5, 0 },
11504         { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
11505         { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
11506         {NULL, NULL, 0}};
11507
11508 /*
11509  * dummy function to satisfy linker dependency
11510  */
11511 struct tevent_context *winbind_event_context(void);
11512 struct tevent_context *winbind_event_context(void)
11513 {
11514         return NULL;
11515 }
11516
11517 /****************************************************************************
11518 run a specified test or "ALL"
11519 ****************************************************************************/
11520 static bool run_test(const char *name)
11521 {
11522         bool ret = True;
11523         bool result = True;
11524         bool found = False;
11525         int i;
11526         double t;
11527         if (strequal(name,"ALL")) {
11528                 for (i=0;torture_ops[i].name;i++) {
11529                         run_test(torture_ops[i].name);
11530                 }
11531                 found = True;
11532         }
11533
11534         for (i=0;torture_ops[i].name;i++) {
11535                 fstr_sprintf(randomfname, "\\XX%x", 
11536                          (unsigned)random());
11537
11538                 if (strequal(name, torture_ops[i].name)) {
11539                         found = True;
11540                         printf("Running %s\n", name);
11541                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
11542                                 t = create_procs(torture_ops[i].fn, &result);
11543                                 if (!result) { 
11544                                         ret = False;
11545                                         printf("TEST %s FAILED!\n", name);
11546                                 }
11547                         } else {
11548                                 struct timeval start;
11549                                 start = timeval_current();
11550                                 if (!torture_ops[i].fn(0)) {
11551                                         ret = False;
11552                                         printf("TEST %s FAILED!\n", name);
11553                                 }
11554                                 t = timeval_elapsed(&start);
11555                         }
11556                         printf("%s took %g secs\n\n", name, t);
11557                 }
11558         }
11559
11560         if (!found) {
11561                 printf("Did not find a test named %s\n", name);
11562                 ret = False;
11563         }
11564
11565         return ret;
11566 }
11567
11568
11569 static void usage(void)
11570 {
11571         int i;
11572
11573         printf("WARNING samba4 test suite is much more complete nowadays.\n");
11574         printf("Please use samba4 torture.\n\n");
11575
11576         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
11577
11578         printf("\t-d debuglevel\n");
11579         printf("\t-U user%%pass\n");
11580         printf("\t-k                    use kerberos\n");
11581         printf("\t-N numprocs\n");
11582         printf("\t-n my_netbios_name\n");
11583         printf("\t-W workgroup\n");
11584         printf("\t-o num_operations\n");
11585         printf("\t-O socket_options\n");
11586         printf("\t-m maximum protocol\n");
11587         printf("\t-L use oplocks\n");
11588         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
11589         printf("\t-A showall\n");
11590         printf("\t-p port\n");
11591         printf("\t-s seed\n");
11592         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
11593         printf("\t-f filename           filename to test\n");
11594         printf("\t-e                    encrypt\n");
11595         printf("\n\n");
11596
11597         printf("tests are:");
11598         for (i=0;torture_ops[i].name;i++) {
11599                 printf(" %s", torture_ops[i].name);
11600         }
11601         printf("\n");
11602
11603         printf("default test is ALL\n");
11604
11605         exit(1);
11606 }
11607
11608 /****************************************************************************
11609   main program
11610 ****************************************************************************/
11611  int main(int argc,char *argv[])
11612 {
11613         int opt, i;
11614         char *p;
11615         int gotuser = 0;
11616         int gotpass = 0;
11617         bool correct = True;
11618         TALLOC_CTX *frame = talloc_stackframe();
11619         int seed = time(NULL);
11620
11621 #ifdef HAVE_SETBUFFER
11622         setbuffer(stdout, NULL, 0);
11623 #endif
11624
11625         setup_logging("smbtorture", DEBUG_STDOUT);
11626
11627         smb_init_locale();
11628         fault_setup();
11629
11630         if (is_default_dyn_CONFIGFILE()) {
11631                 if(getenv("SMB_CONF_PATH")) {
11632                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
11633                 }
11634         }
11635         lp_load_global(get_dyn_CONFIGFILE());
11636         load_interfaces();
11637
11638         if (argc < 2) {
11639                 usage();
11640         }
11641
11642         for(p = argv[1]; *p; p++)
11643           if(*p == '\\')
11644             *p = '/';
11645
11646         if (strncmp(argv[1], "//", 2)) {
11647                 usage();
11648         }
11649
11650         fstrcpy(host, &argv[1][2]);
11651         p = strchr_m(&host[2],'/');
11652         if (!p) {
11653                 usage();
11654         }
11655         *p = 0;
11656         fstrcpy(share, p+1);
11657
11658         fstrcpy(myname, get_myname(talloc_tos()));
11659         if (!*myname) {
11660                 fprintf(stderr, "Failed to get my hostname.\n");
11661                 return 1;
11662         }
11663
11664         if (*username == 0 && getenv("LOGNAME")) {
11665           fstrcpy(username,getenv("LOGNAME"));
11666         }
11667
11668         argc--;
11669         argv++;
11670
11671         fstrcpy(workgroup, lp_workgroup());
11672
11673         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
11674                != EOF) {
11675                 switch (opt) {
11676                 case 'p':
11677                         port_to_use = atoi(optarg);
11678                         break;
11679                 case 's':
11680                         seed = atoi(optarg);
11681                         break;
11682                 case 'W':
11683                         fstrcpy(workgroup,optarg);
11684                         break;
11685                 case 'm':
11686                         lp_set_cmdline("client max protocol", optarg);
11687                         break;
11688                 case 'N':
11689                         torture_nprocs = atoi(optarg);
11690                         break;
11691                 case 'o':
11692                         torture_numops = atoi(optarg);
11693                         break;
11694                 case 'd':
11695                         lp_set_cmdline("log level", optarg);
11696                         break;
11697                 case 'O':
11698                         sockops = optarg;
11699                         break;
11700                 case 'L':
11701                         use_oplocks = True;
11702                         break;
11703                 case 'l':
11704                         local_path = optarg;
11705                         break;
11706                 case 'A':
11707                         torture_showall = True;
11708                         break;
11709                 case 'n':
11710                         fstrcpy(myname, optarg);
11711                         break;
11712                 case 'c':
11713                         client_txt = optarg;
11714                         break;
11715                 case 'e':
11716                         do_encrypt = true;
11717                         break;
11718                 case 'k':
11719 #ifdef HAVE_KRB5
11720                         use_kerberos = True;
11721 #else
11722                         d_printf("No kerberos support compiled in\n");
11723                         exit(1);
11724 #endif
11725                         break;
11726                 case 'U':
11727                         gotuser = 1;
11728                         fstrcpy(username,optarg);
11729                         p = strchr_m(username,'%');
11730                         if (p) {
11731                                 *p = 0;
11732                                 fstrcpy(password, p+1);
11733                                 gotpass = 1;
11734                         }
11735                         break;
11736                 case 'b':
11737                         fstrcpy(multishare_conn_fname, optarg);
11738                         use_multishare_conn = True;
11739                         break;
11740                 case 'B':
11741                         torture_blocksize = atoi(optarg);
11742                         break;
11743                 case 'f':
11744                         test_filename = SMB_STRDUP(optarg);
11745                         break;
11746                 default:
11747                         printf("Unknown option %c (%d)\n", (char)opt, opt);
11748                         usage();
11749                 }
11750         }
11751
11752         d_printf("using seed %d\n", seed);
11753
11754         srandom(seed);
11755
11756         if(use_kerberos && !gotuser) gotpass = True;
11757
11758         while (!gotpass) {
11759                 char pwd[256] = {0};
11760                 int rc;
11761
11762                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
11763                 if (rc == 0) {
11764                         fstrcpy(password, pwd);
11765                         gotpass = 1;
11766                 }
11767         }
11768
11769         printf("host=%s share=%s user=%s myname=%s\n", 
11770                host, share, username, myname);
11771
11772         torture_creds = cli_session_creds_init(frame,
11773                                                username,
11774                                                workgroup,
11775                                                NULL, /* realm */
11776                                                password,
11777                                                use_kerberos,
11778                                                false, /* fallback_after_kerberos */
11779                                                false, /* use_ccache */
11780                                                false); /* password_is_nt_hash */
11781         if (torture_creds == NULL) {
11782                 d_printf("cli_session_creds_init() failed.\n");
11783                 exit(1);
11784         }
11785
11786         if (argc == optind) {
11787                 correct = run_test("ALL");
11788         } else {
11789                 for (i=optind;i<argc;i++) {
11790                         if (!run_test(argv[i])) {
11791                                 correct = False;
11792                         }
11793                 }
11794         }
11795
11796         TALLOC_FREE(frame);
11797
11798         if (correct) {
11799                 return(0);
11800         } else {
11801                 return(1);
11802         }
11803 }