s3: torture: Add test for bug 14708 - POSIX default ACL not mapped into returned...
[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 "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
39 #include "trans2.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
42 #include "util_tdb.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53 #include "lib/util/string_wrappers.h"
54
55 #include <gnutls/gnutls.h>
56 #include <gnutls/crypto.h>
57
58 extern char *optarg;
59 extern int optind;
60
61 fstring host, workgroup, share, password, username, myname;
62 struct cli_credentials *torture_creds;
63 static const char *sockops="TCP_NODELAY";
64 int torture_nprocs=1;
65 static int port_to_use=0;
66 int torture_numops=100;
67 int torture_blocksize=1024*1024;
68 static int procnum; /* records process count number when forking */
69 static struct cli_state *current_cli;
70 static fstring randomfname;
71 static bool use_oplocks;
72 static bool use_level_II_oplocks;
73 static const char *client_txt = "client_oplocks.txt";
74 static bool disable_spnego;
75 static bool use_kerberos;
76 static bool force_dos_errors;
77 static fstring multishare_conn_fname;
78 static bool use_multishare_conn = False;
79 static bool do_encrypt;
80 static const char *local_path = NULL;
81 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
82 char *test_filename;
83
84 bool torture_showall = False;
85
86 static double create_procs(bool (*fn)(int), bool *result);
87
88 /********************************************************************
89  Ensure a connection is encrypted.
90 ********************************************************************/
91
92 static bool force_cli_encryption(struct cli_state *c,
93                         const char *sharename)
94 {
95         uint16_t major, minor;
96         uint32_t caplow, caphigh;
97         NTSTATUS status;
98
99         if (!SERVER_HAS_UNIX_CIFS(c)) {
100                 d_printf("Encryption required and "
101                         "server that doesn't support "
102                         "UNIX extensions - failing connect\n");
103                         return false;
104         }
105
106         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
107                                              &caphigh);
108         if (!NT_STATUS_IS_OK(status)) {
109                 d_printf("Encryption required and "
110                         "can't get UNIX CIFS extensions "
111                         "version from server: %s\n", nt_errstr(status));
112                 return false;
113         }
114
115         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
116                 d_printf("Encryption required and "
117                         "share %s doesn't support "
118                         "encryption.\n", sharename);
119                 return false;
120         }
121
122         status = cli_smb1_setup_encryption(c, torture_creds);
123         if (!NT_STATUS_IS_OK(status)) {
124                 d_printf("Encryption required and "
125                         "setup failed with error %s.\n",
126                         nt_errstr(status));
127                 return false;
128         }
129
130         return true;
131 }
132
133
134 static struct cli_state *open_nbt_connection(void)
135 {
136         struct cli_state *c;
137         NTSTATUS status;
138         int flags = 0;
139
140         if (disable_spnego) {
141                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
142         }
143
144         if (use_oplocks) {
145                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
146         }
147
148         if (use_level_II_oplocks) {
149                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
150         }
151
152         if (force_dos_errors) {
153                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
154         }
155
156         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
157                                 signing_state, flags, &c);
158         if (!NT_STATUS_IS_OK(status)) {
159                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
160                 return NULL;
161         }
162
163         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
164
165         return c;
166 }
167
168 /****************************************************************************
169  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
170 ****************************************************************************/
171
172 static bool cli_bad_session_request(int fd,
173                          struct nmb_name *calling, struct nmb_name *called)
174 {
175         TALLOC_CTX *frame;
176         uint8_t len_buf[4];
177         struct iovec iov[3];
178         ssize_t len;
179         uint8_t *inbuf;
180         int err;
181         bool ret = false;
182         uint8_t message_type;
183         uint8_t error;
184         struct tevent_context *ev;
185         struct tevent_req *req;
186
187         frame = talloc_stackframe();
188
189         iov[0].iov_base = len_buf;
190         iov[0].iov_len  = sizeof(len_buf);
191
192         /* put in the destination name */
193
194         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
195                                       called->name_type);
196         if (iov[1].iov_base == NULL) {
197                 goto fail;
198         }
199         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
200                                   talloc_get_size(iov[1].iov_base));
201
202         /* and my name */
203
204         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
205                                       calling->name_type);
206         if (iov[2].iov_base == NULL) {
207                 goto fail;
208         }
209         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
210                                   talloc_get_size(iov[2].iov_base));
211
212         /* Deliberately corrupt the name len (first byte) */
213         *((uint8_t *)iov[2].iov_base) = 100;
214
215         /* send a session request (RFC 1002) */
216         /* setup the packet length
217          * Remove four bytes from the length count, since the length
218          * field in the NBT Session Service header counts the number
219          * of bytes which follow.  The cli_send_smb() function knows
220          * about this and accounts for those four bytes.
221          * CRH.
222          */
223
224         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
225         SCVAL(len_buf,0,0x81);
226
227         len = write_data_iov(fd, iov, 3);
228         if (len == -1) {
229                 goto fail;
230         }
231
232         ev = samba_tevent_context_init(frame);
233         if (ev == NULL) {
234                 goto fail;
235         }
236         req = read_smb_send(frame, ev, fd);
237         if (req == NULL) {
238                 goto fail;
239         }
240         if (!tevent_req_poll(req, ev)) {
241                 goto fail;
242         }
243         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
244         if (len == -1) {
245                 errno = err;
246                 goto fail;
247         }
248         TALLOC_FREE(ev);
249
250         message_type = CVAL(inbuf, 0);
251         if (message_type != 0x83) {
252                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
253                           message_type);
254                 goto fail;
255         }
256
257         if (smb_len(inbuf) != 1) {
258                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
259                           (int)smb_len(inbuf));
260                 goto fail;
261         }
262
263         error = CVAL(inbuf, 4);
264         if (error !=  0x82) {
265                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
266                           (int)error);
267                 goto fail;
268         }
269
270         ret = true;
271 fail:
272         TALLOC_FREE(frame);
273         return ret;
274 }
275
276 /* Insert a NULL at the first separator of the given path and return a pointer
277  * to the remainder of the string.
278  */
279 static char *
280 terminate_path_at_separator(char * path)
281 {
282         char * p;
283
284         if (!path) {
285                 return NULL;
286         }
287
288         if ((p = strchr_m(path, '/'))) {
289                 *p = '\0';
290                 return p + 1;
291         }
292
293         if ((p = strchr_m(path, '\\'))) {
294                 *p = '\0';
295                 return p + 1;
296         }
297
298         /* No separator. */
299         return NULL;
300 }
301
302 /*
303   parse a //server/share type UNC name
304 */
305 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
306                       char **hostname, char **sharename)
307 {
308         char *p;
309
310         *hostname = *sharename = NULL;
311
312         if (strncmp(unc_name, "\\\\", 2) &&
313             strncmp(unc_name, "//", 2)) {
314                 return False;
315         }
316
317         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
318         p = terminate_path_at_separator(*hostname);
319
320         if (p && *p) {
321                 *sharename = talloc_strdup(mem_ctx, p);
322                 terminate_path_at_separator(*sharename);
323         }
324
325         if (*hostname && *sharename) {
326                 return True;
327         }
328
329         TALLOC_FREE(*hostname);
330         TALLOC_FREE(*sharename);
331         return False;
332 }
333
334 static bool torture_open_connection_share(struct cli_state **c,
335                                    const char *hostname, 
336                                    const char *sharename,
337                                    int flags)
338 {
339         NTSTATUS status;
340
341         status = cli_full_connection_creds(c,
342                                            myname,
343                                            hostname,
344                                            NULL, /* dest_ss */
345                                            port_to_use,
346                                            sharename,
347                                            "?????",
348                                            torture_creds,
349                                            flags);
350         if (!NT_STATUS_IS_OK(status)) {
351                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
352                         hostname, sharename, port_to_use, nt_errstr(status));
353                 return False;
354         }
355
356         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
357
358         if (do_encrypt) {
359                 return force_cli_encryption(*c,
360                                         sharename);
361         }
362         return True;
363 }
364
365 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
366 {
367         char **unc_list = NULL;
368         int num_unc_names = 0;
369         bool result;
370
371         if (use_multishare_conn==True) {
372                 char *h, *s;
373                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
374                 if (!unc_list || num_unc_names <= 0) {
375                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
376                         exit(1);
377                 }
378
379                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
380                                       NULL, &h, &s)) {
381                         printf("Failed to parse UNC name %s\n",
382                                unc_list[conn_index % num_unc_names]);
383                         TALLOC_FREE(unc_list);
384                         exit(1);
385                 }
386
387                 result = torture_open_connection_share(c, h, s, flags);
388
389                 /* h, s were copied earlier */
390                 TALLOC_FREE(unc_list);
391                 return result;
392         }
393
394         return torture_open_connection_share(c, host, share, flags);
395 }
396
397 bool torture_open_connection(struct cli_state **c, int conn_index)
398 {
399         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
400
401         if (use_oplocks) {
402                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
403         }
404         if (use_level_II_oplocks) {
405                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
406         }
407
408         return torture_open_connection_flags(c, conn_index, flags);
409 }
410
411 bool torture_init_connection(struct cli_state **pcli)
412 {
413         struct cli_state *cli;
414
415         cli = open_nbt_connection();
416         if (cli == NULL) {
417                 return false;
418         }
419
420         *pcli = cli;
421         return true;
422 }
423
424 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
425 {
426         uint16_t old_vuid = cli_state_get_uid(cli);
427         NTSTATUS status;
428         bool ret;
429
430         cli_state_set_uid(cli, 0);
431         status = cli_session_setup_creds(cli, torture_creds);
432         ret = NT_STATUS_IS_OK(status);
433         *new_vuid = cli_state_get_uid(cli);
434         cli_state_set_uid(cli, old_vuid);
435         return ret;
436 }
437
438
439 bool torture_close_connection(struct cli_state *c)
440 {
441         bool ret = True;
442         NTSTATUS status;
443
444         status = cli_tdis(c);
445         if (!NT_STATUS_IS_OK(status)) {
446                 printf("tdis failed (%s)\n", nt_errstr(status));
447                 ret = False;
448         }
449
450         cli_shutdown(c);
451
452         return ret;
453 }
454
455 void torture_conn_set_sockopt(struct cli_state *cli)
456 {
457         smbXcli_conn_set_sockopt(cli->conn, sockops);
458 }
459
460 /* check if the server produced the expected dos or nt error code */
461 static bool check_both_error(int line, NTSTATUS status,
462                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
463 {
464         if (NT_STATUS_IS_DOS(status)) {
465                 uint8_t cclass;
466                 uint32_t num;
467
468                 /* Check DOS error */
469                 cclass = NT_STATUS_DOS_CLASS(status);
470                 num = NT_STATUS_DOS_CODE(status);
471
472                 if (eclass != cclass || ecode != num) {
473                         printf("unexpected error code class=%d code=%d\n",
474                                (int)cclass, (int)num);
475                         printf(" expected %d/%d %s (line=%d)\n",
476                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
477                         return false;
478                 }
479         } else {
480                 /* Check NT error */
481                 if (!NT_STATUS_EQUAL(nterr, status)) {
482                         printf("unexpected error code %s\n",
483                                 nt_errstr(status));
484                         printf(" expected %s (line=%d)\n",
485                                 nt_errstr(nterr), line);
486                         return false;
487                 }
488         }
489
490         return true;
491 }
492
493
494 /* check if the server produced the expected error code */
495 static bool check_error(int line, NTSTATUS status,
496                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
497 {
498         if (NT_STATUS_IS_DOS(status)) {
499                 uint8_t cclass;
500                 uint32_t num;
501
502                 /* Check DOS error */
503
504                 cclass = NT_STATUS_DOS_CLASS(status);
505                 num = NT_STATUS_DOS_CODE(status);
506
507                 if (eclass != cclass || ecode != num) {
508                         printf("unexpected error code class=%d code=%d\n", 
509                                (int)cclass, (int)num);
510                         printf(" expected %d/%d %s (line=%d)\n", 
511                                (int)eclass, (int)ecode, nt_errstr(nterr),
512                                line);
513                         return False;
514                 }
515
516         } else {
517                 /* Check NT error */
518
519                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
520                         printf("unexpected error code %s\n",
521                                nt_errstr(status));
522                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
523                                line);
524                         return False;
525                 }
526         }
527
528         return True;
529 }
530
531
532 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
533 {
534         NTSTATUS status;
535
536         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
537
538         while (!NT_STATUS_IS_OK(status)) {
539                 if (!check_both_error(__LINE__, status, ERRDOS,
540                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
541                         return false;
542                 }
543
544                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
545         }
546
547         return true;
548 }
549
550
551 static bool rw_torture(struct cli_state *c)
552 {
553         const char *lockfname = "\\torture.lck";
554         fstring fname;
555         uint16_t fnum;
556         uint16_t fnum2;
557         pid_t pid2, pid = getpid();
558         int i, j;
559         char buf[1024];
560         bool correct = True;
561         size_t nread = 0;
562         NTSTATUS status;
563
564         memset(buf, '\0', sizeof(buf));
565
566         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
567                          DENY_NONE, &fnum2);
568         if (!NT_STATUS_IS_OK(status)) {
569                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
570         }
571         if (!NT_STATUS_IS_OK(status)) {
572                 printf("open of %s failed (%s)\n",
573                        lockfname, nt_errstr(status));
574                 return False;
575         }
576
577         for (i=0;i<torture_numops;i++) {
578                 unsigned n = (unsigned)sys_random()%10;
579
580                 if (i % 10 == 0) {
581                         printf("%d\r", i); fflush(stdout);
582                 }
583                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
584
585                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
586                         return False;
587                 }
588
589                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
590                                   DENY_ALL, &fnum);
591                 if (!NT_STATUS_IS_OK(status)) {
592                         printf("open failed (%s)\n", nt_errstr(status));
593                         correct = False;
594                         break;
595                 }
596
597                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
598                                       sizeof(pid), NULL);
599                 if (!NT_STATUS_IS_OK(status)) {
600                         printf("write failed (%s)\n", nt_errstr(status));
601                         correct = False;
602                 }
603
604                 for (j=0;j<50;j++) {
605                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
606                                               sizeof(pid)+(j*sizeof(buf)),
607                                               sizeof(buf), NULL);
608                         if (!NT_STATUS_IS_OK(status)) {
609                                 printf("write failed (%s)\n",
610                                        nt_errstr(status));
611                                 correct = False;
612                         }
613                 }
614
615                 pid2 = 0;
616
617                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
618                                   &nread);
619                 if (!NT_STATUS_IS_OK(status)) {
620                         printf("read failed (%s)\n", nt_errstr(status));
621                         correct = false;
622                 } else if (nread != sizeof(pid)) {
623                         printf("read/write compare failed: "
624                                "recv %ld req %ld\n", (unsigned long)nread,
625                                (unsigned long)sizeof(pid));
626                         correct = false;
627                 }
628
629                 if (pid2 != pid) {
630                         printf("data corruption!\n");
631                         correct = False;
632                 }
633
634                 status = cli_close(c, fnum);
635                 if (!NT_STATUS_IS_OK(status)) {
636                         printf("close failed (%s)\n", nt_errstr(status));
637                         correct = False;
638                 }
639
640                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
641                 if (!NT_STATUS_IS_OK(status)) {
642                         printf("unlink failed (%s)\n", nt_errstr(status));
643                         correct = False;
644                 }
645
646                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
647                 if (!NT_STATUS_IS_OK(status)) {
648                         printf("unlock failed (%s)\n", nt_errstr(status));
649                         correct = False;
650                 }
651         }
652
653         cli_close(c, fnum2);
654         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
655
656         printf("%d\n", i);
657
658         return correct;
659 }
660
661 static bool run_torture(int dummy)
662 {
663         struct cli_state *cli;
664         bool ret;
665
666         cli = current_cli;
667
668         smbXcli_conn_set_sockopt(cli->conn, sockops);
669
670         ret = rw_torture(cli);
671
672         if (!torture_close_connection(cli)) {
673                 ret = False;
674         }
675
676         return ret;
677 }
678
679 static bool rw_torture3(struct cli_state *c, char *lockfname)
680 {
681         uint16_t fnum = (uint16_t)-1;
682         unsigned int i = 0;
683         char buf[131072];
684         char buf_rd[131072];
685         unsigned count;
686         unsigned countprev = 0;
687         size_t sent = 0;
688         bool correct = True;
689         NTSTATUS status = NT_STATUS_OK;
690
691         srandom(1);
692         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
693         {
694                 SIVAL(buf, i, sys_random());
695         }
696
697         if (procnum == 0)
698         {
699                 status = cli_unlink(
700                         c, lockfname,
701                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
702                 if (!NT_STATUS_IS_OK(status)) {
703                         printf("unlink failed (%s) (normal, this file should "
704                                "not exist)\n", nt_errstr(status));
705                 }
706
707                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
708                                   DENY_NONE, &fnum);
709                 if (!NT_STATUS_IS_OK(status)) {
710                         printf("first open read/write of %s failed (%s)\n",
711                                         lockfname, nt_errstr(status));
712                         return False;
713                 }
714         }
715         else
716         {
717                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
718                 {
719                         status = cli_openx(c, lockfname, O_RDONLY, 
720                                          DENY_NONE, &fnum);
721                         if (NT_STATUS_IS_OK(status)) {
722                                 break;
723                         }
724                         smb_msleep(10);
725                 }
726                 if (!NT_STATUS_IS_OK(status)) {
727                         printf("second open read-only of %s failed (%s)\n",
728                                         lockfname, nt_errstr(status));
729                         return False;
730                 }
731         }
732
733         i = 0;
734         for (count = 0; count < sizeof(buf); count += sent)
735         {
736                 if (count >= countprev) {
737                         printf("%d %8d\r", i, count);
738                         fflush(stdout);
739                         i++;
740                         countprev += (sizeof(buf) / 20);
741                 }
742
743                 if (procnum == 0)
744                 {
745                         sent = ((unsigned)sys_random()%(20))+ 1;
746                         if (sent > sizeof(buf) - count)
747                         {
748                                 sent = sizeof(buf) - count;
749                         }
750
751                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
752                                               count, sent, NULL);
753                         if (!NT_STATUS_IS_OK(status)) {
754                                 printf("write failed (%s)\n",
755                                        nt_errstr(status));
756                                 correct = False;
757                         }
758                 }
759                 else
760                 {
761                         status = cli_read(c, fnum, buf_rd+count, count,
762                                           sizeof(buf)-count, &sent);
763                         if(!NT_STATUS_IS_OK(status)) {
764                                 printf("read failed offset:%d size:%ld (%s)\n",
765                                        count, (unsigned long)sizeof(buf)-count,
766                                        nt_errstr(status));
767                                 correct = False;
768                                 sent = 0;
769                         } else if (sent > 0) {
770                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
771                                 {
772                                         printf("read/write compare failed\n");
773                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
774                                         correct = False;
775                                         break;
776                                 }
777                         }
778                 }
779
780         }
781
782         status = cli_close(c, fnum);
783         if (!NT_STATUS_IS_OK(status)) {
784                 printf("close failed (%s)\n", nt_errstr(status));
785                 correct = False;
786         }
787
788         return correct;
789 }
790
791 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
792 {
793         const char *lockfname = "\\torture2.lck";
794         uint16_t fnum1;
795         uint16_t fnum2;
796         int i;
797         char buf[131072];
798         char buf_rd[131072];
799         bool correct = True;
800         size_t bytes_read;
801         NTSTATUS status;
802
803         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
804         if (!NT_STATUS_IS_OK(status)) {
805                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
806         }
807
808         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
809                           DENY_NONE, &fnum1);
810         if (!NT_STATUS_IS_OK(status)) {
811                 printf("first open read/write of %s failed (%s)\n",
812                                 lockfname, nt_errstr(status));
813                 return False;
814         }
815
816         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
817         if (!NT_STATUS_IS_OK(status)) {
818                 printf("second open read-only of %s failed (%s)\n",
819                                 lockfname, nt_errstr(status));
820                 cli_close(c1, fnum1);
821                 return False;
822         }
823
824         for (i = 0; i < torture_numops; i++)
825         {
826                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
827                 if (i % 10 == 0) {
828                         printf("%d\r", i); fflush(stdout);
829                 }
830
831                 generate_random_buffer((unsigned char *)buf, buf_size);
832
833                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
834                                       buf_size, NULL);
835                 if (!NT_STATUS_IS_OK(status)) {
836                         printf("write failed (%s)\n", nt_errstr(status));
837                         correct = False;
838                         break;
839                 }
840
841                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
842                 if(!NT_STATUS_IS_OK(status)) {
843                         printf("read failed (%s)\n", nt_errstr(status));
844                         correct = false;
845                         break;
846                 } else if (bytes_read != buf_size) {
847                         printf("read failed\n");
848                         printf("read %ld, expected %ld\n",
849                                (unsigned long)bytes_read,
850                                (unsigned long)buf_size); 
851                         correct = False;
852                         break;
853                 }
854
855                 if (memcmp(buf_rd, buf, buf_size) != 0)
856                 {
857                         printf("read/write compare failed\n");
858                         correct = False;
859                         break;
860                 }
861         }
862
863         status = cli_close(c2, fnum2);
864         if (!NT_STATUS_IS_OK(status)) {
865                 printf("close failed (%s)\n", nt_errstr(status));
866                 correct = False;
867         }
868
869         status = cli_close(c1, fnum1);
870         if (!NT_STATUS_IS_OK(status)) {
871                 printf("close failed (%s)\n", nt_errstr(status));
872                 correct = False;
873         }
874
875         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
876         if (!NT_STATUS_IS_OK(status)) {
877                 printf("unlink failed (%s)\n", nt_errstr(status));
878                 correct = False;
879         }
880
881         return correct;
882 }
883
884 static bool run_readwritetest(int dummy)
885 {
886         struct cli_state *cli1, *cli2;
887         bool test1, test2 = False;
888
889         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
890                 return False;
891         }
892         smbXcli_conn_set_sockopt(cli1->conn, sockops);
893         smbXcli_conn_set_sockopt(cli2->conn, sockops);
894
895         printf("starting readwritetest\n");
896
897         test1 = rw_torture2(cli1, cli2);
898         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
899
900         if (test1) {
901                 test2 = rw_torture2(cli1, cli1);
902                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
903         }
904
905         if (!torture_close_connection(cli1)) {
906                 test1 = False;
907         }
908
909         if (!torture_close_connection(cli2)) {
910                 test2 = False;
911         }
912
913         return (test1 && test2);
914 }
915
916 static bool run_readwritemulti(int dummy)
917 {
918         struct cli_state *cli;
919         bool test;
920
921         cli = current_cli;
922
923         smbXcli_conn_set_sockopt(cli->conn, sockops);
924
925         printf("run_readwritemulti: fname %s\n", randomfname);
926         test = rw_torture3(cli, randomfname);
927
928         if (!torture_close_connection(cli)) {
929                 test = False;
930         }
931
932         return test;
933 }
934
935 static bool run_readwritelarge_internal(void)
936 {
937         static struct cli_state *cli1;
938         uint16_t fnum1;
939         const char *lockfname = "\\large.dat";
940         off_t fsize;
941         char buf[126*1024];
942         bool correct = True;
943         NTSTATUS status;
944
945         if (!torture_open_connection(&cli1, 0)) {
946                 return False;
947         }
948         smbXcli_conn_set_sockopt(cli1->conn, sockops);
949         memset(buf,'\0',sizeof(buf));
950
951         printf("starting readwritelarge_internal\n");
952
953         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
954
955         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
956                           DENY_NONE, &fnum1);
957         if (!NT_STATUS_IS_OK(status)) {
958                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
959                 return False;
960         }
961
962         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
963
964         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
965                                      NULL, NULL, NULL);
966         if (!NT_STATUS_IS_OK(status)) {
967                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
968                 correct = False;
969         }
970
971         if (fsize == sizeof(buf))
972                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
973                        (unsigned long)fsize);
974         else {
975                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
976                        (unsigned long)fsize);
977                 correct = False;
978         }
979
980         status = cli_close(cli1, fnum1);
981         if (!NT_STATUS_IS_OK(status)) {
982                 printf("close failed (%s)\n", nt_errstr(status));
983                 correct = False;
984         }
985
986         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
987         if (!NT_STATUS_IS_OK(status)) {
988                 printf("unlink failed (%s)\n", nt_errstr(status));
989                 correct = False;
990         }
991
992         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
993                           DENY_NONE, &fnum1);
994         if (!NT_STATUS_IS_OK(status)) {
995                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
996                 return False;
997         }
998
999         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1000
1001         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1002                                      NULL, NULL, NULL);
1003         if (!NT_STATUS_IS_OK(status)) {
1004                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1005                 correct = False;
1006         }
1007
1008         if (fsize == sizeof(buf))
1009                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1010                        (unsigned long)fsize);
1011         else {
1012                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1013                        (unsigned long)fsize);
1014                 correct = False;
1015         }
1016
1017         status = cli_close(cli1, fnum1);
1018         if (!NT_STATUS_IS_OK(status)) {
1019                 printf("close failed (%s)\n", nt_errstr(status));
1020                 correct = False;
1021         }
1022
1023         if (!torture_close_connection(cli1)) {
1024                 correct = False;
1025         }
1026         return correct;
1027 }
1028
1029 static bool run_readwritelarge(int dummy)
1030 {
1031         return run_readwritelarge_internal();
1032 }
1033
1034 static bool run_readwritelarge_signtest(int dummy)
1035 {
1036         bool ret;
1037         signing_state = SMB_SIGNING_REQUIRED;
1038         ret = run_readwritelarge_internal();
1039         signing_state = SMB_SIGNING_DEFAULT;
1040         return ret;
1041 }
1042
1043 int line_count = 0;
1044 int nbio_id;
1045
1046 #define ival(s) strtol(s, NULL, 0)
1047
1048 /* run a test that simulates an approximate netbench client load */
1049 static bool run_netbench(int client)
1050 {
1051         struct cli_state *cli;
1052         int i;
1053         char line[1024];
1054         char cname[20];
1055         FILE *f;
1056         const char *params[20];
1057         bool correct = True;
1058
1059         cli = current_cli;
1060
1061         nbio_id = client;
1062
1063         smbXcli_conn_set_sockopt(cli->conn, sockops);
1064
1065         nb_setup(cli);
1066
1067         slprintf(cname,sizeof(cname)-1, "client%d", client);
1068
1069         f = fopen(client_txt, "r");
1070
1071         if (!f) {
1072                 perror(client_txt);
1073                 return False;
1074         }
1075
1076         while (fgets(line, sizeof(line)-1, f)) {
1077                 char *saveptr;
1078                 line_count++;
1079
1080                 line[strlen(line)-1] = 0;
1081
1082                 /* printf("[%d] %s\n", line_count, line); */
1083
1084                 all_string_sub(line,"client1", cname, sizeof(line));
1085
1086                 /* parse the command parameters */
1087                 params[0] = strtok_r(line, " ", &saveptr);
1088                 i = 0;
1089                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1090
1091                 params[i] = "";
1092
1093                 if (i < 2) continue;
1094
1095                 if (!strncmp(params[0],"SMB", 3)) {
1096                         printf("ERROR: You are using a dbench 1 load file\n");
1097                         exit(1);
1098                 }
1099
1100                 if (!strcmp(params[0],"NTCreateX")) {
1101                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1102                                    ival(params[4]));
1103                 } else if (!strcmp(params[0],"Close")) {
1104                         nb_close(ival(params[1]));
1105                 } else if (!strcmp(params[0],"Rename")) {
1106                         nb_rename(params[1], params[2]);
1107                 } else if (!strcmp(params[0],"Unlink")) {
1108                         nb_unlink(params[1]);
1109                 } else if (!strcmp(params[0],"Deltree")) {
1110                         nb_deltree(params[1]);
1111                 } else if (!strcmp(params[0],"Rmdir")) {
1112                         nb_rmdir(params[1]);
1113                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1114                         nb_qpathinfo(params[1]);
1115                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1116                         nb_qfileinfo(ival(params[1]));
1117                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1118                         nb_qfsinfo(ival(params[1]));
1119                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1120                         nb_findfirst(params[1]);
1121                 } else if (!strcmp(params[0],"WriteX")) {
1122                         nb_writex(ival(params[1]), 
1123                                   ival(params[2]), ival(params[3]), ival(params[4]));
1124                 } else if (!strcmp(params[0],"ReadX")) {
1125                         nb_readx(ival(params[1]), 
1126                                   ival(params[2]), ival(params[3]), ival(params[4]));
1127                 } else if (!strcmp(params[0],"Flush")) {
1128                         nb_flush(ival(params[1]));
1129                 } else {
1130                         printf("Unknown operation %s\n", params[0]);
1131                         exit(1);
1132                 }
1133         }
1134         fclose(f);
1135
1136         nb_cleanup();
1137
1138         if (!torture_close_connection(cli)) {
1139                 correct = False;
1140         }
1141
1142         return correct;
1143 }
1144
1145
1146 /* run a test that simulates an approximate netbench client load */
1147 static bool run_nbench(int dummy)
1148 {
1149         double t;
1150         bool correct = True;
1151
1152         nbio_shmem(torture_nprocs);
1153
1154         nbio_id = -1;
1155
1156         signal(SIGALRM, nb_alarm);
1157         alarm(1);
1158         t = create_procs(run_netbench, &correct);
1159         alarm(0);
1160
1161         printf("\nThroughput %g MB/sec\n", 
1162                1.0e-6 * nbio_total() / t);
1163         return correct;
1164 }
1165
1166
1167 /*
1168   This test checks for two things:
1169
1170   1) correct support for retaining locks over a close (ie. the server
1171      must not use posix semantics)
1172   2) support for lock timeouts
1173  */
1174 static bool run_locktest1(int dummy)
1175 {
1176         struct cli_state *cli1, *cli2;
1177         const char *fname = "\\lockt1.lck";
1178         uint16_t fnum1, fnum2, fnum3;
1179         time_t t1, t2;
1180         unsigned lock_timeout;
1181         NTSTATUS status;
1182
1183         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1184                 return False;
1185         }
1186         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1187         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1188
1189         printf("starting locktest1\n");
1190
1191         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1192
1193         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1194                           &fnum1);
1195         if (!NT_STATUS_IS_OK(status)) {
1196                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1197                 return False;
1198         }
1199
1200         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1201         if (!NT_STATUS_IS_OK(status)) {
1202                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1203                 return False;
1204         }
1205
1206         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1207         if (!NT_STATUS_IS_OK(status)) {
1208                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1209                 return False;
1210         }
1211
1212         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 printf("lock1 failed (%s)\n", nt_errstr(status));
1215                 return false;
1216         }
1217
1218         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1219         if (NT_STATUS_IS_OK(status)) {
1220                 printf("lock2 succeeded! This is a locking bug\n");
1221                 return false;
1222         } else {
1223                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1224                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1225                         return false;
1226                 }
1227         }
1228
1229         lock_timeout = (1 + (random() % 20));
1230         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1231         t1 = time(NULL);
1232         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1233         if (NT_STATUS_IS_OK(status)) {
1234                 printf("lock3 succeeded! This is a locking bug\n");
1235                 return false;
1236         } else {
1237                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1238                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1239                         return false;
1240                 }
1241         }
1242         t2 = time(NULL);
1243
1244         if (ABS(t2 - t1) < lock_timeout-1) {
1245                 printf("error: This server appears not to support timed lock requests\n");
1246         }
1247
1248         printf("server slept for %u seconds for a %u second timeout\n",
1249                (unsigned int)(t2-t1), lock_timeout);
1250
1251         status = cli_close(cli1, fnum2);
1252         if (!NT_STATUS_IS_OK(status)) {
1253                 printf("close1 failed (%s)\n", nt_errstr(status));
1254                 return False;
1255         }
1256
1257         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1258         if (NT_STATUS_IS_OK(status)) {
1259                 printf("lock4 succeeded! This is a locking bug\n");
1260                 return false;
1261         } else {
1262                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1263                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1264                         return false;
1265                 }
1266         }
1267
1268         status = cli_close(cli1, fnum1);
1269         if (!NT_STATUS_IS_OK(status)) {
1270                 printf("close2 failed (%s)\n", nt_errstr(status));
1271                 return False;
1272         }
1273
1274         status = cli_close(cli2, fnum3);
1275         if (!NT_STATUS_IS_OK(status)) {
1276                 printf("close3 failed (%s)\n", nt_errstr(status));
1277                 return False;
1278         }
1279
1280         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1281         if (!NT_STATUS_IS_OK(status)) {
1282                 printf("unlink failed (%s)\n", nt_errstr(status));
1283                 return False;
1284         }
1285
1286
1287         if (!torture_close_connection(cli1)) {
1288                 return False;
1289         }
1290
1291         if (!torture_close_connection(cli2)) {
1292                 return False;
1293         }
1294
1295         printf("Passed locktest1\n");
1296         return True;
1297 }
1298
1299 /*
1300   this checks to see if a secondary tconx can use open files from an
1301   earlier tconx
1302  */
1303 static bool run_tcon_test(int dummy)
1304 {
1305         static struct cli_state *cli;
1306         const char *fname = "\\tcontest.tmp";
1307         uint16_t fnum1;
1308         uint32_t cnum1, cnum2, cnum3;
1309         struct smbXcli_tcon *orig_tcon = NULL;
1310         uint16_t vuid1, vuid2;
1311         char buf[4];
1312         bool ret = True;
1313         NTSTATUS status;
1314
1315         memset(buf, '\0', sizeof(buf));
1316
1317         if (!torture_open_connection(&cli, 0)) {
1318                 return False;
1319         }
1320         smbXcli_conn_set_sockopt(cli->conn, sockops);
1321
1322         printf("starting tcontest\n");
1323
1324         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1325
1326         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1327         if (!NT_STATUS_IS_OK(status)) {
1328                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1329                 return False;
1330         }
1331
1332         cnum1 = cli_state_get_tid(cli);
1333         vuid1 = cli_state_get_uid(cli);
1334
1335         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1336         if (!NT_STATUS_IS_OK(status)) {
1337                 printf("initial write failed (%s)", nt_errstr(status));
1338                 return False;
1339         }
1340
1341         orig_tcon = cli_state_save_tcon(cli);
1342         if (orig_tcon == NULL) {
1343                 return false;
1344         }
1345
1346         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1347         if (!NT_STATUS_IS_OK(status)) {
1348                 printf("%s refused 2nd tree connect (%s)\n", host,
1349                        nt_errstr(status));
1350                 cli_state_restore_tcon(cli, orig_tcon);
1351                 cli_shutdown(cli);
1352                 return False;
1353         }
1354
1355         cnum2 = cli_state_get_tid(cli);
1356         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1357         vuid2 = cli_state_get_uid(cli) + 1;
1358
1359         /* try a write with the wrong tid */
1360         cli_state_set_tid(cli, cnum2);
1361
1362         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1363         if (NT_STATUS_IS_OK(status)) {
1364                 printf("* server allows write with wrong TID\n");
1365                 ret = False;
1366         } else {
1367                 printf("server fails write with wrong TID : %s\n",
1368                        nt_errstr(status));
1369         }
1370
1371
1372         /* try a write with an invalid tid */
1373         cli_state_set_tid(cli, cnum3);
1374
1375         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1376         if (NT_STATUS_IS_OK(status)) {
1377                 printf("* server allows write with invalid TID\n");
1378                 ret = False;
1379         } else {
1380                 printf("server fails write with invalid TID : %s\n",
1381                        nt_errstr(status));
1382         }
1383
1384         /* try a write with an invalid vuid */
1385         cli_state_set_uid(cli, vuid2);
1386         cli_state_set_tid(cli, cnum1);
1387
1388         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1389         if (NT_STATUS_IS_OK(status)) {
1390                 printf("* server allows write with invalid VUID\n");
1391                 ret = False;
1392         } else {
1393                 printf("server fails write with invalid VUID : %s\n",
1394                        nt_errstr(status));
1395         }
1396
1397         cli_state_set_tid(cli, cnum1);
1398         cli_state_set_uid(cli, vuid1);
1399
1400         status = cli_close(cli, fnum1);
1401         if (!NT_STATUS_IS_OK(status)) {
1402                 printf("close failed (%s)\n", nt_errstr(status));
1403                 cli_state_restore_tcon(cli, orig_tcon);
1404                 cli_shutdown(cli);
1405                 return False;
1406         }
1407
1408         cli_state_set_tid(cli, cnum2);
1409
1410         status = cli_tdis(cli);
1411         if (!NT_STATUS_IS_OK(status)) {
1412                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1413                 cli_state_restore_tcon(cli, orig_tcon);
1414                 cli_shutdown(cli);
1415                 return False;
1416         }
1417
1418         cli_state_restore_tcon(cli, orig_tcon);
1419
1420         cli_state_set_tid(cli, cnum1);
1421
1422         if (!torture_close_connection(cli)) {
1423                 return False;
1424         }
1425
1426         return ret;
1427 }
1428
1429
1430 /*
1431  checks for old style tcon support
1432  */
1433 static bool run_tcon2_test(int dummy)
1434 {
1435         static struct cli_state *cli;
1436         uint16_t cnum, max_xmit;
1437         char *service;
1438         NTSTATUS status;
1439
1440         if (!torture_open_connection(&cli, 0)) {
1441                 return False;
1442         }
1443         smbXcli_conn_set_sockopt(cli->conn, sockops);
1444
1445         printf("starting tcon2 test\n");
1446
1447         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1448                 return false;
1449         }
1450
1451         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1452
1453         SAFE_FREE(service);
1454
1455         if (!NT_STATUS_IS_OK(status)) {
1456                 printf("tcon2 failed : %s\n", nt_errstr(status));
1457         } else {
1458                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1459                        (int)max_xmit, (int)cnum);
1460         }
1461
1462         if (!torture_close_connection(cli)) {
1463                 return False;
1464         }
1465
1466         printf("Passed tcon2 test\n");
1467         return True;
1468 }
1469
1470 static bool tcon_devtest(struct cli_state *cli,
1471                          const char *myshare, const char *devtype,
1472                          const char *return_devtype,
1473                          NTSTATUS expected_error)
1474 {
1475         NTSTATUS status;
1476         bool ret;
1477
1478         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1479
1480         if (NT_STATUS_IS_OK(expected_error)) {
1481                 if (NT_STATUS_IS_OK(status)) {
1482                         if (return_devtype != NULL &&
1483                             strequal(cli->dev, return_devtype)) {
1484                                 ret = True;
1485                         } else { 
1486                                 printf("tconX to share %s with type %s "
1487                                        "succeeded but returned the wrong "
1488                                        "device type (got [%s] but should have got [%s])\n",
1489                                        myshare, devtype, cli->dev, return_devtype);
1490                                 ret = False;
1491                         }
1492                 } else {
1493                         printf("tconX to share %s with type %s "
1494                                "should have succeeded but failed\n",
1495                                myshare, devtype);
1496                         ret = False;
1497                 }
1498                 cli_tdis(cli);
1499         } else {
1500                 if (NT_STATUS_IS_OK(status)) {
1501                         printf("tconx to share %s with type %s "
1502                                "should have failed but succeeded\n",
1503                                myshare, devtype);
1504                         ret = False;
1505                 } else {
1506                         if (NT_STATUS_EQUAL(status, expected_error)) {
1507                                 ret = True;
1508                         } else {
1509                                 printf("Returned unexpected error\n");
1510                                 ret = False;
1511                         }
1512                 }
1513         }
1514         return ret;
1515 }
1516
1517 /*
1518  checks for correct tconX support
1519  */
1520 static bool run_tcon_devtype_test(int dummy)
1521 {
1522         static struct cli_state *cli1 = NULL;
1523         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1524         NTSTATUS status;
1525         bool ret = True;
1526
1527         status = cli_full_connection_creds(&cli1,
1528                                            myname,
1529                                            host,
1530                                            NULL, /* dest_ss */
1531                                            port_to_use,
1532                                            NULL, /* service */
1533                                            NULL, /* service_type */
1534                                            torture_creds,
1535                                            flags);
1536
1537         if (!NT_STATUS_IS_OK(status)) {
1538                 printf("could not open connection\n");
1539                 return False;
1540         }
1541
1542         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543                 ret = False;
1544
1545         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1546                 ret = False;
1547
1548         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1549                 ret = False;
1550
1551         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1552                 ret = False;
1553
1554         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1555                 ret = False;
1556
1557         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1558                 ret = False;
1559
1560         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1561                 ret = False;
1562
1563         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1564                 ret = False;
1565
1566         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567                 ret = False;
1568
1569         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1570                 ret = False;
1571
1572         cli_shutdown(cli1);
1573
1574         if (ret)
1575                 printf("Passed tcondevtest\n");
1576
1577         return ret;
1578 }
1579
1580
1581 /*
1582   This test checks that 
1583
1584   1) the server supports multiple locking contexts on the one SMB
1585   connection, distinguished by PID.  
1586
1587   2) the server correctly fails overlapping locks made by the same PID (this
1588      goes against POSIX behaviour, which is why it is tricky to implement)
1589
1590   3) the server denies unlock requests by an incorrect client PID
1591 */
1592 static bool run_locktest2(int dummy)
1593 {
1594         static struct cli_state *cli;
1595         const char *fname = "\\lockt2.lck";
1596         uint16_t fnum1, fnum2, fnum3;
1597         bool correct = True;
1598         NTSTATUS status;
1599
1600         if (!torture_open_connection(&cli, 0)) {
1601                 return False;
1602         }
1603
1604         smbXcli_conn_set_sockopt(cli->conn, sockops);
1605
1606         printf("starting locktest2\n");
1607
1608         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1609
1610         cli_setpid(cli, 1);
1611
1612         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1613         if (!NT_STATUS_IS_OK(status)) {
1614                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1615                 return False;
1616         }
1617
1618         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1619         if (!NT_STATUS_IS_OK(status)) {
1620                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1621                 return False;
1622         }
1623
1624         cli_setpid(cli, 2);
1625
1626         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1629                 return False;
1630         }
1631
1632         cli_setpid(cli, 1);
1633
1634         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1635         if (!NT_STATUS_IS_OK(status)) {
1636                 printf("lock1 failed (%s)\n", nt_errstr(status));
1637                 return false;
1638         }
1639
1640         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1641         if (NT_STATUS_IS_OK(status)) {
1642                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1643                 correct = false;
1644         } else {
1645                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1646                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1647                         return false;
1648                 }
1649         }
1650
1651         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1652         if (NT_STATUS_IS_OK(status)) {
1653                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1654                 correct = false;
1655         } else {
1656                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1657                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1658                         return false;
1659                 }
1660         }
1661
1662         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1663         if (NT_STATUS_IS_OK(status)) {
1664                 printf("READ lock2 succeeded! This is a locking bug\n");
1665                 correct = false;
1666         } else {
1667                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1668                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1669                         return false;
1670                 }
1671         }
1672
1673         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1674         if (!NT_STATUS_IS_OK(status)) {
1675                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1676         }
1677         cli_setpid(cli, 2);
1678         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1679                 printf("unlock at 100 succeeded! This is a locking bug\n");
1680                 correct = False;
1681         }
1682
1683         status = cli_unlock(cli, fnum1, 0, 4);
1684         if (NT_STATUS_IS_OK(status)) {
1685                 printf("unlock1 succeeded! This is a locking bug\n");
1686                 correct = false;
1687         } else {
1688                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1689                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1690                         return false;
1691                 }
1692         }
1693
1694         status = cli_unlock(cli, fnum1, 0, 8);
1695         if (NT_STATUS_IS_OK(status)) {
1696                 printf("unlock2 succeeded! This is a locking bug\n");
1697                 correct = false;
1698         } else {
1699                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1700                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1701                         return false;
1702                 }
1703         }
1704
1705         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1706         if (NT_STATUS_IS_OK(status)) {
1707                 printf("lock3 succeeded! This is a locking bug\n");
1708                 correct = false;
1709         } else {
1710                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1711                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1712                         return false;
1713                 }
1714         }
1715
1716         cli_setpid(cli, 1);
1717
1718         status = cli_close(cli, fnum1);
1719         if (!NT_STATUS_IS_OK(status)) {
1720                 printf("close1 failed (%s)\n", nt_errstr(status));
1721                 return False;
1722         }
1723
1724         status = cli_close(cli, fnum2);
1725         if (!NT_STATUS_IS_OK(status)) {
1726                 printf("close2 failed (%s)\n", nt_errstr(status));
1727                 return False;
1728         }
1729
1730         status = cli_close(cli, fnum3);
1731         if (!NT_STATUS_IS_OK(status)) {
1732                 printf("close3 failed (%s)\n", nt_errstr(status));
1733                 return False;
1734         }
1735
1736         if (!torture_close_connection(cli)) {
1737                 correct = False;
1738         }
1739
1740         printf("locktest2 finished\n");
1741
1742         return correct;
1743 }
1744
1745
1746 /*
1747   This test checks that 
1748
1749   1) the server supports the full offset range in lock requests
1750 */
1751 static bool run_locktest3(int dummy)
1752 {
1753         static struct cli_state *cli1, *cli2;
1754         const char *fname = "\\lockt3.lck";
1755         uint16_t fnum1, fnum2;
1756         int i;
1757         uint32_t offset;
1758         bool correct = True;
1759         NTSTATUS status;
1760
1761 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1762
1763         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1764                 return False;
1765         }
1766         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1767         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1768
1769         printf("starting locktest3\n");
1770
1771         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1772
1773         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1774                          &fnum1);
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1777                 return False;
1778         }
1779
1780         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1781         if (!NT_STATUS_IS_OK(status)) {
1782                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1783                 return False;
1784         }
1785
1786         for (offset=i=0;i<torture_numops;i++) {
1787                 NEXT_OFFSET;
1788
1789                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1790                 if (!NT_STATUS_IS_OK(status)) {
1791                         printf("lock1 %d failed (%s)\n", 
1792                                i,
1793                                nt_errstr(status));
1794                         return False;
1795                 }
1796
1797                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1798                 if (!NT_STATUS_IS_OK(status)) {
1799                         printf("lock2 %d failed (%s)\n", 
1800                                i,
1801                                nt_errstr(status));
1802                         return False;
1803                 }
1804         }
1805
1806         for (offset=i=0;i<torture_numops;i++) {
1807                 NEXT_OFFSET;
1808
1809                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1810                 if (NT_STATUS_IS_OK(status)) {
1811                         printf("error: lock1 %d succeeded!\n", i);
1812                         return False;
1813                 }
1814
1815                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1816                 if (NT_STATUS_IS_OK(status)) {
1817                         printf("error: lock2 %d succeeded!\n", i);
1818                         return False;
1819                 }
1820
1821                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1822                 if (NT_STATUS_IS_OK(status)) {
1823                         printf("error: lock3 %d succeeded!\n", i);
1824                         return False;
1825                 }
1826
1827                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1828                 if (NT_STATUS_IS_OK(status)) {
1829                         printf("error: lock4 %d succeeded!\n", i);
1830                         return False;
1831                 }
1832         }
1833
1834         for (offset=i=0;i<torture_numops;i++) {
1835                 NEXT_OFFSET;
1836
1837                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1838                 if (!NT_STATUS_IS_OK(status)) {
1839                         printf("unlock1 %d failed (%s)\n", 
1840                                i,
1841                                nt_errstr(status));
1842                         return False;
1843                 }
1844
1845                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1846                 if (!NT_STATUS_IS_OK(status)) {
1847                         printf("unlock2 %d failed (%s)\n", 
1848                                i,
1849                                nt_errstr(status));
1850                         return False;
1851                 }
1852         }
1853
1854         status = cli_close(cli1, fnum1);
1855         if (!NT_STATUS_IS_OK(status)) {
1856                 printf("close1 failed (%s)\n", nt_errstr(status));
1857                 return False;
1858         }
1859
1860         status = cli_close(cli2, fnum2);
1861         if (!NT_STATUS_IS_OK(status)) {
1862                 printf("close2 failed (%s)\n", nt_errstr(status));
1863                 return False;
1864         }
1865
1866         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1867         if (!NT_STATUS_IS_OK(status)) {
1868                 printf("unlink failed (%s)\n", nt_errstr(status));
1869                 return False;
1870         }
1871
1872         if (!torture_close_connection(cli1)) {
1873                 correct = False;
1874         }
1875
1876         if (!torture_close_connection(cli2)) {
1877                 correct = False;
1878         }
1879
1880         printf("finished locktest3\n");
1881
1882         return correct;
1883 }
1884
1885 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1886                            char *buf, off_t offset, size_t size,
1887                            size_t *nread, size_t expect)
1888 {
1889         NTSTATUS status;
1890         size_t l_nread;
1891
1892         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1893
1894         if(!NT_STATUS_IS_OK(status)) {
1895                 return false;
1896         } else if (l_nread != expect) {
1897                 return false;
1898         }
1899
1900         if (nread) {
1901                 *nread = l_nread;
1902         }
1903
1904         return true;
1905 }
1906
1907 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1908         printf("** "); correct = False; \
1909         }
1910
1911 /*
1912   looks at overlapping locks
1913 */
1914 static bool run_locktest4(int dummy)
1915 {
1916         static struct cli_state *cli1, *cli2;
1917         const char *fname = "\\lockt4.lck";
1918         uint16_t fnum1, fnum2, f;
1919         bool ret;
1920         char buf[1000];
1921         bool correct = True;
1922         NTSTATUS status;
1923
1924         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1925                 return False;
1926         }
1927
1928         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1929         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1930
1931         printf("starting locktest4\n");
1932
1933         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1934
1935         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1936         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1937
1938         memset(buf, 0, sizeof(buf));
1939
1940         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1941                               NULL);
1942         if (!NT_STATUS_IS_OK(status)) {
1943                 printf("Failed to create file: %s\n", nt_errstr(status));
1944                 correct = False;
1945                 goto fail;
1946         }
1947
1948         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1949               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1950         EXPECTED(ret, False);
1951         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1952
1953         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1954               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1955         EXPECTED(ret, True);
1956         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1957
1958         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1959               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1960         EXPECTED(ret, False);
1961         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1962
1963         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1964               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1965         EXPECTED(ret, True);
1966         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1967
1968         ret = (cli_setpid(cli1, 1),
1969               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1970               (cli_setpid(cli1, 2),
1971               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1972         EXPECTED(ret, False);
1973         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1974
1975         ret = (cli_setpid(cli1, 1),
1976               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1977               (cli_setpid(cli1, 2),
1978               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1979         EXPECTED(ret, True);
1980         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1981
1982         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1983               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1984         EXPECTED(ret, True);
1985         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1986
1987         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1988               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1989         EXPECTED(ret, False);
1990         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1991
1992         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1993               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1994         EXPECTED(ret, False);
1995         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1996
1997         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1998               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1999         EXPECTED(ret, True);
2000         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2001
2002         ret = (cli_setpid(cli1, 1),
2003              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2004              (cli_setpid(cli1, 2),
2005              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2006         EXPECTED(ret, False);
2007         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2008
2009         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2010               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2011               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2012         EXPECTED(ret, False);
2013         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2014
2015
2016         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2017               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2018         EXPECTED(ret, False);
2019         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2020
2021         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2022         ret = NT_STATUS_IS_OK(status);
2023         if (ret) {
2024                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2025                                       NULL);
2026                 ret = NT_STATUS_IS_OK(status);
2027         }
2028         EXPECTED(ret, False);
2029         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2030
2031
2032         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2033               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2035               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2036         EXPECTED(ret, True);
2037         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2038
2039
2040         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2041               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2042               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2043               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2044               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2045                                              150, 4, NULL))) &&
2046               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2047         EXPECTED(ret, True);
2048         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2049
2050         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2051               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2052               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2053                                            160, 4, NULL)) &&
2054               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2055         EXPECTED(ret, True);
2056         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2057
2058         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2059               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2060               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2061                                            170, 4, NULL)) &&
2062               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2063         EXPECTED(ret, True);
2064         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2065
2066         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2067               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2068               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2069               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2070                                             190, 4, NULL)) &&
2071               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2072         EXPECTED(ret, True);
2073         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2074
2075         cli_close(cli1, fnum1);
2076         cli_close(cli2, fnum2);
2077         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2078         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2079         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2080               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2081               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2082               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2083               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2084         cli_close(cli1, f);
2085         cli_close(cli1, fnum1);
2086         EXPECTED(ret, True);
2087         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2088
2089  fail:
2090         cli_close(cli1, fnum1);
2091         cli_close(cli2, fnum2);
2092         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2093         torture_close_connection(cli1);
2094         torture_close_connection(cli2);
2095
2096         printf("finished locktest4\n");
2097         return correct;
2098 }
2099
2100 /*
2101   looks at lock upgrade/downgrade.
2102 */
2103 static bool run_locktest5(int dummy)
2104 {
2105         static struct cli_state *cli1, *cli2;
2106         const char *fname = "\\lockt5.lck";
2107         uint16_t fnum1, fnum2, fnum3;
2108         bool ret;
2109         char buf[1000];
2110         bool correct = True;
2111         NTSTATUS status;
2112
2113         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2114                 return False;
2115         }
2116
2117         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2118         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2119
2120         printf("starting locktest5\n");
2121
2122         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2123
2124         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2125         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2126         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2127
2128         memset(buf, 0, sizeof(buf));
2129
2130         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2131                               NULL);
2132         if (!NT_STATUS_IS_OK(status)) {
2133                 printf("Failed to create file: %s\n", nt_errstr(status));
2134                 correct = False;
2135                 goto fail;
2136         }
2137
2138         /* Check for NT bug... */
2139         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2140               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2141         cli_close(cli1, fnum1);
2142         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2143         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2144         ret = NT_STATUS_IS_OK(status);
2145         EXPECTED(ret, True);
2146         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2147         cli_close(cli1, fnum1);
2148         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2149         cli_unlock(cli1, fnum3, 0, 1);
2150
2151         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2152               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2153         EXPECTED(ret, True);
2154         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2155
2156         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2157         ret = NT_STATUS_IS_OK(status);
2158         EXPECTED(ret, False);
2159
2160         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2161
2162         /* Unlock the process 2 lock. */
2163         cli_unlock(cli2, fnum2, 0, 4);
2164
2165         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2166         ret = NT_STATUS_IS_OK(status);
2167         EXPECTED(ret, False);
2168
2169         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2170
2171         /* Unlock the process 1 fnum3 lock. */
2172         cli_unlock(cli1, fnum3, 0, 4);
2173
2174         /* Stack 2 more locks here. */
2175         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2176               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2177
2178         EXPECTED(ret, True);
2179         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2180
2181         /* Unlock the first process lock, then check this was the WRITE lock that was
2182                 removed. */
2183
2184         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2185               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2186
2187         EXPECTED(ret, True);
2188         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2189
2190         /* Unlock the process 2 lock. */
2191         cli_unlock(cli2, fnum2, 0, 4);
2192
2193         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2194
2195         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2196                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2197                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2198
2199         EXPECTED(ret, True);
2200         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2201
2202         /* Ensure the next unlock fails. */
2203         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2204         EXPECTED(ret, False);
2205         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2206
2207         /* Ensure connection 2 can get a write lock. */
2208         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2209         ret = NT_STATUS_IS_OK(status);
2210         EXPECTED(ret, True);
2211
2212         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2213
2214
2215  fail:
2216         cli_close(cli1, fnum1);
2217         cli_close(cli2, fnum2);
2218         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219         if (!torture_close_connection(cli1)) {
2220                 correct = False;
2221         }
2222         if (!torture_close_connection(cli2)) {
2223                 correct = False;
2224         }
2225
2226         printf("finished locktest5\n");
2227
2228         return correct;
2229 }
2230
2231 /*
2232   tries the unusual lockingX locktype bits
2233 */
2234 static bool run_locktest6(int dummy)
2235 {
2236         static struct cli_state *cli;
2237         const char *fname[1] = { "\\lock6.txt" };
2238         int i;
2239         uint16_t fnum;
2240         NTSTATUS status;
2241
2242         if (!torture_open_connection(&cli, 0)) {
2243                 return False;
2244         }
2245
2246         smbXcli_conn_set_sockopt(cli->conn, sockops);
2247
2248         printf("starting locktest6\n");
2249
2250         for (i=0;i<1;i++) {
2251                 printf("Testing %s\n", fname[i]);
2252
2253                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2254
2255                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2256                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2257                 cli_close(cli, fnum);
2258                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2259
2260                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2261                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2262                 cli_close(cli, fnum);
2263                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2264
2265                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2266         }
2267
2268         torture_close_connection(cli);
2269
2270         printf("finished locktest6\n");
2271         return True;
2272 }
2273
2274 static bool run_locktest7(int dummy)
2275 {
2276         struct cli_state *cli1;
2277         const char *fname = "\\lockt7.lck";
2278         uint16_t fnum1;
2279         char buf[200];
2280         bool correct = False;
2281         size_t nread;
2282         NTSTATUS status;
2283
2284         if (!torture_open_connection(&cli1, 0)) {
2285                 return False;
2286         }
2287
2288         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2289
2290         printf("starting locktest7\n");
2291
2292         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2293
2294         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2295
2296         memset(buf, 0, sizeof(buf));
2297
2298         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2299                               NULL);
2300         if (!NT_STATUS_IS_OK(status)) {
2301                 printf("Failed to create file: %s\n", nt_errstr(status));
2302                 goto fail;
2303         }
2304
2305         cli_setpid(cli1, 1);
2306
2307         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2308         if (!NT_STATUS_IS_OK(status)) {
2309                 printf("Unable to apply read lock on range 130:4, "
2310                        "error was %s\n", nt_errstr(status));
2311                 goto fail;
2312         } else {
2313                 printf("pid1 successfully locked range 130:4 for READ\n");
2314         }
2315
2316         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2317         if (!NT_STATUS_IS_OK(status)) {
2318                 printf("pid1 unable to read the range 130:4, error was %s\n",
2319                       nt_errstr(status));
2320                 goto fail;
2321         } else if (nread != 4) {
2322                 printf("pid1 unable to read the range 130:4, "
2323                        "recv %ld req %d\n", (unsigned long)nread, 4);
2324                 goto fail;
2325         } else {
2326                 printf("pid1 successfully read the range 130:4\n");
2327         }
2328
2329         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2330         if (!NT_STATUS_IS_OK(status)) {
2331                 printf("pid1 unable to write to the range 130:4, error was "
2332                        "%s\n", nt_errstr(status));
2333                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2334                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2335                         goto fail;
2336                 }
2337         } else {
2338                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2339                 goto fail;
2340         }
2341
2342         cli_setpid(cli1, 2);
2343
2344         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2345         if (!NT_STATUS_IS_OK(status)) {
2346                 printf("pid2 unable to read the range 130:4, error was %s\n",
2347                       nt_errstr(status));
2348                 goto fail;
2349         } else if (nread != 4) {
2350                 printf("pid2 unable to read the range 130:4, "
2351                        "recv %ld req %d\n", (unsigned long)nread, 4);
2352                 goto fail;
2353         } else {
2354                 printf("pid2 successfully read the range 130:4\n");
2355         }
2356
2357         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2358         if (!NT_STATUS_IS_OK(status)) {
2359                 printf("pid2 unable to write to the range 130:4, error was "
2360                        "%s\n", nt_errstr(status));
2361                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2362                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2363                         goto fail;
2364                 }
2365         } else {
2366                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2367                 goto fail;
2368         }
2369
2370         cli_setpid(cli1, 1);
2371         cli_unlock(cli1, fnum1, 130, 4);
2372
2373         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2374         if (!NT_STATUS_IS_OK(status)) {
2375                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2376                 goto fail;
2377         } else {
2378                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2379         }
2380
2381         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2382         if (!NT_STATUS_IS_OK(status)) {
2383                 printf("pid1 unable to read the range 130:4, error was %s\n",
2384                       nt_errstr(status));
2385                 goto fail;
2386         } else if (nread != 4) {
2387                 printf("pid1 unable to read the range 130:4, "
2388                        "recv %ld req %d\n", (unsigned long)nread, 4);
2389                 goto fail;
2390         } else {
2391                 printf("pid1 successfully read the range 130:4\n");
2392         }
2393
2394         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2395         if (!NT_STATUS_IS_OK(status)) {
2396                 printf("pid1 unable to write to the range 130:4, error was "
2397                        "%s\n", nt_errstr(status));
2398                 goto fail;
2399         } else {
2400                 printf("pid1 successfully wrote to the range 130:4\n");
2401         }
2402
2403         cli_setpid(cli1, 2);
2404
2405         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2406         if (!NT_STATUS_IS_OK(status)) {
2407                 printf("pid2 unable to read the range 130:4, error was "
2408                        "%s\n", nt_errstr(status));
2409                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2410                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2411                         goto fail;
2412                 }
2413         } else {
2414                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2415                        (unsigned long)nread);
2416                 goto fail;
2417         }
2418
2419         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2420         if (!NT_STATUS_IS_OK(status)) {
2421                 printf("pid2 unable to write to the range 130:4, error was "
2422                        "%s\n", nt_errstr(status));
2423                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2424                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2425                         goto fail;
2426                 }
2427         } else {
2428                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2429                 goto fail;
2430         }
2431
2432         cli_unlock(cli1, fnum1, 130, 0);
2433         correct = True;
2434
2435 fail:
2436         cli_close(cli1, fnum1);
2437         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2438         torture_close_connection(cli1);
2439
2440         printf("finished locktest7\n");
2441         return correct;
2442 }
2443
2444 /*
2445  * This demonstrates a problem with our use of GPFS share modes: A file
2446  * descriptor sitting in the pending close queue holding a GPFS share mode
2447  * blocks opening a file another time. Happens with Word 2007 temp files.
2448  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2449  * open is denied with NT_STATUS_SHARING_VIOLATION.
2450  */
2451
2452 static bool run_locktest8(int dummy)
2453 {
2454         struct cli_state *cli1;
2455         const char *fname = "\\lockt8.lck";
2456         uint16_t fnum1, fnum2;
2457         char buf[200];
2458         bool correct = False;
2459         NTSTATUS status;
2460
2461         if (!torture_open_connection(&cli1, 0)) {
2462                 return False;
2463         }
2464
2465         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2466
2467         printf("starting locktest8\n");
2468
2469         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2470
2471         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2472                           &fnum1);
2473         if (!NT_STATUS_IS_OK(status)) {
2474                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2475                 return false;
2476         }
2477
2478         memset(buf, 0, sizeof(buf));
2479
2480         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2481         if (!NT_STATUS_IS_OK(status)) {
2482                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2483                           nt_errstr(status));
2484                 goto fail;
2485         }
2486
2487         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2488         if (!NT_STATUS_IS_OK(status)) {
2489                 printf("Unable to apply read lock on range 1:1, error was "
2490                        "%s\n", nt_errstr(status));
2491                 goto fail;
2492         }
2493
2494         status = cli_close(cli1, fnum1);
2495         if (!NT_STATUS_IS_OK(status)) {
2496                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2497                 goto fail;
2498         }
2499
2500         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2501         if (!NT_STATUS_IS_OK(status)) {
2502                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2503                           nt_errstr(status));
2504                 goto fail;
2505         }
2506
2507         correct = true;
2508
2509 fail:
2510         cli_close(cli1, fnum1);
2511         cli_close(cli1, fnum2);
2512         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2513         torture_close_connection(cli1);
2514
2515         printf("finished locktest8\n");
2516         return correct;
2517 }
2518
2519 /*
2520  * This test is designed to be run in conjunction with
2521  * external NFS or POSIX locks taken in the filesystem.
2522  * It checks that the smbd server will block until the
2523  * lock is released and then acquire it. JRA.
2524  */
2525
2526 static bool got_alarm;
2527 static struct cli_state *alarm_cli;
2528
2529 static void alarm_handler(int dummy)
2530 {
2531         got_alarm = True;
2532 }
2533
2534 static void alarm_handler_parent(int dummy)
2535 {
2536         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2537 }
2538
2539 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2540 {
2541         int fd;
2542         char c = '\0';
2543         struct flock lock;
2544         const char *local_pathname = NULL;
2545         int ret;
2546
2547         local_pathname = talloc_asprintf(talloc_tos(),
2548                         "%s/%s", local_path, fname);
2549         if (!local_pathname) {
2550                 printf("child: alloc fail\n");
2551                 exit(1);
2552         }
2553
2554         unlink(local_pathname);
2555         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2556         if (fd == -1) {
2557                 printf("child: open of %s failed %s.\n",
2558                         local_pathname, strerror(errno));
2559                 exit(1);
2560         }
2561
2562         /* Now take a fcntl lock. */
2563         lock.l_type = F_WRLCK;
2564         lock.l_whence = SEEK_SET;
2565         lock.l_start = 0;
2566         lock.l_len = 4;
2567         lock.l_pid = getpid();
2568
2569         ret = fcntl(fd,F_SETLK,&lock);
2570         if (ret == -1) {
2571                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2572                         local_pathname, strerror(errno));
2573                 exit(1);
2574         } else {
2575                 printf("child: got lock 0:4 on file %s.\n",
2576                         local_pathname );
2577                 fflush(stdout);
2578         }
2579
2580         CatchSignal(SIGALRM, alarm_handler);
2581         alarm(5);
2582         /* Signal the parent. */
2583         if (write(write_fd, &c, 1) != 1) {
2584                 printf("child: start signal fail %s.\n",
2585                         strerror(errno));
2586                 exit(1);
2587         }
2588         alarm(0);
2589
2590         alarm(10);
2591         /* Wait for the parent to be ready. */
2592         if (read(read_fd, &c, 1) != 1) {
2593                 printf("child: reply signal fail %s.\n",
2594                         strerror(errno));
2595                 exit(1);
2596         }
2597         alarm(0);
2598
2599         sleep(5);
2600         close(fd);
2601         printf("child: released lock 0:4 on file %s.\n",
2602                 local_pathname );
2603         fflush(stdout);
2604         exit(0);
2605 }
2606
2607 static bool _run_locktest9X(const char *fname, int timeout)
2608 {
2609         struct cli_state *cli1;
2610         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2611         uint16_t fnum;
2612         bool correct = False;
2613         int pipe_in[2], pipe_out[2];
2614         pid_t child_pid;
2615         char c = '\0';
2616         int ret;
2617         struct timeval start;
2618         double seconds;
2619         NTSTATUS status;
2620
2621         printf("starting locktest9X: %s\n", fname);
2622
2623         if (local_path == NULL) {
2624                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2625                 return false;
2626         }
2627
2628         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2629                 return false;
2630         }
2631
2632         child_pid = fork();
2633         if (child_pid == -1) {
2634                 return false;
2635         }
2636
2637         if (child_pid == 0) {
2638                 /* Child. */
2639                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2640                 exit(0);
2641         }
2642
2643         close(pipe_out[0]);
2644         close(pipe_in[1]);
2645         pipe_out[0] = -1;
2646         pipe_in[1] = -1;
2647
2648         /* Parent. */
2649         ret = read(pipe_in[0], &c, 1);
2650         if (ret != 1) {
2651                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2652                         strerror(errno));
2653                 return false;
2654         }
2655
2656         if (!torture_open_connection(&cli1, 0)) {
2657                 return false;
2658         }
2659
2660         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2661
2662         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2663                           &fnum);
2664         if (!NT_STATUS_IS_OK(status)) {
2665                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2666                 return false;
2667         }
2668
2669         /* Ensure the child has the lock. */
2670         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2671         if (NT_STATUS_IS_OK(status)) {
2672                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2673                 goto fail;
2674         } else {
2675                 d_printf("Child has the lock.\n");
2676         }
2677
2678         /* Tell the child to wait 5 seconds then exit. */
2679         ret = write(pipe_out[1], &c, 1);
2680         if (ret != 1) {
2681                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2682                         strerror(errno));
2683                 goto fail;
2684         }
2685
2686         /* Wait 20 seconds for the lock. */
2687         alarm_cli = cli1;
2688         CatchSignal(SIGALRM, alarm_handler_parent);
2689         alarm(20);
2690
2691         start = timeval_current();
2692
2693         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2694         if (!NT_STATUS_IS_OK(status)) {
2695                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2696                        "%s\n", nt_errstr(status));
2697                 goto fail_nofd;
2698         }
2699         alarm(0);
2700
2701         seconds = timeval_elapsed(&start);
2702
2703         printf("Parent got the lock after %.2f seconds.\n",
2704                 seconds);
2705
2706         status = cli_close(cli1, fnum);
2707         if (!NT_STATUS_IS_OK(status)) {
2708                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2709                 goto fail;
2710         }
2711
2712         correct = true;
2713
2714 fail:
2715         cli_close(cli1, fnum);
2716         torture_close_connection(cli1);
2717
2718 fail_nofd:
2719
2720         printf("finished locktest9X: %s\n", fname);
2721         return correct;
2722 }
2723
2724 static bool run_locktest9a(int dummy)
2725 {
2726         return _run_locktest9X("lock9a.dat", -1);
2727 }
2728
2729 static bool run_locktest9b(int dummy)
2730 {
2731         return _run_locktest9X("lock9b.dat", 10000);
2732 }
2733
2734 struct locktest10_state {
2735         bool ok;
2736         bool done;
2737 };
2738
2739 static void locktest10_lockingx_done(struct tevent_req *subreq);
2740 static void locktest10_read_andx_done(struct tevent_req *subreq);
2741
2742 static bool run_locktest10(int dummy)
2743 {
2744         struct tevent_context *ev = NULL;
2745         struct cli_state *cli1 = NULL;
2746         struct cli_state *cli2 = NULL;
2747         struct smb1_lock_element lck = { 0 };
2748         struct tevent_req *reqs[2] = { NULL };
2749         struct tevent_req *smbreqs[2] = { NULL };
2750         const char fname[] = "\\lockt10.lck";
2751         uint16_t fnum1, fnum2;
2752         bool ret = false;
2753         bool ok;
2754         uint8_t data = 1;
2755         struct locktest10_state state = { .ok = true };
2756         NTSTATUS status;
2757
2758         printf("starting locktest10\n");
2759
2760         ev = samba_tevent_context_init(NULL);
2761         if (ev == NULL) {
2762                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2763                 goto done;
2764         }
2765
2766         ok = torture_open_connection(&cli1, 0);
2767         if (!ok) {
2768                 goto done;
2769         }
2770         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2771
2772         ok = torture_open_connection(&cli2, 1);
2773         if (!ok) {
2774                 goto done;
2775         }
2776         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2777
2778         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2779         if (!NT_STATUS_IS_OK(status)) {
2780                 d_fprintf(stderr,
2781                           "cli_openx failed: %s\n",
2782                           nt_errstr(status));
2783                 goto done;
2784         }
2785
2786         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2787         if (!NT_STATUS_IS_OK(status)) {
2788                 d_fprintf(stderr,
2789                           "cli_writeall failed: %s\n",
2790                           nt_errstr(status));
2791                 goto done;
2792         }
2793
2794         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2795         if (!NT_STATUS_IS_OK(status)) {
2796                 d_fprintf(stderr,
2797                           "cli_openx failed: %s\n",
2798                           nt_errstr(status));
2799                 goto done;
2800         }
2801
2802         status = cli_locktype(
2803                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2804         if (!NT_STATUS_IS_OK(status)) {
2805                 d_fprintf(stderr,
2806                           "cli_locktype failed: %s\n",
2807                           nt_errstr(status));
2808                 goto done;
2809         }
2810
2811         lck = (struct smb1_lock_element) {
2812                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2813         };
2814
2815         reqs[0] = cli_lockingx_create(
2816                 ev,                             /* mem_ctx */
2817                 ev,                             /* tevent_context */
2818                 cli1,                           /* cli */
2819                 fnum1,                          /* fnum */
2820                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2821                 0,                              /* newoplocklevel */
2822                 1,                              /* timeout */
2823                 0,                              /* num_unlocks */
2824                 NULL,                           /* unlocks */
2825                 1,                              /* num_locks */
2826                 &lck,                           /* locks */
2827                 &smbreqs[0]);                   /* psmbreq */
2828         if (reqs[0] == NULL) {
2829                 d_fprintf(stderr, "cli_lockingx_create failed\n");
2830                 goto done;
2831         }
2832         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2833
2834         reqs[1] = cli_read_andx_create(
2835                 ev,             /* mem_ctx */
2836                 ev,             /* ev */
2837                 cli1,           /* cli */
2838                 fnum1,          /* fnum */
2839                 0,              /* offset */
2840                 1,              /* size */
2841                 &smbreqs[1]);   /* psmbreq */
2842         if (reqs[1] == NULL) {
2843                 d_fprintf(stderr, "cli_read_andx_create failed\n");
2844                 goto done;
2845         }
2846         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2847
2848         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2849         if (!NT_STATUS_IS_OK(status)) {
2850                 d_fprintf(stderr,
2851                           "smb1cli_req_chain_submit failed: %s\n",
2852                           nt_errstr(status));
2853                 goto done;
2854         }
2855
2856         while (!state.done) {
2857                 tevent_loop_once(ev);
2858         }
2859
2860         torture_close_connection(cli1);
2861
2862         if (state.ok) {
2863                 ret = true;
2864         }
2865 done:
2866         return ret;
2867 }
2868
2869 static void locktest10_lockingx_done(struct tevent_req *subreq)
2870 {
2871         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2872         NTSTATUS status;
2873
2874         status = cli_lockingx_recv(subreq);
2875         TALLOC_FREE(subreq);
2876
2877         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2878                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2879                 state->ok = false;
2880         }
2881 }
2882
2883 static void locktest10_read_andx_done(struct tevent_req *subreq)
2884 {
2885         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2886         ssize_t received = -1;
2887         uint8_t *rcvbuf = NULL;
2888         NTSTATUS status;
2889
2890         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2891
2892         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2893                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2894                 state->ok = false;
2895         }
2896
2897         state->done = true;
2898         TALLOC_FREE(subreq);
2899 }
2900
2901 static bool run_locktest11(int dummy)
2902 {
2903         struct cli_state *cli1;
2904         const char *fname = "\\lockt11.lck";
2905         NTSTATUS status;
2906         uint16_t fnum;
2907         bool ret = false;
2908
2909         if (!torture_open_connection(&cli1, 0)) {
2910                 return false;
2911         }
2912
2913         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2914
2915         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2916
2917         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2918         if (!NT_STATUS_IS_OK(status)) {
2919                 d_fprintf(stderr,
2920                           "cli_openx returned %s\n",
2921                           nt_errstr(status));
2922                 return false;
2923         }
2924
2925         /*
2926          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2927          * returns NT_STATUS_OK
2928          */
2929
2930         status = cli_lockingx(
2931                 cli1,                           /* cli */
2932                 fnum,                           /* fnum */
2933                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
2934                 0,                              /* newoplocklevel */
2935                 0,                              /* timeout */
2936                 0,                              /* num_unlocks */
2937                 NULL,                           /* unlocks */
2938                 0,                              /* num_locks */
2939                 NULL);                          /* locks */
2940
2941         if (!NT_STATUS_IS_OK(status)) {
2942                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2943                 goto fail;
2944         }
2945
2946         ret = true;
2947 fail:
2948         cli_close(cli1, fnum);
2949         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2950
2951         return ret;
2952 }
2953
2954 struct deferred_close_state {
2955         struct tevent_context *ev;
2956         struct cli_state *cli;
2957         uint16_t fnum;
2958 };
2959
2960 static void deferred_close_waited(struct tevent_req *subreq);
2961 static void deferred_close_done(struct tevent_req *subreq);
2962
2963 static struct tevent_req *deferred_close_send(
2964         TALLOC_CTX *mem_ctx,
2965         struct tevent_context *ev,
2966         int wait_secs,
2967         struct cli_state *cli,
2968         uint16_t fnum)
2969 {
2970         struct tevent_req *req = NULL, *subreq = NULL;
2971         struct deferred_close_state *state = NULL;
2972         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2973
2974         req = tevent_req_create(
2975                 mem_ctx, &state, struct deferred_close_state);
2976         if (req == NULL) {
2977                 return NULL;
2978         }
2979         state->ev = ev;
2980         state->cli = cli;
2981         state->fnum = fnum;
2982
2983         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2984         if (tevent_req_nomem(subreq, req)) {
2985                 return tevent_req_post(req, ev);
2986         }
2987         tevent_req_set_callback(subreq, deferred_close_waited, req);
2988         return req;
2989 }
2990
2991 static void deferred_close_waited(struct tevent_req *subreq)
2992 {
2993         struct tevent_req *req = tevent_req_callback_data(
2994                 subreq, struct tevent_req);
2995         struct deferred_close_state *state = tevent_req_data(
2996                 req, struct deferred_close_state);
2997         bool ok;
2998
2999         ok = tevent_wakeup_recv(subreq);
3000         TALLOC_FREE(subreq);
3001         if (!ok) {
3002                 tevent_req_oom(req);
3003                 return;
3004         }
3005
3006         subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3007         if (tevent_req_nomem(subreq, req)) {
3008                 return;
3009         }
3010         tevent_req_set_callback(subreq, deferred_close_done, req);
3011 }
3012
3013 static void deferred_close_done(struct tevent_req *subreq)
3014 {
3015         NTSTATUS status = cli_close_recv(subreq);
3016         tevent_req_simple_finish_ntstatus(subreq, status);
3017 }
3018
3019 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3020 {
3021         return tevent_req_simple_recv_ntstatus(req);
3022 }
3023
3024 struct lockread_state {
3025         struct smb1_lock_element lck;
3026         struct tevent_req *reqs[2];
3027         struct tevent_req *smbreqs[2];
3028         NTSTATUS lock_status;
3029         NTSTATUS read_status;
3030         uint8_t *readbuf;
3031 };
3032
3033 static void lockread_lockingx_done(struct tevent_req *subreq);
3034 static void lockread_read_andx_done(struct tevent_req *subreq);
3035
3036 static struct tevent_req *lockread_send(
3037         TALLOC_CTX *mem_ctx,
3038         struct tevent_context *ev,
3039         struct cli_state *cli,
3040         uint16_t fnum)
3041 {
3042         struct tevent_req *req = NULL;
3043         struct lockread_state *state = NULL;
3044         NTSTATUS status;
3045
3046         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3047         if (req == NULL) {
3048                 return NULL;
3049         }
3050
3051         state->lck = (struct smb1_lock_element) {
3052                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3053         };
3054
3055         state->reqs[0] = cli_lockingx_create(
3056                 ev,                             /* mem_ctx */
3057                 ev,                             /* tevent_context */
3058                 cli,                            /* cli */
3059                 fnum,                           /* fnum */
3060                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3061                 0,                              /* newoplocklevel */
3062                 10000,                          /* timeout */
3063                 0,                              /* num_unlocks */
3064                 NULL,                           /* unlocks */
3065                 1,                              /* num_locks */
3066                 &state->lck,                    /* locks */
3067                 &state->smbreqs[0]);            /* psmbreq */
3068         if (tevent_req_nomem(state->reqs[0], req)) {
3069                 return tevent_req_post(req, ev);
3070         }
3071         tevent_req_set_callback(
3072                 state->reqs[0], lockread_lockingx_done, req);
3073
3074         state->reqs[1] = cli_read_andx_create(
3075                 ev,             /* mem_ctx */
3076                 ev,             /* ev */
3077                 cli,            /* cli */
3078                 fnum,           /* fnum */
3079                 0,              /* offset */
3080                 1,              /* size */
3081                 &state->smbreqs[1]);    /* psmbreq */
3082         if (tevent_req_nomem(state->reqs[1], req)) {
3083                 return tevent_req_post(req, ev);
3084         }
3085         tevent_req_set_callback(
3086                 state->reqs[1], lockread_read_andx_done, req);
3087
3088         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3089         if (tevent_req_nterror(req, status)) {
3090                 return tevent_req_post(req, ev);
3091         }
3092         return req;
3093 }
3094
3095 static void lockread_lockingx_done(struct tevent_req *subreq)
3096 {
3097         struct tevent_req *req = tevent_req_callback_data(
3098                 subreq, struct tevent_req);
3099         struct lockread_state *state = tevent_req_data(
3100                 req, struct lockread_state);
3101         state->lock_status = cli_lockingx_recv(subreq);
3102         TALLOC_FREE(subreq);
3103         d_fprintf(stderr,
3104                   "lockingx returned %s\n",
3105                   nt_errstr(state->lock_status));
3106 }
3107
3108 static void lockread_read_andx_done(struct tevent_req *subreq)
3109 {
3110         struct tevent_req *req = tevent_req_callback_data(
3111                 subreq, struct tevent_req);
3112         struct lockread_state *state = tevent_req_data(
3113                 req, struct lockread_state);
3114         ssize_t received = -1;
3115         uint8_t *rcvbuf = NULL;
3116
3117         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3118
3119         d_fprintf(stderr,
3120                   "read returned %s\n",
3121                   nt_errstr(state->read_status));
3122
3123         if (!NT_STATUS_IS_OK(state->read_status)) {
3124                 TALLOC_FREE(subreq);
3125                 tevent_req_done(req);
3126                 return;
3127         }
3128
3129         if (received > 0) {
3130                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3131                 TALLOC_FREE(subreq);
3132                 if (tevent_req_nomem(state->readbuf, req)) {
3133                         return;
3134                 }
3135         }
3136         TALLOC_FREE(subreq);
3137         tevent_req_done(req);
3138 }
3139
3140 static NTSTATUS lockread_recv(
3141         struct tevent_req *req,
3142         NTSTATUS *lock_status,
3143         NTSTATUS *read_status,
3144         TALLOC_CTX *mem_ctx,
3145         uint8_t **read_buf)
3146 {
3147         struct lockread_state *state = tevent_req_data(
3148                 req, struct lockread_state);
3149         NTSTATUS status;
3150
3151         if (tevent_req_is_nterror(req, &status)) {
3152                 return status;
3153         }
3154
3155         *lock_status = state->lock_status;
3156         *read_status = state->read_status;
3157         if (state->readbuf != NULL) {
3158                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3159         } else {
3160                 *read_buf = NULL;
3161         }
3162
3163         return NT_STATUS_OK;
3164 }
3165
3166 struct lock12_state {
3167         uint8_t dummy;
3168 };
3169
3170 static void lock12_closed(struct tevent_req *subreq);
3171 static void lock12_read(struct tevent_req *subreq);
3172
3173 static struct tevent_req *lock12_send(
3174         TALLOC_CTX *mem_ctx,
3175         struct tevent_context *ev,
3176         struct cli_state *cli,
3177         uint16_t fnum1,
3178         uint16_t fnum2)
3179 {
3180         struct tevent_req *req = NULL, *subreq = NULL;
3181         struct lock12_state *state = NULL;
3182
3183         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3184         if (req == NULL) {
3185                 return NULL;
3186         }
3187
3188         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3189         if (tevent_req_nomem(subreq, req)) {
3190                 return tevent_req_post(req, ev);
3191         }
3192         tevent_req_set_callback(subreq, lock12_closed, req);
3193
3194         subreq = lockread_send(state, ev, cli, fnum2);
3195         if (tevent_req_nomem(subreq, req)) {
3196                 return tevent_req_post(req, ev);
3197         }
3198         tevent_req_set_callback(subreq, lock12_read, req);
3199
3200         return req;
3201 }
3202
3203 static void lock12_closed(struct tevent_req *subreq)
3204 {
3205         struct tevent_req *req = tevent_req_callback_data(
3206                 subreq, struct tevent_req);
3207         NTSTATUS status;
3208
3209         status = deferred_close_recv(subreq);
3210         TALLOC_FREE(subreq);
3211         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3212         if (tevent_req_nterror(req, status)) {
3213                 return;
3214         }
3215 }
3216
3217 static void lock12_read(struct tevent_req *subreq)
3218 {
3219         struct tevent_req *req = tevent_req_callback_data(
3220                 subreq, struct tevent_req);
3221         struct lock12_state *state = tevent_req_data(
3222                 req, struct lock12_state);
3223         NTSTATUS status, lock_status, read_status;
3224         uint8_t *buf = NULL;
3225
3226         status = lockread_recv(
3227                 subreq, &lock_status, &read_status, state, &buf);
3228         TALLOC_FREE(subreq);
3229         if (tevent_req_nterror(req, status) ||
3230             tevent_req_nterror(req, lock_status) ||
3231             tevent_req_nterror(req, read_status)) {
3232                 return;
3233         }
3234         tevent_req_done(req);
3235 }
3236
3237 static NTSTATUS lock12_recv(struct tevent_req *req)
3238
3239 {
3240         NTSTATUS status;
3241
3242         if (tevent_req_is_nterror(req, &status)) {
3243                 return status;
3244         }
3245         return NT_STATUS_OK;
3246 }
3247
3248 static bool run_locktest12(int dummy)
3249 {
3250         struct tevent_context *ev = NULL;
3251         struct tevent_req *req = NULL;
3252         struct cli_state *cli = NULL;
3253         const char fname[] = "\\lockt12.lck";
3254         uint16_t fnum1, fnum2;
3255         bool ret = false;
3256         bool ok;
3257         uint8_t data = 1;
3258         NTSTATUS status;
3259
3260         printf("starting locktest12\n");
3261
3262         ev = samba_tevent_context_init(NULL);
3263         if (ev == NULL) {
3264                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3265                 goto done;
3266         }
3267
3268         ok = torture_open_connection(&cli, 0);
3269         if (!ok) {
3270                 goto done;
3271         }
3272         smbXcli_conn_set_sockopt(cli->conn, sockops);
3273
3274         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3275         if (!NT_STATUS_IS_OK(status)) {
3276                 d_fprintf(stderr,
3277                           "cli_openx failed: %s\n",
3278                           nt_errstr(status));
3279                 goto done;
3280         }
3281
3282         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3283         if (!NT_STATUS_IS_OK(status)) {
3284                 d_fprintf(stderr,
3285                           "cli_openx failed: %s\n",
3286                           nt_errstr(status));
3287                 goto done;
3288         }
3289
3290         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3291         if (!NT_STATUS_IS_OK(status)) {
3292                 d_fprintf(stderr,
3293                           "cli_writeall failed: %s\n",
3294                           nt_errstr(status));
3295                 goto done;
3296         }
3297
3298         status = cli_locktype(
3299                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3300         if (!NT_STATUS_IS_OK(status)) {
3301                 d_fprintf(stderr,
3302                           "cli_locktype failed: %s\n",
3303                           nt_errstr(status));
3304                 goto done;
3305         }
3306
3307         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3308         if (req == NULL) {
3309                 d_fprintf(stderr, "lock12_send failed\n");
3310                 goto done;
3311         }
3312
3313         ok = tevent_req_poll_ntstatus(req, ev, &status);
3314         if (!ok) {
3315                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3316                 goto done;
3317         }
3318
3319         if (!NT_STATUS_IS_OK(status)) {
3320                 d_fprintf(stderr,
3321                           "tevent_req_poll_ntstatus returned %s\n",
3322                           nt_errstr(status));
3323                 goto done;
3324         }
3325
3326         status = lock12_recv(req);
3327         if (!NT_STATUS_IS_OK(status)) {
3328                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3329                 goto done;
3330         }
3331
3332         ret = true;
3333 done:
3334         if (cli != NULL) {
3335                 torture_close_connection(cli);
3336         }
3337         return ret;
3338 }
3339
3340 struct lock_ntcancel_state {
3341         struct timeval start;
3342         struct smb1_lock_element lck;
3343         struct tevent_req *subreq;
3344 };
3345
3346 static void lock_ntcancel_waited(struct tevent_req *subreq);
3347 static void lock_ntcancel_done(struct tevent_req *subreq);
3348
3349 static struct tevent_req *lock_ntcancel_send(
3350         TALLOC_CTX *mem_ctx,
3351         struct tevent_context *ev,
3352         struct cli_state *cli,
3353         uint16_t fnum)
3354 {
3355         struct tevent_req *req = NULL, *subreq = NULL;
3356         struct lock_ntcancel_state *state = NULL;
3357
3358         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3359         if (req == NULL) {
3360                 return NULL;
3361         }
3362         state->lck = (struct smb1_lock_element) {
3363                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3364         };
3365         state->start = timeval_current();
3366
3367         state->subreq = cli_lockingx_send(
3368                 state,                          /* mem_ctx */
3369                 ev,                             /* tevent_context */
3370                 cli,                            /* cli */
3371                 fnum,                           /* fnum */
3372                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3373                 0,                              /* newoplocklevel */
3374                 10000,                          /* timeout */
3375                 0,                              /* num_unlocks */
3376                 NULL,                           /* unlocks */
3377                 1,                              /* num_locks */
3378                 &state->lck);                   /* locks */
3379         if (tevent_req_nomem(state->subreq, req)) {
3380                 return tevent_req_post(req, ev);
3381         }
3382         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3383
3384         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3385         if (tevent_req_nomem(subreq, req)) {
3386                 return tevent_req_post(req, ev);
3387         }
3388         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3389         return req;
3390 }
3391
3392 static void lock_ntcancel_waited(struct tevent_req *subreq)
3393 {
3394         struct tevent_req *req = tevent_req_callback_data(
3395                 subreq, struct tevent_req);
3396         struct lock_ntcancel_state *state = tevent_req_data(
3397                 req, struct lock_ntcancel_state);
3398         bool ok;
3399
3400         ok = tevent_wakeup_recv(subreq);
3401         TALLOC_FREE(subreq);
3402         if (!ok) {
3403                 tevent_req_oom(req);
3404                 return;
3405         }
3406
3407         ok = tevent_req_cancel(state->subreq);
3408         if (!ok) {
3409                 d_fprintf(stderr, "Could not cancel subreq\n");
3410                 tevent_req_oom(req);
3411                 return;
3412         }
3413 }
3414
3415 static void lock_ntcancel_done(struct tevent_req *subreq)
3416 {
3417         struct tevent_req *req = tevent_req_callback_data(
3418                 subreq, struct tevent_req);
3419         struct lock_ntcancel_state *state = tevent_req_data(
3420                 req, struct lock_ntcancel_state);
3421         NTSTATUS status;
3422         double elapsed;
3423
3424         status = cli_lockingx_recv(subreq);
3425         TALLOC_FREE(subreq);
3426
3427         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3428                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3429                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3430                 return;
3431         }
3432
3433         elapsed = timeval_elapsed(&state->start);
3434
3435         if (elapsed > 3) {
3436                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3437                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3438                 return;
3439         }
3440
3441         tevent_req_done(req);
3442 }
3443
3444 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3445 {
3446         return tevent_req_simple_recv_ntstatus(req);
3447 }
3448
3449 static bool run_locktest13(int dummy)
3450 {
3451         struct tevent_context *ev = NULL;
3452         struct tevent_req *req = NULL;
3453         struct cli_state *cli = NULL;
3454         const char fname[] = "\\lockt13.lck";
3455         uint16_t fnum1, fnum2;
3456         bool ret = false;
3457         bool ok;
3458         uint8_t data = 1;
3459         NTSTATUS status;
3460
3461         printf("starting locktest13\n");
3462
3463         ev = samba_tevent_context_init(NULL);
3464         if (ev == NULL) {
3465                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3466                 goto done;
3467         }
3468
3469         ok = torture_open_connection(&cli, 0);
3470         if (!ok) {
3471                 goto done;
3472         }
3473         smbXcli_conn_set_sockopt(cli->conn, sockops);
3474
3475         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3476         if (!NT_STATUS_IS_OK(status)) {
3477                 d_fprintf(stderr,
3478                           "cli_openx failed: %s\n",
3479                           nt_errstr(status));
3480                 goto done;
3481         }
3482
3483         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3484         if (!NT_STATUS_IS_OK(status)) {
3485                 d_fprintf(stderr,
3486                           "cli_openx failed: %s\n",
3487                           nt_errstr(status));
3488                 goto done;
3489         }
3490
3491         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3492         if (!NT_STATUS_IS_OK(status)) {
3493                 d_fprintf(stderr,
3494                           "cli_writeall failed: %s\n",
3495                           nt_errstr(status));
3496                 goto done;
3497         }
3498
3499         status = cli_locktype(
3500                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3501         if (!NT_STATUS_IS_OK(status)) {
3502                 d_fprintf(stderr,
3503                           "cli_locktype failed: %s\n",
3504                           nt_errstr(status));
3505                 goto done;
3506         }
3507
3508         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3509         if (req == NULL) {
3510                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3511                 goto done;
3512         }
3513
3514         ok = tevent_req_poll_ntstatus(req, ev, &status);
3515         if (!ok) {
3516                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3517                 goto done;
3518         }
3519
3520         if (!NT_STATUS_IS_OK(status)) {
3521                 d_fprintf(stderr,
3522                           "tevent_req_poll_ntstatus returned %s\n",
3523                           nt_errstr(status));
3524                 goto done;
3525         }
3526
3527         status = lock_ntcancel_recv(req);
3528         if (!NT_STATUS_IS_OK(status)) {
3529                 d_fprintf(stderr,
3530                           "lock_ntcancel returned %s\n",
3531                           nt_errstr(status));
3532                 goto done;
3533         }
3534
3535         ret = true;
3536 done:
3537         if (cli != NULL) {
3538                 torture_close_connection(cli);
3539         }
3540         return ret;
3541 }
3542
3543 /*
3544 test whether fnums and tids open on one VC are available on another (a major
3545 security hole)
3546 */
3547 static bool run_fdpasstest(int dummy)
3548 {
3549         struct cli_state *cli1, *cli2;
3550         const char *fname = "\\fdpass.tst";
3551         uint16_t fnum1;
3552         char buf[1024];
3553         NTSTATUS status;
3554
3555         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3556                 return False;
3557         }
3558         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3559         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3560
3561         printf("starting fdpasstest\n");
3562
3563         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3564
3565         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3566                           &fnum1);
3567         if (!NT_STATUS_IS_OK(status)) {
3568                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3569                 return False;
3570         }
3571
3572         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3573                               13, NULL);
3574         if (!NT_STATUS_IS_OK(status)) {
3575                 printf("write failed (%s)\n", nt_errstr(status));
3576                 return False;
3577         }
3578
3579         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3580         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3581         cli_setpid(cli2, cli_getpid(cli1));
3582
3583         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3584                 printf("read succeeded! nasty security hole [%s]\n", buf);
3585                 return false;
3586         }
3587
3588         cli_close(cli1, fnum1);
3589         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3590
3591         torture_close_connection(cli1);
3592         torture_close_connection(cli2);
3593
3594         printf("finished fdpasstest\n");
3595         return True;
3596 }
3597
3598 static bool run_fdsesstest(int dummy)
3599 {
3600         struct cli_state *cli;
3601         uint16_t new_vuid;
3602         uint16_t saved_vuid;
3603         uint32_t new_cnum;
3604         uint32_t saved_cnum;
3605         const char *fname = "\\fdsess.tst";
3606         const char *fname1 = "\\fdsess1.tst";
3607         uint16_t fnum1;
3608         uint16_t fnum2;
3609         char buf[1024];
3610         bool ret = True;
3611         NTSTATUS status;
3612
3613         if (!torture_open_connection(&cli, 0))
3614                 return False;
3615         smbXcli_conn_set_sockopt(cli->conn, sockops);
3616
3617         if (!torture_cli_session_setup2(cli, &new_vuid))
3618                 return False;
3619
3620         saved_cnum = cli_state_get_tid(cli);
3621         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3622                 return False;
3623         new_cnum = cli_state_get_tid(cli);
3624         cli_state_set_tid(cli, saved_cnum);
3625
3626         printf("starting fdsesstest\n");
3627
3628         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3629         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3630
3631         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3632         if (!NT_STATUS_IS_OK(status)) {
3633                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3634                 return False;
3635         }
3636
3637         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3638                               NULL);
3639         if (!NT_STATUS_IS_OK(status)) {
3640                 printf("write failed (%s)\n", nt_errstr(status));
3641                 return False;
3642         }
3643
3644         saved_vuid = cli_state_get_uid(cli);
3645         cli_state_set_uid(cli, new_vuid);
3646
3647         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3648                 printf("read succeeded with different vuid! "
3649                        "nasty security hole [%s]\n", buf);
3650                 ret = false;
3651         }
3652         /* Try to open a file with different vuid, samba cnum. */
3653         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3654                 printf("create with different vuid, same cnum succeeded.\n");
3655                 cli_close(cli, fnum2);
3656                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3657         } else {
3658                 printf("create with different vuid, same cnum failed.\n");
3659                 printf("This will cause problems with service clients.\n");
3660                 ret = False;
3661         }
3662
3663         cli_state_set_uid(cli, saved_vuid);
3664
3665         /* Try with same vuid, different cnum. */
3666         cli_state_set_tid(cli, new_cnum);
3667
3668         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3669                 printf("read succeeded with different cnum![%s]\n", buf);
3670                 ret = false;
3671         }
3672
3673         cli_state_set_tid(cli, saved_cnum);
3674         cli_close(cli, fnum1);
3675         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3676
3677         torture_close_connection(cli);
3678
3679         printf("finished fdsesstest\n");
3680         return ret;
3681 }
3682
3683 /*
3684   This test checks that 
3685
3686   1) the server does not allow an unlink on a file that is open
3687 */
3688 static bool run_unlinktest(int dummy)
3689 {
3690         struct cli_state *cli;
3691         const char *fname = "\\unlink.tst";
3692         uint16_t fnum;
3693         bool correct = True;
3694         NTSTATUS status;
3695
3696         if (!torture_open_connection(&cli, 0)) {
3697                 return False;
3698         }
3699
3700         smbXcli_conn_set_sockopt(cli->conn, sockops);
3701
3702         printf("starting unlink test\n");
3703
3704         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3705
3706         cli_setpid(cli, 1);
3707
3708         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3709         if (!NT_STATUS_IS_OK(status)) {
3710                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3711                 return False;
3712         }
3713
3714         status = cli_unlink(cli, fname,
3715                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3716         if (NT_STATUS_IS_OK(status)) {
3717                 printf("error: server allowed unlink on an open file\n");
3718                 correct = False;
3719         } else {
3720                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3721                                       NT_STATUS_SHARING_VIOLATION);
3722         }
3723
3724         cli_close(cli, fnum);
3725         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3726
3727         if (!torture_close_connection(cli)) {
3728                 correct = False;
3729         }
3730
3731         printf("unlink test finished\n");
3732
3733         return correct;
3734 }
3735
3736
3737 /*
3738 test how many open files this server supports on the one socket
3739 */
3740 static bool run_maxfidtest(int dummy)
3741 {
3742         struct cli_state *cli;
3743         fstring fname;
3744         uint16_t fnums[0x11000];
3745         int i;
3746         int retries=4;
3747         bool correct = True;
3748         NTSTATUS status;
3749
3750         cli = current_cli;
3751
3752         if (retries <= 0) {
3753                 printf("failed to connect\n");
3754                 return False;
3755         }
3756
3757         smbXcli_conn_set_sockopt(cli->conn, sockops);
3758
3759         for (i=0; i<0x11000; i++) {
3760                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3761                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3762                                   &fnums[i]);
3763                 if (!NT_STATUS_IS_OK(status)) {
3764                         printf("open of %s failed (%s)\n", 
3765                                fname, nt_errstr(status));
3766                         printf("maximum fnum is %d\n", i);
3767                         break;
3768                 }
3769                 printf("%6d\r", i);
3770         }
3771         printf("%6d\n", i);
3772         i--;
3773
3774         printf("cleaning up\n");
3775         for (;i>=0;i--) {
3776                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3777                 cli_close(cli, fnums[i]);
3778
3779                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3780                 if (!NT_STATUS_IS_OK(status)) {
3781                         printf("unlink of %s failed (%s)\n", 
3782                                fname, nt_errstr(status));
3783                         correct = False;
3784                 }
3785                 printf("%6d\r", i);
3786         }
3787         printf("%6d\n", 0);
3788
3789         printf("maxfid test finished\n");
3790         if (!torture_close_connection(cli)) {
3791                 correct = False;
3792         }
3793         return correct;
3794 }
3795
3796 /* generate a random buffer */
3797 static void rand_buf(char *buf, int len)
3798 {
3799         while (len--) {
3800                 *buf = (char)sys_random();
3801                 buf++;
3802         }
3803 }
3804
3805 /* send smb negprot commands, not reading the response */
3806 static bool run_negprot_nowait(int dummy)
3807 {
3808         struct tevent_context *ev;
3809         int i;
3810         struct cli_state *cli;
3811         bool correct = True;
3812
3813         printf("starting negprot nowait test\n");
3814
3815         ev = samba_tevent_context_init(talloc_tos());
3816         if (ev == NULL) {
3817                 return false;
3818         }
3819
3820         if (!(cli = open_nbt_connection())) {
3821                 TALLOC_FREE(ev);
3822                 return False;
3823         }
3824
3825         for (i=0;i<50000;i++) {
3826                 struct tevent_req *req;
3827
3828                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3829                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3830                 if (req == NULL) {
3831                         TALLOC_FREE(ev);
3832                         return false;
3833                 }
3834                 if (!tevent_req_poll(req, ev)) {
3835                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3836                                   strerror(errno));
3837                         TALLOC_FREE(ev);
3838                         return false;
3839                 }
3840                 TALLOC_FREE(req);
3841         }
3842
3843         if (torture_close_connection(cli)) {
3844                 correct = False;
3845         }
3846
3847         printf("finished negprot nowait test\n");
3848
3849         return correct;
3850 }
3851
3852 /* send smb negprot commands, not reading the response */
3853 static bool run_bad_nbt_session(int dummy)
3854 {
3855         struct nmb_name called, calling;
3856         struct sockaddr_storage ss;
3857         NTSTATUS status;
3858         int fd;
3859         bool ret;
3860
3861         printf("starting bad nbt session test\n");
3862
3863         make_nmb_name(&calling, myname, 0x0);
3864         make_nmb_name(&called , host, 0x20);
3865
3866         if (!resolve_name(host, &ss, 0x20, true)) {
3867                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3868                 return false;
3869         }
3870
3871         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3872         if (!NT_STATUS_IS_OK(status)) {
3873                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3874                           nt_errstr(status));
3875                 return false;
3876         }
3877
3878         ret = cli_bad_session_request(fd, &calling, &called);
3879         close(fd);
3880         if (!ret) {
3881                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3882                           nt_errstr(status));
3883                 return false;
3884         }
3885
3886         printf("finished bad nbt session test\n");
3887         return true;
3888 }
3889
3890 /* send random IPC commands */
3891 static bool run_randomipc(int dummy)
3892 {
3893         char *rparam = NULL;
3894         char *rdata = NULL;
3895         unsigned int rdrcnt,rprcnt;
3896         char param[1024];
3897         int api, param_len, i;
3898         struct cli_state *cli;
3899         bool correct = True;
3900         int count = 50000;
3901
3902         printf("starting random ipc test\n");
3903
3904         if (!torture_open_connection(&cli, 0)) {
3905                 return False;
3906         }
3907
3908         for (i=0;i<count;i++) {
3909                 api = sys_random() % 500;
3910                 param_len = (sys_random() % 64);
3911
3912                 rand_buf(param, param_len);
3913
3914                 SSVAL(param,0,api); 
3915
3916                 cli_api(cli, 
3917                         param, param_len, 8,  
3918                         NULL, 0, CLI_BUFFER_SIZE,
3919                         &rparam, &rprcnt,     
3920                         &rdata, &rdrcnt);
3921                 if (i % 100 == 0) {
3922                         printf("%d/%d\r", i,count);
3923                 }
3924         }
3925         printf("%d/%d\n", i, count);
3926
3927         if (!torture_close_connection(cli)) {
3928                 correct = False;
3929         }
3930
3931         SAFE_FREE(rparam);
3932         SAFE_FREE(rdata);
3933
3934         printf("finished random ipc test\n");
3935
3936         return correct;
3937 }
3938
3939
3940
3941 static void browse_callback(const char *sname, uint32_t stype,
3942                             const char *comment, void *state)
3943 {
3944         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3945 }
3946
3947
3948
3949 /*
3950   This test checks the browse list code
3951
3952 */
3953 static bool run_browsetest(int dummy)
3954 {
3955         static struct cli_state *cli;
3956         bool correct = True;
3957
3958         printf("starting browse test\n");
3959
3960         if (!torture_open_connection(&cli, 0)) {
3961                 return False;
3962         }
3963
3964         printf("domain list:\n");
3965         cli_NetServerEnum(cli, cli->server_domain, 
3966                           SV_TYPE_DOMAIN_ENUM,
3967                           browse_callback, NULL);
3968
3969         printf("machine list:\n");
3970         cli_NetServerEnum(cli, cli->server_domain, 
3971                           SV_TYPE_ALL,
3972                           browse_callback, NULL);
3973
3974         if (!torture_close_connection(cli)) {
3975                 correct = False;
3976         }
3977
3978         printf("browse test finished\n");
3979
3980         return correct;
3981
3982 }
3983
3984 static bool check_attributes(struct cli_state *cli,
3985                                 const char *fname,
3986                                 uint32_t expected_attrs)
3987 {
3988         uint32_t attrs = 0;
3989         NTSTATUS status = cli_getatr(cli,
3990                                 fname,
3991                                 &attrs,
3992                                 NULL,
3993                                 NULL);
3994         if (!NT_STATUS_IS_OK(status)) {
3995                 printf("cli_getatr failed with %s\n",
3996                         nt_errstr(status));
3997                 return false;
3998         }
3999         if (attrs != expected_attrs) {
4000                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4001                         (unsigned int)attrs,
4002                         (unsigned int)expected_attrs);
4003                 return false;
4004         }
4005         return true;
4006 }
4007
4008 /*
4009   This checks how the getatr calls works
4010 */
4011 static bool run_attrtest(int dummy)
4012 {
4013         struct cli_state *cli;
4014         uint16_t fnum;
4015         time_t t, t2;
4016         const char *fname = "\\attrib123456789.tst";
4017         bool correct = True;
4018         NTSTATUS status;
4019
4020         printf("starting attrib test\n");
4021
4022         if (!torture_open_connection(&cli, 0)) {
4023                 return False;
4024         }
4025
4026         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4027         status = cli_unlink(cli, fname, 0x20000);
4028         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4029                 correct = false;
4030                 goto out;
4031         }
4032
4033         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4034         cli_openx(cli, fname, 
4035                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4036         cli_close(cli, fnum);
4037
4038         status = cli_getatr(cli, fname, NULL, NULL, &t);
4039         if (!NT_STATUS_IS_OK(status)) {
4040                 printf("getatr failed (%s)\n", nt_errstr(status));
4041                 correct = False;
4042         }
4043
4044         if (labs(t - time(NULL)) > 60*60*24*10) {
4045                 printf("ERROR: SMBgetatr bug. time is %s",
4046                        ctime(&t));
4047                 t = time(NULL);
4048                 correct = True;
4049         }
4050
4051         t2 = t-60*60*24; /* 1 day ago */
4052
4053         /* Ensure we can't set with out-of-range (unknown) attribute. */
4054         status = cli_setatr(cli, fname, 0x20000, t2);
4055         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4056                 correct = false;
4057                 goto out;
4058         }
4059
4060         status = cli_setatr(cli, fname, 0, t2);
4061         if (!NT_STATUS_IS_OK(status)) {
4062                 printf("setatr failed (%s)\n", nt_errstr(status));
4063                 correct = True;
4064         }
4065
4066         status = cli_getatr(cli, fname, NULL, NULL, &t);
4067         if (!NT_STATUS_IS_OK(status)) {
4068                 printf("getatr failed (%s)\n", nt_errstr(status));
4069                 correct = True;
4070         }
4071
4072         if (t != t2) {
4073                 printf("ERROR: getatr/setatr bug. times are\n%s",
4074                        ctime(&t));
4075                 printf("%s", ctime(&t2));
4076                 correct = True;
4077         }
4078
4079         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4080
4081         /* Check cli_setpathinfo_ext() */
4082         /* Re-create the file. */
4083         status = cli_openx(cli, fname,
4084                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4085         if (!NT_STATUS_IS_OK(status)) {
4086                 printf("Failed to recreate %s (%s)\n",
4087                         fname, nt_errstr(status));
4088                 correct = false;
4089         }
4090         cli_close(cli, fnum);
4091
4092         status = cli_setpathinfo_ext(
4093                 cli,
4094                 fname,
4095                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4096                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4097                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4098                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4099                 FILE_ATTRIBUTE_SYSTEM |
4100                 FILE_ATTRIBUTE_HIDDEN |
4101                 FILE_ATTRIBUTE_READONLY);
4102         if (!NT_STATUS_IS_OK(status)) {
4103                 printf("cli_setpathinfo_ext failed with %s\n",
4104                         nt_errstr(status));
4105                 correct = false;
4106         }
4107
4108         /* Check attributes are correct. */
4109         correct = check_attributes(cli,
4110                         fname,
4111                         FILE_ATTRIBUTE_SYSTEM |
4112                         FILE_ATTRIBUTE_HIDDEN |
4113                         FILE_ATTRIBUTE_READONLY);
4114         if (correct == false) {
4115                 goto out;
4116         }
4117
4118         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4119         status = cli_setpathinfo_ext(
4120                 cli,
4121                 fname,
4122                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4123                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4124                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4125                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4126                 FILE_ATTRIBUTE_NORMAL);
4127         if (!NT_STATUS_IS_OK(status)) {
4128                 printf("cli_setpathinfo_ext failed with %s\n",
4129                         nt_errstr(status));
4130                 correct = false;
4131         }
4132
4133         /* Check attributes are correct. */
4134         correct = check_attributes(cli,
4135                         fname,
4136                         FILE_ATTRIBUTE_SYSTEM |
4137                         FILE_ATTRIBUTE_HIDDEN |
4138                         FILE_ATTRIBUTE_READONLY);
4139         if (correct == false) {
4140                 goto out;
4141         }
4142
4143         /* Setting to (uint16_t)-1 should also be ignored. */
4144         status = cli_setpathinfo_ext(
4145                 cli,
4146                 fname,
4147                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4148                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4149                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4150                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4151                 (uint32_t)-1);
4152         if (!NT_STATUS_IS_OK(status)) {
4153                 printf("cli_setpathinfo_ext failed with %s\n",
4154                         nt_errstr(status));
4155                 correct = false;
4156         }
4157
4158         /* Check attributes are correct. */
4159         correct = check_attributes(cli,
4160                         fname,
4161                         FILE_ATTRIBUTE_SYSTEM |
4162                         FILE_ATTRIBUTE_HIDDEN |
4163                         FILE_ATTRIBUTE_READONLY);
4164         if (correct == false) {
4165                 goto out;
4166         }
4167
4168         /* Setting to 0 should clear them all. */
4169         status = cli_setpathinfo_ext(
4170                 cli,
4171                 fname,
4172                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4173                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4174                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4175                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4176                 0);
4177         if (!NT_STATUS_IS_OK(status)) {
4178                 printf("cli_setpathinfo_ext failed with %s\n",
4179                         nt_errstr(status));
4180                 correct = false;
4181         }
4182
4183         /* Check attributes are correct. */
4184         correct = check_attributes(cli,
4185                         fname,
4186                         FILE_ATTRIBUTE_NORMAL);
4187         if (correct == false) {
4188                 goto out;
4189         }
4190
4191   out:
4192
4193         cli_unlink(cli,
4194                 fname,
4195                 FILE_ATTRIBUTE_SYSTEM |
4196                 FILE_ATTRIBUTE_HIDDEN|
4197                 FILE_ATTRIBUTE_READONLY);
4198
4199         if (!torture_close_connection(cli)) {
4200                 correct = False;
4201         }
4202
4203         printf("attrib test finished\n");
4204
4205         return correct;
4206 }
4207
4208
4209 /*
4210   This checks a couple of trans2 calls
4211 */
4212 static bool run_trans2test(int dummy)
4213 {
4214         struct cli_state *cli;
4215         uint16_t fnum;
4216         off_t size;
4217         time_t c_time, a_time, m_time;
4218         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4219         const char *fname = "\\trans2.tst";
4220         const char *dname = "\\trans2";
4221         const char *fname2 = "\\trans2\\trans2.tst";
4222         char *pname;
4223         bool correct = True;
4224         NTSTATUS status;
4225         uint32_t fs_attr;
4226         uint64_t ino;
4227
4228         printf("starting trans2 test\n");
4229
4230         if (!torture_open_connection(&cli, 0)) {
4231                 return False;
4232         }
4233
4234         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4235                 /* Ensure ino is zero, SMB2 gets a real one. */
4236                 ino = 0;
4237         } else {
4238                 /* Ensure ino is -1, SMB1 never gets a real one. */
4239                 ino = (uint64_t)-1;
4240         }
4241
4242         status = cli_get_fs_attr_info(cli, &fs_attr);
4243         if (!NT_STATUS_IS_OK(status)) {
4244                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4245                        nt_errstr(status));
4246                 correct = false;
4247         }
4248
4249         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4250         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4251         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4252                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4253         if (!NT_STATUS_IS_OK(status)) {
4254                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4255                 correct = False;
4256         }
4257
4258         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4259         if (!NT_STATUS_IS_OK(status)) {
4260                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4261                 correct = False;
4262         }
4263         else if (strcmp(pname, fname)) {
4264                 printf("qfilename gave different name? [%s] [%s]\n",
4265                        fname, pname);
4266                 correct = False;
4267         }
4268
4269         cli_close(cli, fnum);
4270
4271         sleep(2);
4272
4273         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4274         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4275                           &fnum);
4276         if (!NT_STATUS_IS_OK(status)) {
4277                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4278                 return False;
4279         }
4280         cli_close(cli, fnum);
4281
4282         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4283                                 NULL);
4284         if (!NT_STATUS_IS_OK(status)) {
4285                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4286                 correct = False;
4287         } else {
4288                 time_t t = time(NULL);
4289
4290                 if (c_time != m_time) {
4291                         printf("create time=%s", ctime(&c_time));
4292                         printf("modify time=%s", ctime(&m_time));
4293                         printf("This system appears to have sticky create times\n");
4294                 }
4295                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4296                         printf("access time=%s", ctime(&a_time));
4297                         printf("This system appears to set a midnight access time\n");
4298                         correct = False;
4299                 }
4300
4301                 if (labs(m_time - t) > 60*60*24*7) {
4302                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4303                         correct = False;
4304                 }
4305         }
4306
4307
4308         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4309         cli_openx(cli, fname, 
4310                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4311         cli_close(cli, fnum);
4312         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4313                                 &m_time_ts, &size, NULL, &ino);
4314         if (!NT_STATUS_IS_OK(status)) {
4315                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4316                 correct = False;
4317         } else {
4318                 if (w_time_ts.tv_sec < 60*60*24*2) {
4319                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4320                         printf("This system appears to set a initial 0 write time\n");
4321                         correct = False;
4322                 }
4323                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4324                         /* SMB2 should always return an inode. */
4325                         if (ino == 0) {
4326                                 printf("SMB2 bad inode (0)\n");
4327                                 correct = false;
4328                         }
4329                 } else {
4330                         /* SMB1 must always return zero here. */
4331                         if (ino != 0) {
4332                                 printf("SMB1 bad inode (!0)\n");
4333                                 correct = false;
4334                         }
4335                 }
4336         }
4337
4338         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4339
4340
4341         /* check if the server updates the directory modification time
4342            when creating a new file */
4343         status = cli_mkdir(cli, dname);
4344         if (!NT_STATUS_IS_OK(status)) {
4345                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4346                 correct = False;
4347         }
4348         sleep(3);
4349         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4350                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4351         if (!NT_STATUS_IS_OK(status)) {
4352                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4353                 correct = False;
4354         }
4355
4356         cli_openx(cli, fname2, 
4357                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4358         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4359         cli_close(cli, fnum);
4360         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4361                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4362         if (!NT_STATUS_IS_OK(status)) {
4363                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4364                 correct = False;
4365         } else {
4366                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4367                     == 0) {
4368                         printf("This system does not update directory modification times\n");
4369                         correct = False;
4370                 }
4371         }
4372         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4373         cli_rmdir(cli, dname);
4374
4375         if (!torture_close_connection(cli)) {
4376                 correct = False;
4377         }
4378
4379         printf("trans2 test finished\n");
4380
4381         return correct;
4382 }
4383
4384 /*
4385   This checks new W2K calls.
4386 */
4387
4388 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4389 {
4390         uint8_t *buf = NULL;
4391         uint32_t len;
4392         NTSTATUS status;
4393
4394         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4395                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4396         if (!NT_STATUS_IS_OK(status)) {
4397                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4398                        nt_errstr(status));
4399         } else {
4400                 printf("qfileinfo: level %d, len = %u\n", level, len);
4401                 dump_data(0, (uint8_t *)buf, len);
4402                 printf("\n");
4403         }
4404         TALLOC_FREE(buf);
4405         return status;
4406 }
4407
4408 static bool run_w2ktest(int dummy)
4409 {
4410         struct cli_state *cli;
4411         uint16_t fnum;
4412         const char *fname = "\\w2ktest\\w2k.tst";
4413         int level;
4414         bool correct = True;
4415
4416         printf("starting w2k test\n");
4417
4418         if (!torture_open_connection(&cli, 0)) {
4419                 return False;
4420         }
4421
4422         cli_openx(cli, fname, 
4423                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4424
4425         for (level = 1004; level < 1040; level++) {
4426                 new_trans(cli, fnum, level);
4427         }
4428
4429         cli_close(cli, fnum);
4430
4431         if (!torture_close_connection(cli)) {
4432                 correct = False;
4433         }
4434
4435         printf("w2k test finished\n");
4436
4437         return correct;
4438 }
4439
4440
4441 /*
4442   this is a harness for some oplock tests
4443  */
4444 static bool run_oplock1(int dummy)
4445 {
4446         struct cli_state *cli1;
4447         const char *fname = "\\lockt1.lck";
4448         uint16_t fnum1;
4449         bool correct = True;
4450         NTSTATUS status;
4451
4452         printf("starting oplock test 1\n");
4453
4454         if (!torture_open_connection(&cli1, 0)) {
4455                 return False;
4456         }
4457
4458         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4459
4460         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4461
4462         cli1->use_oplocks = True;
4463
4464         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4465                           &fnum1);
4466         if (!NT_STATUS_IS_OK(status)) {
4467                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4468                 return False;
4469         }
4470
4471         cli1->use_oplocks = False;
4472
4473         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4474         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475
4476         status = cli_close(cli1, fnum1);
4477         if (!NT_STATUS_IS_OK(status)) {
4478                 printf("close2 failed (%s)\n", nt_errstr(status));
4479                 return False;
4480         }
4481
4482         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4483         if (!NT_STATUS_IS_OK(status)) {
4484                 printf("unlink failed (%s)\n", nt_errstr(status));
4485                 return False;
4486         }
4487
4488         if (!torture_close_connection(cli1)) {
4489                 correct = False;
4490         }
4491
4492         printf("finished oplock test 1\n");
4493
4494         return correct;
4495 }
4496
4497 static bool run_oplock2(int dummy)
4498 {
4499         struct cli_state *cli1, *cli2;
4500         const char *fname = "\\lockt2.lck";
4501         uint16_t fnum1, fnum2;
4502         int saved_use_oplocks = use_oplocks;
4503         char buf[4];
4504         bool correct = True;
4505         volatile bool *shared_correct;
4506         size_t nread;
4507         NTSTATUS status;
4508
4509         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4510         *shared_correct = True;
4511
4512         use_level_II_oplocks = True;
4513         use_oplocks = True;
4514
4515         printf("starting oplock test 2\n");
4516
4517         if (!torture_open_connection(&cli1, 0)) {
4518                 use_level_II_oplocks = False;
4519                 use_oplocks = saved_use_oplocks;
4520                 return False;
4521         }
4522
4523         if (!torture_open_connection(&cli2, 1)) {
4524                 use_level_II_oplocks = False;
4525                 use_oplocks = saved_use_oplocks;
4526                 return False;
4527         }
4528
4529         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4530
4531         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4532         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4533
4534         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4535                           &fnum1);
4536         if (!NT_STATUS_IS_OK(status)) {
4537                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4538                 return False;
4539         }
4540
4541         /* Don't need the globals any more. */
4542         use_level_II_oplocks = False;
4543         use_oplocks = saved_use_oplocks;
4544
4545         if (fork() == 0) {
4546                 /* Child code */
4547                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4548                 if (!NT_STATUS_IS_OK(status)) {
4549                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4550                         *shared_correct = False;
4551                         exit(0);
4552                 }
4553
4554                 sleep(2);
4555
4556                 status = cli_close(cli2, fnum2);
4557                 if (!NT_STATUS_IS_OK(status)) {
4558                         printf("close2 failed (%s)\n", nt_errstr(status));
4559                         *shared_correct = False;
4560                 }
4561
4562                 exit(0);
4563         }
4564
4565         sleep(2);
4566
4567         /* Ensure cli1 processes the break. Empty file should always return 0
4568          * bytes.  */
4569         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4570         if (!NT_STATUS_IS_OK(status)) {
4571                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4572                 correct = false;
4573         } else if (nread != 0) {
4574                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4575                       (unsigned long)nread, 0);
4576                 correct = false;
4577         }
4578
4579         /* Should now be at level II. */
4580         /* Test if sending a write locks causes a break to none. */
4581         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4582         if (!NT_STATUS_IS_OK(status)) {
4583                 printf("lock failed (%s)\n", nt_errstr(status));
4584                 correct = False;
4585         }
4586
4587         cli_unlock(cli1, fnum1, 0, 4);
4588
4589         sleep(2);
4590
4591         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4592         if (!NT_STATUS_IS_OK(status)) {
4593                 printf("lock failed (%s)\n", nt_errstr(status));
4594                 correct = False;
4595         }
4596
4597         cli_unlock(cli1, fnum1, 0, 4);
4598
4599         sleep(2);
4600
4601         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4602
4603         status = cli_close(cli1, fnum1);
4604         if (!NT_STATUS_IS_OK(status)) {
4605                 printf("close1 failed (%s)\n", nt_errstr(status));
4606                 correct = False;
4607         }
4608
4609         sleep(4);
4610
4611         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4612         if (!NT_STATUS_IS_OK(status)) {
4613                 printf("unlink failed (%s)\n", nt_errstr(status));
4614                 correct = False;
4615         }
4616
4617         if (!torture_close_connection(cli1)) {
4618                 correct = False;
4619         }
4620
4621         if (!*shared_correct) {
4622                 correct = False;
4623         }
4624
4625         printf("finished oplock test 2\n");
4626
4627         return correct;
4628 }
4629
4630 struct oplock4_state {
4631         struct tevent_context *ev;
4632         struct cli_state *cli;
4633         bool *got_break;
4634         uint16_t *fnum2;
4635 };
4636
4637 static void oplock4_got_break(struct tevent_req *req);
4638 static void oplock4_got_open(struct tevent_req *req);
4639
4640 static bool run_oplock4(int dummy)
4641 {
4642         struct tevent_context *ev;
4643         struct cli_state *cli1, *cli2;
4644         struct tevent_req *oplock_req, *open_req;
4645         const char *fname = "\\lockt4.lck";
4646         const char *fname_ln = "\\lockt4_ln.lck";
4647         uint16_t fnum1, fnum2;
4648         int saved_use_oplocks = use_oplocks;
4649         NTSTATUS status;
4650         bool correct = true;
4651
4652         bool got_break;
4653
4654         struct oplock4_state *state;
4655
4656         printf("starting oplock test 4\n");
4657
4658         if (!torture_open_connection(&cli1, 0)) {
4659                 use_level_II_oplocks = false;
4660                 use_oplocks = saved_use_oplocks;
4661                 return false;
4662         }
4663
4664         if (!torture_open_connection(&cli2, 1)) {
4665                 use_level_II_oplocks = false;
4666                 use_oplocks = saved_use_oplocks;
4667                 return false;
4668         }
4669
4670         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4671         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4672
4673         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4674         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4675
4676         /* Create the file. */
4677         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4678                           &fnum1);
4679         if (!NT_STATUS_IS_OK(status)) {
4680                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4681                 return false;
4682         }
4683
4684         status = cli_close(cli1, fnum1);
4685         if (!NT_STATUS_IS_OK(status)) {
4686                 printf("close1 failed (%s)\n", nt_errstr(status));
4687                 return false;
4688         }
4689
4690         /* Now create a hardlink. */
4691         status = cli_hardlink(cli1, fname, fname_ln);
4692         if (!NT_STATUS_IS_OK(status)) {
4693                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4694                 return false;
4695         }
4696
4697         /* Prove that opening hardlinks cause deny modes to conflict. */
4698         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4699         if (!NT_STATUS_IS_OK(status)) {
4700                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4701                 return false;
4702         }
4703
4704         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4705         if (NT_STATUS_IS_OK(status)) {
4706                 printf("open of %s succeeded - should fail with sharing violation.\n",
4707                         fname_ln);
4708                 return false;
4709         }
4710
4711         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4712                 printf("open of %s should fail with sharing violation. Got %s\n",
4713                         fname_ln, nt_errstr(status));
4714                 return false;
4715         }
4716
4717         status = cli_close(cli1, fnum1);
4718         if (!NT_STATUS_IS_OK(status)) {
4719                 printf("close1 failed (%s)\n", nt_errstr(status));
4720                 return false;
4721         }
4722
4723         cli1->use_oplocks = true;
4724         cli2->use_oplocks = true;
4725
4726         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4727         if (!NT_STATUS_IS_OK(status)) {
4728                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4729                 return false;
4730         }
4731
4732         ev = samba_tevent_context_init(talloc_tos());
4733         if (ev == NULL) {
4734                 printf("tevent_context_init failed\n");
4735                 return false;
4736         }
4737
4738         state = talloc(ev, struct oplock4_state);
4739         if (state == NULL) {
4740                 printf("talloc failed\n");
4741                 return false;
4742         }
4743         state->ev = ev;
4744         state->cli = cli1;
4745         state->got_break = &got_break;
4746         state->fnum2 = &fnum2;
4747
4748         oplock_req = cli_smb_oplock_break_waiter_send(
4749                 talloc_tos(), ev, cli1);
4750         if (oplock_req == NULL) {
4751                 printf("cli_smb_oplock_break_waiter_send failed\n");
4752                 return false;
4753         }
4754         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4755
4756         open_req = cli_openx_send(
4757                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4758         if (open_req == NULL) {
4759                 printf("cli_openx_send failed\n");
4760                 return false;
4761         }
4762         tevent_req_set_callback(open_req, oplock4_got_open, state);
4763
4764         got_break = false;
4765         fnum2 = 0xffff;
4766
4767         while (!got_break || fnum2 == 0xffff) {
4768                 int ret;
4769                 ret = tevent_loop_once(ev);
4770                 if (ret == -1) {
4771                         printf("tevent_loop_once failed: %s\n",
4772                                strerror(errno));
4773                         return false;
4774                 }
4775         }
4776
4777         status = cli_close(cli2, fnum2);
4778         if (!NT_STATUS_IS_OK(status)) {
4779                 printf("close2 failed (%s)\n", nt_errstr(status));
4780                 correct = false;
4781         }
4782
4783         status = cli_close(cli1, fnum1);
4784         if (!NT_STATUS_IS_OK(status)) {
4785                 printf("close1 failed (%s)\n", nt_errstr(status));
4786                 correct = false;
4787         }
4788
4789         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4790         if (!NT_STATUS_IS_OK(status)) {
4791                 printf("unlink failed (%s)\n", nt_errstr(status));
4792                 correct = false;
4793         }
4794
4795         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796         if (!NT_STATUS_IS_OK(status)) {
4797                 printf("unlink failed (%s)\n", nt_errstr(status));
4798                 correct = false;
4799         }
4800
4801         if (!torture_close_connection(cli1)) {
4802                 correct = false;
4803         }
4804
4805         if (!got_break) {
4806                 correct = false;
4807         }
4808
4809         printf("finished oplock test 4\n");
4810
4811         return correct;
4812 }
4813
4814 static void oplock4_got_break(struct tevent_req *req)
4815 {
4816         struct oplock4_state *state = tevent_req_callback_data(
4817                 req, struct oplock4_state);
4818         uint16_t fnum;
4819         uint8_t level;
4820         NTSTATUS status;
4821
4822         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4823         TALLOC_FREE(req);
4824         if (!NT_STATUS_IS_OK(status)) {
4825                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4826                        nt_errstr(status));
4827                 return;
4828         }
4829         *state->got_break = true;
4830
4831         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4832                                   NO_OPLOCK);
4833         if (req == NULL) {
4834                 printf("cli_oplock_ack_send failed\n");
4835                 return;
4836         }
4837 }
4838
4839 static void oplock4_got_open(struct tevent_req *req)
4840 {
4841         struct oplock4_state *state = tevent_req_callback_data(
4842                 req, struct oplock4_state);
4843         NTSTATUS status;
4844
4845         status = cli_openx_recv(req, state->fnum2);
4846         if (!NT_STATUS_IS_OK(status)) {
4847                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4848                 *state->fnum2 = 0xffff;
4849         }
4850 }
4851
4852 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4853
4854 struct oplock5_state {
4855         int pipe_down_fd;
4856 };
4857
4858 /*
4859  * Async open the file that has a kernel oplock, do an echo to get
4860  * that 100% across, close the file to signal to the child fd that the
4861  * oplock can be dropped, wait for the open reply.
4862  */
4863
4864 static void oplock5_opened(struct tevent_req *subreq);
4865 static void oplock5_pong(struct tevent_req *subreq);
4866 static void oplock5_timedout(struct tevent_req *subreq);
4867
4868 static struct tevent_req *oplock5_send(
4869         TALLOC_CTX *mem_ctx,
4870         struct tevent_context *ev,
4871         struct cli_state *cli,
4872         const char *fname,
4873         int pipe_down_fd)
4874 {
4875         struct tevent_req *req = NULL, *subreq = NULL;
4876         struct oplock5_state *state = NULL;
4877         static uint8_t data = 0;
4878
4879         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4880         if (req == NULL) {
4881                 return NULL;
4882         }
4883         state->pipe_down_fd = pipe_down_fd;
4884
4885         subreq = cli_ntcreate_send(
4886                 state,
4887                 ev,
4888                 cli,
4889                 fname,
4890                 0,                      /* CreatFlags */
4891                 SEC_FILE_READ_DATA,    /* DesiredAccess */
4892                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
4893                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4894                 FILE_OPEN,               /* CreateDisposition */
4895                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4896                 0,                       /* Impersonation */
4897                 0);                      /* SecurityFlags */
4898         if (tevent_req_nomem(subreq, req)) {
4899                 return tevent_req_post(req, ev);
4900         }
4901         tevent_req_set_callback(subreq, oplock5_opened, req);
4902
4903         subreq = cli_echo_send(
4904                 state,
4905                 ev,
4906                 cli,
4907                 1,
4908                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4909         if (tevent_req_nomem(subreq, req)) {
4910                 return tevent_req_post(req, ev);
4911         }
4912         tevent_req_set_callback(subreq, oplock5_pong, req);
4913
4914         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4915         if (tevent_req_nomem(subreq, req)) {
4916                 return tevent_req_post(req, ev);
4917         }
4918         tevent_req_set_callback(subreq, oplock5_timedout, req);
4919
4920         return req;
4921 }
4922
4923 static void oplock5_opened(struct tevent_req *subreq)
4924 {
4925         struct tevent_req *req = tevent_req_callback_data(
4926                 subreq, struct tevent_req);
4927         NTSTATUS status;
4928         uint16_t fnum;
4929
4930         status = cli_ntcreate_recv(subreq, &fnum, NULL);
4931         TALLOC_FREE(subreq);
4932         if (tevent_req_nterror(req, status)) {
4933                 return;
4934         }
4935         tevent_req_done(req);
4936 }
4937
4938 static void oplock5_pong(struct tevent_req *subreq)
4939 {
4940         struct tevent_req *req = tevent_req_callback_data(
4941                 subreq, struct tevent_req);
4942         struct oplock5_state *state = tevent_req_data(
4943                 req, struct oplock5_state);
4944         NTSTATUS status;
4945
4946         status = cli_echo_recv(subreq);
4947         TALLOC_FREE(subreq);
4948         if (tevent_req_nterror(req, status)) {
4949                 return;
4950         }
4951
4952         close(state->pipe_down_fd);
4953 }
4954
4955 static void oplock5_timedout(struct tevent_req *subreq)
4956 {
4957         struct tevent_req *req = tevent_req_callback_data(
4958                 subreq, struct tevent_req);
4959         bool ok;
4960
4961         ok = tevent_wakeup_recv(subreq);
4962         TALLOC_FREE(subreq);
4963         if (!ok) {
4964                 tevent_req_oom(req);
4965                 return;
4966         }
4967         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4968 }
4969
4970 static NTSTATUS oplock5_recv(struct tevent_req *req)
4971 {
4972         return tevent_req_simple_recv_ntstatus(req);
4973 }
4974
4975 static bool run_oplock5(int dummy)
4976 {
4977         struct tevent_context *ev = NULL;
4978         struct tevent_req *req = NULL;
4979         struct cli_state *cli = NULL;
4980         const char *fname = "oplock5.txt";
4981         int pipe_down[2], pipe_up[2];
4982         pid_t child_pid;
4983         uint8_t c = '\0';
4984         NTSTATUS status;
4985         int ret;
4986         bool ok;
4987
4988         printf("starting oplock5\n");
4989
4990         if (local_path == NULL) {
4991                 d_fprintf(stderr, "oplock5 must be given a local path via "
4992                           "-l <localpath>\n");
4993                 return false;
4994         }
4995
4996         ret = pipe(pipe_down);
4997         if (ret == -1) {
4998                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4999                 return false;
5000         }
5001         ret = pipe(pipe_up);
5002         if (ret == -1) {
5003                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5004                 return false;
5005         }
5006
5007         child_pid = fork();
5008         if (child_pid == -1) {
5009                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5010                 return false;
5011         }
5012
5013         if (child_pid == 0) {
5014                 char *local_file = NULL;
5015                 int fd;
5016
5017                 close(pipe_down[1]);
5018                 close(pipe_up[0]);
5019
5020                 local_file = talloc_asprintf(
5021                         talloc_tos(), "%s/%s", local_path, fname);
5022                 if (local_file == 0) {
5023                         c = 1;
5024                         goto do_write;
5025                 }
5026                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5027                 if (fd == -1) {
5028                         d_fprintf(stderr,
5029                                   "open(%s) in child failed: %s\n",
5030                                   local_file,
5031                                   strerror(errno));
5032                         c = 2;
5033                         goto do_write;
5034                 }
5035
5036                 signal(SIGIO, SIG_IGN);
5037
5038                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5039                 if (ret == -1) {
5040                         d_fprintf(stderr,
5041                                   "SETLEASE in child failed: %s\n",
5042                                   strerror(errno));
5043                         c = 3;
5044                         goto do_write;
5045                 }
5046
5047         do_write:
5048                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5049                 if (ret == -1) {
5050                         d_fprintf(stderr,
5051                                   "sys_write failed: %s\n",
5052                                   strerror(errno));
5053                         exit(4);
5054                 }
5055                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5056                 if (ret == -1) {
5057                         d_fprintf(stderr,
5058                                   "sys_read failed: %s\n",
5059                                   strerror(errno));
5060                         exit(5);
5061                 }
5062                 exit(0);
5063         }
5064
5065         close(pipe_up[1]);
5066         close(pipe_down[0]);
5067
5068         ret = sys_read(pipe_up[0], &c, sizeof(c));
5069         if (ret != 1) {
5070                 d_fprintf(stderr,
5071                           "sys_read failed: %s\n",
5072                           strerror(errno));
5073                 return false;
5074         }
5075         if (c != 0) {
5076                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5077                 return false;
5078         }
5079
5080         ok = torture_open_connection(&cli, 0);
5081         if (!ok) {
5082                 d_fprintf(stderr, "torture_open_connection failed\n");
5083                 return false;
5084         }
5085
5086         ev = samba_tevent_context_init(talloc_tos());
5087         if (ev == NULL) {
5088                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5089                 return false;
5090         }
5091
5092         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5093         if (req == NULL) {
5094                 d_fprintf(stderr, "oplock5_send failed\n");
5095                 return false;
5096         }
5097
5098         ok = tevent_req_poll_ntstatus(req, ev, &status);
5099         if (!ok) {
5100                 d_fprintf(stderr,
5101                           "tevent_req_poll_ntstatus failed: %s\n",
5102                           nt_errstr(status));
5103                 return false;
5104         }
5105
5106         status = oplock5_recv(req);
5107         TALLOC_FREE(req);
5108         if (!NT_STATUS_IS_OK(status)) {
5109                 d_fprintf(stderr,
5110                           "oplock5 failed: %s\n",
5111                           nt_errstr(status));
5112                 return false;
5113         }
5114
5115         return true;
5116 }
5117
5118 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5119
5120 /*
5121   Test delete on close semantics.
5122  */
5123 static bool run_deletetest(int dummy)
5124 {
5125         struct cli_state *cli1 = NULL;
5126         struct cli_state *cli2 = NULL;
5127         const char *fname = "\\delete.file";
5128         uint16_t fnum1 = (uint16_t)-1;
5129         uint16_t fnum2 = (uint16_t)-1;
5130         bool correct = false;
5131         NTSTATUS status;
5132
5133         printf("starting delete test\n");
5134
5135         if (!torture_open_connection(&cli1, 0)) {
5136                 return False;
5137         }
5138
5139         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5140
5141         /* Test 1 - this should delete the file on close. */
5142
5143         cli_setatr(cli1, fname, 0, 0);
5144         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5145
5146         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5147                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5148                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5149         if (!NT_STATUS_IS_OK(status)) {
5150                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5151                 goto fail;
5152         }
5153
5154         status = cli_close(cli1, fnum1);
5155         if (!NT_STATUS_IS_OK(status)) {
5156                 printf("[1] close failed (%s)\n", nt_errstr(status));
5157                 goto fail;
5158         }
5159
5160         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5161         if (NT_STATUS_IS_OK(status)) {
5162                 printf("[1] open of %s succeeded (should fail)\n", fname);
5163                 goto fail;
5164         }
5165
5166         printf("first delete on close test succeeded.\n");
5167
5168         /* Test 2 - this should delete the file on close. */
5169
5170         cli_setatr(cli1, fname, 0, 0);
5171         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5172
5173         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5174                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5175                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5176         if (!NT_STATUS_IS_OK(status)) {
5177                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5178                 goto fail;
5179         }
5180
5181         status = cli_nt_delete_on_close(cli1, fnum1, true);
5182         if (!NT_STATUS_IS_OK(status)) {
5183                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5184                 goto fail;
5185         }
5186
5187         status = cli_close(cli1, fnum1);
5188         if (!NT_STATUS_IS_OK(status)) {
5189                 printf("[2] close failed (%s)\n", nt_errstr(status));
5190                 goto fail;
5191         }
5192
5193         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5194         if (NT_STATUS_IS_OK(status)) {
5195                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5196                 status = cli_close(cli1, fnum1);
5197                 if (!NT_STATUS_IS_OK(status)) {
5198                         printf("[2] close failed (%s)\n", nt_errstr(status));
5199                 }
5200                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5201                 goto fail;
5202         }
5203
5204         printf("second delete on close test succeeded.\n");
5205
5206         /* Test 3 - ... */
5207         cli_setatr(cli1, fname, 0, 0);
5208         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5209
5210         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5211                               FILE_ATTRIBUTE_NORMAL,
5212                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5213                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5214         if (!NT_STATUS_IS_OK(status)) {
5215                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5216                 goto fail;
5217         }
5218
5219         /* This should fail with a sharing violation - open for delete is only compatible
5220            with SHARE_DELETE. */
5221
5222         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5223                               FILE_ATTRIBUTE_NORMAL,
5224                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5225                               FILE_OPEN, 0, 0, &fnum2, NULL);
5226         if (NT_STATUS_IS_OK(status)) {
5227                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5228                 goto fail;
5229         }
5230
5231         /* This should succeed. */
5232         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5233                              FILE_ATTRIBUTE_NORMAL,
5234                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5235                              FILE_OPEN, 0, 0, &fnum2, NULL);
5236         if (!NT_STATUS_IS_OK(status)) {
5237                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5238                 goto fail;
5239         }
5240
5241         status = cli_nt_delete_on_close(cli1, fnum1, true);
5242         if (!NT_STATUS_IS_OK(status)) {
5243                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5244                 goto fail;
5245         }
5246
5247         status = cli_close(cli1, fnum1);
5248         if (!NT_STATUS_IS_OK(status)) {
5249                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5250                 goto fail;
5251         }
5252
5253         status = cli_close(cli1, fnum2);
5254         if (!NT_STATUS_IS_OK(status)) {
5255                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5256                 goto fail;
5257         }
5258
5259         /* This should fail - file should no longer be there. */
5260
5261         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5262         if (NT_STATUS_IS_OK(status)) {
5263                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5264                 status = cli_close(cli1, fnum1);
5265                 if (!NT_STATUS_IS_OK(status)) {
5266                         printf("[3] close failed (%s)\n", nt_errstr(status));
5267                 }
5268                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5269                 goto fail;
5270         }
5271
5272         printf("third delete on close test succeeded.\n");
5273
5274         /* Test 4 ... */
5275         cli_setatr(cli1, fname, 0, 0);
5276         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5277
5278         status = cli_ntcreate(cli1, fname, 0,
5279                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5280                               FILE_ATTRIBUTE_NORMAL,
5281                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5282                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5283         if (!NT_STATUS_IS_OK(status)) {
5284                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5285                 goto fail;
5286         }
5287
5288         /* This should succeed. */
5289         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5290                              FILE_ATTRIBUTE_NORMAL,
5291                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5292                              FILE_OPEN, 0, 0, &fnum2, NULL);
5293         if (!NT_STATUS_IS_OK(status)) {
5294                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5295                 goto fail;
5296         }
5297
5298         status = cli_close(cli1, fnum2);
5299         if (!NT_STATUS_IS_OK(status)) {
5300                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5301                 goto fail;
5302         }
5303
5304         status = cli_nt_delete_on_close(cli1, fnum1, true);
5305         if (!NT_STATUS_IS_OK(status)) {
5306                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5307                 goto fail;
5308         }
5309
5310         /* This should fail - no more opens once delete on close set. */
5311         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5312                               FILE_ATTRIBUTE_NORMAL,
5313                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5314                               FILE_OPEN, 0, 0, &fnum2, NULL);
5315         if (NT_STATUS_IS_OK(status)) {
5316                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5317                 goto fail;
5318         }
5319
5320         status = cli_close(cli1, fnum1);
5321         if (!NT_STATUS_IS_OK(status)) {
5322                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5323                 goto fail;
5324         }
5325
5326         printf("fourth delete on close test succeeded.\n");
5327
5328         /* Test 5 ... */
5329         cli_setatr(cli1, fname, 0, 0);
5330         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5331
5332         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5333         if (!NT_STATUS_IS_OK(status)) {
5334                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5335                 goto fail;
5336         }
5337
5338         /* This should fail - only allowed on NT opens with DELETE access. */
5339
5340         status = cli_nt_delete_on_close(cli1, fnum1, true);
5341         if (NT_STATUS_IS_OK(status)) {
5342                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5343                 goto fail;
5344         }
5345
5346         status = cli_close(cli1, fnum1);
5347         if (!NT_STATUS_IS_OK(status)) {
5348                 printf("[5] close failed (%s)\n", nt_errstr(status));
5349                 goto fail;
5350         }
5351
5352         printf("fifth delete on close test succeeded.\n");
5353
5354         /* Test 6 ... */
5355         cli_setatr(cli1, fname, 0, 0);
5356         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5357
5358         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5359                              FILE_ATTRIBUTE_NORMAL,
5360                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5361                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5362         if (!NT_STATUS_IS_OK(status)) {
5363                 printf("[6] open of %s failed (%s)\n", fname,
5364                        nt_errstr(status));
5365                 goto fail;
5366         }
5367
5368         /* This should fail - only allowed on NT opens with DELETE access. */
5369
5370         status = cli_nt_delete_on_close(cli1, fnum1, true);
5371         if (NT_STATUS_IS_OK(status)) {
5372                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5373                 goto fail;
5374         }
5375
5376         status = cli_close(cli1, fnum1);
5377         if (!NT_STATUS_IS_OK(status)) {
5378                 printf("[6] close failed (%s)\n", nt_errstr(status));
5379                 goto fail;
5380         }
5381
5382         printf("sixth delete on close test succeeded.\n");
5383
5384         /* Test 7 ... */
5385         cli_setatr(cli1, fname, 0, 0);
5386         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5387
5388         status = cli_ntcreate(cli1, fname, 0,
5389                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5390                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5391                               0, 0, &fnum1, NULL);
5392         if (!NT_STATUS_IS_OK(status)) {
5393                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5394                 goto fail;
5395         }
5396
5397         status = cli_nt_delete_on_close(cli1, fnum1, true);
5398         if (!NT_STATUS_IS_OK(status)) {
5399                 printf("[7] setting delete_on_close on file failed !\n");
5400                 goto fail;
5401         }
5402
5403         status = cli_nt_delete_on_close(cli1, fnum1, false);
5404         if (!NT_STATUS_IS_OK(status)) {
5405                 printf("[7] unsetting delete_on_close on file failed !\n");
5406                 goto fail;
5407         }
5408
5409         status = cli_close(cli1, fnum1);
5410         if (!NT_STATUS_IS_OK(status)) {
5411                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5412                 goto fail;
5413         }
5414
5415         /* This next open should succeed - we reset the flag. */
5416         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5417         if (!NT_STATUS_IS_OK(status)) {
5418                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5419                 goto fail;
5420         }
5421
5422         status = cli_close(cli1, fnum1);
5423         if (!NT_STATUS_IS_OK(status)) {
5424                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5425                 goto fail;
5426         }
5427
5428         printf("seventh delete on close test succeeded.\n");
5429
5430         /* Test 8 ... */
5431         cli_setatr(cli1, fname, 0, 0);
5432         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5433
5434         if (!torture_open_connection(&cli2, 1)) {
5435                 printf("[8] failed to open second connection.\n");
5436                 goto fail;
5437         }
5438
5439         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5440
5441         status = cli_ntcreate(cli1, fname, 0,
5442                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5443                              FILE_ATTRIBUTE_NORMAL,
5444                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5445                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5446         if (!NT_STATUS_IS_OK(status)) {
5447                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5448                 goto fail;
5449         }
5450
5451         status = cli_ntcreate(cli2, fname, 0,
5452                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5453                              FILE_ATTRIBUTE_NORMAL,
5454                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5455                              FILE_OPEN, 0, 0, &fnum2, NULL);
5456         if (!NT_STATUS_IS_OK(status)) {
5457                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5458                 goto fail;
5459         }
5460
5461         status = cli_nt_delete_on_close(cli1, fnum1, true);
5462         if (!NT_STATUS_IS_OK(status)) {
5463                 printf("[8] setting delete_on_close on file failed !\n");
5464                 goto fail;
5465         }
5466
5467         status = cli_close(cli1, fnum1);
5468         if (!NT_STATUS_IS_OK(status)) {
5469                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5470                 goto fail;
5471         }
5472
5473         status = cli_close(cli2, fnum2);
5474         if (!NT_STATUS_IS_OK(status)) {
5475                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5476                 goto fail;
5477         }
5478
5479         /* This should fail.. */
5480         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5481         if (NT_STATUS_IS_OK(status)) {
5482                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5483                 goto fail;
5484         }
5485
5486         printf("eighth delete on close test succeeded.\n");
5487
5488         /* Test 9 ... */
5489
5490         /* This should fail - we need to set DELETE_ACCESS. */
5491         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5492                               FILE_ATTRIBUTE_NORMAL,
5493                               FILE_SHARE_NONE,
5494                               FILE_OVERWRITE_IF,
5495                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5496         if (NT_STATUS_IS_OK(status)) {
5497                 printf("[9] open of %s succeeded should have failed!\n", fname);
5498                 goto fail;
5499         }
5500
5501         printf("ninth delete on close test succeeded.\n");
5502
5503         /* Test 10 ... */
5504
5505         status = cli_ntcreate(cli1, fname, 0,
5506                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5507                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5508                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5509                              0, &fnum1, NULL);
5510         if (!NT_STATUS_IS_OK(status)) {
5511                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5512                 goto fail;
5513         }
5514
5515         /* This should delete the file. */
5516         status = cli_close(cli1, fnum1);
5517         if (!NT_STATUS_IS_OK(status)) {
5518                 printf("[10] close failed (%s)\n", nt_errstr(status));
5519                 goto fail;
5520         }
5521
5522         /* This should fail.. */
5523         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5524         if (NT_STATUS_IS_OK(status)) {
5525                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5526                 goto fail;
5527         }
5528
5529         printf("tenth delete on close test succeeded.\n");
5530
5531         /* Test 11 ... */
5532
5533         cli_setatr(cli1, fname, 0, 0);
5534         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5535
5536         /* Can we open a read-only file with delete access? */
5537
5538         /* Create a readonly file. */
5539         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5540                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5541                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5542         if (!NT_STATUS_IS_OK(status)) {
5543                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5544                 goto fail;
5545         }
5546
5547         status = cli_close(cli1, fnum1);
5548         if (!NT_STATUS_IS_OK(status)) {
5549                 printf("[11] close failed (%s)\n", nt_errstr(status));
5550                 goto fail;
5551         }
5552
5553         /* Now try open for delete access. */
5554         status = cli_ntcreate(cli1, fname, 0,
5555                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5556                              0,
5557                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5558                              FILE_OPEN, 0, 0, &fnum1, NULL);
5559         if (!NT_STATUS_IS_OK(status)) {
5560                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5561                 goto fail;
5562         }
5563
5564         cli_close(cli1, fnum1);
5565
5566         printf("eleventh delete on close test succeeded.\n");
5567
5568         /*
5569          * Test 12
5570          * like test 4 but with initial delete on close
5571          */
5572
5573         cli_setatr(cli1, fname, 0, 0);
5574         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5575
5576         status = cli_ntcreate(cli1, fname, 0,
5577                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5578                               FILE_ATTRIBUTE_NORMAL,
5579                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5580                               FILE_OVERWRITE_IF,
5581                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5582         if (!NT_STATUS_IS_OK(status)) {
5583                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5584                 goto fail;
5585         }
5586
5587         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5588                               FILE_ATTRIBUTE_NORMAL,
5589                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5590                               FILE_OPEN, 0, 0, &fnum2, NULL);
5591         if (!NT_STATUS_IS_OK(status)) {
5592                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5593                 goto fail;
5594         }
5595
5596         status = cli_close(cli1, fnum2);
5597         if (!NT_STATUS_IS_OK(status)) {
5598                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5599                 goto fail;
5600         }
5601
5602         status = cli_nt_delete_on_close(cli1, fnum1, true);
5603         if (!NT_STATUS_IS_OK(status)) {
5604                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5605                 goto fail;
5606         }
5607
5608         /* This should fail - no more opens once delete on close set. */
5609         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5610                               FILE_ATTRIBUTE_NORMAL,
5611                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5612                               FILE_OPEN, 0, 0, &fnum2, NULL);
5613         if (NT_STATUS_IS_OK(status)) {
5614                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5615                 goto fail;
5616         }
5617
5618         status = cli_nt_delete_on_close(cli1, fnum1, false);
5619         if (!NT_STATUS_IS_OK(status)) {
5620                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5621                 goto fail;
5622         }
5623
5624         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5625                               FILE_ATTRIBUTE_NORMAL,
5626                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627                               FILE_OPEN, 0, 0, &fnum2, NULL);
5628         if (!NT_STATUS_IS_OK(status)) {
5629                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5630                 goto fail;
5631         }
5632
5633         status = cli_close(cli1, fnum2);
5634         if (!NT_STATUS_IS_OK(status)) {
5635                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5636                 goto fail;
5637         }
5638
5639         status = cli_close(cli1, fnum1);
5640         if (!NT_STATUS_IS_OK(status)) {
5641                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5642                 goto fail;
5643         }
5644
5645         /*
5646          * setting delete on close on the handle does
5647          * not unset the initial delete on close...
5648          */
5649         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5650                               FILE_ATTRIBUTE_NORMAL,
5651                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5652                               FILE_OPEN, 0, 0, &fnum2, NULL);
5653         if (NT_STATUS_IS_OK(status)) {
5654                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5655                 goto fail;
5656         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5657                 printf("ntcreate returned %s, expected "
5658                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5659                        nt_errstr(status));
5660                 goto fail;
5661         }
5662
5663         printf("twelfth delete on close test succeeded.\n");
5664
5665
5666         printf("finished delete test\n");
5667
5668         correct = true;
5669
5670   fail:
5671         /* FIXME: This will crash if we aborted before cli2 got
5672          * intialized, because these functions don't handle
5673          * uninitialized connections. */
5674
5675         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5676         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5677         cli_setatr(cli1, fname, 0, 0);
5678         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5679
5680         if (cli1 && !torture_close_connection(cli1)) {
5681                 correct = False;
5682         }
5683         if (cli2 && !torture_close_connection(cli2)) {
5684                 correct = False;
5685         }
5686         return correct;
5687 }
5688
5689 struct delete_stream_state {
5690         bool closed;
5691 };
5692
5693 static void delete_stream_unlinked(struct tevent_req *subreq);
5694 static void delete_stream_closed(struct tevent_req *subreq);
5695
5696 static struct tevent_req *delete_stream_send(
5697         TALLOC_CTX *mem_ctx,
5698         struct tevent_context *ev,
5699         struct cli_state *cli,
5700         const char *base_fname,
5701         uint16_t stream_fnum)
5702 {
5703         struct tevent_req *req = NULL, *subreq = NULL;
5704         struct delete_stream_state *state = NULL;
5705
5706         req = tevent_req_create(
5707                 mem_ctx, &state, struct delete_stream_state);
5708         if (req == NULL) {
5709                 return NULL;
5710         }
5711
5712         subreq = cli_unlink_send(
5713                 state,
5714                 ev,
5715                 cli,
5716                 base_fname,
5717                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5718         if (tevent_req_nomem(subreq, req)) {
5719                 return tevent_req_post(req, ev);
5720         }
5721         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5722
5723         subreq = cli_close_send(state, ev, cli, stream_fnum);
5724         if (tevent_req_nomem(subreq, req)) {
5725                 return tevent_req_post(req, ev);
5726         }
5727         tevent_req_set_callback(subreq, delete_stream_closed, req);
5728
5729         return req;
5730 }
5731
5732 static void delete_stream_unlinked(struct tevent_req *subreq)
5733 {
5734         struct tevent_req *req = tevent_req_callback_data(
5735                 subreq, struct tevent_req);
5736         struct delete_stream_state *state = tevent_req_data(
5737                 req, struct delete_stream_state);
5738         NTSTATUS status;
5739
5740         status = cli_unlink_recv(subreq);
5741         TALLOC_FREE(subreq);
5742         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5743                 printf("cli_unlink returned %s\n",
5744                        nt_errstr(status));
5745                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5746                 return;
5747         }
5748         if (!state->closed) {
5749                 /* close reply should have come in first */
5750                 printf("Not closed\n");
5751                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5752                 return;
5753         }
5754         tevent_req_done(req);
5755 }
5756
5757 static void delete_stream_closed(struct tevent_req *subreq)
5758 {
5759         struct tevent_req *req = tevent_req_callback_data(
5760                 subreq, struct tevent_req);
5761         struct delete_stream_state *state = tevent_req_data(
5762                 req, struct delete_stream_state);
5763         NTSTATUS status;
5764
5765         status = cli_close_recv(subreq);
5766         TALLOC_FREE(subreq);
5767         if (tevent_req_nterror(req, status)) {
5768                 return;
5769         }
5770         /* also waiting for the unlink to come back */
5771         state->closed = true;
5772 }
5773
5774 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5775 {
5776         return tevent_req_simple_recv_ntstatus(req);
5777 }
5778
5779 static bool run_delete_stream(int dummy)
5780 {
5781         struct tevent_context *ev = NULL;
5782         struct tevent_req *req = NULL;
5783         struct cli_state *cli = NULL;
5784         const char fname[] = "delete_stream";
5785         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5786         uint16_t fnum1, fnum2;
5787         NTSTATUS status;
5788         bool ok;
5789
5790         printf("Starting stream delete test\n");
5791
5792         ok = torture_open_connection(&cli, 0);
5793         if (!ok) {
5794                 return false;
5795         }
5796
5797         cli_setatr(cli, fname, 0, 0);
5798         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5799
5800         /* Create the file. */
5801         status = cli_ntcreate(
5802                 cli,
5803                 fname,
5804                 0,
5805                 READ_CONTROL_ACCESS,
5806                 0,
5807                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5808                 FILE_CREATE,
5809                 0x0,
5810                 0x0,
5811                 &fnum1,
5812                 NULL);
5813         if (!NT_STATUS_IS_OK(status)) {
5814                 d_fprintf(stderr,
5815                           "cli_ntcreate of %s failed (%s)\n",
5816                           fname,
5817                           nt_errstr(status));
5818                 return false;
5819         }
5820         status = cli_close(cli, fnum1);
5821         if (!NT_STATUS_IS_OK(status)) {
5822                 d_fprintf(stderr,
5823                           "cli_close of %s failed (%s)\n",
5824                           fname,
5825                           nt_errstr(status));
5826                 return false;
5827         }
5828
5829         /* Now create the stream. */
5830         status = cli_ntcreate(
5831                 cli,
5832                 fname_stream,
5833                 0,
5834                 FILE_WRITE_DATA,
5835                 0,
5836                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5837                 FILE_CREATE,
5838                 0x0,
5839                 0x0,
5840                 &fnum1,
5841                 NULL);
5842
5843         if (!NT_STATUS_IS_OK(status)) {
5844                 d_fprintf(stderr,
5845                           "cli_ntcreate of %s failed (%s)\n",
5846                           fname_stream,
5847                           nt_errstr(status));
5848                 return false;
5849         }
5850
5851         /* open it a second time */
5852
5853         status = cli_ntcreate(
5854                 cli,
5855                 fname_stream,
5856                 0,
5857                 FILE_WRITE_DATA,
5858                 0,
5859                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5860                 FILE_OPEN,
5861                 0x0,
5862                 0x0,
5863                 &fnum2,
5864                 NULL);
5865
5866         if (!NT_STATUS_IS_OK(status)) {
5867                 d_fprintf(stderr,
5868                           "2nd cli_ntcreate of %s failed (%s)\n",
5869                           fname_stream,
5870                           nt_errstr(status));
5871                 return false;
5872         }
5873
5874         ev = samba_tevent_context_init(talloc_tos());
5875         if (ev == NULL) {
5876                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5877                 return false;
5878         }
5879
5880         req = delete_stream_send(ev, ev, cli, fname, fnum1);
5881         if (req == NULL) {
5882                 d_fprintf(stderr, "delete_stream_send failed\n");
5883                 return false;
5884         }
5885
5886         ok = tevent_req_poll_ntstatus(req, ev, &status);
5887         if (!ok) {
5888                 d_fprintf(stderr,
5889                           "tevent_req_poll_ntstatus failed: %s\n",
5890                           nt_errstr(status));
5891                 return false;
5892         }
5893
5894         status = delete_stream_recv(req);
5895         TALLOC_FREE(req);
5896         if (!NT_STATUS_IS_OK(status)) {
5897                 d_fprintf(stderr,
5898                           "delete_stream failed: %s\n",
5899                           nt_errstr(status));
5900                 return false;
5901         }
5902
5903         status = cli_close(cli, fnum2);
5904         if (!NT_STATUS_IS_OK(status)) {
5905                 d_fprintf(stderr,
5906                           "close failed: %s\n",
5907                           nt_errstr(status));
5908                 return false;
5909         }
5910
5911         status = cli_unlink(
5912                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5913         if (!NT_STATUS_IS_OK(status)) {
5914                 d_fprintf(stderr,
5915                           "unlink failed: %s\n",
5916                           nt_errstr(status));
5917                 return false;
5918         }
5919
5920         return true;
5921 }
5922
5923 /*
5924   Exercise delete on close semantics - use on the PRINT1 share in torture
5925   testing.
5926  */
5927 static bool run_delete_print_test(int dummy)
5928 {
5929         struct cli_state *cli1 = NULL;
5930         const char *fname = "print_delete.file";
5931         uint16_t fnum1 = (uint16_t)-1;
5932         bool correct = false;
5933         const char *buf = "print file data\n";
5934         NTSTATUS status;
5935
5936         printf("starting print delete test\n");
5937
5938         if (!torture_open_connection(&cli1, 0)) {
5939                 return false;
5940         }
5941
5942         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5943
5944         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5945                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5946                               0, 0, &fnum1, NULL);
5947         if (!NT_STATUS_IS_OK(status)) {
5948                 printf("open of %s failed (%s)\n",
5949                         fname,
5950                         nt_errstr(status));
5951                 goto fail;
5952         }
5953
5954         status = cli_writeall(cli1,
5955                         fnum1,
5956                         0,
5957                         (const uint8_t *)buf,
5958                         0, /* offset */
5959                         strlen(buf), /* size */
5960                         NULL);
5961         if (!NT_STATUS_IS_OK(status)) {
5962                 printf("writing print file data failed (%s)\n",
5963                         nt_errstr(status));
5964                 goto fail;
5965         }
5966
5967         status = cli_nt_delete_on_close(cli1, fnum1, true);
5968         if (!NT_STATUS_IS_OK(status)) {
5969                 printf("setting delete_on_close failed (%s)\n",
5970                         nt_errstr(status));
5971                 goto fail;
5972         }
5973
5974         status = cli_close(cli1, fnum1);
5975         if (!NT_STATUS_IS_OK(status)) {
5976                 printf("close failed (%s)\n", nt_errstr(status));
5977                 goto fail;
5978         }
5979
5980         printf("finished print delete test\n");
5981
5982         correct = true;
5983
5984   fail:
5985
5986         if (fnum1 != (uint16_t)-1) {
5987                 cli_close(cli1, fnum1);
5988         }
5989
5990         if (cli1 && !torture_close_connection(cli1)) {
5991                 correct = false;
5992         }
5993         return correct;
5994 }
5995
5996 /*
5997   Test wildcard delete.
5998  */
5999 static bool run_wild_deletetest(int dummy)
6000 {
6001         struct cli_state *cli = NULL;
6002         const char *dname = "\\WTEST";
6003         const char *fname = "\\WTEST\\A";
6004         const char *wunlink_name = "\\WTEST\\*";
6005         uint16_t fnum1 = (uint16_t)-1;
6006         bool correct = false;
6007         NTSTATUS status;
6008
6009         printf("starting wildcard delete test\n");
6010
6011         if (!torture_open_connection(&cli, 0)) {
6012                 return false;
6013         }
6014
6015         smbXcli_conn_set_sockopt(cli->conn, sockops);
6016
6017         cli_unlink(cli, fname, 0);
6018         cli_rmdir(cli, dname);
6019         status = cli_mkdir(cli, dname);
6020         if (!NT_STATUS_IS_OK(status)) {
6021                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6022                 goto fail;
6023         }
6024         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6025         if (!NT_STATUS_IS_OK(status)) {
6026                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6027                 goto fail;
6028         }
6029         status = cli_close(cli, fnum1);
6030         fnum1 = -1;
6031
6032         /*
6033          * Note the unlink attribute-type of zero. This should
6034          * map into FILE_ATTRIBUTE_NORMAL at the server even
6035          * on a wildcard delete.
6036          */
6037
6038         status = cli_unlink(cli, wunlink_name, 0);
6039         if (!NT_STATUS_IS_OK(status)) {
6040                 printf("unlink of %s failed %s!\n",
6041                         wunlink_name, nt_errstr(status));
6042                 goto fail;
6043         }
6044
6045         printf("finished wildcard delete test\n");
6046
6047         correct = true;
6048
6049   fail:
6050
6051         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6052         cli_unlink(cli, fname, 0);
6053         cli_rmdir(cli, dname);
6054
6055         if (cli && !torture_close_connection(cli)) {
6056                 correct = false;
6057         }
6058         return correct;
6059 }
6060
6061 static bool run_deletetest_ln(int dummy)
6062 {
6063         struct cli_state *cli;
6064         const char *fname = "\\delete1";
6065         const char *fname_ln = "\\delete1_ln";
6066         uint16_t fnum;
6067         uint16_t fnum1;
6068         NTSTATUS status;
6069         bool correct = true;
6070         time_t t;
6071
6072         printf("starting deletetest-ln\n");
6073
6074         if (!torture_open_connection(&cli, 0)) {
6075                 return false;
6076         }
6077
6078         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6079         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6080
6081         smbXcli_conn_set_sockopt(cli->conn, sockops);
6082
6083         /* Create the file. */
6084         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6085         if (!NT_STATUS_IS_OK(status)) {
6086                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6087                 return false;
6088         }
6089
6090         status = cli_close(cli, fnum);
6091         if (!NT_STATUS_IS_OK(status)) {
6092                 printf("close1 failed (%s)\n", nt_errstr(status));
6093                 return false;
6094         }
6095
6096         /* Now create a hardlink. */
6097         status = cli_hardlink(cli, fname, fname_ln);
6098         if (!NT_STATUS_IS_OK(status)) {
6099                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6100                 return false;
6101         }
6102
6103         /* Open the original file. */
6104         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6105                         FILE_ATTRIBUTE_NORMAL,
6106                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6107                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6108         if (!NT_STATUS_IS_OK(status)) {
6109                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6110                 return false;
6111         }
6112
6113         /* Unlink the hard link path. */
6114         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6115                         FILE_ATTRIBUTE_NORMAL,
6116                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6117                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6118         if (!NT_STATUS_IS_OK(status)) {
6119                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6120                 return false;
6121         }
6122         status = cli_nt_delete_on_close(cli, fnum1, true);
6123         if (!NT_STATUS_IS_OK(status)) {
6124                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6125                         __location__, fname_ln, nt_errstr(status));
6126                 return false;
6127         }
6128
6129         status = cli_close(cli, fnum1);
6130         if (!NT_STATUS_IS_OK(status)) {
6131                 printf("close %s failed (%s)\n",
6132                         fname_ln, nt_errstr(status));
6133                 return false;
6134         }
6135
6136         status = cli_close(cli, fnum);
6137         if (!NT_STATUS_IS_OK(status)) {
6138                 printf("close %s failed (%s)\n",
6139                         fname, nt_errstr(status));
6140                 return false;
6141         }
6142
6143         /* Ensure the original file is still there. */
6144         status = cli_getatr(cli, fname, NULL, NULL, &t);
6145         if (!NT_STATUS_IS_OK(status)) {
6146                 printf("%s getatr on file %s failed (%s)\n",
6147                         __location__,
6148                         fname,
6149                         nt_errstr(status));
6150                 correct = False;
6151         }
6152
6153         /* Ensure the link path is gone. */
6154         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6155         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6156                 printf("%s, getatr for file %s returned wrong error code %s "
6157                         "- should have been deleted\n",
6158                         __location__,
6159                         fname_ln, nt_errstr(status));
6160                 correct = False;
6161         }
6162
6163         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6164         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6165
6166         if (!torture_close_connection(cli)) {
6167                 correct = false;
6168         }
6169
6170         printf("finished deletetest-ln\n");
6171
6172         return correct;
6173 }
6174
6175 /*
6176   print out server properties
6177  */
6178 static bool run_properties(int dummy)
6179 {
6180         struct cli_state *cli;
6181         bool correct = True;
6182
6183         printf("starting properties test\n");
6184
6185         ZERO_STRUCT(cli);
6186
6187         if (!torture_open_connection(&cli, 0)) {
6188                 return False;
6189         }
6190
6191         smbXcli_conn_set_sockopt(cli->conn, sockops);
6192
6193         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6194
6195         if (!torture_close_connection(cli)) {
6196                 correct = False;
6197         }
6198
6199         return correct;
6200 }
6201
6202
6203
6204 /* FIRST_DESIRED_ACCESS   0xf019f */
6205 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6206                                FILE_READ_EA|                           /* 0xf */ \
6207                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6208                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6209                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6210                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6211 /* SECOND_DESIRED_ACCESS  0xe0080 */
6212 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6213                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6214                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6215
6216 #if 0
6217 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6218                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6219                                FILE_READ_DATA|\
6220                                WRITE_OWNER_ACCESS                      /* */
6221 #endif
6222
6223 /*
6224   Test ntcreate calls made by xcopy
6225  */
6226 static bool run_xcopy(int dummy)
6227 {
6228         static struct cli_state *cli1;
6229         const char *fname = "\\test.txt";
6230         bool correct = True;
6231         uint16_t fnum1, fnum2;
6232         NTSTATUS status;
6233
6234         printf("starting xcopy test\n");
6235
6236         if (!torture_open_connection(&cli1, 0)) {
6237                 return False;
6238         }
6239
6240         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6241                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6242                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6243         if (!NT_STATUS_IS_OK(status)) {
6244                 printf("First open failed - %s\n", nt_errstr(status));
6245                 return False;
6246         }
6247
6248         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6249                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6250                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6251         if (!NT_STATUS_IS_OK(status)) {
6252                 printf("second open failed - %s\n", nt_errstr(status));
6253                 return False;
6254         }
6255
6256         if (!torture_close_connection(cli1)) {
6257                 correct = False;
6258         }
6259
6260         return correct;
6261 }
6262
6263 /*
6264   Test rename on files open with share delete and no share delete.
6265  */
6266 static bool run_rename(int dummy)
6267 {
6268         static struct cli_state *cli1;
6269         const char *fname = "\\test.txt";
6270         const char *fname1 = "\\test1.txt";
6271         bool correct = True;
6272         uint16_t fnum1;
6273         uint32_t attr;
6274         NTSTATUS status;
6275
6276         printf("starting rename test\n");
6277
6278         if (!torture_open_connection(&cli1, 0)) {
6279                 return False;
6280         }
6281
6282         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6283         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6284
6285         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6286                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6287                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6288         if (!NT_STATUS_IS_OK(status)) {
6289                 printf("First open failed - %s\n", nt_errstr(status));
6290                 return False;
6291         }
6292
6293         status = cli_rename(cli1, fname, fname1, false);
6294         if (!NT_STATUS_IS_OK(status)) {
6295                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6296         } else {
6297                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6298                 correct = False;
6299         }
6300
6301         status = cli_close(cli1, fnum1);
6302         if (!NT_STATUS_IS_OK(status)) {
6303                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6304                 return False;
6305         }
6306
6307         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6308         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6309         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6310 #if 0
6311                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6312 #else
6313                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6314 #endif
6315                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6316         if (!NT_STATUS_IS_OK(status)) {
6317                 printf("Second open failed - %s\n", nt_errstr(status));
6318                 return False;
6319         }
6320
6321         status = cli_rename(cli1, fname, fname1, false);
6322         if (!NT_STATUS_IS_OK(status)) {
6323                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6324                 correct = False;
6325         } else {
6326                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6327         }
6328
6329         status = cli_close(cli1, fnum1);
6330         if (!NT_STATUS_IS_OK(status)) {
6331                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6332                 return False;
6333         }
6334
6335         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6336         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6337
6338         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6339                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6340                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6341         if (!NT_STATUS_IS_OK(status)) {
6342                 printf("Third open failed - %s\n", nt_errstr(status));
6343                 return False;
6344         }
6345
6346
6347         status = cli_rename(cli1, fname, fname1, false);
6348         if (!NT_STATUS_IS_OK(status)) {
6349                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6350                 correct = False;
6351         } else {
6352                 printf("Third rename succeeded (SHARE_NONE)\n");
6353         }
6354
6355         status = cli_close(cli1, fnum1);
6356         if (!NT_STATUS_IS_OK(status)) {
6357                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6358                 return False;
6359         }
6360
6361         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6362         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6363
6364         /*----*/
6365
6366         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6367                               FILE_ATTRIBUTE_NORMAL,
6368                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6369                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6370         if (!NT_STATUS_IS_OK(status)) {
6371                 printf("Fourth open failed - %s\n", nt_errstr(status));
6372                 return False;
6373         }
6374
6375         status = cli_rename(cli1, fname, fname1, false);
6376         if (!NT_STATUS_IS_OK(status)) {
6377                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6378         } else {
6379                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6380                 correct = False;
6381         }
6382
6383         status = cli_close(cli1, fnum1);
6384         if (!NT_STATUS_IS_OK(status)) {
6385                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6386                 return False;
6387         }
6388
6389         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6390         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6391
6392         /*--*/
6393
6394         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6395                          FILE_ATTRIBUTE_NORMAL,
6396                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6397                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6398         if (!NT_STATUS_IS_OK(status)) {
6399                 printf("Fifth open failed - %s\n", nt_errstr(status));
6400                 return False;
6401         }
6402
6403         status = cli_rename(cli1, fname, fname1, false);
6404         if (!NT_STATUS_IS_OK(status)) {
6405                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6406                 correct = False;
6407         } else {
6408                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6409         }
6410
6411         /*--*/
6412         status = cli_close(cli1, fnum1);
6413         if (!NT_STATUS_IS_OK(status)) {
6414                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6415                 return False;
6416         }
6417
6418         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6419         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6420         if (!NT_STATUS_IS_OK(status)) {
6421                 printf("getatr on file %s failed - %s ! \n",
6422                         fname1, nt_errstr(status));
6423                 correct = False;
6424         } else {
6425                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6426                         printf("Renamed file %s has wrong attr 0x%x "
6427                                 "(should be 0x%x)\n",
6428                                 fname1,
6429                                 attr,
6430                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6431                         correct = False;
6432                 } else {
6433                         printf("Renamed file %s has archive bit set\n", fname1);
6434                 }
6435         }
6436
6437         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6438         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6439
6440         if (!torture_close_connection(cli1)) {
6441                 correct = False;
6442         }
6443
6444         return correct;
6445 }
6446
6447 /*
6448   Test rename into a directory with an ACL denying it.
6449  */
6450 static bool run_rename_access(int dummy)
6451 {
6452         static struct cli_state *cli = NULL;
6453         static struct cli_state *posix_cli = NULL;
6454         const char *src = "test.txt";
6455         const char *dname = "dir";
6456         const char *dst = "dir\\test.txt";
6457         const char *dsrc = "test.dir";
6458         const char *ddst = "dir\\test.dir";
6459         uint16_t fnum = (uint16_t)-1;
6460         struct security_descriptor *sd = NULL;
6461         struct security_descriptor *newsd = NULL;
6462         NTSTATUS status;
6463         TALLOC_CTX *frame = NULL;
6464
6465         frame = talloc_stackframe();
6466         printf("starting rename access test\n");
6467
6468         /* Windows connection. */
6469         if (!torture_open_connection(&cli, 0)) {
6470                 goto fail;
6471         }
6472
6473         smbXcli_conn_set_sockopt(cli->conn, sockops);
6474
6475         /* Posix connection. */
6476         if (!torture_open_connection(&posix_cli, 0)) {
6477                 goto fail;
6478         }
6479
6480         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6481
6482         status = torture_setup_unix_extensions(posix_cli);
6483         if (!NT_STATUS_IS_OK(status)) {
6484                 goto fail;
6485         }
6486
6487         /* Start with a clean slate. */
6488         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6489         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6490         cli_rmdir(cli, dsrc);
6491         cli_rmdir(cli, ddst);
6492         cli_rmdir(cli, dname);
6493
6494         /*
6495          * Setup the destination directory with a DENY ACE to
6496          * prevent new files within it.
6497          */
6498         status = cli_ntcreate(cli,
6499                                 dname,
6500                                 0,
6501                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6502                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6503                                         WRITE_OWNER_ACCESS,
6504                                 FILE_ATTRIBUTE_DIRECTORY,
6505                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6506                                 FILE_CREATE,
6507                                 FILE_DIRECTORY_FILE,
6508                                 0,
6509                                 &fnum,
6510                                 NULL);
6511         if (!NT_STATUS_IS_OK(status)) {
6512                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6513                 goto fail;
6514         }
6515
6516         status = cli_query_secdesc(cli,
6517                                 fnum,
6518                                 frame,
6519                                 &sd);
6520         if (!NT_STATUS_IS_OK(status)) {
6521                 printf("cli_query_secdesc failed for %s (%s)\n",
6522                         dname, nt_errstr(status));
6523                 goto fail;
6524         }
6525
6526         newsd = security_descriptor_dacl_create(frame,
6527                                         0,
6528                                         NULL,
6529                                         NULL,
6530                                         SID_WORLD,
6531                                         SEC_ACE_TYPE_ACCESS_DENIED,
6532                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6533                                         0,
6534                                         NULL);
6535         if (newsd == NULL) {
6536                 goto fail;
6537         }
6538         sd->dacl = security_acl_concatenate(frame,
6539                                         newsd->dacl,
6540                                         sd->dacl);
6541         if (sd->dacl == NULL) {
6542                 goto fail;
6543         }
6544         status = cli_set_secdesc(cli, fnum, sd);
6545         if (!NT_STATUS_IS_OK(status)) {
6546                 printf("cli_set_secdesc failed for %s (%s)\n",
6547                         dname, nt_errstr(status));
6548                 goto fail;
6549         }
6550         status = cli_close(cli, fnum);
6551         if (!NT_STATUS_IS_OK(status)) {
6552                 printf("close failed for %s (%s)\n",
6553                         dname, nt_errstr(status));
6554                 goto fail;
6555         }
6556         /* Now go around the back and chmod to 777 via POSIX. */
6557         status = cli_posix_chmod(posix_cli, dname, 0777);
6558         if (!NT_STATUS_IS_OK(status)) {
6559                 printf("cli_posix_chmod failed for %s (%s)\n",
6560                         dname, nt_errstr(status));
6561                 goto fail;
6562         }
6563
6564         /* Check we can't create a file within dname via Windows. */
6565         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6566         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6567                 cli_close(posix_cli, fnum);
6568                 printf("Create of %s should be ACCESS denied, was %s\n",
6569                         dst, nt_errstr(status));
6570                 goto fail;
6571         }
6572
6573         /* Make the sample file/directory. */
6574         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6575         if (!NT_STATUS_IS_OK(status)) {
6576                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6577                 goto fail;
6578         }
6579         status = cli_close(cli, fnum);
6580         if (!NT_STATUS_IS_OK(status)) {
6581                 printf("cli_close failed (%s)\n", nt_errstr(status));
6582                 goto fail;
6583         }
6584
6585         status = cli_mkdir(cli, dsrc);
6586         if (!NT_STATUS_IS_OK(status)) {
6587                 printf("cli_mkdir of %s failed (%s)\n",
6588                         dsrc, nt_errstr(status));
6589                 goto fail;
6590         }
6591
6592         /*
6593          * OK - renames of the new file and directory into the
6594          * dst directory should fail.
6595          */
6596
6597         status = cli_rename(cli, src, dst, false);
6598         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6599                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6600                         src, dst, nt_errstr(status));
6601                 goto fail;
6602         }
6603         status = cli_rename(cli, dsrc, ddst, false);
6604         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6605                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6606                         src, dst, nt_errstr(status));
6607                 goto fail;
6608         }
6609
6610         TALLOC_FREE(frame);
6611         return true;
6612
6613   fail:
6614
6615         if (posix_cli) {
6616                 torture_close_connection(posix_cli);
6617         }
6618
6619         if (cli) {
6620                 if (fnum != (uint16_t)-1) {
6621                         cli_close(cli, fnum);
6622                 }
6623                 cli_unlink(cli, src,
6624                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6625                 cli_unlink(cli, dst,
6626                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6627                 cli_rmdir(cli, dsrc);
6628                 cli_rmdir(cli, ddst);
6629                 cli_rmdir(cli, dname);
6630
6631                 torture_close_connection(cli);
6632         }
6633
6634         TALLOC_FREE(frame);
6635         return false;
6636 }
6637
6638 /*
6639   Test owner rights ACE.
6640  */
6641 static bool run_owner_rights(int dummy)
6642 {
6643         static struct cli_state *cli = NULL;
6644         const char *fname = "owner_rights.txt";
6645         uint16_t fnum = (uint16_t)-1;
6646         struct security_descriptor *sd = NULL;
6647         struct security_descriptor *newsd = NULL;
6648         NTSTATUS status;
6649         TALLOC_CTX *frame = NULL;
6650
6651         frame = talloc_stackframe();
6652         printf("starting owner rights test\n");
6653
6654         /* Windows connection. */
6655         if (!torture_open_connection(&cli, 0)) {
6656                 goto fail;
6657         }
6658
6659         smbXcli_conn_set_sockopt(cli->conn, sockops);
6660
6661         /* Start with a clean slate. */
6662         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6663
6664         /* Create the test file. */
6665         /* Now try and open for read and write-dac. */
6666         status = cli_ntcreate(cli,
6667                                 fname,
6668                                 0,
6669                                 GENERIC_ALL_ACCESS,
6670                                 FILE_ATTRIBUTE_NORMAL,
6671                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6672                                         FILE_SHARE_DELETE,
6673                                 FILE_CREATE,
6674                                 0,
6675                                 0,
6676                                 &fnum,
6677                                 NULL);
6678         if (!NT_STATUS_IS_OK(status)) {
6679                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6680                 goto fail;
6681         }
6682
6683         /* Get the original SD. */
6684         status = cli_query_secdesc(cli,
6685                                 fnum,
6686                                 frame,
6687                                 &sd);
6688         if (!NT_STATUS_IS_OK(status)) {
6689                 printf("cli_query_secdesc failed for %s (%s)\n",
6690                         fname, nt_errstr(status));
6691                 goto fail;
6692         }
6693
6694         /*
6695          * Add an "owner-rights" ACE denying WRITE_DATA,
6696          * and an "owner-rights" ACE allowing READ_DATA.
6697          */
6698
6699         newsd = security_descriptor_dacl_create(frame,
6700                                         0,
6701                                         NULL,
6702                                         NULL,
6703                                         SID_OWNER_RIGHTS,
6704                                         SEC_ACE_TYPE_ACCESS_DENIED,
6705                                         FILE_WRITE_DATA,
6706                                         0,
6707                                         SID_OWNER_RIGHTS,
6708                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6709                                         FILE_READ_DATA,
6710                                         0,
6711                                         NULL);
6712         if (newsd == NULL) {
6713                 goto fail;
6714         }
6715         sd->dacl = security_acl_concatenate(frame,
6716                                         newsd->dacl,
6717                                         sd->dacl);
6718         if (sd->dacl == NULL) {
6719                 goto fail;
6720         }
6721         status = cli_set_secdesc(cli, fnum, sd);
6722         if (!NT_STATUS_IS_OK(status)) {
6723                 printf("cli_set_secdesc failed for %s (%s)\n",
6724                         fname, nt_errstr(status));
6725                 goto fail;
6726         }
6727         status = cli_close(cli, fnum);
6728         if (!NT_STATUS_IS_OK(status)) {
6729                 printf("close failed for %s (%s)\n",
6730                         fname, nt_errstr(status));
6731                 goto fail;
6732         }
6733         fnum = (uint16_t)-1;
6734
6735         /* Try and open for FILE_WRITE_DATA */
6736         status = cli_ntcreate(cli,
6737                                 fname,
6738                                 0,
6739                                 FILE_WRITE_DATA,
6740                                 FILE_ATTRIBUTE_NORMAL,
6741                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6742                                         FILE_SHARE_DELETE,
6743                                 FILE_OPEN,
6744                                 0,
6745                                 0,
6746                                 &fnum,
6747                                 NULL);
6748         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6749                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6750                 goto fail;
6751         }
6752
6753         /* Now try and open for FILE_READ_DATA */
6754         status = cli_ntcreate(cli,
6755                                 fname,
6756                                 0,
6757                                 FILE_READ_DATA,
6758                                 FILE_ATTRIBUTE_NORMAL,
6759                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6760                                         FILE_SHARE_DELETE,
6761                                 FILE_OPEN,
6762                                 0,
6763                                 0,
6764                                 &fnum,
6765                                 NULL);
6766         if (!NT_STATUS_IS_OK(status)) {
6767                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6768                 goto fail;
6769         }
6770
6771         status = cli_close(cli, fnum);
6772         if (!NT_STATUS_IS_OK(status)) {
6773                 printf("close failed for %s (%s)\n",
6774                         fname, nt_errstr(status));
6775                 goto fail;
6776         }
6777
6778         /* Restore clean slate. */
6779         TALLOC_FREE(sd);
6780         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6781
6782         /* Create the test file. */
6783         status = cli_ntcreate(cli,
6784                                 fname,
6785                                 0,
6786                                 GENERIC_ALL_ACCESS,
6787                                 FILE_ATTRIBUTE_NORMAL,
6788                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6789                                         FILE_SHARE_DELETE,
6790                                 FILE_CREATE,
6791                                 0,
6792                                 0,
6793                                 &fnum,
6794                                 NULL);
6795         if (!NT_STATUS_IS_OK(status)) {
6796                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6797                 goto fail;
6798         }
6799
6800         /* Get the original SD. */
6801         status = cli_query_secdesc(cli,
6802                                 fnum,
6803                                 frame,
6804                                 &sd);
6805         if (!NT_STATUS_IS_OK(status)) {
6806                 printf("cli_query_secdesc failed for %s (%s)\n",
6807                         fname, nt_errstr(status));
6808                 goto fail;
6809         }
6810
6811         /*
6812          * Add an "owner-rights ACE denying WRITE_DATA,
6813          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6814          */
6815
6816         newsd = security_descriptor_dacl_create(frame,
6817                                         0,
6818                                         NULL,
6819                                         NULL,
6820                                         SID_OWNER_RIGHTS,
6821                                         SEC_ACE_TYPE_ACCESS_DENIED,
6822                                         FILE_WRITE_DATA,
6823                                         0,
6824                                         SID_OWNER_RIGHTS,
6825                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6826                                         FILE_READ_DATA|FILE_WRITE_DATA,
6827                                         0,
6828                                         NULL);
6829         if (newsd == NULL) {
6830                 goto fail;
6831         }
6832         sd->dacl = security_acl_concatenate(frame,
6833                                         newsd->dacl,
6834                                         sd->dacl);
6835         if (sd->dacl == NULL) {
6836                 goto fail;
6837         }
6838         status = cli_set_secdesc(cli, fnum, sd);
6839         if (!NT_STATUS_IS_OK(status)) {
6840                 printf("cli_set_secdesc failed for %s (%s)\n",
6841                         fname, nt_errstr(status));
6842                 goto fail;
6843         }
6844         status = cli_close(cli, fnum);
6845         if (!NT_STATUS_IS_OK(status)) {
6846                 printf("close failed for %s (%s)\n",
6847                         fname, nt_errstr(status));
6848                 goto fail;
6849         }
6850         fnum = (uint16_t)-1;
6851
6852         /* Try and open for FILE_WRITE_DATA */
6853         status = cli_ntcreate(cli,
6854                                 fname,
6855                                 0,
6856                                 FILE_WRITE_DATA,
6857                                 FILE_ATTRIBUTE_NORMAL,
6858                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6859                                         FILE_SHARE_DELETE,
6860                                 FILE_OPEN,
6861                                 0,
6862                                 0,
6863                                 &fnum,
6864                                 NULL);
6865         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6866                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6867                 goto fail;
6868         }
6869
6870         /* Now try and open for FILE_READ_DATA */
6871         status = cli_ntcreate(cli,
6872                                 fname,
6873                                 0,
6874                                 FILE_READ_DATA,
6875                                 FILE_ATTRIBUTE_NORMAL,
6876                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6877                                         FILE_SHARE_DELETE,
6878                                 FILE_OPEN,
6879                                 0,
6880                                 0,
6881                                 &fnum,
6882                                 NULL);
6883         if (!NT_STATUS_IS_OK(status)) {
6884                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6885                 goto fail;
6886         }
6887
6888         status = cli_close(cli, fnum);
6889         if (!NT_STATUS_IS_OK(status)) {
6890                 printf("close failed for %s (%s)\n",
6891                         fname, nt_errstr(status));
6892                 goto fail;
6893         }
6894
6895         /* Restore clean slate. */
6896         TALLOC_FREE(sd);
6897         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6898
6899
6900         /* Create the test file. */
6901         status = cli_ntcreate(cli,
6902                                 fname,
6903                                 0,
6904                                 GENERIC_ALL_ACCESS,
6905                                 FILE_ATTRIBUTE_NORMAL,
6906                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6907                                         FILE_SHARE_DELETE,
6908                                 FILE_CREATE,
6909                                 0,
6910                                 0,
6911                                 &fnum,
6912                                 NULL);
6913         if (!NT_STATUS_IS_OK(status)) {
6914                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6915                 goto fail;
6916         }
6917
6918         /* Get the original SD. */
6919         status = cli_query_secdesc(cli,
6920                                 fnum,
6921                                 frame,
6922                                 &sd);
6923         if (!NT_STATUS_IS_OK(status)) {
6924                 printf("cli_query_secdesc failed for %s (%s)\n",
6925                         fname, nt_errstr(status));
6926                 goto fail;
6927         }
6928
6929         /*
6930          * Add an "authenticated users" ACE allowing READ_DATA,
6931          * add an "owner-rights" denying READ_DATA,
6932          * and an "authenticated users" ACE allowing WRITE_DATA.
6933          */
6934
6935         newsd = security_descriptor_dacl_create(frame,
6936                                         0,
6937                                         NULL,
6938                                         NULL,
6939                                         SID_NT_AUTHENTICATED_USERS,
6940                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6941                                         FILE_READ_DATA,
6942                                         0,
6943                                         SID_OWNER_RIGHTS,
6944                                         SEC_ACE_TYPE_ACCESS_DENIED,
6945                                         FILE_READ_DATA,
6946                                         0,
6947                                         SID_NT_AUTHENTICATED_USERS,
6948                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6949                                         FILE_WRITE_DATA,
6950                                         0,
6951                                         NULL);
6952         if (newsd == NULL) {
6953                 printf("newsd == NULL\n");
6954                 goto fail;
6955         }
6956         sd->dacl = security_acl_concatenate(frame,
6957                                         newsd->dacl,
6958                                         sd->dacl);
6959         if (sd->dacl == NULL) {
6960                 printf("sd->dacl == NULL\n");
6961                 goto fail;
6962         }
6963         status = cli_set_secdesc(cli, fnum, sd);
6964         if (!NT_STATUS_IS_OK(status)) {
6965                 printf("cli_set_secdesc failed for %s (%s)\n",
6966                         fname, nt_errstr(status));
6967                 goto fail;
6968         }
6969         status = cli_close(cli, fnum);
6970         if (!NT_STATUS_IS_OK(status)) {
6971                 printf("close failed for %s (%s)\n",
6972                         fname, nt_errstr(status));
6973                 goto fail;
6974         }
6975         fnum = (uint16_t)-1;
6976
6977         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6978         status = cli_ntcreate(cli,
6979                                 fname,
6980                                 0,
6981                                 FILE_READ_DATA|FILE_WRITE_DATA,
6982                                 FILE_ATTRIBUTE_NORMAL,
6983                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6984                                         FILE_SHARE_DELETE,
6985                                 FILE_OPEN,
6986                                 0,
6987                                 0,
6988                                 &fnum,
6989                                 NULL);
6990         if (!NT_STATUS_IS_OK(status)) {
6991                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6992                 goto fail;
6993         }
6994
6995         status = cli_close(cli, fnum);
6996         if (!NT_STATUS_IS_OK(status)) {
6997                 printf("close failed for %s (%s)\n",
6998                         fname, nt_errstr(status));
6999                 goto fail;
7000         }
7001
7002         cli_unlink(cli, fname,
7003                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7004
7005         TALLOC_FREE(frame);
7006         return true;
7007
7008   fail:
7009
7010         if (cli) {
7011                 if (fnum != (uint16_t)-1) {
7012                         cli_close(cli, fnum);
7013                 }
7014                 cli_unlink(cli, fname,
7015                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7016                 torture_close_connection(cli);
7017         }
7018
7019         TALLOC_FREE(frame);
7020         return false;
7021 }
7022
7023 /*
7024  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7025  * Note this test only works with a user with SeSecurityPrivilege set.
7026  *
7027  * NB. This is also tested in samba3.base.createx_access
7028  * but this makes it very explicit what we're looking for.
7029  */
7030 static bool run_smb1_system_security(int dummy)
7031 {
7032         static struct cli_state *cli = NULL;
7033         const char *fname = "system_security.txt";
7034         uint16_t fnum = (uint16_t)-1;
7035         NTSTATUS status;
7036         TALLOC_CTX *frame = NULL;
7037
7038         frame = talloc_stackframe();
7039         printf("starting smb1 system security test\n");
7040
7041         /* SMB1 connection - torture_open_connection() forces this. */
7042         if (!torture_open_connection(&cli, 0)) {
7043                 goto fail;
7044         }
7045
7046         smbXcli_conn_set_sockopt(cli->conn, sockops);
7047
7048         /* Start with a clean slate. */
7049         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7050
7051         /* Create the test file. */
7052         status = cli_ntcreate(cli,
7053                                 fname,
7054                                 0,
7055                                 GENERIC_ALL_ACCESS,
7056                                 FILE_ATTRIBUTE_NORMAL,
7057                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7058                                         FILE_SHARE_DELETE,
7059                                 FILE_CREATE,
7060                                 0,
7061                                 0,
7062                                 &fnum,
7063                                 NULL);
7064         if (!NT_STATUS_IS_OK(status)) {
7065                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7066                 goto fail;
7067         }
7068
7069         status = cli_close(cli, fnum);
7070
7071         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7072         /*
7073          * On SMB1 this succeeds - SMB2 it fails,
7074          * see the SMB2-SACL test.
7075          */
7076         status = cli_ntcreate(cli,
7077                                 fname,
7078                                 0,
7079                                 SEC_FLAG_SYSTEM_SECURITY,
7080                                 FILE_ATTRIBUTE_NORMAL,
7081                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7082                                         FILE_SHARE_DELETE,
7083                                 FILE_OPEN,
7084                                 0,
7085                                 0,
7086                                 &fnum,
7087                                 NULL);
7088         if (!NT_STATUS_IS_OK(status)) {
7089                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7090                 goto fail;
7091         }
7092
7093         status = cli_close(cli, fnum);
7094
7095         cli_unlink(cli, fname,
7096                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7097
7098         torture_close_connection(cli);
7099         TALLOC_FREE(frame);
7100         return true;
7101
7102   fail:
7103
7104         if (cli) {
7105                 if (fnum != (uint16_t)-1) {
7106                         cli_close(cli, fnum);
7107                 }
7108                 cli_unlink(cli, fname,
7109                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7110                 torture_close_connection(cli);
7111         }
7112
7113         TALLOC_FREE(frame);
7114         return false;
7115 }
7116
7117 static bool run_pipe_number(int dummy)
7118 {
7119         struct cli_state *cli1;
7120         const char *pipe_name = "\\SPOOLSS";
7121         uint16_t fnum;
7122         int num_pipes = 0;
7123         NTSTATUS status;
7124
7125         printf("starting pipenumber test\n");
7126         if (!torture_open_connection(&cli1, 0)) {
7127                 return False;
7128         }
7129
7130         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7131         while(1) {
7132                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7133                                       FILE_ATTRIBUTE_NORMAL,
7134                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7135                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7136                 if (!NT_STATUS_IS_OK(status)) {
7137                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7138                         break;
7139                 }
7140                 num_pipes++;
7141                 printf("\r%6d", num_pipes);
7142         }
7143
7144         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7145         torture_close_connection(cli1);
7146         return True;
7147 }
7148
7149 /*
7150   Test open mode returns on read-only files.
7151  */
7152 static bool run_opentest(int dummy)
7153 {
7154         static struct cli_state *cli1;
7155         static struct cli_state *cli2;
7156         const char *fname = "\\readonly.file";
7157         uint16_t fnum1, fnum2;
7158         char buf[20];
7159         off_t fsize;
7160         bool correct = True;
7161         char *tmp_path;
7162         NTSTATUS status;
7163
7164         printf("starting open test\n");
7165
7166         if (!torture_open_connection(&cli1, 0)) {
7167                 return False;
7168         }
7169
7170         cli_setatr(cli1, fname, 0, 0);
7171         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7172
7173         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7174
7175         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7176         if (!NT_STATUS_IS_OK(status)) {
7177                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7178                 return False;
7179         }
7180
7181         status = cli_close(cli1, fnum1);
7182         if (!NT_STATUS_IS_OK(status)) {
7183                 printf("close2 failed (%s)\n", nt_errstr(status));
7184                 return False;
7185         }
7186
7187         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7188         if (!NT_STATUS_IS_OK(status)) {
7189                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7190                 return False;
7191         }
7192
7193         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7194         if (!NT_STATUS_IS_OK(status)) {
7195                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7196                 return False;
7197         }
7198
7199         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7200         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7201
7202         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7203                         NT_STATUS_ACCESS_DENIED)) {
7204                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7205         }
7206
7207         printf("finished open test 1\n");
7208
7209         cli_close(cli1, fnum1);
7210
7211         /* Now try not readonly and ensure ERRbadshare is returned. */
7212
7213         cli_setatr(cli1, fname, 0, 0);
7214
7215         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7216         if (!NT_STATUS_IS_OK(status)) {
7217                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7218                 return False;
7219         }
7220
7221         /* This will fail - but the error should be ERRshare. */
7222         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7223
7224         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7225                         NT_STATUS_SHARING_VIOLATION)) {
7226                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7227         }
7228
7229         status = cli_close(cli1, fnum1);
7230         if (!NT_STATUS_IS_OK(status)) {
7231                 printf("close2 failed (%s)\n", nt_errstr(status));
7232                 return False;
7233         }
7234
7235         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7236
7237         printf("finished open test 2\n");
7238
7239         /* Test truncate open disposition on file opened for read. */
7240         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7241         if (!NT_STATUS_IS_OK(status)) {
7242                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7243                 return False;
7244         }
7245
7246         /* write 20 bytes. */
7247
7248         memset(buf, '\0', 20);
7249
7250         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7251         if (!NT_STATUS_IS_OK(status)) {
7252                 printf("write failed (%s)\n", nt_errstr(status));
7253                 correct = False;
7254         }
7255
7256         status = cli_close(cli1, fnum1);
7257         if (!NT_STATUS_IS_OK(status)) {
7258                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7259                 return False;
7260         }
7261
7262         /* Ensure size == 20. */
7263         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7264         if (!NT_STATUS_IS_OK(status)) {
7265                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7266                 return False;
7267         }
7268
7269         if (fsize != 20) {
7270                 printf("(3) file size != 20\n");
7271                 return False;
7272         }
7273
7274         /* Now test if we can truncate a file opened for readonly. */
7275         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7276         if (!NT_STATUS_IS_OK(status)) {
7277                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7278                 return False;
7279         }
7280
7281         status = cli_close(cli1, fnum1);
7282         if (!NT_STATUS_IS_OK(status)) {
7283                 printf("close2 failed (%s)\n", nt_errstr(status));
7284                 return False;
7285         }
7286
7287         /* Ensure size == 0. */
7288         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7289         if (!NT_STATUS_IS_OK(status)) {
7290                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7291                 return False;
7292         }
7293
7294         if (fsize != 0) {
7295                 printf("(3) file size != 0\n");
7296                 return False;
7297         }
7298         printf("finished open test 3\n");
7299
7300         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7301
7302         printf("Do ctemp tests\n");
7303         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7304         if (!NT_STATUS_IS_OK(status)) {
7305                 printf("ctemp failed (%s)\n", nt_errstr(status));
7306                 return False;
7307         }
7308
7309         printf("ctemp gave path %s\n", tmp_path);
7310         status = cli_close(cli1, fnum1);
7311         if (!NT_STATUS_IS_OK(status)) {
7312                 printf("close of temp failed (%s)\n", nt_errstr(status));
7313         }
7314
7315         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7316         if (!NT_STATUS_IS_OK(status)) {
7317                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7318         }
7319
7320         /* Test the non-io opens... */
7321
7322         if (!torture_open_connection(&cli2, 1)) {
7323                 return False;
7324         }
7325
7326         cli_setatr(cli2, fname, 0, 0);
7327         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7328
7329         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7330
7331         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7332         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7333                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7334                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7335         if (!NT_STATUS_IS_OK(status)) {
7336                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7337                 return False;
7338         }
7339
7340         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7341                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7342                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7343         if (!NT_STATUS_IS_OK(status)) {
7344                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7345                 return False;
7346         }
7347
7348         status = cli_close(cli1, fnum1);
7349         if (!NT_STATUS_IS_OK(status)) {
7350                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7351                 return False;
7352         }
7353
7354         status = cli_close(cli2, fnum2);
7355         if (!NT_STATUS_IS_OK(status)) {
7356                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7357                 return False;
7358         }
7359
7360         printf("non-io open test #1 passed.\n");
7361
7362         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7363
7364         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7365
7366         status = cli_ntcreate(cli1, fname, 0,
7367                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7368                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7369                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7370         if (!NT_STATUS_IS_OK(status)) {
7371                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7372                 return False;
7373         }
7374
7375         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7376                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7377                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7378         if (!NT_STATUS_IS_OK(status)) {
7379                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7380                 return False;
7381         }
7382
7383         status = cli_close(cli1, fnum1);
7384         if (!NT_STATUS_IS_OK(status)) {
7385                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7386                 return False;
7387         }
7388
7389         status = cli_close(cli2, fnum2);
7390         if (!NT_STATUS_IS_OK(status)) {
7391                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7392                 return False;
7393         }
7394
7395         printf("non-io open test #2 passed.\n");
7396
7397         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7398
7399         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7400
7401         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7402                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7403                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7404         if (!NT_STATUS_IS_OK(status)) {
7405                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7406                 return False;
7407         }
7408
7409         status = cli_ntcreate(cli2, fname, 0,
7410                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7411                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7412                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7413         if (!NT_STATUS_IS_OK(status)) {
7414                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7415                 return False;
7416         }
7417
7418         status = cli_close(cli1, fnum1);
7419         if (!NT_STATUS_IS_OK(status)) {
7420                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7421                 return False;
7422         }
7423
7424         status = cli_close(cli2, fnum2);
7425         if (!NT_STATUS_IS_OK(status)) {
7426                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7427                 return False;
7428         }
7429
7430         printf("non-io open test #3 passed.\n");
7431
7432         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7433
7434         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7435
7436         status = cli_ntcreate(cli1, fname, 0,
7437                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7438                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7439                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7440         if (!NT_STATUS_IS_OK(status)) {
7441                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7442                 return False;
7443         }
7444
7445         status = cli_ntcreate(cli2, fname, 0,
7446                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7447                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7448                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7449         if (NT_STATUS_IS_OK(status)) {
7450                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7451                 return False;
7452         }
7453
7454         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7455
7456         status = cli_close(cli1, fnum1);
7457         if (!NT_STATUS_IS_OK(status)) {
7458                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7459                 return False;
7460         }
7461
7462         printf("non-io open test #4 passed.\n");
7463
7464         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7465
7466         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7467
7468         status = cli_ntcreate(cli1, fname, 0,
7469                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7470                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7471                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7472         if (!NT_STATUS_IS_OK(status)) {
7473                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7474                 return False;
7475         }
7476
7477         status = cli_ntcreate(cli2, fname, 0,
7478                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7479                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7480                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7481         if (!NT_STATUS_IS_OK(status)) {
7482                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7483                 return False;
7484         }
7485
7486         status = cli_close(cli1, fnum1);
7487         if (!NT_STATUS_IS_OK(status)) {
7488                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7489                 return False;
7490         }
7491
7492         status = cli_close(cli2, fnum2);
7493         if (!NT_STATUS_IS_OK(status)) {
7494                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7495                 return False;
7496         }
7497
7498         printf("non-io open test #5 passed.\n");
7499
7500         printf("TEST #6 testing 1 non-io open, one io open\n");
7501
7502         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7503
7504         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7505                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7506                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7507         if (!NT_STATUS_IS_OK(status)) {
7508                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7509                 return False;
7510         }
7511
7512         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7513                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7514                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7515         if (!NT_STATUS_IS_OK(status)) {
7516                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7517                 return False;
7518         }
7519
7520         status = cli_close(cli1, fnum1);
7521         if (!NT_STATUS_IS_OK(status)) {
7522                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7523                 return False;
7524         }
7525
7526         status = cli_close(cli2, fnum2);
7527         if (!NT_STATUS_IS_OK(status)) {
7528                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7529                 return False;
7530         }
7531
7532         printf("non-io open test #6 passed.\n");
7533
7534         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7535
7536         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7537
7538         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7539                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7540                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7541         if (!NT_STATUS_IS_OK(status)) {
7542                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7543                 return False;
7544         }
7545
7546         status = cli_ntcreate(cli2, fname, 0,
7547                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7548                               FILE_ATTRIBUTE_NORMAL,
7549                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7550                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7551         if (NT_STATUS_IS_OK(status)) {
7552                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7553                 return False;
7554         }
7555
7556         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7557
7558         status = cli_close(cli1, fnum1);
7559         if (!NT_STATUS_IS_OK(status)) {
7560                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7561                 return False;
7562         }
7563
7564         printf("non-io open test #7 passed.\n");
7565
7566         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7567
7568         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7569         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7570                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7571                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7572         if (!NT_STATUS_IS_OK(status)) {
7573                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7574                 correct = false;
7575                 goto out;
7576         }
7577
7578         /* Write to ensure we have to update the file time. */
7579         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7580                               NULL);
7581         if (!NT_STATUS_IS_OK(status)) {
7582                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7583                 correct = false;
7584                 goto out;
7585         }
7586
7587         status = cli_close(cli1, fnum1);
7588         if (!NT_STATUS_IS_OK(status)) {
7589                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7590                 correct = false;
7591         }
7592
7593   out:
7594
7595         if (!torture_close_connection(cli1)) {
7596                 correct = False;
7597         }
7598         if (!torture_close_connection(cli2)) {
7599                 correct = False;
7600         }
7601
7602         return correct;
7603 }
7604
7605 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7606 {
7607         uint16_t major, minor;
7608         uint32_t caplow, caphigh;
7609         NTSTATUS status;
7610
7611         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7612                 printf("Server doesn't support UNIX CIFS extensions.\n");
7613                 return NT_STATUS_NOT_SUPPORTED;
7614         }
7615
7616         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7617                                              &caphigh);
7618         if (!NT_STATUS_IS_OK(status)) {
7619                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7620                        nt_errstr(status));
7621                 return status;
7622         }
7623
7624         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7625                                                       caplow, caphigh);
7626         if (!NT_STATUS_IS_OK(status)) {
7627                 printf("Server doesn't support setting UNIX CIFS extensions: "
7628                        "%s.\n", nt_errstr(status));
7629                 return status;
7630         }
7631
7632         return NT_STATUS_OK;
7633 }
7634
7635 /*
7636   Test POSIX open /mkdir calls.
7637  */
7638 static bool run_simple_posix_open_test(int dummy)
7639 {
7640         static struct cli_state *cli1;
7641         const char *fname = "posix:file";
7642         const char *hname = "posix:hlink";
7643         const char *sname = "posix:symlink";
7644         const char *dname = "posix:dir";
7645         char buf[10];
7646         char *target = NULL;
7647         uint16_t fnum1 = (uint16_t)-1;
7648         SMB_STRUCT_STAT sbuf;
7649         bool correct = false;
7650         NTSTATUS status;
7651         size_t nread;
7652         const char *fname_windows = "windows_file";
7653         uint16_t fnum2 = (uint16_t)-1;
7654
7655         printf("Starting simple POSIX open test\n");
7656
7657         if (!torture_open_connection(&cli1, 0)) {
7658                 return false;
7659         }
7660
7661         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7662
7663         status = torture_setup_unix_extensions(cli1);
7664         if (!NT_STATUS_IS_OK(status)) {
7665                 return false;
7666         }
7667
7668         cli_setatr(cli1, fname, 0, 0);
7669         cli_posix_unlink(cli1, fname);
7670         cli_setatr(cli1, dname, 0, 0);
7671         cli_posix_rmdir(cli1, dname);
7672         cli_setatr(cli1, hname, 0, 0);
7673         cli_posix_unlink(cli1, hname);
7674         cli_setatr(cli1, sname, 0, 0);
7675         cli_posix_unlink(cli1, sname);
7676         cli_setatr(cli1, fname_windows, 0, 0);
7677         cli_posix_unlink(cli1, fname_windows);
7678
7679         /* Create a directory. */
7680         status = cli_posix_mkdir(cli1, dname, 0777);
7681         if (!NT_STATUS_IS_OK(status)) {
7682                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7683                 goto out;
7684         }
7685
7686         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7687                                 0600, &fnum1);
7688         if (!NT_STATUS_IS_OK(status)) {
7689                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7690                 goto out;
7691         }
7692
7693         /* Test ftruncate - set file size. */
7694         status = cli_ftruncate(cli1, fnum1, 1000);
7695         if (!NT_STATUS_IS_OK(status)) {
7696                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7697                 goto out;
7698         }
7699
7700         /* Ensure st_size == 1000 */
7701         status = cli_posix_stat(cli1, fname, &sbuf);
7702         if (!NT_STATUS_IS_OK(status)) {
7703                 printf("stat failed (%s)\n", nt_errstr(status));
7704                 goto out;
7705         }
7706
7707         if (sbuf.st_ex_size != 1000) {
7708                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7709                 goto out;
7710         }
7711
7712         /* Ensure st_mode == 0600 */
7713         if ((sbuf.st_ex_mode & 07777) != 0600) {
7714                 printf("posix_open - bad permissions 0%o != 0600\n",
7715                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7716                 goto out;
7717         }
7718
7719         /* Test ftruncate - set file size back to zero. */
7720         status = cli_ftruncate(cli1, fnum1, 0);
7721         if (!NT_STATUS_IS_OK(status)) {
7722                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7723                 goto out;
7724         }
7725
7726         status = cli_close(cli1, fnum1);
7727         if (!NT_STATUS_IS_OK(status)) {
7728                 printf("close failed (%s)\n", nt_errstr(status));
7729                 goto out;
7730         }
7731
7732         /* Now open the file again for read only. */
7733         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7734         if (!NT_STATUS_IS_OK(status)) {
7735                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7736                 goto out;
7737         }
7738
7739         /* Now unlink while open. */
7740         status = cli_posix_unlink(cli1, fname);
7741         if (!NT_STATUS_IS_OK(status)) {
7742                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7743                 goto out;
7744         }
7745
7746         status = cli_close(cli1, fnum1);
7747         if (!NT_STATUS_IS_OK(status)) {
7748                 printf("close(2) failed (%s)\n", nt_errstr(status));
7749                 goto out;
7750         }
7751
7752         /* Ensure the file has gone. */
7753         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7754         if (NT_STATUS_IS_OK(status)) {
7755                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7756                 goto out;
7757         }
7758
7759         /* Create again to test open with O_TRUNC. */
7760         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7761         if (!NT_STATUS_IS_OK(status)) {
7762                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7763                 goto out;
7764         }
7765
7766         /* Test ftruncate - set file size. */
7767         status = cli_ftruncate(cli1, fnum1, 1000);
7768         if (!NT_STATUS_IS_OK(status)) {
7769                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7770                 goto out;
7771         }
7772
7773         /* Ensure st_size == 1000 */
7774         status = cli_posix_stat(cli1, fname, &sbuf);
7775         if (!NT_STATUS_IS_OK(status)) {
7776                 printf("stat failed (%s)\n", nt_errstr(status));
7777                 goto out;
7778         }
7779
7780         if (sbuf.st_ex_size != 1000) {
7781                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7782                 goto out;
7783         }
7784
7785         status = cli_close(cli1, fnum1);
7786         if (!NT_STATUS_IS_OK(status)) {
7787                 printf("close(2) failed (%s)\n", nt_errstr(status));
7788                 goto out;
7789         }
7790
7791         /* Re-open with O_TRUNC. */
7792         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7793         if (!NT_STATUS_IS_OK(status)) {
7794                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7795                 goto out;
7796         }
7797
7798         /* Ensure st_size == 0 */
7799         status = cli_posix_stat(cli1, fname, &sbuf);
7800         if (!NT_STATUS_IS_OK(status)) {
7801                 printf("stat failed (%s)\n", nt_errstr(status));
7802                 goto out;
7803         }
7804
7805         if (sbuf.st_ex_size != 0) {
7806                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7807                 goto out;
7808         }
7809
7810         status = cli_close(cli1, fnum1);
7811         if (!NT_STATUS_IS_OK(status)) {
7812                 printf("close failed (%s)\n", nt_errstr(status));
7813                 goto out;
7814         }
7815
7816         status = cli_posix_unlink(cli1, fname);
7817         if (!NT_STATUS_IS_OK(status)) {
7818                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7819                 goto out;
7820         }
7821
7822         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7823         if (!NT_STATUS_IS_OK(status)) {
7824                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7825                         dname, nt_errstr(status));
7826                 goto out;
7827         }
7828
7829         cli_close(cli1, fnum1);
7830
7831         /* What happens when we try and POSIX open a directory for write ? */
7832         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7833         if (NT_STATUS_IS_OK(status)) {
7834                 printf("POSIX open of directory %s succeeded, "
7835                        "should have failed.\n",
7836                        dname);
7837                 goto out;
7838         } else {
7839                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7840                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7841                         goto out;
7842                 }
7843         }
7844
7845         /* Create the file. */
7846         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7847                                 0600, &fnum1);
7848         if (!NT_STATUS_IS_OK(status)) {
7849                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7850                 goto out;
7851         }
7852
7853         /* Write some data into it. */
7854         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7855                               NULL);
7856         if (!NT_STATUS_IS_OK(status)) {
7857                 printf("cli_write failed: %s\n", nt_errstr(status));
7858                 goto out;
7859         }
7860
7861         cli_close(cli1, fnum1);
7862
7863         /* Now create a hardlink. */
7864         status = cli_posix_hardlink(cli1, fname, hname);
7865         if (!NT_STATUS_IS_OK(status)) {
7866                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7867                 goto out;
7868         }
7869
7870         /* Now create a symlink. */
7871         status = cli_posix_symlink(cli1, fname, sname);
7872         if (!NT_STATUS_IS_OK(status)) {
7873                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7874                 goto out;
7875         }
7876
7877         /* Open the hardlink for read. */
7878         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7879         if (!NT_STATUS_IS_OK(status)) {
7880                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7881                 goto out;
7882         }
7883
7884         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7885         if (!NT_STATUS_IS_OK(status)) {
7886                 printf("POSIX read of %s failed (%s)\n", hname,
7887                        nt_errstr(status));
7888                 goto out;
7889         } else if (nread != 10) {
7890                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7891                        hname, (unsigned long)nread, 10);
7892                 goto out;
7893         }
7894
7895         if (memcmp(buf, "TEST DATA\n", 10)) {
7896                 printf("invalid data read from hardlink\n");
7897                 goto out;
7898         }
7899
7900         /* Do a POSIX lock/unlock. */
7901         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7902         if (!NT_STATUS_IS_OK(status)) {
7903                 printf("POSIX lock failed %s\n", nt_errstr(status));
7904                 goto out;
7905         }
7906
7907         /* Punch a hole in the locked area. */
7908         status = cli_posix_unlock(cli1, fnum1, 10, 80);
7909         if (!NT_STATUS_IS_OK(status)) {
7910                 printf("POSIX unlock failed %s\n", nt_errstr(status));
7911                 goto out;
7912         }
7913
7914         cli_close(cli1, fnum1);
7915
7916         /* Open the symlink for read - this should fail. A POSIX
7917            client should not be doing opens on a symlink. */
7918         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7919         if (NT_STATUS_IS_OK(status)) {
7920                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7921                 goto out;
7922         } else {
7923                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7924                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7925                         printf("POSIX open of %s should have failed "
7926                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7927                                 "failed with %s instead.\n",
7928                                 sname, nt_errstr(status));
7929                         goto out;
7930                 }
7931         }
7932
7933         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7934         if (!NT_STATUS_IS_OK(status)) {
7935                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7936                 goto out;
7937         }
7938
7939         if (strcmp(target, fname) != 0) {
7940                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7941                         sname, fname, target);
7942                 goto out;
7943         }
7944
7945         status = cli_posix_rmdir(cli1, dname);
7946         if (!NT_STATUS_IS_OK(status)) {
7947                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7948                 goto out;
7949         }
7950
7951         /* Check directory opens with a specific permission. */
7952         status = cli_posix_mkdir(cli1, dname, 0700);
7953         if (!NT_STATUS_IS_OK(status)) {
7954                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7955                 goto out;
7956         }
7957
7958         /* Ensure st_mode == 0700 */
7959         status = cli_posix_stat(cli1, dname, &sbuf);
7960         if (!NT_STATUS_IS_OK(status)) {
7961                 printf("stat failed (%s)\n", nt_errstr(status));
7962                 goto out;
7963         }
7964
7965         if ((sbuf.st_ex_mode & 07777) != 0700) {
7966                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7967                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7968                 goto out;
7969         }
7970
7971         /*
7972          * Now create a Windows file, and attempt a POSIX unlink.
7973          * This should fail with a sharing violation but due to:
7974          *
7975          * [Bug 9571] Unlink after open causes smbd to panic
7976          *
7977          * ensure we've fixed the lock ordering violation.
7978          */
7979
7980         status = cli_ntcreate(cli1, fname_windows, 0,
7981                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
7982                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7983                         FILE_CREATE,
7984                         0x0, 0x0, &fnum2, NULL);
7985         if (!NT_STATUS_IS_OK(status)) {
7986                 printf("Windows create of %s failed (%s)\n", fname_windows,
7987                         nt_errstr(status));
7988                 goto out;
7989         }
7990
7991         /* Now try posix_unlink. */
7992         status = cli_posix_unlink(cli1, fname_windows);
7993         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7994                 printf("POSIX unlink of %s should fail "
7995                         "with NT_STATUS_SHARING_VIOLATION "
7996                         "got %s instead !\n",
7997                         fname_windows,
7998                         nt_errstr(status));
7999                 goto out;
8000         }
8001
8002         cli_close(cli1, fnum2);
8003
8004         printf("Simple POSIX open test passed\n");
8005         correct = true;
8006
8007   out:
8008
8009         if (fnum1 != (uint16_t)-1) {
8010                 cli_close(cli1, fnum1);
8011                 fnum1 = (uint16_t)-1;
8012         }
8013
8014         if (fnum2 != (uint16_t)-1) {
8015                 cli_close(cli1, fnum2);
8016                 fnum2 = (uint16_t)-1;
8017         }
8018
8019         cli_setatr(cli1, sname, 0, 0);
8020         cli_posix_unlink(cli1, sname);
8021         cli_setatr(cli1, hname, 0, 0);
8022         cli_posix_unlink(cli1, hname);
8023         cli_setatr(cli1, fname, 0, 0);
8024         cli_posix_unlink(cli1, fname);
8025         cli_setatr(cli1, dname, 0, 0);
8026         cli_posix_rmdir(cli1, dname);
8027         cli_setatr(cli1, fname_windows, 0, 0);
8028         cli_posix_unlink(cli1, fname_windows);
8029
8030         if (!torture_close_connection(cli1)) {
8031                 correct = false;
8032         }
8033
8034         return correct;
8035 }
8036
8037 /*
8038   Test POSIX and Windows ACLs are rejected on symlinks.
8039  */
8040 static bool run_acl_symlink_test(int dummy)
8041 {
8042         static struct cli_state *cli;
8043         const char *fname = "posix_file";
8044         const char *sname = "posix_symlink";
8045         uint16_t fnum = (uint16_t)-1;
8046         bool correct = false;
8047         NTSTATUS status;
8048         char *posix_acl = NULL;
8049         size_t posix_acl_len = 0;
8050         char *posix_acl_sym = NULL;
8051         size_t posix_acl_len_sym = 0;
8052         struct security_descriptor *sd = NULL;
8053         TALLOC_CTX *frame = NULL;
8054
8055         frame = talloc_stackframe();
8056
8057         printf("Starting acl symlink test\n");
8058
8059         if (!torture_open_connection(&cli, 0)) {
8060                 TALLOC_FREE(frame);
8061                 return false;
8062         }
8063
8064         smbXcli_conn_set_sockopt(cli->conn, sockops);
8065
8066         status = torture_setup_unix_extensions(cli);
8067         if (!NT_STATUS_IS_OK(status)) {
8068                 TALLOC_FREE(frame);
8069                 return false;
8070         }
8071
8072         cli_setatr(cli, fname, 0, 0);
8073         cli_posix_unlink(cli, fname);
8074         cli_setatr(cli, sname, 0, 0);
8075         cli_posix_unlink(cli, sname);
8076
8077         status = cli_ntcreate(cli,
8078                         fname,
8079                         0,
8080                         READ_CONTROL_ACCESS,
8081                         0,
8082                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8083                         FILE_CREATE,
8084                         0x0,
8085                         0x0,
8086                         &fnum,
8087                         NULL);
8088
8089         if (!NT_STATUS_IS_OK(status)) {
8090                 printf("cli_ntcreate of %s failed (%s)\n",
8091                         fname,
8092                         nt_errstr(status));
8093                 goto out;
8094         }
8095
8096         /* Get the Windows ACL on the file. */
8097         status = cli_query_secdesc(cli,
8098                                 fnum,
8099                                 frame,
8100                                 &sd);
8101         if (!NT_STATUS_IS_OK(status)) {
8102                 printf("cli_query_secdesc failed (%s)\n",
8103                         nt_errstr(status));
8104                 goto out;
8105         }
8106
8107         /* Get the POSIX ACL on the file. */
8108         status = cli_posix_getacl(cli,
8109                                 fname,
8110                                 frame,
8111                                 &posix_acl_len,
8112                                 &posix_acl);
8113
8114         if (!NT_STATUS_IS_OK(status)) {
8115                 printf("cli_posix_getacl failed (%s)\n",
8116                         nt_errstr(status));
8117                 goto out;
8118         }
8119
8120         status = cli_close(cli, fnum);
8121         if (!NT_STATUS_IS_OK(status)) {
8122                 printf("close failed (%s)\n", nt_errstr(status));
8123                 goto out;
8124         }
8125         fnum = (uint16_t)-1;
8126
8127         /* Now create a symlink. */
8128         status = cli_posix_symlink(cli, fname, sname);
8129         if (!NT_STATUS_IS_OK(status)) {
8130                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8131                         sname,
8132                         fname,
8133                         nt_errstr(status));
8134                 goto out;
8135         }
8136
8137         /* Open a handle on the symlink for SD set/get should fail. */
8138         status = cli_ntcreate(cli,
8139                         sname,
8140                         0,
8141                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8142                         0,
8143                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8144                         FILE_OPEN,
8145                         0x0,
8146                         0x0,
8147                         &fnum,
8148                         NULL);
8149
8150         if (NT_STATUS_IS_OK(status)) {
8151                 printf("Symlink open for getsd/setsd of %s "
8152                         "succeeded (should fail)\n",
8153                         sname);
8154                 goto out;
8155         }
8156
8157         /* Try a stat-open on the symlink, should also fail. */
8158         status = cli_ntcreate(cli,
8159                         sname,
8160                         0,
8161                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8162                         0,
8163                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8164                         FILE_OPEN,
8165                         0x0,
8166                         0x0,
8167                         &fnum,
8168                         NULL);
8169
8170         if (NT_STATUS_IS_OK(status)) {
8171                 printf("Stat-open of symlink succeeded (should fail)\n");
8172                 goto out;
8173         }
8174
8175         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8176         status = cli_posix_getacl(cli,
8177                                 sname,
8178                                 frame,
8179                                 &posix_acl_len_sym,
8180                                 &posix_acl_sym);
8181
8182         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8183                 printf("cli_posix_getacl on a symlink gave %s. "
8184                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8185                         nt_errstr(status));
8186                 goto out;
8187         }
8188
8189         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8190         status = cli_posix_setacl(cli,
8191                                 sname,
8192                                 posix_acl,
8193                                 posix_acl_len);
8194
8195         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8196                 printf("cli_posix_setacl on a symlink gave %s. "
8197                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8198                         nt_errstr(status));
8199                 goto out;
8200         }
8201
8202         printf("ACL symlink test passed\n");
8203         correct = true;
8204
8205   out:
8206
8207         if (fnum != (uint16_t)-1) {
8208                 cli_close(cli, fnum);
8209                 fnum = (uint16_t)-1;
8210         }
8211
8212         cli_setatr(cli, sname, 0, 0);
8213         cli_posix_unlink(cli, sname);
8214         cli_setatr(cli, fname, 0, 0);
8215         cli_posix_unlink(cli, fname);
8216
8217         if (!torture_close_connection(cli)) {
8218                 correct = false;
8219         }
8220
8221         TALLOC_FREE(frame);
8222         return correct;
8223 }
8224
8225 /*
8226   Test POSIX can delete a file containing streams.
8227  */
8228 static bool run_posix_stream_delete(int dummy)
8229 {
8230         struct cli_state *cli1 = NULL;
8231         struct cli_state *cli2 = NULL;
8232         const char *fname = "streamfile";
8233         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8234         uint16_t fnum1 = (uint16_t)-1;
8235         bool correct = false;
8236         NTSTATUS status;
8237         TALLOC_CTX *frame = NULL;
8238
8239         frame = talloc_stackframe();
8240
8241         printf("Starting POSIX stream delete test\n");
8242
8243         if (!torture_open_connection(&cli1, 0) ||
8244                         !torture_open_connection(&cli2, 1)) {
8245                 TALLOC_FREE(frame);
8246                 return false;
8247         }
8248
8249         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8250         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8251
8252         status = torture_setup_unix_extensions(cli2);
8253         if (!NT_STATUS_IS_OK(status)) {
8254                 goto out;
8255         }
8256
8257         cli_setatr(cli1, fname, 0, 0);
8258         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8259
8260         /* Create the file. */
8261         status = cli_ntcreate(cli1,
8262                         fname,
8263                         0,
8264                         READ_CONTROL_ACCESS,
8265                         0,
8266                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8267                         FILE_CREATE,
8268                         0x0,
8269                         0x0,
8270                         &fnum1,
8271                         NULL);
8272
8273         if (!NT_STATUS_IS_OK(status)) {
8274                 printf("cli_ntcreate of %s failed (%s)\n",
8275                         fname,
8276                         nt_errstr(status));
8277                 goto out;
8278         }
8279
8280         status = cli_close(cli1, fnum1);
8281         if (!NT_STATUS_IS_OK(status)) {
8282                 printf("cli_close of %s failed (%s)\n",
8283                         fname,
8284                         nt_errstr(status));
8285                 goto out;
8286         }
8287         fnum1 = (uint16_t)-1;
8288
8289         /* Now create the stream. */
8290         status = cli_ntcreate(cli1,
8291                         stream_fname,
8292                         0,
8293                         FILE_WRITE_DATA,
8294                         0,
8295                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8296                         FILE_CREATE,
8297                         0x0,
8298                         0x0,
8299                         &fnum1,
8300                         NULL);
8301
8302         if (!NT_STATUS_IS_OK(status)) {
8303                 printf("cli_ntcreate of %s failed (%s)\n",
8304                         stream_fname,
8305                         nt_errstr(status));
8306                 goto out;
8307         }
8308
8309         /* Leave the stream handle open... */
8310
8311         /* POSIX unlink should fail. */
8312         status = cli_posix_unlink(cli2, fname);
8313         if (NT_STATUS_IS_OK(status)) {
8314                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8315                         fname);
8316                 goto out;
8317         }
8318
8319         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8320                 printf("cli_posix_unlink of %s failed with (%s) "
8321                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8322                         fname,
8323                         nt_errstr(status));
8324                 goto out;
8325         }
8326
8327         /* Close the stream handle. */
8328         status = cli_close(cli1, fnum1);
8329         if (!NT_STATUS_IS_OK(status)) {
8330                 printf("cli_close of %s failed (%s)\n",
8331                         stream_fname,
8332                         nt_errstr(status));
8333                 goto out;
8334         }
8335         fnum1 = (uint16_t)-1;
8336
8337         /* POSIX unlink after stream handle closed should succeed. */
8338         status = cli_posix_unlink(cli2, fname);
8339         if (!NT_STATUS_IS_OK(status)) {
8340                 printf("cli_posix_unlink of %s failed (%s)\n",
8341                         fname,
8342                         nt_errstr(status));
8343                 goto out;
8344         }
8345
8346         printf("POSIX stream delete test passed\n");
8347         correct = true;
8348
8349   out:
8350
8351         if (fnum1 != (uint16_t)-1) {
8352                 cli_close(cli1, fnum1);
8353                 fnum1 = (uint16_t)-1;
8354         }
8355
8356         cli_setatr(cli1, fname, 0, 0);
8357         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8358
8359         if (!torture_close_connection(cli1)) {
8360                 correct = false;
8361         }
8362         if (!torture_close_connection(cli2)) {
8363                 correct = false;
8364         }
8365
8366         TALLOC_FREE(frame);
8367         return correct;
8368 }
8369
8370 /*
8371   Test setting EA's are rejected on symlinks.
8372  */
8373 static bool run_ea_symlink_test(int dummy)
8374 {
8375         static struct cli_state *cli;
8376         const char *fname = "posix_file_ea";
8377         const char *sname = "posix_symlink_ea";
8378         const char *ea_name = "testea_name";
8379         const char *ea_value = "testea_value";
8380         uint16_t fnum = (uint16_t)-1;
8381         bool correct = false;
8382         NTSTATUS status;
8383         size_t i, num_eas;
8384         struct ea_struct *eas = NULL;
8385         TALLOC_CTX *frame = NULL;
8386
8387         frame = talloc_stackframe();
8388
8389         printf("Starting EA symlink test\n");
8390
8391         if (!torture_open_connection(&cli, 0)) {
8392                 TALLOC_FREE(frame);
8393                 return false;
8394         }
8395
8396         smbXcli_conn_set_sockopt(cli->conn, sockops);
8397
8398         status = torture_setup_unix_extensions(cli);
8399         if (!NT_STATUS_IS_OK(status)) {
8400                 TALLOC_FREE(frame);
8401                 return false;
8402         }
8403
8404         cli_setatr(cli, fname, 0, 0);
8405         cli_posix_unlink(cli, fname);
8406         cli_setatr(cli, sname, 0, 0);
8407         cli_posix_unlink(cli, sname);
8408
8409         status = cli_ntcreate(cli,
8410                         fname,
8411                         0,
8412                         READ_CONTROL_ACCESS,
8413                         0,
8414                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8415                         FILE_CREATE,
8416                         0x0,
8417                         0x0,
8418                         &fnum,
8419                         NULL);
8420
8421         if (!NT_STATUS_IS_OK(status)) {
8422                 printf("cli_ntcreate of %s failed (%s)\n",
8423                         fname,
8424                         nt_errstr(status));
8425                 goto out;
8426         }
8427
8428         status = cli_close(cli, fnum);
8429         if (!NT_STATUS_IS_OK(status)) {
8430                 printf("close failed (%s)\n",
8431                         nt_errstr(status));
8432                 goto out;
8433         }
8434         fnum = (uint16_t)-1;
8435
8436         /* Set an EA on the path. */
8437         status = cli_set_ea_path(cli,
8438                                 fname,
8439                                 ea_name,
8440                                 ea_value,
8441                                 strlen(ea_value)+1);
8442
8443         if (!NT_STATUS_IS_OK(status)) {
8444                 printf("cli_set_ea_path failed (%s)\n",
8445                         nt_errstr(status));
8446                 goto out;
8447         }
8448
8449         /* Now create a symlink. */
8450         status = cli_posix_symlink(cli, fname, sname);
8451         if (!NT_STATUS_IS_OK(status)) {
8452                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8453                         sname,
8454                         fname,
8455                         nt_errstr(status));
8456                 goto out;
8457         }
8458
8459         /* Get the EA list on the path. Should return value set. */
8460         status = cli_get_ea_list_path(cli,
8461                                 fname,
8462                                 frame,
8463                                 &num_eas,
8464                                 &eas);
8465
8466         if (!NT_STATUS_IS_OK(status)) {
8467                 printf("cli_get_ea_list_path failed (%s)\n",
8468                         nt_errstr(status));
8469                 goto out;
8470         }
8471
8472         /* Ensure the EA we set is there. */
8473         for (i=0; i<num_eas; i++) {
8474                 if (strcmp(eas[i].name, ea_name) == 0 &&
8475                                 eas[i].value.length == strlen(ea_value)+1 &&
8476                                 memcmp(eas[i].value.data,
8477                                         ea_value,
8478                                         eas[i].value.length) == 0) {
8479                         break;
8480                 }
8481         }
8482
8483         if (i == num_eas) {
8484                 printf("Didn't find EA on pathname %s\n",
8485                         fname);
8486                 goto out;
8487         }
8488
8489         num_eas = 0;
8490         TALLOC_FREE(eas);
8491
8492         /* Get the EA list on the symlink. Should return empty list. */
8493         status = cli_get_ea_list_path(cli,
8494                                 sname,
8495                                 frame,
8496                                 &num_eas,
8497                                 &eas);
8498
8499         if (!NT_STATUS_IS_OK(status)) {
8500                 printf("cli_get_ea_list_path failed (%s)\n",
8501                         nt_errstr(status));
8502                 goto out;
8503         }
8504
8505         if (num_eas != 0) {
8506                 printf("cli_get_ea_list_path failed (%s)\n",
8507                         nt_errstr(status));
8508                 goto out;
8509         }
8510
8511         /* Set an EA on the symlink. Should fail. */
8512         status = cli_set_ea_path(cli,
8513                                 sname,
8514                                 ea_name,
8515                                 ea_value,
8516                                 strlen(ea_value)+1);
8517
8518         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8519                 printf("cli_set_ea_path on a symlink gave %s. "
8520                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8521                         nt_errstr(status));
8522                 goto out;
8523         }
8524
8525         printf("EA symlink test passed\n");
8526         correct = true;
8527
8528   out:
8529
8530         if (fnum != (uint16_t)-1) {
8531                 cli_close(cli, fnum);
8532                 fnum = (uint16_t)-1;
8533         }
8534
8535         cli_setatr(cli, sname, 0, 0);
8536         cli_posix_unlink(cli, sname);
8537         cli_setatr(cli, fname, 0, 0);
8538         cli_posix_unlink(cli, fname);
8539
8540         if (!torture_close_connection(cli)) {
8541                 correct = false;
8542         }
8543
8544         TALLOC_FREE(frame);
8545         return correct;
8546 }
8547
8548 /*
8549   Test POSIX locks are OFD-locks.
8550  */
8551 static bool run_posix_ofd_lock_test(int dummy)
8552 {
8553         static struct cli_state *cli;
8554         const char *fname = "posix_file";
8555         uint16_t fnum1 = (uint16_t)-1;
8556         uint16_t fnum2 = (uint16_t)-1;
8557         bool correct = false;
8558         NTSTATUS status;
8559         TALLOC_CTX *frame = NULL;
8560
8561         frame = talloc_stackframe();
8562
8563         printf("Starting POSIX ofd-lock test\n");
8564
8565         if (!torture_open_connection(&cli, 0)) {
8566                 TALLOC_FREE(frame);
8567                 return false;
8568         }
8569
8570         smbXcli_conn_set_sockopt(cli->conn, sockops);
8571
8572         status = torture_setup_unix_extensions(cli);
8573         if (!NT_STATUS_IS_OK(status)) {
8574                 TALLOC_FREE(frame);
8575                 return false;
8576         }
8577
8578         cli_setatr(cli, fname, 0, 0);
8579         cli_posix_unlink(cli, fname);
8580
8581         /* Open the file twice. */
8582         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8583                                 0600, &fnum1);
8584         if (!NT_STATUS_IS_OK(status)) {
8585                 printf("First POSIX open of %s failed\n", fname);
8586                 goto out;
8587         }
8588
8589         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8590         if (!NT_STATUS_IS_OK(status)) {
8591                 printf("First POSIX open of %s failed\n", fname);
8592                 goto out;
8593         }
8594
8595         /* Set a 0-50 lock on fnum1. */
8596         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8597         if (!NT_STATUS_IS_OK(status)) {
8598                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8599                 goto out;
8600         }
8601
8602         /* Set a 60-100 lock on fnum2. */
8603         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8604         if (!NT_STATUS_IS_OK(status)) {
8605                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8606                 goto out;
8607         }
8608
8609         /* close fnum1 - 0-50 lock should go away. */
8610         status = cli_close(cli, fnum1);
8611         if (!NT_STATUS_IS_OK(status)) {
8612                 printf("close failed (%s)\n",
8613                         nt_errstr(status));
8614                 goto out;
8615         }
8616         fnum1 = (uint16_t)-1;
8617
8618         /* Change the lock context. */
8619         cli_setpid(cli, cli_getpid(cli) + 1);
8620
8621         /* Re-open fnum1. */
8622         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8623         if (!NT_STATUS_IS_OK(status)) {
8624                 printf("Third POSIX open of %s failed\n", fname);
8625                 goto out;
8626         }
8627
8628         /* 60-100 lock should still be there. */
8629         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8630         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8631                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8632                 goto out;
8633         }
8634
8635         /* 0-50 lock should be gone. */
8636         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8637         if (!NT_STATUS_IS_OK(status)) {
8638                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8639                 goto out;
8640         }
8641
8642         printf("POSIX OFD lock test passed\n");
8643         correct = true;
8644
8645   out:
8646
8647         if (fnum1 != (uint16_t)-1) {
8648                 cli_close(cli, fnum1);
8649                 fnum1 = (uint16_t)-1;
8650         }
8651         if (fnum2 != (uint16_t)-1) {
8652                 cli_close(cli, fnum2);
8653                 fnum2 = (uint16_t)-1;
8654         }
8655
8656         cli_setatr(cli, fname, 0, 0);
8657         cli_posix_unlink(cli, fname);
8658
8659         if (!torture_close_connection(cli)) {
8660                 correct = false;
8661         }
8662
8663         TALLOC_FREE(frame);
8664         return correct;
8665 }
8666
8667 struct posix_blocking_state {
8668         struct tevent_context *ev;
8669         struct cli_state *cli1;
8670         uint16_t fnum1;
8671         struct cli_state *cli2;
8672         uint16_t fnum2;
8673         bool gotblocked;
8674         bool gotecho;
8675 };
8676
8677 static void posix_blocking_locked(struct tevent_req *subreq);
8678 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8679 static void posix_blocking_gotecho(struct tevent_req *subreq);
8680 static void posix_blocking_unlocked(struct tevent_req *subreq);
8681
8682 static struct tevent_req *posix_blocking_send(
8683         TALLOC_CTX *mem_ctx,
8684         struct tevent_context *ev,
8685         struct cli_state *cli1,
8686         uint16_t fnum1,
8687         struct cli_state *cli2,
8688         uint16_t fnum2)
8689 {
8690         struct tevent_req *req = NULL, *subreq = NULL;
8691         struct posix_blocking_state *state = NULL;
8692
8693         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8694         if (req == NULL) {
8695                 return NULL;
8696         }
8697         state->ev = ev;
8698         state->cli1 = cli1;
8699         state->fnum1 = fnum1;
8700         state->cli2 = cli2;
8701         state->fnum2 = fnum2;
8702
8703         subreq = cli_posix_lock_send(
8704                 state,
8705                 state->ev,
8706                 state->cli1,
8707                 state->fnum1,
8708                 0,
8709                 1,
8710                 false,
8711                 WRITE_LOCK);
8712         if (tevent_req_nomem(subreq, req)) {
8713                 return tevent_req_post(req, ev);
8714         }
8715         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8716         return req;
8717 }
8718
8719 static void posix_blocking_locked(struct tevent_req *subreq)
8720 {
8721         struct tevent_req *req = tevent_req_callback_data(
8722                 subreq, struct tevent_req);
8723         struct posix_blocking_state *state = tevent_req_data(
8724                 req, struct posix_blocking_state);
8725         NTSTATUS status;
8726
8727         status = cli_posix_lock_recv(subreq);
8728         TALLOC_FREE(subreq);
8729         if (tevent_req_nterror(req, status)) {
8730                 return;
8731         }
8732
8733         subreq = cli_posix_lock_send(
8734                 state,
8735                 state->ev,
8736                 state->cli2,
8737                 state->fnum2,
8738                 0,
8739                 1,
8740                 true,
8741                 WRITE_LOCK);
8742         if (tevent_req_nomem(subreq, req)) {
8743                 return;
8744         }
8745         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8746
8747         /* Make sure the blocking request is delivered */
8748         subreq = cli_echo_send(
8749                 state,
8750                 state->ev,
8751                 state->cli2,
8752                 1,
8753                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8754         if (tevent_req_nomem(subreq, req)) {
8755                 return;
8756         }
8757         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8758 }
8759
8760 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8761 {
8762         struct tevent_req *req = tevent_req_callback_data(
8763                 subreq, struct tevent_req);
8764         struct posix_blocking_state *state = tevent_req_data(
8765                 req, struct posix_blocking_state);
8766         NTSTATUS status;
8767
8768         status = cli_posix_lock_recv(subreq);
8769         TALLOC_FREE(subreq);
8770         if (tevent_req_nterror(req, status)) {
8771                 return;
8772         }
8773         if (!state->gotecho) {
8774                 printf("blocked req got through before echo\n");
8775                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8776                 return;
8777         }
8778         tevent_req_done(req);
8779 }
8780
8781 static void posix_blocking_gotecho(struct tevent_req *subreq)
8782 {
8783         struct tevent_req *req = tevent_req_callback_data(
8784                 subreq, struct tevent_req);
8785         struct posix_blocking_state *state = tevent_req_data(
8786                 req, struct posix_blocking_state);
8787         NTSTATUS status;
8788
8789         status = cli_echo_recv(subreq);
8790         TALLOC_FREE(subreq);
8791         if (tevent_req_nterror(req, status)) {
8792                 return;
8793         }
8794         if (state->gotblocked) {
8795                 printf("blocked req got through before echo\n");
8796                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8797                 return;
8798         }
8799         state->gotecho = true;
8800
8801         subreq = cli_posix_lock_send(
8802                 state,
8803                 state->ev,
8804                 state->cli1,
8805                 state->fnum1,
8806                 0,
8807                 1,
8808                 false,
8809                 UNLOCK_LOCK);
8810         if (tevent_req_nomem(subreq, req)) {
8811                 return;
8812         }
8813         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8814 }
8815
8816 static void posix_blocking_unlocked(struct tevent_req *subreq)
8817 {
8818         struct tevent_req *req = tevent_req_callback_data(
8819                 subreq, struct tevent_req);
8820         NTSTATUS status;
8821
8822         status = cli_posix_lock_recv(subreq);
8823         TALLOC_FREE(subreq);
8824         if (tevent_req_nterror(req, status)) {
8825                 return;
8826         }
8827         /* tevent_req_done in posix_blocking_gotlocked */
8828 }
8829
8830 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8831 {
8832         return tevent_req_simple_recv_ntstatus(req);
8833 }
8834
8835 static bool run_posix_blocking_lock(int dummy)
8836 {
8837         struct tevent_context *ev = NULL;
8838         struct cli_state *cli1 = NULL, *cli2 = NULL;
8839         const char *fname = "posix_blocking";
8840         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8841         struct tevent_req *req = NULL;
8842         NTSTATUS status;
8843         bool ret = false;
8844         bool ok;
8845
8846         printf("Starting posix blocking lock test\n");
8847
8848         ev = samba_tevent_context_init(NULL);
8849         if (ev == NULL) {
8850                 return false;
8851         }
8852
8853         ok = torture_open_connection(&cli1, 0);
8854         if (!ok) {
8855                 goto fail;
8856         }
8857         ok = torture_open_connection(&cli2, 0);
8858         if (!ok) {
8859                 goto fail;
8860         }
8861
8862         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8863
8864         status = torture_setup_unix_extensions(cli1);
8865         if (!NT_STATUS_IS_OK(status)) {
8866                 return false;
8867         }
8868
8869         cli_setatr(cli1, fname, 0, 0);
8870         cli_posix_unlink(cli1, fname);
8871
8872         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8873                                 0600, &fnum1);
8874         if (!NT_STATUS_IS_OK(status)) {
8875                 printf("First POSIX open of %s failed: %s\n",
8876                        fname,
8877                        nt_errstr(status));
8878                 goto fail;
8879         }
8880
8881         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8882         if (!NT_STATUS_IS_OK(status)) {
8883                 printf("Second POSIX open of %s failed: %s\n",
8884                        fname,
8885                        nt_errstr(status));
8886                 goto fail;
8887         }
8888
8889         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8890         if (req == NULL) {
8891                 printf("cli_posix_blocking failed\n");
8892                 goto fail;
8893         }
8894
8895         ok = tevent_req_poll_ntstatus(req, ev, &status);
8896         if (!ok) {
8897                 printf("tevent_req_poll_ntstatus failed: %s\n",
8898                        nt_errstr(status));
8899                 goto fail;
8900         }
8901         status = posix_blocking_recv(req);
8902         TALLOC_FREE(req);
8903         if (!NT_STATUS_IS_OK(status)) {
8904                 printf("posix_blocking_recv returned %s\n",
8905                        nt_errstr(status));
8906                 goto fail;
8907         }
8908
8909         ret = true;
8910 fail:
8911
8912         if (fnum1 != UINT16_MAX) {
8913                 cli_close(cli1, fnum1);
8914                 fnum1 = UINT16_MAX;
8915         }
8916         if (fnum2 != UINT16_MAX) {
8917                 cli_close(cli2, fnum2);
8918                 fnum2 = UINT16_MAX;
8919         }
8920
8921         if (cli1 != NULL) {
8922                 cli_setatr(cli1, fname, 0, 0);
8923                 cli_posix_unlink(cli1, fname);
8924         }
8925
8926         ok = true;
8927
8928         if (cli1 != NULL) {
8929                 ok &= torture_close_connection(cli1);
8930                 cli1 = NULL;
8931         }
8932         if (cli2 != NULL) {
8933                 ok &= torture_close_connection(cli2);
8934                 cli2 = NULL;
8935         }
8936
8937         if (!ok) {
8938                 ret = false;
8939         }
8940         TALLOC_FREE(ev);
8941         return ret;
8942 }
8943
8944 /*
8945   Test POSIX mkdir is case-sensitive.
8946  */
8947 static bool run_posix_mkdir_test(int dummy)
8948 {
8949         static struct cli_state *cli;
8950         const char *fname_foo = "POSIX_foo";
8951         const char *fname_foo_Foo = "POSIX_foo/Foo";
8952         const char *fname_foo_foo = "POSIX_foo/foo";
8953         const char *fname_Foo = "POSIX_Foo";
8954         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8955         const char *fname_Foo_foo = "POSIX_Foo/foo";
8956         bool correct = false;
8957         NTSTATUS status;
8958         TALLOC_CTX *frame = NULL;
8959         uint16_t fnum = (uint16_t)-1;
8960
8961         frame = talloc_stackframe();
8962
8963         printf("Starting POSIX mkdir test\n");
8964
8965         if (!torture_open_connection(&cli, 0)) {
8966                 TALLOC_FREE(frame);
8967                 return false;
8968         }
8969
8970         smbXcli_conn_set_sockopt(cli->conn, sockops);
8971
8972         status = torture_setup_unix_extensions(cli);
8973         if (!NT_STATUS_IS_OK(status)) {
8974                 TALLOC_FREE(frame);
8975                 return false;
8976         }
8977
8978         cli_posix_rmdir(cli, fname_foo_foo);
8979         cli_posix_rmdir(cli, fname_foo_Foo);
8980         cli_posix_rmdir(cli, fname_foo);
8981
8982         cli_posix_rmdir(cli, fname_Foo_foo);
8983         cli_posix_rmdir(cli, fname_Foo_Foo);
8984         cli_posix_rmdir(cli, fname_Foo);
8985
8986         /*
8987          * Create a file POSIX_foo then try
8988          * and use it in a directory path by
8989          * doing mkdir POSIX_foo/bar.
8990          * The mkdir should fail with
8991          * NT_STATUS_OBJECT_PATH_NOT_FOUND
8992          */
8993
8994         status = cli_posix_open(cli,
8995                         fname_foo,
8996                         O_RDWR|O_CREAT,
8997                         0666,
8998                         &fnum);
8999         if (!NT_STATUS_IS_OK(status)) {
9000                 printf("cli_posix_open of %s failed error %s\n",
9001                         fname_foo,
9002                         nt_errstr(status));
9003                 goto out;
9004         }
9005
9006         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9007         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9008                 printf("cli_posix_mkdir of %s should fail with "
9009                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9010                         "%s instead\n",
9011                         fname_foo_foo,
9012                         nt_errstr(status));
9013                 goto out;
9014         }
9015
9016         status = cli_close(cli, fnum);
9017         if (!NT_STATUS_IS_OK(status)) {
9018                 printf("cli_close failed %s\n", nt_errstr(status));
9019                 goto out;
9020         }
9021         fnum = (uint16_t)-1;
9022
9023         status = cli_posix_unlink(cli, fname_foo);
9024         if (!NT_STATUS_IS_OK(status)) {
9025                 printf("cli_posix_unlink of %s failed error %s\n",
9026                         fname_foo,
9027                         nt_errstr(status));
9028                 goto out;
9029         }
9030
9031         /*
9032          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9033          * posix_open, posix_unlink, on
9034          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9035          * not silently create POSIX_foo/foo.
9036          */
9037
9038         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9039         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9040                 printf("cli_posix_mkdir of %s should fail with "
9041                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9042                         "%s instead\n",
9043                         fname_foo_foo,
9044                         nt_errstr(status));
9045                 goto out;
9046         }
9047
9048         status = cli_posix_rmdir(cli, fname_foo_foo);
9049         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9050                 printf("cli_posix_rmdir of %s should fail with "
9051                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9052                         "%s instead\n",
9053                         fname_foo_foo,
9054                         nt_errstr(status));
9055                 goto out;
9056         }
9057
9058         status = cli_posix_open(cli,
9059                         fname_foo_foo,
9060                         O_RDWR|O_CREAT,
9061                         0666,
9062                         &fnum);
9063         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9064                 printf("cli_posix_open of %s should fail with "
9065                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9066                         "%s instead\n",
9067                         fname_foo_foo,
9068                         nt_errstr(status));
9069                 goto out;
9070         }
9071
9072         status = cli_posix_unlink(cli, fname_foo_foo);
9073         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9074                 printf("cli_posix_unlink of %s should fail with "
9075                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9076                         "%s instead\n",
9077                         fname_foo_foo,
9078                         nt_errstr(status));
9079                 goto out;
9080         }
9081
9082         status = cli_posix_mkdir(cli, fname_foo, 0777);
9083         if (!NT_STATUS_IS_OK(status)) {
9084                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9085                 goto out;
9086         }
9087
9088         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9089         if (!NT_STATUS_IS_OK(status)) {
9090                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9091                 goto out;
9092         }
9093
9094         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9095         if (!NT_STATUS_IS_OK(status)) {
9096                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9097                 goto out;
9098         }
9099
9100         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9101         if (!NT_STATUS_IS_OK(status)) {
9102                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9103                 goto out;
9104         }
9105
9106         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9107         if (!NT_STATUS_IS_OK(status)) {
9108                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9109                 goto out;
9110         }
9111
9112         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9113         if (!NT_STATUS_IS_OK(status)) {
9114                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9115                 goto out;
9116         }
9117
9118         printf("POSIX mkdir test passed\n");
9119         correct = true;
9120
9121   out:
9122
9123         if (fnum != (uint16_t)-1) {
9124                 cli_close(cli, fnum);
9125                 fnum = (uint16_t)-1;
9126         }
9127
9128         cli_posix_rmdir(cli, fname_foo_foo);
9129         cli_posix_rmdir(cli, fname_foo_Foo);
9130         cli_posix_rmdir(cli, fname_foo);
9131
9132         cli_posix_rmdir(cli, fname_Foo_foo);
9133         cli_posix_rmdir(cli, fname_Foo_Foo);
9134         cli_posix_rmdir(cli, fname_Foo);
9135
9136         if (!torture_close_connection(cli)) {
9137                 correct = false;
9138         }
9139
9140         TALLOC_FREE(frame);
9141         return correct;
9142 }
9143
9144 struct posix_acl_oplock_state {
9145         struct tevent_context *ev;
9146         struct cli_state *cli;
9147         bool *got_break;
9148         bool *acl_ret;
9149         NTSTATUS status;
9150 };
9151
9152 static void posix_acl_oplock_got_break(struct tevent_req *req)
9153 {
9154         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9155                 req, struct posix_acl_oplock_state);
9156         uint16_t fnum;
9157         uint8_t level;
9158         NTSTATUS status;
9159
9160         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9161         TALLOC_FREE(req);
9162         if (!NT_STATUS_IS_OK(status)) {
9163                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9164                        nt_errstr(status));
9165                 return;
9166         }
9167         *state->got_break = true;
9168
9169         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9170                                   NO_OPLOCK);
9171         if (req == NULL) {
9172                 printf("cli_oplock_ack_send failed\n");
9173                 return;
9174         }
9175 }
9176
9177 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9178 {
9179         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9180                 req, struct posix_acl_oplock_state);
9181         size_t ret_size = 0;
9182         char *ret_data = NULL;
9183
9184         state->status = cli_posix_getacl_recv(req,
9185                         state,
9186                         &ret_size,
9187                         &ret_data);
9188
9189         if (!NT_STATUS_IS_OK(state->status)) {
9190                 printf("cli_posix_getacl_recv returned %s\n",
9191                         nt_errstr(state->status));
9192         }
9193         *state->acl_ret = true;
9194 }
9195
9196 static bool run_posix_acl_oplock_test(int dummy)
9197 {
9198         struct tevent_context *ev;
9199         struct cli_state *cli1, *cli2;
9200         struct tevent_req *oplock_req, *getacl_req;
9201         const char *fname = "posix_acl_oplock";
9202         uint16_t fnum;
9203         int saved_use_oplocks = use_oplocks;
9204         NTSTATUS status;
9205         bool correct = true;
9206         bool got_break = false;
9207         bool acl_ret = false;
9208
9209         struct posix_acl_oplock_state *state;
9210
9211         printf("starting posix_acl_oplock test\n");
9212
9213         if (!torture_open_connection(&cli1, 0)) {
9214                 use_level_II_oplocks = false;
9215                 use_oplocks = saved_use_oplocks;
9216                 return false;
9217         }
9218
9219         if (!torture_open_connection(&cli2, 1)) {
9220                 use_level_II_oplocks = false;
9221                 use_oplocks = saved_use_oplocks;
9222                 return false;
9223         }
9224
9225         /* Setup posix on cli2 only. */
9226         status = torture_setup_unix_extensions(cli2);
9227         if (!NT_STATUS_IS_OK(status)) {
9228                 return false;
9229         }
9230
9231         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9232         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9233
9234         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9235
9236         /* Create the file on the Windows connection. */
9237         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9238                           &fnum);
9239         if (!NT_STATUS_IS_OK(status)) {
9240                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9241                 return false;
9242         }
9243
9244         status = cli_close(cli1, fnum);
9245         if (!NT_STATUS_IS_OK(status)) {
9246                 printf("close1 failed (%s)\n", nt_errstr(status));
9247                 return false;
9248         }
9249
9250         cli1->use_oplocks = true;
9251
9252         /* Open with oplock. */
9253         status = cli_ntcreate(cli1,
9254                         fname,
9255                         0,
9256                         FILE_READ_DATA,
9257                         FILE_ATTRIBUTE_NORMAL,
9258                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9259                         FILE_OPEN,
9260                         0,
9261                         0,
9262                         &fnum,
9263                         NULL);
9264
9265         if (!NT_STATUS_IS_OK(status)) {
9266                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9267                 return false;
9268         }
9269
9270         ev = samba_tevent_context_init(talloc_tos());
9271         if (ev == NULL) {
9272                 printf("tevent_context_init failed\n");
9273                 return false;
9274         }
9275
9276         state = talloc_zero(ev, struct posix_acl_oplock_state);
9277         if (state == NULL) {
9278                 printf("talloc failed\n");
9279                 return false;
9280         }
9281         state->ev = ev;
9282         state->cli = cli1;
9283         state->got_break = &got_break;
9284         state->acl_ret = &acl_ret;
9285
9286         oplock_req = cli_smb_oplock_break_waiter_send(
9287                 talloc_tos(), ev, cli1);
9288         if (oplock_req == NULL) {
9289                 printf("cli_smb_oplock_break_waiter_send failed\n");
9290                 return false;
9291         }
9292         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9293
9294         /* Get ACL on POSIX connection - should break oplock. */
9295         getacl_req = cli_posix_getacl_send(talloc_tos(),
9296                                 ev,
9297                                 cli2,
9298                                 fname);
9299         if (getacl_req == NULL) {
9300                 printf("cli_posix_getacl_send failed\n");
9301                 return false;
9302         }
9303         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9304
9305         while (!got_break || !acl_ret) {
9306                 int ret;
9307                 ret = tevent_loop_once(ev);
9308                 if (ret == -1) {
9309                         printf("tevent_loop_once failed: %s\n",
9310                                strerror(errno));
9311                         return false;
9312                 }
9313         }
9314
9315         if (!NT_STATUS_IS_OK(state->status)) {
9316                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9317                 correct = false;
9318         }
9319
9320         status = cli_close(cli1, fnum);
9321         if (!NT_STATUS_IS_OK(status)) {
9322                 printf("close2 failed (%s)\n", nt_errstr(status));
9323                 correct = false;
9324         }
9325
9326         status = cli_unlink(cli1,
9327                         fname,
9328                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9329         if (!NT_STATUS_IS_OK(status)) {
9330                 printf("unlink failed (%s)\n", nt_errstr(status));
9331                 correct = false;
9332         }
9333
9334         if (!torture_close_connection(cli1)) {
9335                 correct = false;
9336         }
9337         if (!torture_close_connection(cli2)) {
9338                 correct = false;
9339         }
9340
9341         if (!got_break) {
9342                 correct = false;
9343         }
9344
9345         printf("finished posix acl oplock test\n");
9346
9347         return correct;
9348 }
9349
9350 static bool run_posix_acl_shareroot_test(int dummy)
9351 {
9352         struct cli_state *cli;
9353         NTSTATUS status;
9354         bool correct = false;
9355         char *posix_acl = NULL;
9356         size_t posix_acl_len = 0;
9357         uint16_t num_file_acls = 0;
9358         uint16_t num_dir_acls = 0;
9359         uint16_t i;
9360         uint32_t expected_size = 0;
9361         bool got_user = false;
9362         bool got_group = false;
9363         bool got_other = false;
9364         TALLOC_CTX *frame = NULL;
9365
9366         frame = talloc_stackframe();
9367
9368         printf("starting posix_acl_shareroot test\n");
9369
9370         if (!torture_open_connection(&cli, 0)) {
9371                 TALLOC_FREE(frame);
9372                 return false;
9373         }
9374
9375         smbXcli_conn_set_sockopt(cli->conn, sockops);
9376
9377         status = torture_setup_unix_extensions(cli);
9378         if (!NT_STATUS_IS_OK(status)) {
9379                 printf("Failed to setup unix extensions\n");
9380                 goto out;
9381         }
9382
9383         /* Get the POSIX ACL on the root of the share. */
9384         status = cli_posix_getacl(cli,
9385                                 ".",
9386                                 frame,
9387                                 &posix_acl_len,
9388                                 &posix_acl);
9389
9390         if (!NT_STATUS_IS_OK(status)) {
9391                 printf("cli_posix_getacl of '.' failed (%s)\n",
9392                         nt_errstr(status));
9393                 goto out;
9394         }
9395
9396         if (posix_acl_len < 6 ||
9397                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9398                 printf("getfacl ., unknown POSIX acl version %u.\n",
9399                         (unsigned int)CVAL(posix_acl,0) );
9400                 goto out;
9401         }
9402
9403         num_file_acls = SVAL(posix_acl,2);
9404         num_dir_acls = SVAL(posix_acl,4);
9405         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9406                                 SMB_POSIX_ACL_ENTRY_SIZE*
9407                                 (num_file_acls+num_dir_acls);
9408
9409         if (posix_acl_len != expected_size) {
9410                 printf("incorrect POSIX acl buffer size "
9411                         "(should be %u, was %u).\n",
9412                         (unsigned int)expected_size,
9413                         (unsigned int)posix_acl_len);
9414                 goto out;
9415         }
9416
9417         /*
9418          * We don't need to know what the ACL's are
9419          * we just need to know we have at least 3
9420          * file entries (u,g,o).
9421          */
9422
9423         for (i = 0; i < num_file_acls; i++) {
9424                 unsigned char tagtype =
9425                         CVAL(posix_acl,
9426                                 SMB_POSIX_ACL_HEADER_SIZE+
9427                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9428
9429                 switch(tagtype) {
9430                         case SMB_POSIX_ACL_USER_OBJ:
9431                                 got_user = true;
9432                                 break;
9433                         case SMB_POSIX_ACL_GROUP_OBJ:
9434                                 got_group = true;
9435                                 break;
9436                         case SMB_POSIX_ACL_OTHER:
9437                                 got_other = true;
9438                                 break;
9439                         default:
9440                                 break;
9441                 }
9442         }
9443
9444         if (!got_user) {
9445                 printf("Missing user entry\n");
9446                 goto out;
9447         }
9448
9449         if (!got_group) {
9450                 printf("Missing group entry\n");
9451                 goto out;
9452         }
9453
9454         if (!got_other) {
9455                 printf("Missing other entry\n");
9456                 goto out;
9457         }
9458
9459         correct = true;
9460
9461   out:
9462
9463         if (!torture_close_connection(cli)) {
9464                 correct = false;
9465         }
9466
9467         printf("finished posix acl shareroot test\n");
9468         TALLOC_FREE(frame);
9469
9470         return correct;
9471 }
9472
9473 static uint32_t open_attrs_table[] = {
9474                 FILE_ATTRIBUTE_NORMAL,
9475                 FILE_ATTRIBUTE_ARCHIVE,
9476                 FILE_ATTRIBUTE_READONLY,
9477                 FILE_ATTRIBUTE_HIDDEN,
9478                 FILE_ATTRIBUTE_SYSTEM,
9479
9480                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9481                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9482                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9483                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9484                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9485                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9486
9487                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9488                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9489                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9490                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9491 };
9492
9493 struct trunc_open_results {
9494         unsigned int num;
9495         uint32_t init_attr;
9496         uint32_t trunc_attr;
9497         uint32_t result_attr;
9498 };
9499
9500 static struct trunc_open_results attr_results[] = {
9501         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9502         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9503         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9504         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9505         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9506         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9507         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9508         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9509         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9510         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9511         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9512         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9513         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9514         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9515         { 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 },
9516         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9517         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9518         { 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 },
9519         { 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 },
9520         { 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 },
9521         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9522         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9523         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9524         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9525         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9526         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9527 };
9528
9529 static bool run_openattrtest(int dummy)
9530 {
9531         static struct cli_state *cli1;
9532         const char *fname = "\\openattr.file";
9533         uint16_t fnum1;
9534         bool correct = True;
9535         uint32_t attr;
9536         unsigned int i, j, k, l;
9537         NTSTATUS status;
9538
9539         printf("starting open attr test\n");
9540
9541         if (!torture_open_connection(&cli1, 0)) {
9542                 return False;
9543         }
9544
9545         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9546
9547         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9548                 cli_setatr(cli1, fname, 0, 0);
9549                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9550
9551                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9552                                        open_attrs_table[i], FILE_SHARE_NONE,
9553                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9554                 if (!NT_STATUS_IS_OK(status)) {
9555                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9556                         return False;
9557                 }
9558
9559                 status = cli_close(cli1, fnum1);
9560                 if (!NT_STATUS_IS_OK(status)) {
9561                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9562                         return False;
9563                 }
9564
9565                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9566                         status = cli_ntcreate(cli1, fname, 0,
9567                                               FILE_READ_DATA|FILE_WRITE_DATA,
9568                                               open_attrs_table[j],
9569                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9570                                               0, 0, &fnum1, NULL);
9571                         if (!NT_STATUS_IS_OK(status)) {
9572                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9573                                         if (attr_results[l].num == k) {
9574                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9575                                                                 k, open_attrs_table[i],
9576                                                                 open_attrs_table[j],
9577                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9578                                                 correct = False;
9579                                         }
9580                                 }
9581
9582                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9583                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9584                                                         k, open_attrs_table[i], open_attrs_table[j],
9585                                                         nt_errstr(status));
9586                                         correct = False;
9587                                 }
9588 #if 0
9589                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9590 #endif
9591                                 k++;
9592                                 continue;
9593                         }
9594
9595                         status = cli_close(cli1, fnum1);
9596                         if (!NT_STATUS_IS_OK(status)) {
9597                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9598                                 return False;
9599                         }
9600
9601                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9602                         if (!NT_STATUS_IS_OK(status)) {
9603                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9604                                 return False;
9605                         }
9606
9607 #if 0
9608                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9609                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9610 #endif
9611
9612                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9613                                 if (attr_results[l].num == k) {
9614                                         if (attr != attr_results[l].result_attr ||
9615                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9616                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9617                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9618                                                 open_attrs_table[i],
9619                                                 open_attrs_table[j],
9620                                                 (unsigned int)attr,
9621                                                 attr_results[l].result_attr);
9622                                                 correct = False;
9623                                         }
9624                                         break;
9625                                 }
9626                         }
9627                         k++;
9628                 }
9629         }
9630
9631         cli_setatr(cli1, fname, 0, 0);
9632         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9633
9634         printf("open attr test %s.\n", correct ? "passed" : "failed");
9635
9636         if (!torture_close_connection(cli1)) {
9637                 correct = False;
9638         }
9639         return correct;
9640 }
9641
9642 static NTSTATUS list_fn(struct file_info *finfo,
9643                     const char *name, void *state)
9644 {
9645         int *matched = (int *)state;
9646         if (matched != NULL) {
9647                 *matched += 1;
9648         }
9649         return NT_STATUS_OK;
9650 }
9651
9652 /*
9653   test directory listing speed
9654  */
9655 static bool run_dirtest(int dummy)
9656 {
9657         int i;
9658         static struct cli_state *cli;
9659         uint16_t fnum;
9660         struct timeval core_start;
9661         bool correct = True;
9662         int matched;
9663
9664         printf("starting directory test\n");
9665
9666         if (!torture_open_connection(&cli, 0)) {
9667                 return False;
9668         }
9669
9670         smbXcli_conn_set_sockopt(cli->conn, sockops);
9671
9672         srandom(0);
9673         for (i=0;i<torture_numops;i++) {
9674                 fstring fname;
9675                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9676                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9677                         fprintf(stderr,"Failed to open %s\n", fname);
9678                         return False;
9679                 }
9680                 cli_close(cli, fnum);
9681         }
9682
9683         core_start = timeval_current();
9684
9685         matched = 0;
9686         cli_list(cli, "a*.*", 0, list_fn, &matched);
9687         printf("Matched %d\n", matched);
9688
9689         matched = 0;
9690         cli_list(cli, "b*.*", 0, list_fn, &matched);
9691         printf("Matched %d\n", matched);
9692
9693         matched = 0;
9694         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9695         printf("Matched %d\n", matched);
9696
9697         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9698
9699         srandom(0);
9700         for (i=0;i<torture_numops;i++) {
9701                 fstring fname;
9702                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9703                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9704         }
9705
9706         if (!torture_close_connection(cli)) {
9707                 correct = False;
9708         }
9709
9710         printf("finished dirtest\n");
9711
9712         return correct;
9713 }
9714
9715 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9716                    void *state)
9717 {
9718         struct cli_state *pcli = (struct cli_state *)state;
9719         fstring fname;
9720         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9721
9722         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9723                 return NT_STATUS_OK;
9724
9725         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9726                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9727                         printf("del_fn: failed to rmdir %s\n,", fname );
9728         } else {
9729                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9730                         printf("del_fn: failed to unlink %s\n,", fname );
9731         }
9732         return NT_STATUS_OK;
9733 }
9734
9735
9736 /*
9737   sees what IOCTLs are supported
9738  */
9739 bool torture_ioctl_test(int dummy)
9740 {
9741         static struct cli_state *cli;
9742         uint16_t device, function;
9743         uint16_t fnum;
9744         const char *fname = "\\ioctl.dat";
9745         DATA_BLOB blob;
9746         NTSTATUS status;
9747
9748         if (!torture_open_connection(&cli, 0)) {
9749                 return False;
9750         }
9751
9752         printf("starting ioctl test\n");
9753
9754         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9755
9756         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9757         if (!NT_STATUS_IS_OK(status)) {
9758                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9759                 return False;
9760         }
9761
9762         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9763         printf("ioctl device info: %s\n", nt_errstr(status));
9764
9765         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9766         printf("ioctl job info: %s\n", nt_errstr(status));
9767
9768         for (device=0;device<0x100;device++) {
9769                 printf("ioctl test with device = 0x%x\n", device);
9770                 for (function=0;function<0x100;function++) {
9771                         uint32_t code = (device<<16) | function;
9772
9773                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9774
9775                         if (NT_STATUS_IS_OK(status)) {
9776                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9777                                        (int)blob.length);
9778                                 data_blob_free(&blob);
9779                         }
9780                 }
9781         }
9782
9783         if (!torture_close_connection(cli)) {
9784                 return False;
9785         }
9786
9787         return True;
9788 }
9789
9790
9791 /*
9792   tries varients of chkpath
9793  */
9794 bool torture_chkpath_test(int dummy)
9795 {
9796         static struct cli_state *cli;
9797         uint16_t fnum;
9798         bool ret;
9799         NTSTATUS status;
9800
9801         if (!torture_open_connection(&cli, 0)) {
9802                 return False;
9803         }
9804
9805         printf("starting chkpath test\n");
9806
9807         /* cleanup from an old run */
9808         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9809         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9810         cli_rmdir(cli, "\\chkpath.dir");
9811
9812         status = cli_mkdir(cli, "\\chkpath.dir");
9813         if (!NT_STATUS_IS_OK(status)) {
9814                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9815                 return False;
9816         }
9817
9818         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9819         if (!NT_STATUS_IS_OK(status)) {
9820                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9821                 return False;
9822         }
9823
9824         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9825                           DENY_NONE, &fnum);
9826         if (!NT_STATUS_IS_OK(status)) {
9827                 printf("open1 failed (%s)\n", nt_errstr(status));
9828                 return False;
9829         }
9830         cli_close(cli, fnum);
9831
9832         status = cli_chkpath(cli, "\\chkpath.dir");
9833         if (!NT_STATUS_IS_OK(status)) {
9834                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9835                 ret = False;
9836         }
9837
9838         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9839         if (!NT_STATUS_IS_OK(status)) {
9840                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9841                 ret = False;
9842         }
9843
9844         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9845         if (!NT_STATUS_IS_OK(status)) {
9846                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9847                                   NT_STATUS_NOT_A_DIRECTORY);
9848         } else {
9849                 printf("* chkpath on a file should fail\n");
9850                 ret = False;
9851         }
9852
9853         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9854         if (!NT_STATUS_IS_OK(status)) {
9855                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9856                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9857         } else {
9858                 printf("* chkpath on a non existent file should fail\n");
9859                 ret = False;
9860         }
9861
9862         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9863         if (!NT_STATUS_IS_OK(status)) {
9864                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9865                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9866         } else {
9867                 printf("* chkpath on a non existent component should fail\n");
9868                 ret = False;
9869         }
9870
9871         cli_rmdir(cli, "\\chkpath.dir\\dir2");
9872         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9873         cli_rmdir(cli, "\\chkpath.dir");
9874
9875         if (!torture_close_connection(cli)) {
9876                 return False;
9877         }
9878
9879         return ret;
9880 }
9881
9882 static bool run_eatest(int dummy)
9883 {
9884         static struct cli_state *cli;
9885         const char *fname = "\\eatest.txt";
9886         bool correct = True;
9887         uint16_t fnum;
9888         int i;
9889         size_t num_eas;
9890         struct ea_struct *ea_list = NULL;
9891         TALLOC_CTX *mem_ctx = talloc_init("eatest");
9892         NTSTATUS status;
9893
9894         printf("starting eatest\n");
9895
9896         if (!torture_open_connection(&cli, 0)) {
9897                 talloc_destroy(mem_ctx);
9898                 return False;
9899         }
9900
9901         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9902
9903         status = cli_ntcreate(cli, fname, 0,
9904                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9905                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9906                               0x4044, 0, &fnum, NULL);
9907         if (!NT_STATUS_IS_OK(status)) {
9908                 printf("open failed - %s\n", nt_errstr(status));
9909                 talloc_destroy(mem_ctx);
9910                 return False;
9911         }
9912
9913         for (i = 0; i < 10; i++) {
9914                 fstring ea_name, ea_val;
9915
9916                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9917                 memset(ea_val, (char)i+1, i+1);
9918                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9919                 if (!NT_STATUS_IS_OK(status)) {
9920                         printf("ea_set of name %s failed - %s\n", ea_name,
9921                                nt_errstr(status));
9922                         talloc_destroy(mem_ctx);
9923                         return False;
9924                 }
9925         }
9926
9927         cli_close(cli, fnum);
9928         for (i = 0; i < 10; i++) {
9929                 fstring ea_name, ea_val;
9930
9931                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9932                 memset(ea_val, (char)i+1, i+1);
9933                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9934                 if (!NT_STATUS_IS_OK(status)) {
9935                         printf("ea_set of name %s failed - %s\n", ea_name,
9936                                nt_errstr(status));
9937                         talloc_destroy(mem_ctx);
9938                         return False;
9939                 }
9940         }
9941
9942         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9943         if (!NT_STATUS_IS_OK(status)) {
9944                 printf("ea_get list failed - %s\n", nt_errstr(status));
9945                 correct = False;
9946         }
9947
9948         printf("num_eas = %d\n", (int)num_eas);
9949
9950         if (num_eas != 20) {
9951                 printf("Should be 20 EA's stored... failing.\n");
9952                 correct = False;
9953         }
9954
9955         for (i = 0; i < num_eas; i++) {
9956                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9957                 dump_data(0, ea_list[i].value.data,
9958                           ea_list[i].value.length);
9959         }
9960
9961         /* Setting EA's to zero length deletes them. Test this */
9962         printf("Now deleting all EA's - case indepenent....\n");
9963
9964 #if 1
9965         cli_set_ea_path(cli, fname, "", "", 0);
9966 #else
9967         for (i = 0; i < 20; i++) {
9968                 fstring ea_name;
9969                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9970                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9971                 if (!NT_STATUS_IS_OK(status)) {
9972                         printf("ea_set of name %s failed - %s\n", ea_name,
9973                                nt_errstr(status));
9974                         talloc_destroy(mem_ctx);
9975                         return False;
9976                 }
9977         }
9978 #endif
9979
9980         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9981         if (!NT_STATUS_IS_OK(status)) {
9982                 printf("ea_get list failed - %s\n", nt_errstr(status));
9983                 correct = False;
9984         }
9985
9986         printf("num_eas = %d\n", (int)num_eas);
9987         for (i = 0; i < num_eas; i++) {
9988                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9989                 dump_data(0, ea_list[i].value.data,
9990                           ea_list[i].value.length);
9991         }
9992
9993         if (num_eas != 0) {
9994                 printf("deleting EA's failed.\n");
9995                 correct = False;
9996         }
9997
9998         /* Try and delete a non existent EA. */
9999         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10000         if (!NT_STATUS_IS_OK(status)) {
10001                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10002                        nt_errstr(status));
10003                 correct = False;
10004         }
10005
10006         talloc_destroy(mem_ctx);
10007         if (!torture_close_connection(cli)) {
10008                 correct = False;
10009         }
10010
10011         return correct;
10012 }
10013
10014 static bool run_dirtest1(int dummy)
10015 {
10016         int i;
10017         static struct cli_state *cli;
10018         uint16_t fnum;
10019         int num_seen;
10020         bool correct = True;
10021
10022         printf("starting directory test\n");
10023
10024         if (!torture_open_connection(&cli, 0)) {
10025                 return False;
10026         }
10027
10028         smbXcli_conn_set_sockopt(cli->conn, sockops);
10029
10030         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10031         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10032         cli_rmdir(cli, "\\LISTDIR");
10033         cli_mkdir(cli, "\\LISTDIR");
10034
10035         /* Create 1000 files and 1000 directories. */
10036         for (i=0;i<1000;i++) {
10037                 fstring fname;
10038                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10039                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10040                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10041                                    0, 0, &fnum, NULL))) {
10042                         fprintf(stderr,"Failed to open %s\n", fname);
10043                         return False;
10044                 }
10045                 cli_close(cli, fnum);
10046         }
10047         for (i=0;i<1000;i++) {
10048                 fstring fname;
10049                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10050                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10051                         fprintf(stderr,"Failed to open %s\n", fname);
10052                         return False;
10053                 }
10054         }
10055
10056         /* Now ensure that doing an old list sees both files and directories. */
10057         num_seen = 0;
10058         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10059         printf("num_seen = %d\n", num_seen );
10060         /* We should see 100 files + 1000 directories + . and .. */
10061         if (num_seen != 2002)
10062                 correct = False;
10063
10064         /* Ensure if we have the "must have" bits we only see the
10065          * relevent entries.
10066          */
10067         num_seen = 0;
10068         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10069         printf("num_seen = %d\n", num_seen );
10070         if (num_seen != 1002)
10071                 correct = False;
10072
10073         num_seen = 0;
10074         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10075         printf("num_seen = %d\n", num_seen );
10076         if (num_seen != 1000)
10077                 correct = False;
10078
10079         /* Delete everything. */
10080         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10081         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10082         cli_rmdir(cli, "\\LISTDIR");
10083
10084 #if 0
10085         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10086         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10087         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10088 #endif
10089
10090         if (!torture_close_connection(cli)) {
10091                 correct = False;
10092         }
10093
10094         printf("finished dirtest1\n");
10095
10096         return correct;
10097 }
10098
10099 static bool run_error_map_extract(int dummy) {
10100
10101         static struct cli_state *c_dos;
10102         static struct cli_state *c_nt;
10103         NTSTATUS status;
10104
10105         uint32_t error;
10106
10107         uint32_t errnum;
10108         uint8_t errclass;
10109
10110         NTSTATUS nt_status;
10111
10112         fstring user;
10113
10114         /* NT-Error connection */
10115
10116         disable_spnego = true;
10117         if (!(c_nt = open_nbt_connection())) {
10118                 disable_spnego = false;
10119                 return False;
10120         }
10121         disable_spnego = false;
10122
10123         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10124                                  PROTOCOL_NT1);
10125
10126         if (!NT_STATUS_IS_OK(status)) {
10127                 printf("%s rejected the NT-error negprot (%s)\n", host,
10128                        nt_errstr(status));
10129                 cli_shutdown(c_nt);
10130                 return False;
10131         }
10132
10133         status = cli_session_setup_anon(c_nt);
10134         if (!NT_STATUS_IS_OK(status)) {
10135                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10136                 return False;
10137         }
10138
10139         /* DOS-Error connection */
10140
10141         disable_spnego = true;
10142         force_dos_errors = true;
10143         if (!(c_dos = open_nbt_connection())) {
10144                 disable_spnego = false;
10145                 force_dos_errors = false;
10146                 return False;
10147         }
10148         disable_spnego = false;
10149         force_dos_errors = false;
10150
10151         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10152                                  PROTOCOL_NT1);
10153         if (!NT_STATUS_IS_OK(status)) {
10154                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10155                        nt_errstr(status));
10156                 cli_shutdown(c_dos);
10157                 return False;
10158         }
10159
10160         status = cli_session_setup_anon(c_dos);
10161         if (!NT_STATUS_IS_OK(status)) {
10162                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10163                         host, nt_errstr(status));
10164                 return False;
10165         }
10166
10167         c_nt->map_dos_errors = false;
10168         c_dos->map_dos_errors = false;
10169
10170         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10171                 struct cli_credentials *user_creds = NULL;
10172
10173                 fstr_sprintf(user, "%X", error);
10174
10175                 user_creds = cli_session_creds_init(talloc_tos(),
10176                                                     user,
10177                                                     workgroup,
10178                                                     NULL, /* realm */
10179                                                     password,
10180                                                     false, /* use_kerberos */
10181                                                     false, /* fallback_after_kerberos */
10182                                                     false, /* use_ccache */
10183                                                     false); /* password_is_nt_hash */
10184                 if (user_creds == NULL) {
10185                         printf("cli_session_creds_init(%s) failed\n", user);
10186                         return false;
10187                 }
10188
10189                 status = cli_session_setup_creds(c_nt, user_creds);
10190                 if (NT_STATUS_IS_OK(status)) {
10191                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10192                 }
10193
10194                 /* Case #1: 32-bit NT errors */
10195                 if (!NT_STATUS_IS_DOS(status)) {
10196                         nt_status = status;
10197                 } else {
10198                         printf("/** Dos error on NT connection! (%s) */\n", 
10199                                nt_errstr(status));
10200                         nt_status = NT_STATUS(0xc0000000);
10201                 }
10202
10203                 status = cli_session_setup_creds(c_dos, user_creds);
10204                 if (NT_STATUS_IS_OK(status)) {
10205                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10206                 }
10207
10208                 /* Case #1: 32-bit NT errors */
10209                 if (NT_STATUS_IS_DOS(status)) {
10210                         printf("/** NT error on DOS connection! (%s) */\n", 
10211                                nt_errstr(status));
10212                         errnum = errclass = 0;
10213                 } else {
10214                         errclass = NT_STATUS_DOS_CLASS(status);
10215                         errnum = NT_STATUS_DOS_CODE(status);
10216                 }
10217
10218                 if (NT_STATUS_V(nt_status) != error) { 
10219                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10220                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10221                                get_nt_error_c_code(talloc_tos(), nt_status));
10222                 }
10223
10224                 printf("\t{%s,\t%s,\t%s},\n", 
10225                        smb_dos_err_class(errclass), 
10226                        smb_dos_err_name(errclass, errnum), 
10227                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10228
10229                 TALLOC_FREE(user_creds);
10230         }
10231         return True;
10232 }
10233
10234 static bool run_sesssetup_bench(int dummy)
10235 {
10236         static struct cli_state *c;
10237         const char *fname = "\\file.dat";
10238         uint16_t fnum;
10239         NTSTATUS status;
10240         int i;
10241
10242         if (!torture_open_connection(&c, 0)) {
10243                 return false;
10244         }
10245
10246         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10247                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10248                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10249         if (!NT_STATUS_IS_OK(status)) {
10250                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10251                 return false;
10252         }
10253
10254         for (i=0; i<torture_numops; i++) {
10255                 status = cli_session_setup_creds(c, torture_creds);
10256                 if (!NT_STATUS_IS_OK(status)) {
10257                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10258                                  __location__, nt_errstr(status));
10259                         return false;
10260                 }
10261
10262                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10263
10264                 status = cli_ulogoff(c);
10265                 if (!NT_STATUS_IS_OK(status)) {
10266                         d_printf("(%s) cli_ulogoff failed: %s\n",
10267                                  __location__, nt_errstr(status));
10268                         return false;
10269                 }
10270         }
10271
10272         return true;
10273 }
10274
10275 static bool subst_test(const char *str, const char *user, const char *domain,
10276                        uid_t uid, gid_t gid, const char *expected)
10277 {
10278         char *subst;
10279         bool result = true;
10280
10281         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10282
10283         if (strcmp(subst, expected) != 0) {
10284                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10285                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10286                        expected);
10287                 result = false;
10288         }
10289
10290         TALLOC_FREE(subst);
10291         return result;
10292 }
10293
10294 static void chain1_open_completion(struct tevent_req *req)
10295 {
10296         uint16_t fnum;
10297         NTSTATUS status;
10298         status = cli_openx_recv(req, &fnum);
10299         TALLOC_FREE(req);
10300
10301         d_printf("cli_openx_recv returned %s: %d\n",
10302                  nt_errstr(status),
10303                  NT_STATUS_IS_OK(status) ? fnum : -1);
10304 }
10305
10306 static void chain1_write_completion(struct tevent_req *req)
10307 {
10308         size_t written;
10309         NTSTATUS status;
10310         status = cli_write_andx_recv(req, &written);
10311         TALLOC_FREE(req);
10312
10313         d_printf("cli_write_andx_recv returned %s: %d\n",
10314                  nt_errstr(status),
10315                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10316 }
10317
10318 static void chain1_close_completion(struct tevent_req *req)
10319 {
10320         NTSTATUS status;
10321         bool *done = (bool *)tevent_req_callback_data_void(req);
10322
10323         status = cli_close_recv(req);
10324         *done = true;
10325
10326         TALLOC_FREE(req);
10327
10328         d_printf("cli_close returned %s\n", nt_errstr(status));
10329 }
10330
10331 static bool run_chain1(int dummy)
10332 {
10333         struct cli_state *cli1;
10334         struct tevent_context *evt = samba_tevent_context_init(NULL);
10335         struct tevent_req *reqs[3], *smbreqs[3];
10336         bool done = false;
10337         const char *str = "foobar";
10338         const char *fname = "\\test_chain";
10339         NTSTATUS status;
10340
10341         printf("starting chain1 test\n");
10342         if (!torture_open_connection(&cli1, 0)) {
10343                 return False;
10344         }
10345
10346         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10347
10348         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10349
10350         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10351                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10352         if (reqs[0] == NULL) return false;
10353         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10354
10355
10356         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10357                                         (const uint8_t *)str, 0, strlen(str)+1,
10358                                         smbreqs, 1, &smbreqs[1]);
10359         if (reqs[1] == NULL) return false;
10360         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10361
10362         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10363         if (reqs[2] == NULL) return false;
10364         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10365
10366         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10367         if (!NT_STATUS_IS_OK(status)) {
10368                 return false;
10369         }
10370
10371         while (!done) {
10372                 tevent_loop_once(evt);
10373         }
10374
10375         torture_close_connection(cli1);
10376         return True;
10377 }
10378
10379 static void chain2_sesssetup_completion(struct tevent_req *req)
10380 {
10381         NTSTATUS status;
10382         status = cli_session_setup_guest_recv(req);
10383         d_printf("sesssetup returned %s\n", nt_errstr(status));
10384 }
10385
10386 static void chain2_tcon_completion(struct tevent_req *req)
10387 {
10388         bool *done = (bool *)tevent_req_callback_data_void(req);
10389         NTSTATUS status;
10390         status = cli_tcon_andx_recv(req);
10391         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10392         *done = true;
10393 }
10394
10395 static bool run_chain2(int dummy)
10396 {
10397         struct cli_state *cli1;
10398         struct tevent_context *evt = samba_tevent_context_init(NULL);
10399         struct tevent_req *reqs[2], *smbreqs[2];
10400         bool done = false;
10401         NTSTATUS status;
10402         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10403
10404         printf("starting chain2 test\n");
10405         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10406                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10407         if (!NT_STATUS_IS_OK(status)) {
10408                 return False;
10409         }
10410
10411         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10412
10413         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10414                                                  &smbreqs[0]);
10415         if (reqs[0] == NULL) return false;
10416         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10417
10418         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10419                                        "?????", NULL, 0, &smbreqs[1]);
10420         if (reqs[1] == NULL) return false;
10421         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10422
10423         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10424         if (!NT_STATUS_IS_OK(status)) {
10425                 return false;
10426         }
10427
10428         while (!done) {
10429                 tevent_loop_once(evt);
10430         }
10431
10432         torture_close_connection(cli1);
10433         return True;
10434 }
10435
10436
10437 struct torture_createdel_state {
10438         struct tevent_context *ev;
10439         struct cli_state *cli;
10440 };
10441
10442 static void torture_createdel_created(struct tevent_req *subreq);
10443 static void torture_createdel_closed(struct tevent_req *subreq);
10444
10445 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10446                                                  struct tevent_context *ev,
10447                                                  struct cli_state *cli,
10448                                                  const char *name)
10449 {
10450         struct tevent_req *req, *subreq;
10451         struct torture_createdel_state *state;
10452
10453         req = tevent_req_create(mem_ctx, &state,
10454                                 struct torture_createdel_state);
10455         if (req == NULL) {
10456                 return NULL;
10457         }
10458         state->ev = ev;
10459         state->cli = cli;
10460
10461         subreq = cli_ntcreate_send(
10462                 state, ev, cli, name, 0,
10463                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10464                 FILE_ATTRIBUTE_NORMAL,
10465                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10466                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10467                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10468
10469         if (tevent_req_nomem(subreq, req)) {
10470                 return tevent_req_post(req, ev);
10471         }
10472         tevent_req_set_callback(subreq, torture_createdel_created, req);
10473         return req;
10474 }
10475
10476 static void torture_createdel_created(struct tevent_req *subreq)
10477 {
10478         struct tevent_req *req = tevent_req_callback_data(
10479                 subreq, struct tevent_req);
10480         struct torture_createdel_state *state = tevent_req_data(
10481                 req, struct torture_createdel_state);
10482         NTSTATUS status;
10483         uint16_t fnum;
10484
10485         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10486         TALLOC_FREE(subreq);
10487         if (tevent_req_nterror(req, status)) {
10488                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10489                            nt_errstr(status)));
10490                 return;
10491         }
10492
10493         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10494         if (tevent_req_nomem(subreq, req)) {
10495                 return;
10496         }
10497         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10498 }
10499
10500 static void torture_createdel_closed(struct tevent_req *subreq)
10501 {
10502         struct tevent_req *req = tevent_req_callback_data(
10503                 subreq, struct tevent_req);
10504         NTSTATUS status;
10505
10506         status = cli_close_recv(subreq);
10507         if (tevent_req_nterror(req, status)) {
10508                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10509                 return;
10510         }
10511         tevent_req_done(req);
10512 }
10513
10514 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10515 {
10516         return tevent_req_simple_recv_ntstatus(req);
10517 }
10518
10519 struct torture_createdels_state {
10520         struct tevent_context *ev;
10521         struct cli_state *cli;
10522         const char *base_name;
10523         int sent;
10524         int received;
10525         int num_files;
10526         struct tevent_req **reqs;
10527 };
10528
10529 static void torture_createdels_done(struct tevent_req *subreq);
10530
10531 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10532                                                   struct tevent_context *ev,
10533                                                   struct cli_state *cli,
10534                                                   const char *base_name,
10535                                                   int num_parallel,
10536                                                   int num_files)
10537 {
10538         struct tevent_req *req;
10539         struct torture_createdels_state *state;
10540         int i;
10541
10542         req = tevent_req_create(mem_ctx, &state,
10543                                 struct torture_createdels_state);
10544         if (req == NULL) {
10545                 return NULL;
10546         }
10547         state->ev = ev;
10548         state->cli = cli;
10549         state->base_name = talloc_strdup(state, base_name);
10550         if (tevent_req_nomem(state->base_name, req)) {
10551                 return tevent_req_post(req, ev);
10552         }
10553         state->num_files = MAX(num_parallel, num_files);
10554         state->sent = 0;
10555         state->received = 0;
10556
10557         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10558         if (tevent_req_nomem(state->reqs, req)) {
10559                 return tevent_req_post(req, ev);
10560         }
10561
10562         for (i=0; i<num_parallel; i++) {
10563                 char *name;
10564
10565                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10566                                        state->sent);
10567                 if (tevent_req_nomem(name, req)) {
10568                         return tevent_req_post(req, ev);
10569                 }
10570                 state->reqs[i] = torture_createdel_send(
10571                         state->reqs, state->ev, state->cli, name);
10572                 if (tevent_req_nomem(state->reqs[i], req)) {
10573                         return tevent_req_post(req, ev);
10574                 }
10575                 name = talloc_move(state->reqs[i], &name);
10576                 tevent_req_set_callback(state->reqs[i],
10577                                         torture_createdels_done, req);
10578                 state->sent += 1;
10579         }
10580         return req;
10581 }
10582
10583 static void torture_createdels_done(struct tevent_req *subreq)
10584 {
10585         struct tevent_req *req = tevent_req_callback_data(
10586                 subreq, struct tevent_req);
10587         struct torture_createdels_state *state = tevent_req_data(
10588                 req, struct torture_createdels_state);
10589         size_t num_parallel = talloc_array_length(state->reqs);
10590         NTSTATUS status;
10591         char *name;
10592         int i;
10593
10594         status = torture_createdel_recv(subreq);
10595         if (!NT_STATUS_IS_OK(status)){
10596                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10597                            nt_errstr(status)));
10598                 TALLOC_FREE(subreq);
10599                 tevent_req_nterror(req, status);
10600                 return;
10601         }
10602
10603         for (i=0; i<num_parallel; i++) {
10604                 if (subreq == state->reqs[i]) {
10605                         break;
10606                 }
10607         }
10608         if (i == num_parallel) {
10609                 DEBUG(10, ("received something we did not send\n"));
10610                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10611                 return;
10612         }
10613         TALLOC_FREE(state->reqs[i]);
10614
10615         if (state->sent >= state->num_files) {
10616                 tevent_req_done(req);
10617                 return;
10618         }
10619
10620         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10621                                state->sent);
10622         if (tevent_req_nomem(name, req)) {
10623                 return;
10624         }
10625         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10626                                                 state->cli, name);
10627         if (tevent_req_nomem(state->reqs[i], req)) {
10628                 return;
10629         }
10630         name = talloc_move(state->reqs[i], &name);
10631         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10632         state->sent += 1;
10633 }
10634
10635 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10636 {
10637         return tevent_req_simple_recv_ntstatus(req);
10638 }
10639
10640 struct swallow_notify_state {
10641         struct tevent_context *ev;
10642         struct cli_state *cli;
10643         uint16_t fnum;
10644         uint32_t completion_filter;
10645         bool recursive;
10646         bool (*fn)(uint32_t action, const char *name, void *priv);
10647         void *priv;
10648 };
10649
10650 static void swallow_notify_done(struct tevent_req *subreq);
10651
10652 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10653                                               struct tevent_context *ev,
10654                                               struct cli_state *cli,
10655                                               uint16_t fnum,
10656                                               uint32_t completion_filter,
10657                                               bool recursive,
10658                                               bool (*fn)(uint32_t action,
10659                                                          const char *name,
10660                                                          void *priv),
10661                                               void *priv)
10662 {
10663         struct tevent_req *req, *subreq;
10664         struct swallow_notify_state *state;
10665
10666         req = tevent_req_create(mem_ctx, &state,
10667                                 struct swallow_notify_state);
10668         if (req == NULL) {
10669                 return NULL;
10670         }
10671         state->ev = ev;
10672         state->cli = cli;
10673         state->fnum = fnum;
10674         state->completion_filter = completion_filter;
10675         state->recursive = recursive;
10676         state->fn = fn;
10677         state->priv = priv;
10678
10679         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10680                                  0xffff, state->completion_filter,
10681                                  state->recursive);
10682         if (tevent_req_nomem(subreq, req)) {
10683                 return tevent_req_post(req, ev);
10684         }
10685         tevent_req_set_callback(subreq, swallow_notify_done, req);
10686         return req;
10687 }
10688
10689 static void swallow_notify_done(struct tevent_req *subreq)
10690 {
10691         struct tevent_req *req = tevent_req_callback_data(
10692                 subreq, struct tevent_req);
10693         struct swallow_notify_state *state = tevent_req_data(
10694                 req, struct swallow_notify_state);
10695         NTSTATUS status;
10696         uint32_t i, num_changes;
10697         struct notify_change *changes;
10698
10699         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10700         TALLOC_FREE(subreq);
10701         if (!NT_STATUS_IS_OK(status)) {
10702                 DEBUG(10, ("cli_notify_recv returned %s\n",
10703                            nt_errstr(status)));
10704                 tevent_req_nterror(req, status);
10705                 return;
10706         }
10707
10708         for (i=0; i<num_changes; i++) {
10709                 state->fn(changes[i].action, changes[i].name, state->priv);
10710         }
10711         TALLOC_FREE(changes);
10712
10713         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10714                                  0xffff, state->completion_filter,
10715                                  state->recursive);
10716         if (tevent_req_nomem(subreq, req)) {
10717                 return;
10718         }
10719         tevent_req_set_callback(subreq, swallow_notify_done, req);
10720 }
10721
10722 static bool print_notifies(uint32_t action, const char *name, void *priv)
10723 {
10724         if (DEBUGLEVEL > 5) {
10725                 d_printf("%d %s\n", (int)action, name);
10726         }
10727         return true;
10728 }
10729
10730 static void notify_bench_done(struct tevent_req *req)
10731 {
10732         int *num_finished = (int *)tevent_req_callback_data_void(req);
10733         *num_finished += 1;
10734 }
10735
10736 static bool run_notify_bench(int dummy)
10737 {
10738         const char *dname = "\\notify-bench";
10739         struct tevent_context *ev;
10740         NTSTATUS status;
10741         uint16_t dnum;
10742         struct tevent_req *req1;
10743         struct tevent_req *req2 = NULL;
10744         int i, num_unc_names;
10745         int num_finished = 0;
10746
10747         printf("starting notify-bench test\n");
10748
10749         if (use_multishare_conn) {
10750                 char **unc_list;
10751                 unc_list = file_lines_load(multishare_conn_fname,
10752                                            &num_unc_names, 0, NULL);
10753                 if (!unc_list || num_unc_names <= 0) {
10754                         d_printf("Failed to load unc names list from '%s'\n",
10755                                  multishare_conn_fname);
10756                         return false;
10757                 }
10758                 TALLOC_FREE(unc_list);
10759         } else {
10760                 num_unc_names = 1;
10761         }
10762
10763         ev = samba_tevent_context_init(talloc_tos());
10764         if (ev == NULL) {
10765                 d_printf("tevent_context_init failed\n");
10766                 return false;
10767         }
10768
10769         for (i=0; i<num_unc_names; i++) {
10770                 struct cli_state *cli;
10771                 char *base_fname;
10772
10773                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10774                                              dname, i);
10775                 if (base_fname == NULL) {
10776                         return false;
10777                 }
10778
10779                 if (!torture_open_connection(&cli, i)) {
10780                         return false;
10781                 }
10782
10783                 status = cli_ntcreate(cli, dname, 0,
10784                                       MAXIMUM_ALLOWED_ACCESS,
10785                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10786                                       FILE_SHARE_DELETE,
10787                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10788                                       &dnum, NULL);
10789
10790                 if (!NT_STATUS_IS_OK(status)) {
10791                         d_printf("Could not create %s: %s\n", dname,
10792                                  nt_errstr(status));
10793                         return false;
10794                 }
10795
10796                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10797                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10798                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10799                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10800                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10801                                            false, print_notifies, NULL);
10802                 if (req1 == NULL) {
10803                         d_printf("Could not create notify request\n");
10804                         return false;
10805                 }
10806
10807                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10808                                                base_fname, 10, torture_numops);
10809                 if (req2 == NULL) {
10810                         d_printf("Could not create createdels request\n");
10811                         return false;
10812                 }
10813                 TALLOC_FREE(base_fname);
10814
10815                 tevent_req_set_callback(req2, notify_bench_done,
10816                                         &num_finished);
10817         }
10818
10819         while (num_finished < num_unc_names) {
10820                 int ret;
10821                 ret = tevent_loop_once(ev);
10822                 if (ret != 0) {
10823                         d_printf("tevent_loop_once failed\n");
10824                         return false;
10825                 }
10826         }
10827
10828         if (!tevent_req_poll(req2, ev)) {
10829                 d_printf("tevent_req_poll failed\n");
10830         }
10831
10832         status = torture_createdels_recv(req2);
10833         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10834
10835         return true;
10836 }
10837
10838 static bool run_mangle1(int dummy)
10839 {
10840         struct cli_state *cli;
10841         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10842         uint16_t fnum;
10843         fstring alt_name;
10844         NTSTATUS status;
10845         time_t change_time, access_time, write_time;
10846         off_t size;
10847         uint32_t attr;
10848
10849         printf("starting mangle1 test\n");
10850         if (!torture_open_connection(&cli, 0)) {
10851                 return False;
10852         }
10853
10854         smbXcli_conn_set_sockopt(cli->conn, sockops);
10855
10856         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10857                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10858                               0, 0, &fnum, NULL);
10859         if (!NT_STATUS_IS_OK(status)) {
10860                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10861                 return false;
10862         }
10863         cli_close(cli, fnum);
10864
10865         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10866         if (!NT_STATUS_IS_OK(status)) {
10867                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10868                          nt_errstr(status));
10869                 return false;
10870         }
10871         d_printf("alt_name: %s\n", alt_name);
10872
10873         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10874         if (!NT_STATUS_IS_OK(status)) {
10875                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10876                          nt_errstr(status));
10877                 return false;
10878         }
10879         cli_close(cli, fnum);
10880
10881         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10882                                 &write_time, &size, &attr);
10883         if (!NT_STATUS_IS_OK(status)) {
10884                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10885                          nt_errstr(status));
10886                 return false;
10887         }
10888
10889         return true;
10890 }
10891
10892 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
10893                                                  const char *mask,
10894                                                  void *state)
10895 {
10896         if (f->short_name == NULL) {
10897                 return NT_STATUS_OK;
10898         }
10899
10900         if (strlen(f->short_name) == 0) {
10901                 return NT_STATUS_OK;
10902         }
10903
10904         printf("unexpected shortname: %s\n", f->short_name);
10905
10906         return NT_STATUS_OBJECT_NAME_INVALID;
10907 }
10908
10909 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
10910                                             const char *mask,
10911                                             void *state)
10912 {
10913         char *name = state;
10914
10915         printf("name: %s\n", f->name);
10916         fstrcpy(name, f->name);
10917         return NT_STATUS_OK;
10918 }
10919
10920 static bool run_mangle_illegal(int dummy)
10921 {
10922         struct cli_state *cli = NULL;
10923         struct cli_state *cli_posix = NULL;
10924         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10925         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10926         char *mangled_path = NULL;
10927         uint16_t fnum;
10928         fstring name;
10929         fstring alt_name;
10930         NTSTATUS status;
10931
10932         printf("starting mangle-illegal test\n");
10933
10934         if (!torture_open_connection(&cli, 0)) {
10935                 return False;
10936         }
10937
10938         smbXcli_conn_set_sockopt(cli->conn, sockops);
10939
10940         if (!torture_open_connection(&cli_posix, 0)) {
10941                 return false;
10942         }
10943
10944         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10945
10946         status = torture_setup_unix_extensions(cli_posix);
10947         if (!NT_STATUS_IS_OK(status)) {
10948                 return false;
10949         }
10950
10951         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10952         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10953         if (!NT_STATUS_IS_OK(status)) {
10954                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10955                 return False;
10956         }
10957
10958         /*
10959          * Create a file with illegal NTFS characters and test that we
10960          * get a usable mangled name
10961          */
10962
10963         cli_setatr(cli_posix, illegal_fname, 0, 0);
10964         cli_posix_unlink(cli_posix, illegal_fname);
10965
10966         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10967                                 0600, &fnum);
10968         if (!NT_STATUS_IS_OK(status)) {
10969                 printf("POSIX create of %s failed (%s)\n",
10970                        illegal_fname, nt_errstr(status));
10971                 return false;
10972         }
10973
10974         status = cli_close(cli_posix, fnum);
10975         if (!NT_STATUS_IS_OK(status)) {
10976                 printf("close failed (%s)\n", nt_errstr(status));
10977                 return false;
10978         }
10979
10980         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10981         if (!NT_STATUS_IS_OK(status)) {
10982                 d_printf("cli_list failed: %s\n", nt_errstr(status));
10983                 return false;
10984         }
10985
10986         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10987         if (mangled_path == NULL) {
10988                 return false;
10989         }
10990
10991         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
10992         if (!NT_STATUS_IS_OK(status)) {
10993                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
10994                 TALLOC_FREE(mangled_path);
10995                 return false;
10996         }
10997         TALLOC_FREE(mangled_path);
10998         cli_close(cli, fnum);
10999
11000         cli_setatr(cli_posix, illegal_fname, 0, 0);
11001         cli_posix_unlink(cli_posix, illegal_fname);
11002
11003         /*
11004          * Create a file with a long name and check that we got *no* short name.
11005          */
11006
11007         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11008                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11009                               0, 0, &fnum, NULL);
11010         if (!NT_STATUS_IS_OK(status)) {
11011                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11012                 return false;
11013         }
11014         cli_close(cli, fnum);
11015
11016         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11017         if (!NT_STATUS_IS_OK(status)) {
11018                 d_printf("cli_list failed\n");
11019                 return false;
11020         }
11021
11022         cli_unlink(cli, fname, 0);
11023         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11024
11025         if (!torture_close_connection(cli_posix)) {
11026                 return false;
11027         }
11028
11029         if (!torture_close_connection(cli)) {
11030                 return false;
11031         }
11032
11033         return true;
11034 }
11035
11036 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11037 {
11038         size_t *to_pull = (size_t *)priv;
11039         size_t thistime = *to_pull;
11040
11041         thistime = MIN(thistime, n);
11042         if (thistime == 0) {
11043                 return 0;
11044         }
11045
11046         memset(buf, 0, thistime);
11047         *to_pull -= thistime;
11048         return thistime;
11049 }
11050
11051 static bool run_windows_write(int dummy)
11052 {
11053         struct cli_state *cli1;
11054         uint16_t fnum;
11055         int i;
11056         bool ret = false;
11057         const char *fname = "\\writetest.txt";
11058         struct timeval start_time;
11059         double seconds;
11060         double kbytes;
11061         NTSTATUS status;
11062
11063         printf("starting windows_write test\n");
11064         if (!torture_open_connection(&cli1, 0)) {
11065                 return False;
11066         }
11067
11068         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11069         if (!NT_STATUS_IS_OK(status)) {
11070                 printf("open failed (%s)\n", nt_errstr(status));
11071                 return False;
11072         }
11073
11074         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11075
11076         start_time = timeval_current();
11077
11078         for (i=0; i<torture_numops; i++) {
11079                 uint8_t c = 0;
11080                 off_t start = i * torture_blocksize;
11081                 size_t to_pull = torture_blocksize - 1;
11082
11083                 status = cli_writeall(cli1, fnum, 0, &c,
11084                                       start + torture_blocksize - 1, 1, NULL);
11085                 if (!NT_STATUS_IS_OK(status)) {
11086                         printf("cli_write failed: %s\n", nt_errstr(status));
11087                         goto fail;
11088                 }
11089
11090                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11091                                   null_source, &to_pull);
11092                 if (!NT_STATUS_IS_OK(status)) {
11093                         printf("cli_push returned: %s\n", nt_errstr(status));
11094                         goto fail;
11095                 }
11096         }
11097
11098         seconds = timeval_elapsed(&start_time);
11099         kbytes = (double)torture_blocksize * torture_numops;
11100         kbytes /= 1024;
11101
11102         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11103                (double)seconds, (int)(kbytes/seconds));
11104
11105         ret = true;
11106  fail:
11107         cli_close(cli1, fnum);
11108         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11109         torture_close_connection(cli1);
11110         return ret;
11111 }
11112
11113 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11114 {
11115         size_t max_pdu = 0x1FFFF;
11116
11117         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11118                 max_pdu = 0xFFFFFF;
11119         }
11120
11121         if (smb1cli_conn_signing_is_active(cli->conn)) {
11122                 max_pdu = 0x1FFFF;
11123         }
11124
11125         if (smb1cli_conn_encryption_on(cli->conn)) {
11126                 max_pdu = CLI_BUFFER_SIZE;
11127         }
11128
11129         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11130                 len_requested &= 0xFFFF;
11131         }
11132
11133         return MIN(len_requested,
11134                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11135 }
11136
11137 static bool check_read_call(struct cli_state *cli,
11138                             uint16_t fnum,
11139                             uint8_t *buf,
11140                             size_t len_requested)
11141 {
11142         NTSTATUS status;
11143         struct tevent_req *subreq = NULL;
11144         ssize_t len_read = 0;
11145         size_t len_expected = 0;
11146         struct tevent_context *ev = NULL;
11147
11148         ev = samba_tevent_context_init(talloc_tos());
11149         if (ev == NULL) {
11150                 return false;
11151         }
11152
11153         subreq = cli_read_andx_send(talloc_tos(),
11154                                     ev,
11155                                     cli,
11156                                     fnum,
11157                                     0,
11158                                     len_requested);
11159
11160         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11161                 return false;
11162         }
11163
11164         status = cli_read_andx_recv(subreq, &len_read, &buf);
11165         if (!NT_STATUS_IS_OK(status)) {
11166                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11167                 return false;
11168         }
11169
11170         TALLOC_FREE(subreq);
11171         TALLOC_FREE(ev);
11172
11173         len_expected = calc_expected_return(cli, len_requested);
11174
11175         if (len_expected > 0x10000 && len_read == 0x10000) {
11176                 /* Windows servers only return a max of 0x10000,
11177                    doesn't matter if you set CAP_LARGE_READX in
11178                    the client sessionsetupX call or not. */
11179                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11180                         (unsigned int)len_requested);
11181         } else if (len_read != len_expected) {
11182                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11183                         (unsigned int)len_requested,
11184                         (unsigned int)len_read,
11185                         (unsigned int)len_expected);
11186                 return false;
11187         } else {
11188                 d_printf("Correct read reply.\n");
11189         }
11190
11191         return true;
11192 }
11193
11194 /* Test large readX variants. */
11195 static bool large_readx_tests(struct cli_state *cli,
11196                                 uint16_t fnum,
11197                                 uint8_t *buf)
11198 {
11199         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11200         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11201                 return false;
11202         }
11203         /* A read of 0x10000 should return 0x10000 bytes. */
11204         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11205                 return false;
11206         }
11207         /* A read of 0x10000 should return 0x10001 bytes. */
11208         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11209                 return false;
11210         }
11211         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11212            the requested number of bytes. */
11213         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11214                 return false;
11215         }
11216         /* A read of 1MB should return 1MB bytes (on Samba). */
11217         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11218                 return false;
11219         }
11220
11221         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11222                 return false;
11223         }
11224         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11225                 return false;
11226         }
11227         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11228                 return false;
11229         }
11230         return true;
11231 }
11232
11233 static bool run_large_readx(int dummy)
11234 {
11235         uint8_t *buf = NULL;
11236         struct cli_state *cli1 = NULL;
11237         struct cli_state *cli2 = NULL;
11238         bool correct = false;
11239         const char *fname = "\\large_readx.dat";
11240         NTSTATUS status;
11241         uint16_t fnum1 = UINT16_MAX;
11242         uint32_t normal_caps = 0;
11243         size_t file_size = 20*1024*1024;
11244         TALLOC_CTX *frame = talloc_stackframe();
11245         size_t i;
11246         struct {
11247                 const char *name;
11248                 enum smb_signing_setting signing_setting;
11249                 enum protocol_types protocol;
11250         } runs[] = {
11251                 {
11252                         .name = "NT1",
11253                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11254                         .protocol = PROTOCOL_NT1,
11255                 },{
11256                         .name = "NT1 - SIGNING_REQUIRED",
11257                         .signing_setting = SMB_SIGNING_REQUIRED,
11258                         .protocol = PROTOCOL_NT1,
11259                 },
11260         };
11261
11262         printf("starting large_readx test\n");
11263
11264         if (!torture_open_connection(&cli1, 0)) {
11265                 goto out;
11266         }
11267
11268         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11269
11270         if (!(normal_caps & CAP_LARGE_READX)) {
11271                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11272                         (unsigned int)normal_caps);
11273                 goto out;
11274         }
11275
11276         /* Create a file of size 4MB. */
11277         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11278                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11279                         0, 0, &fnum1, NULL);
11280
11281         if (!NT_STATUS_IS_OK(status)) {
11282                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11283                 goto out;
11284         }
11285
11286         /* Write file_size bytes. */
11287         buf = talloc_zero_array(frame, uint8_t, file_size);
11288         if (buf == NULL) {
11289                 goto out;
11290         }
11291
11292         status = cli_writeall(cli1,
11293                               fnum1,
11294                               0,
11295                               buf,
11296                               0,
11297                               file_size,
11298                               NULL);
11299         if (!NT_STATUS_IS_OK(status)) {
11300                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11301                 goto out;
11302         }
11303
11304         status = cli_close(cli1, fnum1);
11305         if (!NT_STATUS_IS_OK(status)) {
11306                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11307                 goto out;
11308         }
11309
11310         fnum1 = UINT16_MAX;
11311
11312         for (i=0; i < ARRAY_SIZE(runs); i++) {
11313                 enum smb_signing_setting saved_signing_setting = signing_state;
11314                 uint16_t fnum2 = -1;
11315
11316                 if (do_encrypt &&
11317                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11318                 {
11319                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11320                         continue;
11321                 }
11322
11323                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11324
11325                 signing_state = runs[i].signing_setting;
11326                 cli2 = open_nbt_connection();
11327                 signing_state = saved_signing_setting;
11328                 if (cli2 == NULL) {
11329                         goto out;
11330                 }
11331
11332                 status = smbXcli_negprot(cli2->conn,
11333                                          cli2->timeout,
11334                                          runs[i].protocol,
11335                                          runs[i].protocol);
11336                 if (!NT_STATUS_IS_OK(status)) {
11337                         goto out;
11338                 }
11339
11340                 status = cli_session_setup_creds(cli2, torture_creds);
11341                 if (!NT_STATUS_IS_OK(status)) {
11342                         goto out;
11343                 }
11344
11345                 status = cli_tree_connect(cli2,
11346                                         share,
11347                                         "?????",
11348                                         password);
11349                 if (!NT_STATUS_IS_OK(status)) {
11350                         goto out;
11351                 }
11352
11353                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11354
11355                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11356
11357                 if (!(normal_caps & CAP_LARGE_READX)) {
11358                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11359                                 (unsigned int)normal_caps);
11360                         goto out;
11361                 }
11362
11363                 if (do_encrypt) {
11364                         if (force_cli_encryption(cli2, share) == false) {
11365                                 goto out;
11366                         }
11367                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11368                         uint16_t major, minor;
11369                         uint32_t caplow, caphigh;
11370
11371                         status = cli_unix_extensions_version(cli2,
11372                                                              &major, &minor,
11373                                                              &caplow, &caphigh);
11374                         if (!NT_STATUS_IS_OK(status)) {
11375                                 goto out;
11376                         }
11377                 }
11378
11379                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11380                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11381                                 0, 0, &fnum2, NULL);
11382                 if (!NT_STATUS_IS_OK(status)) {
11383                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11384                         goto out;
11385                 }
11386
11387                 /* All reads must return less than file_size bytes. */
11388                 if (!large_readx_tests(cli2, fnum2, buf)) {
11389                         goto out;
11390                 }
11391
11392                 status = cli_close(cli2, fnum2);
11393                 if (!NT_STATUS_IS_OK(status)) {
11394                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11395                         goto out;
11396                 }
11397                 fnum2 = -1;
11398
11399                 if (!torture_close_connection(cli2)) {
11400                         goto out;
11401                 }
11402                 cli2 = NULL;
11403         }
11404
11405         correct = true;
11406         printf("Success on large_readx test\n");
11407
11408   out:
11409
11410         if (cli2) {
11411                 if (!torture_close_connection(cli2)) {
11412                         correct = false;
11413                 }
11414         }
11415
11416         if (cli1) {
11417                 if (fnum1 != UINT16_MAX) {
11418                         status = cli_close(cli1, fnum1);
11419                         if (!NT_STATUS_IS_OK(status)) {
11420                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11421                         }
11422                         fnum1 = UINT16_MAX;
11423                 }
11424
11425                 status = cli_unlink(cli1, fname,
11426                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11427                 if (!NT_STATUS_IS_OK(status)) {
11428                         printf("unlink failed (%s)\n", nt_errstr(status));
11429                 }
11430
11431                 if (!torture_close_connection(cli1)) {
11432                         correct = false;
11433                 }
11434         }
11435
11436         TALLOC_FREE(frame);
11437
11438         printf("finished large_readx test\n");
11439         return correct;
11440 }
11441
11442 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11443                                   const char *mask,
11444                                   void *private_data)
11445 {
11446         uint32_t *p_attr = (uint32_t *)private_data;
11447
11448         if (strequal(finfo->name, test_filename)) {
11449                 *p_attr = finfo->attr;
11450         }
11451
11452         return NT_STATUS_OK;
11453 }
11454
11455 static bool run_msdfs_attribute(int dummy)
11456 {
11457         static struct cli_state *cli;
11458         bool correct = false;
11459         uint32_t attr = 0;
11460         NTSTATUS status;
11461
11462         printf("Starting MSDFS-ATTRIBUTE test\n");
11463
11464         if (test_filename == NULL || test_filename[0] == '\0') {
11465                 printf("MSDFS-ATTRIBUTE test "
11466                         "needs -f filename-of-msdfs-link\n");
11467                 return false;
11468         }
11469
11470         /*
11471          * NB. We use torture_open_connection_flags() not
11472          * torture_open_connection() as the latter forces
11473          * SMB1.
11474          */
11475         if (!torture_open_connection_flags(&cli, 0, 0)) {
11476                 return false;
11477         }
11478
11479         smbXcli_conn_set_sockopt(cli->conn, sockops);
11480
11481         status = cli_list(cli,
11482                         "*",
11483                         FILE_ATTRIBUTE_DIRECTORY,
11484                         msdfs_attribute_list_fn,
11485                         &attr);
11486
11487         if (!NT_STATUS_IS_OK(status)) {
11488                 printf("cli_list failed with %s\n",
11489                         nt_errstr(status));
11490                 goto out;
11491         }
11492         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11493                 printf("file %s should have "
11494                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11495                         test_filename,
11496                         (unsigned int)attr);
11497                 goto out;
11498         }
11499
11500         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11501                 printf("file %s should have "
11502                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11503                         test_filename,
11504                         (unsigned int)attr);
11505                 goto out;
11506         }
11507
11508         correct = true;
11509
11510   out:
11511
11512         torture_close_connection(cli);
11513         return correct;
11514 }
11515
11516 static bool run_cli_echo(int dummy)
11517 {
11518         struct cli_state *cli;
11519         NTSTATUS status;
11520
11521         printf("starting cli_echo test\n");
11522         if (!torture_open_connection(&cli, 0)) {
11523                 return false;
11524         }
11525         smbXcli_conn_set_sockopt(cli->conn, sockops);
11526
11527         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11528
11529         d_printf("cli_echo returned %s\n", nt_errstr(status));
11530
11531         torture_close_connection(cli);
11532         return NT_STATUS_IS_OK(status);
11533 }
11534
11535 static int splice_status(off_t written, void *priv)
11536 {
11537         return true;
11538 }
11539
11540 static bool run_cli_splice(int dummy)
11541 {
11542         uint8_t *buf = NULL;
11543         struct cli_state *cli1 = NULL;
11544         bool correct = false;
11545         const char *fname_src = "\\splice_src.dat";
11546         const char *fname_dst = "\\splice_dst.dat";
11547         NTSTATUS status;
11548         uint16_t fnum1 = UINT16_MAX;
11549         uint16_t fnum2 = UINT16_MAX;
11550         size_t file_size = 2*1024*1024;
11551         size_t splice_size = 1*1024*1024 + 713;
11552         uint8_t digest1[16], digest2[16];
11553         off_t written = 0;
11554         size_t nread = 0;
11555         TALLOC_CTX *frame = talloc_stackframe();
11556
11557         printf("starting cli_splice test\n");
11558
11559         if (!torture_open_connection(&cli1, 0)) {
11560                 goto out;
11561         }
11562
11563         cli_unlink(cli1, fname_src,
11564                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11565         cli_unlink(cli1, fname_dst,
11566                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11567
11568         /* Create a file */
11569         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11570                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11571                         0, 0, &fnum1, NULL);
11572
11573         if (!NT_STATUS_IS_OK(status)) {
11574                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11575                 goto out;
11576         }
11577
11578         /* Write file_size bytes - must be bigger than splice_size. */
11579         buf = talloc_zero_array(frame, uint8_t, file_size);
11580         if (buf == NULL) {
11581                 d_printf("talloc_fail\n");
11582                 goto out;
11583         }
11584
11585         /* Fill it with random numbers. */
11586         generate_random_buffer(buf, file_size);
11587
11588         /* MD5 the first 1MB + 713 bytes. */
11589         gnutls_hash_fast(GNUTLS_DIG_MD5,
11590                          buf,
11591                          splice_size,
11592                          digest1);
11593
11594         status = cli_writeall(cli1,
11595                               fnum1,
11596                               0,
11597                               buf,
11598                               0,
11599                               file_size,
11600                               NULL);
11601         if (!NT_STATUS_IS_OK(status)) {
11602                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11603                 goto out;
11604         }
11605
11606         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11607                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11608                         0, 0, &fnum2, NULL);
11609
11610         if (!NT_STATUS_IS_OK(status)) {
11611                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11612                 goto out;
11613         }
11614
11615         /* Now splice 1MB + 713 bytes. */
11616         status = cli_splice(cli1,
11617                                 cli1,
11618                                 fnum1,
11619                                 fnum2,
11620                                 splice_size,
11621                                 0,
11622                                 0,
11623                                 &written,
11624                                 splice_status,
11625                                 NULL);
11626
11627         if (!NT_STATUS_IS_OK(status)) {
11628                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11629                 goto out;
11630         }
11631
11632         /* Clear the old buffer. */
11633         memset(buf, '\0', file_size);
11634
11635         /* Read the new file. */
11636         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11637         if (!NT_STATUS_IS_OK(status)) {
11638                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11639                 goto out;
11640         }
11641         if (nread != splice_size) {
11642                 d_printf("bad read of 0x%x, should be 0x%x\n",
11643                         (unsigned int)nread,
11644                         (unsigned int)splice_size);
11645                 goto out;
11646         }
11647
11648         /* MD5 the first 1MB + 713 bytes. */
11649         gnutls_hash_fast(GNUTLS_DIG_MD5,
11650                          buf,
11651                          splice_size,
11652                          digest2);
11653
11654         /* Must be the same. */
11655         if (memcmp(digest1, digest2, 16) != 0) {
11656                 d_printf("bad MD5 compare\n");
11657                 goto out;
11658         }
11659
11660         correct = true;
11661         printf("Success on cli_splice test\n");
11662
11663   out:
11664
11665         if (cli1) {
11666                 if (fnum1 != UINT16_MAX) {
11667                         cli_close(cli1, fnum1);
11668                 }
11669                 if (fnum2 != UINT16_MAX) {
11670                         cli_close(cli1, fnum2);
11671                 }
11672
11673                 cli_unlink(cli1, fname_src,
11674                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11675                 cli_unlink(cli1, fname_dst,
11676                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11677
11678                 if (!torture_close_connection(cli1)) {
11679                         correct = false;
11680                 }
11681         }
11682
11683         TALLOC_FREE(frame);
11684         return correct;
11685 }
11686
11687 static bool run_uid_regression_test(int dummy)
11688 {
11689         static struct cli_state *cli;
11690         int16_t old_vuid;
11691         int32_t old_cnum;
11692         bool correct = True;
11693         struct smbXcli_tcon *tcon_copy = NULL;
11694         NTSTATUS status;
11695
11696         printf("starting uid regression test\n");
11697
11698         if (!torture_open_connection(&cli, 0)) {
11699                 return False;
11700         }
11701
11702         smbXcli_conn_set_sockopt(cli->conn, sockops);
11703
11704         /* Ok - now save then logoff our current user. */
11705         old_vuid = cli_state_get_uid(cli);
11706
11707         status = cli_ulogoff(cli);
11708         if (!NT_STATUS_IS_OK(status)) {
11709                 d_printf("(%s) cli_ulogoff failed: %s\n",
11710                          __location__, nt_errstr(status));
11711                 correct = false;
11712                 goto out;
11713         }
11714
11715         cli_state_set_uid(cli, old_vuid);
11716
11717         /* Try an operation. */
11718         status = cli_mkdir(cli, "\\uid_reg_test");
11719         if (NT_STATUS_IS_OK(status)) {
11720                 d_printf("(%s) cli_mkdir succeeded\n",
11721                          __location__);
11722                 correct = false;
11723                 goto out;
11724         } else {
11725                 /* Should be bad uid. */
11726                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11727                                  NT_STATUS_USER_SESSION_DELETED)) {
11728                         correct = false;
11729                         goto out;
11730                 }
11731         }
11732
11733         old_cnum = cli_state_get_tid(cli);
11734         /*
11735          * This is an SMB1-only test.
11736          * Copy the tcon, not "save/restore".
11737          *
11738          * In SMB1 the cli_tdis() below frees
11739          * cli->smb1.tcon so we need a copy
11740          * of the struct to put back for the
11741          * second tdis call with invalid vuid.
11742          *
11743          * This is a test-only hack. Real client code
11744          * uses cli_state_save_tcon()/cli_state_restore_tcon().
11745          */
11746         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11747         if (tcon_copy == NULL) {
11748                 correct = false;
11749                 goto out;
11750         }
11751
11752         /* Now try a SMBtdis with the invalid vuid set to zero. */
11753         cli_state_set_uid(cli, 0);
11754
11755         /* This should succeed. */
11756         status = cli_tdis(cli);
11757
11758         if (NT_STATUS_IS_OK(status)) {
11759                 d_printf("First tdis with invalid vuid should succeed.\n");
11760         } else {
11761                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11762                 correct = false;
11763                 cli->smb1.tcon = tcon_copy;
11764                 goto out;
11765         }
11766
11767         cli->smb1.tcon = tcon_copy;
11768         cli_state_set_uid(cli, old_vuid);
11769         cli_state_set_tid(cli, old_cnum);
11770
11771         /* This should fail. */
11772         status = cli_tdis(cli);
11773         if (NT_STATUS_IS_OK(status)) {
11774                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11775                 correct = false;
11776                 goto out;
11777         } else {
11778                 /* Should be bad tid. */
11779                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11780                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11781                         correct = false;
11782                         goto out;
11783                 }
11784         }
11785
11786         cli_rmdir(cli, "\\uid_reg_test");
11787
11788   out:
11789
11790         cli_shutdown(cli);
11791         return correct;
11792 }
11793
11794
11795 static const char *illegal_chars = "*\\/?<>|\":";
11796 static char force_shortname_chars[] = " +,.[];=\177";
11797
11798 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11799                              const char *mask, void *state)
11800 {
11801         struct cli_state *pcli = (struct cli_state *)state;
11802         fstring fname;
11803         NTSTATUS status = NT_STATUS_OK;
11804
11805         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11806
11807         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11808                 return NT_STATUS_OK;
11809
11810         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11811                 status = cli_rmdir(pcli, fname);
11812                 if (!NT_STATUS_IS_OK(status)) {
11813                         printf("del_fn: failed to rmdir %s\n,", fname );
11814                 }
11815         } else {
11816                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11817                 if (!NT_STATUS_IS_OK(status)) {
11818                         printf("del_fn: failed to unlink %s\n,", fname );
11819                 }
11820         }
11821         return status;
11822 }
11823
11824 struct sn_state {
11825         int matched;
11826         int i;
11827         bool val;
11828 };
11829
11830 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11831                               const char *name, void *state)
11832 {
11833         struct sn_state *s = (struct sn_state  *)state;
11834         int i = s->i;
11835
11836 #if 0
11837         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11838                 i, finfo->name, finfo->short_name);
11839 #endif
11840
11841         if (strchr(force_shortname_chars, i)) {
11842                 if (!finfo->short_name) {
11843                         /* Shortname not created when it should be. */
11844                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11845                                 __location__, finfo->name, i);
11846                         s->val = true;
11847                 }
11848         } else if (finfo->short_name){
11849                 /* Shortname created when it should not be. */
11850                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11851                         __location__, finfo->short_name, finfo->name);
11852                 s->val = true;
11853         }
11854         s->matched += 1;
11855         return NT_STATUS_OK;
11856 }
11857
11858 static bool run_shortname_test(int dummy)
11859 {
11860         static struct cli_state *cli;
11861         bool correct = True;
11862         int i;
11863         struct sn_state s;
11864         char fname[40];
11865         NTSTATUS status;
11866
11867         printf("starting shortname test\n");
11868
11869         if (!torture_open_connection(&cli, 0)) {
11870                 return False;
11871         }
11872
11873         smbXcli_conn_set_sockopt(cli->conn, sockops);
11874
11875         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11876         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11877         cli_rmdir(cli, "\\shortname");
11878
11879         status = cli_mkdir(cli, "\\shortname");
11880         if (!NT_STATUS_IS_OK(status)) {
11881                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11882                         __location__, nt_errstr(status));
11883                 correct = false;
11884                 goto out;
11885         }
11886
11887         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11888                 correct = false;
11889                 goto out;
11890         }
11891         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11892                 correct = false;
11893                 goto out;
11894         }
11895
11896         s.val = false;
11897
11898         for (i = 32; i < 128; i++) {
11899                 uint16_t fnum = (uint16_t)-1;
11900
11901                 s.i = i;
11902
11903                 if (strchr(illegal_chars, i)) {
11904                         continue;
11905                 }
11906                 fname[15] = i;
11907
11908                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11909                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
11910                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11911                 if (!NT_STATUS_IS_OK(status)) {
11912                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
11913                                 __location__, fname, nt_errstr(status));
11914                         correct = false;
11915                         goto out;
11916                 }
11917                 cli_close(cli, fnum);
11918
11919                 s.matched = 0;
11920                 status = cli_list(cli, "\\shortname\\test*.*", 0,
11921                                   shortname_list_fn, &s);
11922                 if (s.matched != 1) {
11923                         d_printf("(%s) failed to list %s: %s\n",
11924                                 __location__, fname, nt_errstr(status));
11925                         correct = false;
11926                         goto out;
11927                 }
11928
11929                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930                 if (!NT_STATUS_IS_OK(status)) {
11931                         d_printf("(%s) failed to delete %s: %s\n",
11932                                 __location__, fname, nt_errstr(status));
11933                         correct = false;
11934                         goto out;
11935                 }
11936
11937                 if (s.val) {
11938                         correct = false;
11939                         goto out;
11940                 }
11941         }
11942
11943   out:
11944
11945         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11946         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11947         cli_rmdir(cli, "\\shortname");
11948         torture_close_connection(cli);
11949         return correct;
11950 }
11951
11952 TLDAPRC callback_code;
11953
11954 static void pagedsearch_cb(struct tevent_req *req)
11955 {
11956         TLDAPRC rc;
11957         struct tldap_message *msg;
11958         char *dn;
11959
11960         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11961         if (!TLDAP_RC_IS_SUCCESS(rc)) {
11962                 d_printf("tldap_search_paged_recv failed: %s\n",
11963                          tldap_rc2string(rc));
11964                 callback_code = rc;
11965                 return;
11966         }
11967         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11968                 TALLOC_FREE(msg);
11969                 return;
11970         }
11971         if (!tldap_entry_dn(msg, &dn)) {
11972                 d_printf("tldap_entry_dn failed\n");
11973                 return;
11974         }
11975         d_printf("%s\n", dn);
11976         TALLOC_FREE(msg);
11977 }
11978
11979 enum tldap_extended_val {
11980         EXTENDED_ZERO = 0,
11981         EXTENDED_ONE = 1,
11982         EXTENDED_NONE = 2,
11983 };
11984
11985 /*
11986  * Construct an extended dn control with either no value, 0 or 1
11987  *
11988  * No value and 0 are equivalent (non-hyphenated GUID)
11989  * 1 has the hyphenated GUID
11990  */
11991 static struct tldap_control *
11992 tldap_build_extended_control(enum tldap_extended_val val)
11993 {
11994         struct tldap_control empty_control;
11995         struct asn1_data *data;
11996
11997         ZERO_STRUCT(empty_control);
11998
11999         if (val != EXTENDED_NONE) {
12000                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12001
12002                 if (!data) {
12003                         return NULL;
12004                 }
12005
12006                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12007                         return NULL;
12008                 }
12009
12010                 if (!asn1_write_Integer(data, (int)val)) {
12011                         return NULL;
12012                 }
12013
12014                 if (!asn1_pop_tag(data)) {
12015                         return NULL;
12016                 }
12017
12018                 if (!asn1_blob(data, &empty_control.value)) {
12019                         return NULL;
12020                 }
12021         }
12022
12023         empty_control.oid = "1.2.840.113556.1.4.529";
12024         empty_control.critical = true;
12025
12026         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12027
12028 }
12029
12030 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12031                                       enum tldap_extended_val control_val)
12032 {
12033         struct tldap_control *control = tldap_build_extended_control(control_val);
12034         char *dn = NULL;
12035         struct tldap_message **msg;
12036         TLDAPRC rc;
12037
12038         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12039                           "(objectClass=*)", NULL, 0, 0,
12040                           control, 1, NULL,
12041                           0, 0, 0, 0, talloc_tos(), &msg);
12042         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12043                 d_printf("tldap_search for domain DN failed: %s\n",
12044                          tldap_errstr(talloc_tos(), ld, rc));
12045                 return false;
12046         }
12047
12048         if (!tldap_entry_dn(msg[0], &dn)) {
12049                 d_printf("tldap_search domain DN fetch failed: %s\n",
12050                          tldap_errstr(talloc_tos(), ld, rc));
12051                 return false;
12052         }
12053
12054         d_printf("%s\n", dn);
12055         {
12056                 uint32_t time_low;
12057                 uint32_t time_mid, time_hi_and_version;
12058                 uint32_t clock_seq[2];
12059                 uint32_t node[6];
12060                 char next;
12061
12062                 switch (control_val) {
12063                 case EXTENDED_NONE:
12064                 case EXTENDED_ZERO:
12065                         /*
12066                          * When reading GUIDs with hyphens, scanf will treat
12067                          * hyphen as a hex character (and counts as part of the
12068                          * width). This creates leftover GUID string which we
12069                          * check will for with 'next' and closing '>'.
12070                          */
12071                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12072                                          &time_low, &time_mid,
12073                                          &time_hi_and_version, &clock_seq[0],
12074                                          &clock_seq[1], &node[0], &node[1],
12075                                          &node[2], &node[3], &node[4],
12076                                          &node[5], &next)) {
12077                                 /* This GUID is good */
12078                         } else {
12079                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12080                                 return false;
12081                         }
12082
12083                         break;
12084                 case EXTENDED_ONE:
12085                         if (12 == sscanf(dn,
12086                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12087                                          &time_low, &time_mid,
12088                                          &time_hi_and_version, &clock_seq[0],
12089                                          &clock_seq[1], &node[0], &node[1],
12090                                          &node[2], &node[3], &node[4],
12091                                          &node[5], &next)) {
12092                                 /* This GUID is good */
12093                         } else {
12094                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12095                                 return false;
12096                         }
12097
12098                         break;
12099                 default:
12100                         return false;
12101                 }
12102         }
12103
12104         return true;
12105 }
12106
12107 static bool run_tldap(int dummy)
12108 {
12109         struct tldap_context *ld;
12110         int fd;
12111         TLDAPRC rc;
12112         NTSTATUS status;
12113         struct sockaddr_storage addr;
12114         struct tevent_context *ev;
12115         struct tevent_req *req;
12116         char *basedn;
12117         const char *filter;
12118
12119         if (!resolve_name(host, &addr, 0, false)) {
12120                 d_printf("could not find host %s\n", host);
12121                 return false;
12122         }
12123         status = open_socket_out(&addr, 389, 9999, &fd);
12124         if (!NT_STATUS_IS_OK(status)) {
12125                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12126                 return false;
12127         }
12128
12129         ld = tldap_context_create(talloc_tos(), fd);
12130         if (ld == NULL) {
12131                 close(fd);
12132                 d_printf("tldap_context_create failed\n");
12133                 return false;
12134         }
12135
12136         rc = tldap_fetch_rootdse(ld);
12137         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12138                 d_printf("tldap_fetch_rootdse failed: %s\n",
12139                          tldap_errstr(talloc_tos(), ld, rc));
12140                 return false;
12141         }
12142
12143         basedn = tldap_talloc_single_attribute(
12144                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12145         if (basedn == NULL) {
12146                 d_printf("no defaultNamingContext\n");
12147                 return false;
12148         }
12149         d_printf("defaultNamingContext: %s\n", basedn);
12150
12151         ev = samba_tevent_context_init(talloc_tos());
12152         if (ev == NULL) {
12153                 d_printf("tevent_context_init failed\n");
12154                 return false;
12155         }
12156
12157         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12158                                loadparm_init_s3(talloc_tos(),
12159                                                 loadparm_s3_helpers()),
12160                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12161
12162         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12163                 d_printf("tldap_gensec_bind failed\n");
12164                 return false;
12165         }
12166
12167         callback_code = TLDAP_SUCCESS;
12168
12169         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12170                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12171                                       NULL, 0, 0,
12172                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12173         if (req == NULL) {
12174                 d_printf("tldap_search_paged_send failed\n");
12175                 return false;
12176         }
12177         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12178
12179         tevent_req_poll(req, ev);
12180
12181         TALLOC_FREE(req);
12182
12183         rc = callback_code;
12184
12185         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12186                 d_printf("tldap_search with paging failed: %s\n",
12187                          tldap_errstr(talloc_tos(), ld, rc));
12188                 return false;
12189         }
12190
12191         /* test search filters against rootDSE */
12192         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12193                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12194
12195         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12196                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12197                           talloc_tos(), NULL);
12198         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12199                 d_printf("tldap_search with complex filter failed: %s\n",
12200                          tldap_errstr(talloc_tos(), ld, rc));
12201                 return false;
12202         }
12203
12204         /*
12205          * Tests to check for regression of:
12206          *
12207          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12208          *
12209          * TLDAP used here to pick apart the original string DN (with GUID)
12210          */
12211         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12212                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12213                          tldap_errstr(talloc_tos(), ld, rc));
12214                 return false;
12215         }
12216         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12217                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12218                          tldap_errstr(talloc_tos(), ld, rc));
12219                 return false;
12220         }
12221         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12222                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12223                          tldap_errstr(talloc_tos(), ld, rc));
12224                 return false;
12225         }
12226
12227         TALLOC_FREE(ld);
12228         return true;
12229 }
12230
12231 /* Torture test to ensure no regression of :
12232 https://bugzilla.samba.org/show_bug.cgi?id=7084
12233 */
12234
12235 static bool run_dir_createtime(int dummy)
12236 {
12237         struct cli_state *cli;
12238         const char *dname = "\\testdir_createtime";
12239         const char *fname = "\\testdir_createtime\\testfile";
12240         NTSTATUS status;
12241         struct timespec create_time;
12242         struct timespec create_time1;
12243         uint16_t fnum;
12244         bool ret = false;
12245         uint64_t ino;
12246
12247         if (!torture_open_connection(&cli, 0)) {
12248                 return false;
12249         }
12250
12251         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12252                 /* Ensure ino is zero, SMB2 gets a real one. */
12253                 ino = 0;
12254         } else {
12255                 /* Ensure ino is -1, SMB1 never gets a real one. */
12256                 ino = (uint64_t)-1;
12257         }
12258
12259         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12260         cli_rmdir(cli, dname);
12261
12262         status = cli_mkdir(cli, dname);
12263         if (!NT_STATUS_IS_OK(status)) {
12264                 printf("mkdir failed: %s\n", nt_errstr(status));
12265                 goto out;
12266         }
12267
12268         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12269                                 NULL, NULL, &ino);
12270         if (!NT_STATUS_IS_OK(status)) {
12271                 printf("cli_qpathinfo2 returned %s\n",
12272                        nt_errstr(status));
12273                 goto out;
12274         }
12275
12276         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12277                 /* SMB2 should always return an inode. */
12278                 if (ino == 0) {
12279                         printf("SMB2 bad inode (0)\n");
12280                         goto out;
12281                 }
12282         } else {
12283                 /* SMB1 must always return zero here. */
12284                 if (ino != 0) {
12285                         printf("SMB1 bad inode (!0)\n");
12286                         goto out;
12287                 }
12288         }
12289
12290         /* Sleep 3 seconds, then create a file. */
12291         sleep(3);
12292
12293         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12294                          DENY_NONE, &fnum);
12295         if (!NT_STATUS_IS_OK(status)) {
12296                 printf("cli_openx failed: %s\n", nt_errstr(status));
12297                 goto out;
12298         }
12299
12300         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12301                                 NULL, NULL, NULL);
12302         if (!NT_STATUS_IS_OK(status)) {
12303                 printf("cli_qpathinfo2 (2) returned %s\n",
12304                        nt_errstr(status));
12305                 goto out;
12306         }
12307
12308         if (timespec_compare(&create_time1, &create_time)) {
12309                 printf("run_dir_createtime: create time was updated (error)\n");
12310         } else {
12311                 printf("run_dir_createtime: create time was not updated (correct)\n");
12312                 ret = true;
12313         }
12314
12315   out:
12316
12317         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12318         cli_rmdir(cli, dname);
12319         if (!torture_close_connection(cli)) {
12320                 ret = false;
12321         }
12322         return ret;
12323 }
12324
12325
12326 static bool run_streamerror(int dummy)
12327 {
12328         struct cli_state *cli;
12329         const char *dname = "\\testdir_streamerror";
12330         const char *streamname =
12331                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12332         NTSTATUS status;
12333         time_t change_time, access_time, write_time;
12334         off_t size;
12335         uint16_t fnum;
12336         uint32_t attr;
12337         bool ret = true;
12338
12339         if (!torture_open_connection(&cli, 0)) {
12340                 return false;
12341         }
12342
12343         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12344         cli_rmdir(cli, dname);
12345
12346         status = cli_mkdir(cli, dname);
12347         if (!NT_STATUS_IS_OK(status)) {
12348                 printf("mkdir failed: %s\n", nt_errstr(status));
12349                 return false;
12350         }
12351
12352         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12353                                 &write_time, &size, &attr);
12354         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12355                 printf("pathinfo returned %s, expected "
12356                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12357                        nt_errstr(status));
12358                 ret = false;
12359         }
12360
12361         status = cli_ntcreate(cli, streamname, 0x16,
12362                               FILE_READ_DATA|FILE_READ_EA|
12363                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12364                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12365                               FILE_OPEN, 0, 0, &fnum, NULL);
12366
12367         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12368                 printf("ntcreate returned %s, expected "
12369                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12370                        nt_errstr(status));
12371                 ret = false;
12372         }
12373
12374
12375         cli_rmdir(cli, dname);
12376         return ret;
12377 }
12378
12379 struct pidtest_state {
12380         bool success;
12381         uint16_t vwv[1];
12382         DATA_BLOB data;
12383 };
12384
12385 static void pid_echo_done(struct tevent_req *subreq);
12386
12387 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12388                         struct tevent_context *ev,
12389                         struct cli_state *cli)
12390 {
12391         struct tevent_req *req, *subreq;
12392         struct pidtest_state *state;
12393
12394         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12395         if (req == NULL) {
12396                 return NULL;
12397         }
12398
12399         SSVAL(state->vwv, 0, 1);
12400         state->data = data_blob_const("hello", 5);
12401
12402         subreq = smb1cli_req_send(state,
12403                                 ev,
12404                                 cli->conn,
12405                                 SMBecho,
12406                                 0, 0, /* *_flags */
12407                                 0, 0, /* *_flags2 */
12408                                 cli->timeout,
12409                                 0xDEADBEEF, /* pid */
12410                                 NULL, /* tcon */
12411                                 NULL, /* session */
12412                                 ARRAY_SIZE(state->vwv), state->vwv,
12413                                 state->data.length, state->data.data);
12414
12415         if (tevent_req_nomem(subreq, req)) {
12416                 return tevent_req_post(req, ev);
12417         }
12418         tevent_req_set_callback(subreq, pid_echo_done, req);
12419         return req;
12420 }
12421
12422 static void pid_echo_done(struct tevent_req *subreq)
12423 {
12424         struct tevent_req *req = tevent_req_callback_data(
12425                 subreq, struct tevent_req);
12426         struct pidtest_state *state = tevent_req_data(
12427                 req, struct pidtest_state);
12428         NTSTATUS status;
12429         uint32_t num_bytes;
12430         uint8_t *bytes = NULL;
12431         struct iovec *recv_iov = NULL;
12432         uint8_t *phdr = NULL;
12433         uint16_t pidlow = 0;
12434         uint16_t pidhigh = 0;
12435         struct smb1cli_req_expected_response expected[] = {
12436         {
12437                 .status = NT_STATUS_OK,
12438                 .wct    = 1,
12439         },
12440         };
12441
12442         status = smb1cli_req_recv(subreq, state,
12443                                 &recv_iov,
12444                                 &phdr,
12445                                 NULL, /* pwct */
12446                                 NULL, /* pvwv */
12447                                 NULL, /* pvwv_offset */
12448                                 &num_bytes,
12449                                 &bytes,
12450                                 NULL, /* pbytes_offset */
12451                                 NULL, /* pinbuf */
12452                                 expected, ARRAY_SIZE(expected));
12453
12454         TALLOC_FREE(subreq);
12455
12456         if (!NT_STATUS_IS_OK(status)) {
12457                 tevent_req_nterror(req, status);
12458                 return;
12459         }
12460
12461         if (num_bytes != state->data.length) {
12462                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12463                 return;
12464         }
12465
12466         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12467                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12468                 return;
12469         }
12470
12471         /* Check pid low/high == DEADBEEF */
12472         pidlow = SVAL(phdr, HDR_PID);
12473         if (pidlow != 0xBEEF){
12474                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12475                         (unsigned int)pidlow);
12476                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12477                 return;
12478         }
12479         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12480         if (pidhigh != 0xDEAD){
12481                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12482                         (unsigned int)pidhigh);
12483                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12484                 return;
12485         }
12486
12487         tevent_req_done(req);
12488 }
12489
12490 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12491 {
12492         return tevent_req_simple_recv_ntstatus(req);
12493 }
12494
12495 static bool run_pidhigh(int dummy)
12496 {
12497         bool success = false;
12498         struct cli_state *cli = NULL;
12499         NTSTATUS status;
12500         struct tevent_context *ev = NULL;
12501         struct tevent_req *req = NULL;
12502         TALLOC_CTX *frame = talloc_stackframe();
12503
12504         printf("starting pid high test\n");
12505         if (!torture_open_connection(&cli, 0)) {
12506                 return false;
12507         }
12508         smbXcli_conn_set_sockopt(cli->conn, sockops);
12509
12510         ev = samba_tevent_context_init(frame);
12511         if (ev == NULL) {
12512                 goto fail;
12513         }
12514
12515         req = pid_echo_send(frame, ev, cli);
12516         if (req == NULL) {
12517                 goto fail;
12518         }
12519
12520         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12521                 goto fail;
12522         }
12523
12524         status = pid_echo_recv(req);
12525         if (NT_STATUS_IS_OK(status)) {
12526                 printf("pid high test ok\n");
12527                 success = true;
12528         }
12529
12530  fail:
12531
12532         TALLOC_FREE(frame);
12533         torture_close_connection(cli);
12534         return success;
12535 }
12536
12537 /*
12538   Test Windows open on a bad POSIX symlink.
12539  */
12540 static bool run_symlink_open_test(int dummy)
12541 {
12542         static struct cli_state *cli;
12543         const char *fname = "non_existant_file";
12544         const char *sname = "dangling_symlink";
12545         uint16_t fnum = (uint16_t)-1;
12546         bool correct = false;
12547         NTSTATUS status;
12548         TALLOC_CTX *frame = NULL;
12549
12550         frame = talloc_stackframe();
12551
12552         printf("Starting Windows bad symlink open test\n");
12553
12554         if (!torture_open_connection(&cli, 0)) {
12555                 TALLOC_FREE(frame);
12556                 return false;
12557         }
12558
12559         smbXcli_conn_set_sockopt(cli->conn, sockops);
12560
12561         status = torture_setup_unix_extensions(cli);
12562         if (!NT_STATUS_IS_OK(status)) {
12563                 TALLOC_FREE(frame);
12564                 return false;
12565         }
12566
12567         /* Ensure nothing exists. */
12568         cli_setatr(cli, fname, 0, 0);
12569         cli_posix_unlink(cli, fname);
12570         cli_setatr(cli, sname, 0, 0);
12571         cli_posix_unlink(cli, sname);
12572
12573         /* Create a symlink pointing nowhere. */
12574         status = cli_posix_symlink(cli, fname, sname);
12575         if (!NT_STATUS_IS_OK(status)) {
12576                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12577                         sname,
12578                         fname,
12579                         nt_errstr(status));
12580                 goto out;
12581         }
12582
12583         /* Now ensure that a Windows open doesn't hang. */
12584         status = cli_ntcreate(cli,
12585                         sname,
12586                         0,
12587                         FILE_READ_DATA|FILE_WRITE_DATA,
12588                         0,
12589                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12590                         FILE_OPEN_IF,
12591                         0x0,
12592                         0x0,
12593                         &fnum,
12594                         NULL);
12595
12596         /*
12597          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12598          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12599          * we use O_NOFOLLOW on the server or not.
12600          */
12601         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12602             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12603         {
12604                 correct = true;
12605         } else {
12606                 printf("cli_ntcreate of %s returned %s - should return"
12607                                 " either (%s) or (%s)\n",
12608                         sname,
12609                         nt_errstr(status),
12610                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12611                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12612                 goto out;
12613         }
12614
12615         correct = true;
12616
12617   out:
12618
12619         if (fnum != (uint16_t)-1) {
12620                 cli_close(cli, fnum);
12621                 fnum = (uint16_t)-1;
12622         }
12623
12624         cli_setatr(cli, sname, 0, 0);
12625         cli_posix_unlink(cli, sname);
12626         cli_setatr(cli, fname, 0, 0);
12627         cli_posix_unlink(cli, fname);
12628
12629         if (!torture_close_connection(cli)) {
12630                 correct = false;
12631         }
12632
12633         TALLOC_FREE(frame);
12634         return correct;
12635 }
12636
12637 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12638                                         const char *name,
12639                                         void *state)
12640 {
12641         char **mangled_name_return = (char **)state;
12642         bool is_mangled = strchr(finfo->name, '~');
12643
12644         if (is_mangled) {
12645                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12646                 if (*mangled_name_return == NULL) {
12647                         return NT_STATUS_NO_MEMORY;
12648                 }
12649         }
12650         return NT_STATUS_OK;
12651 }
12652
12653 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12654 {
12655         static struct cli_state *cli_posix = NULL;
12656         static struct cli_state *cli = NULL;
12657         uint16_t fnum = (uint16_t)-1;
12658         bool correct = false;
12659         const char *dname = "smb1_wild_mangle_unlink";
12660         const char *aname = "smb1_wild_mangle_unlink/a";
12661         const char *star_name = "smb1_wild_mangle_unlink/*";
12662         char *windows_unlink_name = NULL;
12663         char *mangled_name = NULL;
12664         NTSTATUS status;
12665
12666         printf("Starting SMB1 wild mangle unlink test\n");
12667
12668         /* Open a Windows connection. */
12669         if (!torture_open_connection(&cli, 0)) {
12670                 return false;
12671         }
12672
12673         smbXcli_conn_set_sockopt(cli->conn, sockops);
12674
12675         /* Open a POSIX connection. */
12676         if (!torture_open_connection(&cli_posix, 0)) {
12677                 goto out;
12678         }
12679
12680         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12681
12682         status = torture_setup_unix_extensions(cli_posix);
12683         if (!NT_STATUS_IS_OK(status)) {
12684                 printf("server doesn't support POSIX\n");
12685                 goto out;
12686         }
12687
12688         /* Start fresh. */
12689         cli_unlink(cli,
12690                 star_name,
12691                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12692         cli_rmdir(cli, dname);
12693
12694         /*
12695          * Create two files - 'a' and '*'.
12696          * We need POSIX extensions for this as '*'
12697          * is not a valid Windows name.
12698          */
12699
12700         status = cli_mkdir(cli, dname);
12701         if (!NT_STATUS_IS_OK(status)) {
12702                 printf("cli_mkdir of %s returned %s\n",
12703                         dname,
12704                         nt_errstr(status));
12705                 goto out;
12706         }
12707
12708         status = cli_posix_open(cli_posix,
12709                                 aname,
12710                                 O_RDWR|O_CREAT|O_EXCL,
12711                                 0660,
12712                                 &fnum);
12713         if (!NT_STATUS_IS_OK(status)) {
12714                 printf("cli_posix_open (create) of %s returned %s\n",
12715                         aname,
12716                         nt_errstr(status));
12717                 goto out;
12718         }
12719         status = cli_close(cli_posix, fnum);
12720         if (!NT_STATUS_IS_OK(status)) {
12721                 goto out;
12722         }
12723         status = cli_posix_open(cli_posix,
12724                                 star_name,
12725                                 O_RDWR|O_CREAT|O_EXCL,
12726                                 0660,
12727                                 &fnum);
12728         if (!NT_STATUS_IS_OK(status)) {
12729                 printf("cli_posix_open (create) of %s returned %s\n",
12730                         star_name,
12731                         nt_errstr(status));
12732                 goto out;
12733         }
12734         status = cli_close(cli_posix, fnum);
12735         if (!NT_STATUS_IS_OK(status)) {
12736                 goto out;
12737         }
12738
12739         status = cli_list(cli,
12740                         star_name,
12741                         0,
12742                         smb1_wild_mangle_list_fn,
12743                         &mangled_name);
12744         if (!NT_STATUS_IS_OK(status)) {
12745                 printf("cli_list of %s returned %s\n",
12746                         star_name,
12747                         nt_errstr(status));
12748                 goto out;
12749         }
12750
12751         if (mangled_name == NULL) {
12752                 goto out;
12753         }
12754
12755         printf("mangled_name = %s\n",
12756                 mangled_name);
12757
12758         /*
12759          * Try a Windows unlink with the mangled name.
12760          * This should *NOT* unlink the 'a' name.
12761          */
12762
12763         windows_unlink_name = talloc_asprintf(cli_posix,
12764                                         "%s\\%s",
12765                                         dname,
12766                                         mangled_name);
12767
12768         status = cli_unlink(cli, windows_unlink_name, 0);
12769         if (!NT_STATUS_IS_OK(status)) {
12770                 printf("cli_unlink of %s returned %s\n",
12771                         windows_unlink_name,
12772                         nt_errstr(status));
12773                 goto out;
12774         }
12775
12776         /* Does 'a' still exist ? */
12777         status = cli_posix_open(cli_posix,
12778                                 aname,
12779                                 O_RDONLY,
12780                                 0,
12781                                 &fnum);
12782         if (!NT_STATUS_IS_OK(status)) {
12783                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12784                         aname,
12785                         nt_errstr(status));
12786                 goto out;
12787         }
12788
12789         status = cli_close(cli_posix, fnum);
12790         if (!NT_STATUS_IS_OK(status)) {
12791                 goto out;
12792         }
12793
12794         correct = true;
12795
12796   out:
12797
12798         TALLOC_FREE(windows_unlink_name);
12799         TALLOC_FREE(mangled_name);
12800
12801         if (cli != NULL) {
12802                 cli_unlink(cli,
12803                         star_name,
12804                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12805                 cli_rmdir(cli, dname);
12806                 torture_close_connection(cli);
12807         }
12808
12809         if (cli_posix != NULL) {
12810                 torture_close_connection(cli_posix);
12811         }
12812
12813         return correct;
12814 }
12815
12816 static bool run_smb1_wild_mangle_rename_test(int dummy)
12817 {
12818         static struct cli_state *cli_posix = NULL;
12819         static struct cli_state *cli = NULL;
12820         uint16_t fnum = (uint16_t)-1;
12821         bool correct = false;
12822         const char *dname = "smb1_wild_mangle_rename";
12823         const char *fooname = "smb1_wild_mangle_rename/foo";
12824         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12825         const char *wild_name = "smb1_wild_mangle_rename/*";
12826         char *windows_rename_src = NULL;
12827         const char *windows_rename_dst = "smb1_wild_mangle_rename\\ba*";
12828         char *mangled_name = NULL;
12829         NTSTATUS status;
12830
12831         printf("Starting SMB1 wild mangle rename test\n");
12832
12833         if (!torture_open_connection(&cli_posix, 0)) {
12834                 return false;
12835         }
12836
12837         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12838
12839         status = torture_setup_unix_extensions(cli_posix);
12840         if (!NT_STATUS_IS_OK(status)) {
12841                 printf("server doesn't support POSIX\n");
12842                 return false;
12843         }
12844
12845         /* Open a Windows connection. */
12846         if (!torture_open_connection(&cli, 0)) {
12847                 goto out;
12848         }
12849
12850         smbXcli_conn_set_sockopt(cli->conn, sockops);
12851
12852         /* Ensure we start from fresh. */
12853         cli_unlink(cli,
12854                 wild_name,
12855                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12856         cli_posix_rmdir(cli_posix, dname);
12857
12858         /*
12859          * Create two files - 'foo' and 'fo*'.
12860          * We need POSIX extensions for this as 'fo*'
12861          * is not a valid Windows name.
12862          */
12863
12864         status = cli_posix_mkdir(cli_posix, dname, 0770);
12865         if (!NT_STATUS_IS_OK(status)) {
12866                 printf("cli_posix_mkdir of %s returned %s\n",
12867                         dname,
12868                         nt_errstr(status));
12869                 goto out;
12870         }
12871
12872         status = cli_posix_open(cli_posix,
12873                                 fooname,
12874                                 O_RDWR|O_CREAT|O_EXCL,
12875                                 0660,
12876                                 &fnum);
12877         if (!NT_STATUS_IS_OK(status)) {
12878                 printf("cli_posix_open (create) of %s returned %s\n",
12879                         fooname,
12880                         nt_errstr(status));
12881                 goto out;
12882         }
12883         status = cli_close(cli_posix, fnum);
12884         if (!NT_STATUS_IS_OK(status)) {
12885                 goto out;
12886         }
12887         status = cli_posix_open(cli_posix,
12888                                 foostar_name,
12889                                 O_RDWR|O_CREAT|O_EXCL,
12890                                 0660,
12891                                 &fnum);
12892         if (!NT_STATUS_IS_OK(status)) {
12893                 printf("cli_posix_open (create) of %s returned %s\n",
12894                         foostar_name,
12895                         nt_errstr(status));
12896                 goto out;
12897         }
12898         status = cli_close(cli_posix, fnum);
12899         if (!NT_STATUS_IS_OK(status)) {
12900                 goto out;
12901         }
12902
12903         /*
12904          * Get the mangled name. We can re-use the
12905          * previous smb1_wild_mangle_list_fn for this.
12906          */
12907
12908         status = cli_list(cli,
12909                         wild_name,
12910                         0,
12911                         smb1_wild_mangle_list_fn,
12912                         &mangled_name);
12913         if (!NT_STATUS_IS_OK(status)) {
12914                 printf("cli_list of %s returned %s\n",
12915                         wild_name,
12916                         nt_errstr(status));
12917                 goto out;
12918         }
12919
12920         if (mangled_name == NULL) {
12921                 goto out;
12922         }
12923
12924         printf("mangled_name = %s\n",
12925                 mangled_name);
12926
12927         /*
12928          * Try a Windows rename with the mangled name.
12929          * This should *NOT* rename the 'foo' name.
12930          */
12931
12932         windows_rename_src = talloc_asprintf(cli_posix,
12933                                         "%s\\%s",
12934                                         dname,
12935                                         mangled_name);
12936
12937         status = cli_rename(cli,
12938                         windows_rename_src,
12939                         windows_rename_dst,
12940                         false);
12941         if (!NT_STATUS_IS_OK(status)) {
12942                 printf("cli_rename of %s -> %s returned %s\n",
12943                         windows_rename_src,
12944                         windows_rename_dst,
12945                         nt_errstr(status));
12946                 goto out;
12947         }
12948
12949         /* Does 'foo' still exist ? */
12950         status = cli_posix_open(cli_posix,
12951                                 fooname,
12952                                 O_RDONLY,
12953                                 0,
12954                                 &fnum);
12955         if (!NT_STATUS_IS_OK(status)) {
12956                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12957                         fooname,
12958                         nt_errstr(status));
12959                 goto out;
12960         }
12961
12962         status = cli_close(cli_posix, fnum);
12963         if (!NT_STATUS_IS_OK(status)) {
12964                 goto out;
12965         }
12966
12967         correct = true;
12968
12969   out:
12970
12971         TALLOC_FREE(mangled_name);
12972         TALLOC_FREE(windows_rename_src);
12973
12974         if (cli != NULL) {
12975                 cli_unlink(cli,
12976                         wild_name,
12977                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12978                 torture_close_connection(cli);
12979         }
12980
12981         cli_posix_rmdir(cli_posix, dname);
12982         torture_close_connection(cli_posix);
12983
12984         return correct;
12985 }
12986
12987 /*
12988  * Only testing minimal time strings, as the others
12989  * need (locale-dependent) guessing at what strftime does and
12990  * even may differ in builds.
12991  */
12992 static bool timesubst_test(void)
12993 {
12994         TALLOC_CTX *ctx = NULL;
12995         /* Sa 23. Dez 04:33:20 CET 2017 */
12996         const struct timeval tv = { 1514000000, 123 };
12997         const char* expect_minimal = "20171223_033320";
12998         const char* expect_minus   = "20171223_033320_000123";
12999         char *s;
13000         char *env_tz, *orig_tz = NULL;
13001         bool result = true;
13002
13003         ctx = talloc_new(NULL);
13004
13005         env_tz = getenv("TZ");
13006         if(env_tz) {
13007                 orig_tz = talloc_strdup(ctx, env_tz);
13008         }
13009         setenv("TZ", "UTC", 1);
13010
13011         s = minimal_timeval_string(ctx, &tv, false);
13012
13013         if(!s || strcmp(s, expect_minimal)) {
13014                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13015                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13016                 result = false;
13017         }
13018         TALLOC_FREE(s);
13019         s = minimal_timeval_string(ctx, &tv, true);
13020         if(!s || strcmp(s, expect_minus)) {
13021                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13022                        "[%s]\n", s ? s : "<nil>", expect_minus);
13023                 result = false;
13024         }
13025         TALLOC_FREE(s);
13026
13027         if(orig_tz) {
13028                 setenv("TZ", orig_tz, 1);
13029         }
13030
13031         TALLOC_FREE(ctx);
13032         return result;
13033 }
13034
13035 static bool run_local_substitute(int dummy)
13036 {
13037         bool ok = true;
13038
13039         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13040         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13041         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13042         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13043         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13044         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13045         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13046         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13047         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13048         /* Substitution depends on current time, so better test the underlying
13049            formatting function. At least covers %t. */
13050         ok &= timesubst_test();
13051
13052         /* Different captialization rules in sub_basic... */
13053
13054         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13055                        "blaDOM") == 0);
13056
13057         return ok;
13058 }
13059
13060 static bool run_local_base64(int dummy)
13061 {
13062         int i;
13063         bool ret = true;
13064
13065         for (i=1; i<2000; i++) {
13066                 DATA_BLOB blob1, blob2;
13067                 char *b64;
13068
13069                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13070                 blob1.length = i;
13071                 generate_random_buffer(blob1.data, blob1.length);
13072
13073                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13074                 if (b64 == NULL) {
13075                         d_fprintf(stderr, "base64_encode_data_blob failed "
13076                                   "for %d bytes\n", i);
13077                         ret = false;
13078                 }
13079                 blob2 = base64_decode_data_blob(b64);
13080                 TALLOC_FREE(b64);
13081
13082                 if (data_blob_cmp(&blob1, &blob2)) {
13083                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13084                                   "bytes\n", i);
13085                         ret = false;
13086                 }
13087                 TALLOC_FREE(blob1.data);
13088                 data_blob_free(&blob2);
13089         }
13090         return ret;
13091 }
13092
13093 static void parse_fn(const struct gencache_timeout *t,
13094                      DATA_BLOB blob,
13095                      void *private_data)
13096 {
13097         return;
13098 }
13099
13100 static bool run_local_gencache(int dummy)
13101 {
13102         char *val;
13103         time_t tm;
13104         DATA_BLOB blob;
13105         char v;
13106         struct memcache *mem;
13107         int i;
13108
13109         mem = memcache_init(NULL, 0);
13110         if (mem == NULL) {
13111                 d_printf("%s: memcache_init failed\n", __location__);
13112                 return false;
13113         }
13114         memcache_set_global(mem);
13115
13116         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13117                 d_printf("%s: gencache_set() failed\n", __location__);
13118                 return False;
13119         }
13120
13121         if (!gencache_get("foo", NULL, NULL, NULL)) {
13122                 d_printf("%s: gencache_get() failed\n", __location__);
13123                 return False;
13124         }
13125
13126         for (i=0; i<1000000; i++) {
13127                 gencache_parse("foo", parse_fn, NULL);
13128         }
13129
13130         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13131                 d_printf("%s: gencache_get() failed\n", __location__);
13132                 return False;
13133         }
13134         TALLOC_FREE(val);
13135
13136         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13137                 d_printf("%s: gencache_get() failed\n", __location__);
13138                 return False;
13139         }
13140
13141         if (strcmp(val, "bar") != 0) {
13142                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13143                          __location__, val, "bar");
13144                 TALLOC_FREE(val);
13145                 return False;
13146         }
13147
13148         TALLOC_FREE(val);
13149
13150         if (!gencache_del("foo")) {
13151                 d_printf("%s: gencache_del() failed\n", __location__);
13152                 return False;
13153         }
13154         if (gencache_del("foo")) {
13155                 d_printf("%s: second gencache_del() succeeded\n",
13156                          __location__);
13157                 return False;
13158         }
13159
13160         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13161                 d_printf("%s: gencache_get() on deleted entry "
13162                          "succeeded\n", __location__);
13163                 return False;
13164         }
13165
13166         blob = data_blob_string_const_null("bar");
13167         tm = time(NULL) + 60;
13168
13169         if (!gencache_set_data_blob("foo", blob, tm)) {
13170                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13171                 return False;
13172         }
13173
13174         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13175                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13176                 return False;
13177         }
13178
13179         if (strcmp((const char *)blob.data, "bar") != 0) {
13180                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13181                          __location__, (const char *)blob.data, "bar");
13182                 data_blob_free(&blob);
13183                 return False;
13184         }
13185
13186         data_blob_free(&blob);
13187
13188         if (!gencache_del("foo")) {
13189                 d_printf("%s: gencache_del() failed\n", __location__);
13190                 return False;
13191         }
13192         if (gencache_del("foo")) {
13193                 d_printf("%s: second gencache_del() succeeded\n",
13194                          __location__);
13195                 return False;
13196         }
13197
13198         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13199                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13200                          "succeeded\n", __location__);
13201                 return False;
13202         }
13203
13204         v = 1;
13205         blob.data = (uint8_t *)&v;
13206         blob.length = sizeof(v);
13207
13208         if (!gencache_set_data_blob("blob", blob, tm)) {
13209                 d_printf("%s: gencache_set_data_blob() failed\n",
13210                          __location__);
13211                 return false;
13212         }
13213         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13214                 d_printf("%s: gencache_get succeeded\n", __location__);
13215                 return false;
13216         }
13217
13218         return True;
13219 }
13220
13221 static bool rbt_testflags(struct db_context *db, const char *key,
13222                           const char *value)
13223 {
13224         bool ret = false;
13225         NTSTATUS status;
13226         struct db_record *rec;
13227
13228         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13229         if (rec == NULL) {
13230                 d_fprintf(stderr, "fetch_locked failed\n");
13231                 goto done;
13232         }
13233
13234         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13235         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13236                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13237                           nt_errstr(status));
13238                 goto done;
13239         }
13240
13241         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13242                                      TDB_INSERT);
13243         if (!NT_STATUS_IS_OK(status)) {
13244                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13245                           nt_errstr(status));
13246                 goto done;
13247         }
13248
13249         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13250         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13251                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13252                           nt_errstr(status));
13253                 goto done;
13254         }
13255
13256         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13257         if (!NT_STATUS_IS_OK(status)) {
13258                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13259                           nt_errstr(status));
13260                 goto done;
13261         }
13262
13263         ret = true;
13264 done:
13265         TALLOC_FREE(rec);
13266         return ret;
13267 }
13268
13269 static bool rbt_testval(struct db_context *db, const char *key,
13270                         const char *value)
13271 {
13272         struct db_record *rec;
13273         TDB_DATA data = string_tdb_data(value);
13274         bool ret = false;
13275         NTSTATUS status;
13276         TDB_DATA dbvalue;
13277
13278         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13279         if (rec == NULL) {
13280                 d_fprintf(stderr, "fetch_locked failed\n");
13281                 goto done;
13282         }
13283         status = dbwrap_record_store(rec, data, 0);
13284         if (!NT_STATUS_IS_OK(status)) {
13285                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13286                 goto done;
13287         }
13288         TALLOC_FREE(rec);
13289
13290         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13291         if (rec == NULL) {
13292                 d_fprintf(stderr, "second fetch_locked failed\n");
13293                 goto done;
13294         }
13295
13296         dbvalue = dbwrap_record_get_value(rec);
13297         if ((dbvalue.dsize != data.dsize)
13298             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13299                 d_fprintf(stderr, "Got wrong data back\n");
13300                 goto done;
13301         }
13302
13303         ret = true;
13304  done:
13305         TALLOC_FREE(rec);
13306         return ret;
13307 }
13308
13309 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13310 {
13311         int *count2 = (int *)private_data;
13312         (*count2)++;
13313         return 0;
13314 }
13315
13316 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13317 {
13318         int *count2 = (int *)private_data;
13319         (*count2)++;
13320         dbwrap_record_delete(rec);
13321         return 0;
13322 }
13323
13324 static bool run_local_rbtree(int dummy)
13325 {
13326         struct db_context *db;
13327         bool ret = false;
13328         int i;
13329         NTSTATUS status;
13330         int count = 0;
13331         int count2 = 0;
13332
13333         db = db_open_rbt(NULL);
13334
13335         if (db == NULL) {
13336                 d_fprintf(stderr, "db_open_rbt failed\n");
13337                 return false;
13338         }
13339
13340         if (!rbt_testflags(db, "firstkey", "firstval")) {
13341                 goto done;
13342         }
13343
13344         for (i = 0; i < 999; i++) {
13345                 char key[sizeof("key-9223372036854775807")];
13346                 char value[sizeof("value-9223372036854775807")];
13347
13348                 snprintf(key, sizeof(key), "key%ld", random());
13349                 snprintf(value, sizeof(value) ,"value%ld", random());
13350
13351                 if (!rbt_testval(db, key, value)) {
13352                         goto done;
13353                 }
13354
13355                 snprintf(value, sizeof(value) ,"value%ld", random());
13356
13357                 if (!rbt_testval(db, key, value)) {
13358                         goto done;
13359                 }
13360         }
13361
13362         ret = true;
13363         count = 0; count2 = 0;
13364         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13365                                       &count2, &count);
13366         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13367         if ((count != count2) || (count != 1000)) {
13368                 ret = false;
13369         }
13370         count = 0; count2 = 0;
13371         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13372                                  &count2, &count);
13373         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13374         if ((count != count2) || (count != 1000)) {
13375                 ret = false;
13376         }
13377         count = 0; count2 = 0;
13378         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13379                                       &count2, &count);
13380         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13381         if ((count != count2) || (count != 0)) {
13382                 ret = false;
13383         }
13384
13385  done:
13386         TALLOC_FREE(db);
13387         return ret;
13388 }
13389
13390
13391 /*
13392   local test for character set functions
13393
13394   This is a very simple test for the functionality in convert_string_error()
13395  */
13396 static bool run_local_convert_string(int dummy)
13397 {
13398         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13399         const char *test_strings[2] = { "March", "M\303\244rz" };
13400         char dst[7];
13401         int i;
13402
13403         for (i=0; i<2; i++) {
13404                 const char *str = test_strings[i];
13405                 int len = strlen(str);
13406                 size_t converted_size;
13407                 bool ret;
13408
13409                 memset(dst, 'X', sizeof(dst));
13410
13411                 /* first try with real source length */
13412                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13413                                            str, len,
13414                                            dst, sizeof(dst),
13415                                            &converted_size);
13416                 if (ret != true) {
13417                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13418                         goto failed;
13419                 }
13420
13421                 if (converted_size != len) {
13422                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13423                                   str, len, (int)converted_size);
13424                         goto failed;
13425                 }
13426
13427                 if (strncmp(str, dst, converted_size) != 0) {
13428                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13429                         goto failed;
13430                 }
13431
13432                 if (strlen(str) != converted_size) {
13433                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13434                                   (int)strlen(str), (int)converted_size);
13435                         goto failed;
13436                 }
13437
13438                 if (dst[converted_size] != 'X') {
13439                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13440                         goto failed;
13441                 }
13442
13443                 /* now with srclen==-1, this causes the nul to be
13444                  * converted too */
13445                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13446                                            str, -1,
13447                                            dst, sizeof(dst),
13448                                            &converted_size);
13449                 if (ret != true) {
13450                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13451                         goto failed;
13452                 }
13453
13454                 if (converted_size != len+1) {
13455                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13456                                   str, len, (int)converted_size);
13457                         goto failed;
13458                 }
13459
13460                 if (strncmp(str, dst, converted_size) != 0) {
13461                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13462                         goto failed;
13463                 }
13464
13465                 if (len+1 != converted_size) {
13466                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13467                                   len+1, (int)converted_size);
13468                         goto failed;
13469                 }
13470
13471                 if (dst[converted_size] != 'X') {
13472                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13473                         goto failed;
13474                 }
13475
13476         }
13477
13478
13479         TALLOC_FREE(tmp_ctx);
13480         return true;
13481 failed:
13482         TALLOC_FREE(tmp_ctx);
13483         return false;
13484 }
13485
13486 static bool run_local_string_to_sid(int dummy) {
13487         struct dom_sid sid;
13488
13489         if (string_to_sid(&sid, "S--1-5-32-545")) {
13490                 printf("allowing S--1-5-32-545\n");
13491                 return false;
13492         }
13493         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13494                 printf("allowing S-1-5-32-+545\n");
13495                 return false;
13496         }
13497         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")) {
13498                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13499                 return false;
13500         }
13501         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13502                 printf("allowing S-1-5-32-545-abc\n");
13503                 return false;
13504         }
13505         if (string_to_sid(&sid, "S-300-5-32-545")) {
13506                 printf("allowing S-300-5-32-545\n");
13507                 return false;
13508         }
13509         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13510                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13511                 return false;
13512         }
13513         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13514                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13515                 return false;
13516         }
13517         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13518                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13519                 return false;
13520         }
13521         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13522                 printf("could not parse S-1-5-32-545\n");
13523                 return false;
13524         }
13525         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13526                 struct dom_sid_buf buf;
13527                 printf("mis-parsed S-1-5-32-545 as %s\n",
13528                        dom_sid_str_buf(&sid, &buf));
13529                 return false;
13530         }
13531         return true;
13532 }
13533
13534 static bool sid_to_string_test(const char *expected) {
13535         char *str;
13536         bool res = true;
13537         struct dom_sid sid;
13538
13539         if (!string_to_sid(&sid, expected)) {
13540                 printf("could not parse %s\n", expected);
13541                 return false;
13542         }
13543
13544         str = dom_sid_string(NULL, &sid);
13545         if (strcmp(str, expected)) {
13546                 printf("Comparison failed (%s != %s)\n", str, expected);
13547                 res = false;
13548         }
13549         TALLOC_FREE(str);
13550         return res;
13551 }
13552
13553 static bool run_local_sid_to_string(int dummy) {
13554         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13555                 return false;
13556         if (!sid_to_string_test("S-1-545"))
13557                 return false;
13558         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13559                 return false;
13560         return true;
13561 }
13562
13563 static bool run_local_binary_to_sid(int dummy) {
13564         ssize_t ret;
13565         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13566         static const uint8_t good_binary_sid[] = {
13567                 0x1, /* revision number */
13568                 15, /* num auths */
13569                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13570                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13571                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13572                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13573                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13574                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13575                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13576                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13577                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13578                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13579                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13580                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13581                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13582                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13583                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13584                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13585         };
13586
13587         static const uint8_t long_binary_sid[] = {
13588                 0x1, /* revision number */
13589                 15, /* num auths */
13590                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13591                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13592                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13593                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13594                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13595                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13596                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13597                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13598                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13599                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13600                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13601                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13602                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13603                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13604                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13605                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13606                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13607                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13608                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13609         };
13610
13611         static const uint8_t long_binary_sid2[] = {
13612                 0x1, /* revision number */
13613                 32, /* num auths */
13614                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13615                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13616                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13617                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13618                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13619                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13620                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13621                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13622                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13623                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13624                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13625                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13626                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13627                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13628                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13629                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13630                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13631                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13632                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13633                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13634                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13635                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13636                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13637                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13638                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13639                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13640                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13641                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13642                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13643                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13644                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13645                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13646                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13647         };
13648
13649         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13650         if (ret == -1) {
13651                 return false;
13652         }
13653         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13654         if (ret != -1) {
13655                 return false;
13656         }
13657         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13658         if (ret != -1) {
13659                 return false;
13660         }
13661         return true;
13662 }
13663
13664 /* Split a path name into filename and stream name components. Canonicalise
13665  * such that an implicit $DATA token is always explicit.
13666  *
13667  * The "specification" of this function can be found in the
13668  * run_local_stream_name() function in torture.c, I've tried those
13669  * combinations against a W2k3 server.
13670  */
13671
13672 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13673                                        char **pbase, char **pstream)
13674 {
13675         char *base = NULL;
13676         char *stream = NULL;
13677         char *sname; /* stream name */
13678         const char *stype; /* stream type */
13679
13680         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13681
13682         sname = strchr_m(fname, ':');
13683
13684         if (sname == NULL) {
13685                 if (pbase != NULL) {
13686                         base = talloc_strdup(mem_ctx, fname);
13687                         NT_STATUS_HAVE_NO_MEMORY(base);
13688                 }
13689                 goto done;
13690         }
13691
13692         if (pbase != NULL) {
13693                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13694                 NT_STATUS_HAVE_NO_MEMORY(base);
13695         }
13696
13697         sname += 1;
13698
13699         stype = strchr_m(sname, ':');
13700
13701         if (stype == NULL) {
13702                 sname = talloc_strdup(mem_ctx, sname);
13703                 stype = "$DATA";
13704         }
13705         else {
13706                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13707                         /*
13708                          * If there is an explicit stream type, so far we only
13709                          * allow $DATA. Is there anything else allowed? -- vl
13710                          */
13711                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13712                         TALLOC_FREE(base);
13713                         return NT_STATUS_OBJECT_NAME_INVALID;
13714                 }
13715                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13716                 stype += 1;
13717         }
13718
13719         if (sname == NULL) {
13720                 TALLOC_FREE(base);
13721                 return NT_STATUS_NO_MEMORY;
13722         }
13723
13724         if (sname[0] == '\0') {
13725                 /*
13726                  * no stream name, so no stream
13727                  */
13728                 goto done;
13729         }
13730
13731         if (pstream != NULL) {
13732                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13733                 if (stream == NULL) {
13734                         TALLOC_FREE(sname);
13735                         TALLOC_FREE(base);
13736                         return NT_STATUS_NO_MEMORY;
13737                 }
13738                 /*
13739                  * upper-case the type field
13740                  */
13741                 (void)strupper_m(strchr_m(stream, ':')+1);
13742         }
13743
13744  done:
13745         if (pbase != NULL) {
13746                 *pbase = base;
13747         }
13748         if (pstream != NULL) {
13749                 *pstream = stream;
13750         }
13751         return NT_STATUS_OK;
13752 }
13753
13754 static bool test_stream_name(const char *fname, const char *expected_base,
13755                              const char *expected_stream,
13756                              NTSTATUS expected_status)
13757 {
13758         NTSTATUS status;
13759         char *base = NULL;
13760         char *stream = NULL;
13761
13762         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13763         if (!NT_STATUS_EQUAL(status, expected_status)) {
13764                 goto error;
13765         }
13766
13767         if (!NT_STATUS_IS_OK(status)) {
13768                 return true;
13769         }
13770
13771         if (base == NULL) goto error;
13772
13773         if (strcmp(expected_base, base) != 0) goto error;
13774
13775         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13776         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13777
13778         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13779                 goto error;
13780
13781         TALLOC_FREE(base);
13782         TALLOC_FREE(stream);
13783         return true;
13784
13785  error:
13786         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13787                   fname, expected_base ? expected_base : "<NULL>",
13788                   expected_stream ? expected_stream : "<NULL>",
13789                   nt_errstr(expected_status));
13790         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13791                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13792                   nt_errstr(status));
13793         TALLOC_FREE(base);
13794         TALLOC_FREE(stream);
13795         return false;
13796 }
13797
13798 static bool run_local_stream_name(int dummy)
13799 {
13800         bool ret = true;
13801
13802         ret &= test_stream_name(
13803                 "bla", "bla", NULL, NT_STATUS_OK);
13804         ret &= test_stream_name(
13805                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13806         ret &= test_stream_name(
13807                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13808         ret &= test_stream_name(
13809                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13810         ret &= test_stream_name(
13811                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13812         ret &= test_stream_name(
13813                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13814         ret &= test_stream_name(
13815                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13816         ret &= test_stream_name(
13817                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13818
13819         return ret;
13820 }
13821
13822 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13823 {
13824         if (a.length != b.length) {
13825                 printf("a.length=%d != b.length=%d\n",
13826                        (int)a.length, (int)b.length);
13827                 return false;
13828         }
13829         if (memcmp(a.data, b.data, a.length) != 0) {
13830                 printf("a.data and b.data differ\n");
13831                 return false;
13832         }
13833         return true;
13834 }
13835
13836 static bool run_local_memcache(int dummy)
13837 {
13838         struct memcache *cache;
13839         DATA_BLOB k1, k2, k3, k4, k5;
13840         DATA_BLOB d1, d3;
13841         DATA_BLOB v1, v3;
13842
13843         TALLOC_CTX *mem_ctx;
13844         char *ptr1 = NULL;
13845         char *ptr2 = NULL;
13846         char *ptr3 = NULL;
13847
13848         char *str1, *str2;
13849         size_t size1, size2;
13850         bool ret = false;
13851
13852         mem_ctx = talloc_init("foo");
13853         if (mem_ctx == NULL) {
13854                 return false;
13855         }
13856
13857         /* STAT_CACHE TESTS */
13858
13859         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13860
13861         if (cache == NULL) {
13862                 printf("memcache_init failed\n");
13863                 return false;
13864         }
13865
13866         d1 = data_blob_const("d1", 2);
13867         d3 = data_blob_const("d3", 2);
13868
13869         k1 = data_blob_const("d1", 2);
13870         k2 = data_blob_const("d2", 2);
13871         k3 = data_blob_const("d3", 2);
13872         k4 = data_blob_const("d4", 2);
13873         k5 = data_blob_const("d5", 2);
13874
13875         memcache_add(cache, STAT_CACHE, k1, d1);
13876
13877         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13878                 printf("could not find k1\n");
13879                 return false;
13880         }
13881         if (!data_blob_equal(d1, v1)) {
13882                 return false;
13883         }
13884
13885         memcache_add(cache, STAT_CACHE, k1, d3);
13886
13887         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13888                 printf("could not find replaced k1\n");
13889                 return false;
13890         }
13891         if (!data_blob_equal(d3, v3)) {
13892                 return false;
13893         }
13894
13895         TALLOC_FREE(cache);
13896
13897         /* GETWD_CACHE TESTS */
13898         str1 = talloc_strdup(mem_ctx, "string1");
13899         if (str1 == NULL) {
13900                 return false;
13901         }
13902         ptr2 = str1; /* Keep an alias for comparison. */
13903
13904         str2 = talloc_strdup(mem_ctx, "string2");
13905         if (str2 == NULL) {
13906                 return false;
13907         }
13908
13909         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13910         if (cache == NULL) {
13911                 printf("memcache_init failed\n");
13912                 return false;
13913         }
13914
13915         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13916         /* str1 == NULL now. */
13917         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13918         if (ptr1 == NULL) {
13919                 printf("could not find k2\n");
13920                 return false;
13921         }
13922         if (ptr1 != ptr2) {
13923                 printf("fetch of k2 got wrong string\n");
13924                 return false;
13925         }
13926
13927         /* Add a blob to ensure k2 gets purged. */
13928         d3 = data_blob_talloc_zero(mem_ctx, 180);
13929         memcache_add(cache, STAT_CACHE, k3, d3);
13930
13931         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13932         if (ptr2 != NULL) {
13933                 printf("Did find k2, should have been purged\n");
13934                 return false;
13935         }
13936
13937         /*
13938          * Test that talloc size also is accounted in memcache and
13939          * causes purge of other object.
13940          */
13941
13942         str1 = talloc_zero_size(mem_ctx, 100);
13943         str2 = talloc_zero_size(mem_ctx, 100);
13944
13945         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13946         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13947
13948         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13949         if (ptr3 != NULL) {
13950                 printf("Did find k4, should have been purged\n");
13951                 return false;
13952         }
13953
13954         /*
13955          * Test that adding a duplicate non-talloced
13956          * key/value on top of a talloced key/value takes account
13957          * of the talloc_freed value size.
13958          */
13959         TALLOC_FREE(cache);
13960         TALLOC_FREE(mem_ctx);
13961
13962         mem_ctx = talloc_init("key_replace");
13963         if (mem_ctx == NULL) {
13964                 return false;
13965         }
13966
13967         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13968         if (cache == NULL) {
13969                 return false;
13970         }
13971
13972         /*
13973          * Add a 100 byte talloced string. This will
13974          * store a (4 or 8 byte) pointer and record the
13975          * total talloced size.
13976          */
13977         str1 = talloc_zero_size(mem_ctx, 100);
13978         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13979         /*
13980          * Now overwrite with a small talloced
13981          * value. This should fit in the existing size
13982          * and the total talloced size should be removed
13983          * from the cache size.
13984          */
13985         str1 = talloc_zero_size(mem_ctx, 2);
13986         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13987         /*
13988          * Now store a 20 byte string. If the
13989          * total talloced size wasn't accounted for
13990          * and removed in the overwrite, then this
13991          * will evict k4.
13992          */
13993         str2 = talloc_zero_size(mem_ctx, 20);
13994         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13995
13996         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13997         if (ptr3 == NULL) {
13998                 printf("Did not find k4, should not have been purged\n");
13999                 return false;
14000         }
14001
14002         TALLOC_FREE(cache);
14003         TALLOC_FREE(mem_ctx);
14004
14005         mem_ctx = talloc_init("foo");
14006         if (mem_ctx == NULL) {
14007                 return false;
14008         }
14009
14010         cache = memcache_init(NULL, 0);
14011         if (cache == NULL) {
14012                 return false;
14013         }
14014
14015         str1 = talloc_strdup(mem_ctx, "string1");
14016         if (str1 == NULL) {
14017                 return false;
14018         }
14019         str2 = talloc_strdup(mem_ctx, "string2");
14020         if (str2 == NULL) {
14021                 return false;
14022         }
14023         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14024                             data_blob_string_const("torture"), &str1);
14025         size1 = talloc_total_size(cache);
14026
14027         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14028                             data_blob_string_const("torture"), &str2);
14029         size2 = talloc_total_size(cache);
14030
14031         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14032
14033         if (size2 > size1) {
14034                 printf("memcache leaks memory!\n");
14035                 goto fail;
14036         }
14037
14038         ret = true;
14039  fail:
14040         TALLOC_FREE(cache);
14041         return ret;
14042 }
14043
14044 static void wbclient_done(struct tevent_req *req)
14045 {
14046         wbcErr wbc_err;
14047         struct winbindd_response *wb_resp;
14048         int *i = (int *)tevent_req_callback_data_void(req);
14049
14050         wbc_err = wb_trans_recv(req, req, &wb_resp);
14051         TALLOC_FREE(req);
14052         *i += 1;
14053         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14054 }
14055
14056 static bool run_wbclient_multi_ping(int dummy)
14057 {
14058         struct tevent_context *ev;
14059         struct wb_context **wb_ctx;
14060         struct winbindd_request wb_req;
14061         bool result = false;
14062         int i, j;
14063
14064         BlockSignals(True, SIGPIPE);
14065
14066         ev = tevent_context_init(talloc_tos());
14067         if (ev == NULL) {
14068                 goto fail;
14069         }
14070
14071         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14072         if (wb_ctx == NULL) {
14073                 goto fail;
14074         }
14075
14076         ZERO_STRUCT(wb_req);
14077         wb_req.cmd = WINBINDD_PING;
14078
14079         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14080
14081         for (i=0; i<torture_nprocs; i++) {
14082                 wb_ctx[i] = wb_context_init(ev, NULL);
14083                 if (wb_ctx[i] == NULL) {
14084                         goto fail;
14085                 }
14086                 for (j=0; j<torture_numops; j++) {
14087                         struct tevent_req *req;
14088                         req = wb_trans_send(ev, ev, wb_ctx[i],
14089                                             (j % 2) == 0, &wb_req);
14090                         if (req == NULL) {
14091                                 goto fail;
14092                         }
14093                         tevent_req_set_callback(req, wbclient_done, &i);
14094                 }
14095         }
14096
14097         i = 0;
14098
14099         while (i < torture_nprocs * torture_numops) {
14100                 tevent_loop_once(ev);
14101         }
14102
14103         result = true;
14104  fail:
14105         TALLOC_FREE(ev);
14106         return result;
14107 }
14108
14109 static bool dbtrans_inc(struct db_context *db)
14110 {
14111         struct db_record *rec;
14112         uint32_t val;
14113         bool ret = false;
14114         NTSTATUS status;
14115         TDB_DATA value;
14116
14117         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14118         if (rec == NULL) {
14119                 printf(__location__ "fetch_lock failed\n");
14120                 return false;
14121         }
14122
14123         value = dbwrap_record_get_value(rec);
14124
14125         if (value.dsize != sizeof(uint32_t)) {
14126                 printf(__location__ "value.dsize = %d\n",
14127                        (int)value.dsize);
14128                 goto fail;
14129         }
14130
14131         memcpy(&val, value.dptr, sizeof(val));
14132         val += 1;
14133
14134         status = dbwrap_record_store(
14135                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14136         if (!NT_STATUS_IS_OK(status)) {
14137                 printf(__location__ "store failed: %s\n",
14138                        nt_errstr(status));
14139                 goto fail;
14140         }
14141
14142         ret = true;
14143 fail:
14144         TALLOC_FREE(rec);
14145         return ret;
14146 }
14147
14148 static bool run_local_dbtrans(int dummy)
14149 {
14150         struct db_context *db;
14151         struct db_record *rec;
14152         NTSTATUS status;
14153         uint32_t initial;
14154         int res;
14155         TDB_DATA value;
14156
14157         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14158                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14159                      DBWRAP_FLAG_NONE);
14160         if (db == NULL) {
14161                 printf("Could not open transtest.db\n");
14162                 return false;
14163         }
14164
14165         res = dbwrap_transaction_start(db);
14166         if (res != 0) {
14167                 printf(__location__ "transaction_start failed\n");
14168                 return false;
14169         }
14170
14171         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14172         if (rec == NULL) {
14173                 printf(__location__ "fetch_lock failed\n");
14174                 return false;
14175         }
14176
14177         value = dbwrap_record_get_value(rec);
14178
14179         if (value.dptr == NULL) {
14180                 initial = 0;
14181                 status = dbwrap_record_store(
14182                         rec, make_tdb_data((uint8_t *)&initial,
14183                                            sizeof(initial)),
14184                         0);
14185                 if (!NT_STATUS_IS_OK(status)) {
14186                         printf(__location__ "store returned %s\n",
14187                                nt_errstr(status));
14188                         return false;
14189                 }
14190         }
14191
14192         TALLOC_FREE(rec);
14193
14194         res = dbwrap_transaction_commit(db);
14195         if (res != 0) {
14196                 printf(__location__ "transaction_commit failed\n");
14197                 return false;
14198         }
14199
14200         while (true) {
14201                 uint32_t val, val2;
14202                 int i;
14203
14204                 res = dbwrap_transaction_start(db);
14205                 if (res != 0) {
14206                         printf(__location__ "transaction_start failed\n");
14207                         break;
14208                 }
14209
14210                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14211                 if (!NT_STATUS_IS_OK(status)) {
14212                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14213                                nt_errstr(status));
14214                         break;
14215                 }
14216
14217                 for (i=0; i<10; i++) {
14218                         if (!dbtrans_inc(db)) {
14219                                 return false;
14220                         }
14221                 }
14222
14223                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14224                 if (!NT_STATUS_IS_OK(status)) {
14225                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14226                                nt_errstr(status));
14227                         break;
14228                 }
14229
14230                 if (val2 != val + 10) {
14231                         printf(__location__ "val=%d, val2=%d\n",
14232                                (int)val, (int)val2);
14233                         break;
14234                 }
14235
14236                 printf("val2=%d\r", val2);
14237
14238                 res = dbwrap_transaction_commit(db);
14239                 if (res != 0) {
14240                         printf(__location__ "transaction_commit failed\n");
14241                         break;
14242                 }
14243         }
14244
14245         TALLOC_FREE(db);
14246         return true;
14247 }
14248
14249 /*
14250  * Just a dummy test to be run under a debugger. There's no real way
14251  * to inspect the tevent_poll specific function from outside of
14252  * tevent_poll.c.
14253  */
14254
14255 static bool run_local_tevent_poll(int dummy)
14256 {
14257         struct tevent_context *ev;
14258         struct tevent_fd *fd1, *fd2;
14259         bool result = false;
14260
14261         ev = tevent_context_init_byname(NULL, "poll");
14262         if (ev == NULL) {
14263                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14264                 goto fail;
14265         }
14266
14267         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14268         if (fd1 == NULL) {
14269                 d_fprintf(stderr, "tevent_add_fd failed\n");
14270                 goto fail;
14271         }
14272         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14273         if (fd2 == NULL) {
14274                 d_fprintf(stderr, "tevent_add_fd failed\n");
14275                 goto fail;
14276         }
14277         TALLOC_FREE(fd2);
14278
14279         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14280         if (fd2 == NULL) {
14281                 d_fprintf(stderr, "tevent_add_fd failed\n");
14282                 goto fail;
14283         }
14284
14285         result = true;
14286 fail:
14287         TALLOC_FREE(ev);
14288         return result;
14289 }
14290
14291 static bool run_local_hex_encode_buf(int dummy)
14292 {
14293         char buf[17];
14294         uint8_t src[8];
14295         int i;
14296
14297         for (i=0; i<sizeof(src); i++) {
14298                 src[i] = i;
14299         }
14300         hex_encode_buf(buf, src, sizeof(src));
14301         if (strcmp(buf, "0001020304050607") != 0) {
14302                 return false;
14303         }
14304         hex_encode_buf(buf, NULL, 0);
14305         if (buf[0] != '\0') {
14306                 return false;
14307         }
14308         return true;
14309 }
14310
14311 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14312         "0.0.0.0",
14313         "::0",
14314         "1.2.3.1",
14315         "0.0.0.0",
14316         "0.0.0.0",
14317         "1.2.3.2",
14318         "1.2.3.3",
14319         "1.2.3.4",
14320         "1.2.3.5",
14321         "::0",
14322         "1.2.3.6",
14323         "1.2.3.7",
14324         "::0",
14325         "::0",
14326         "::0",
14327         "1.2.3.8",
14328         "1.2.3.9",
14329         "1.2.3.10",
14330         "1.2.3.11",
14331         "1.2.3.12",
14332         "1.2.3.13",
14333         "1001:1111:1111:1000:0:1111:1111:1111",
14334         "1.2.3.1",
14335         "1.2.3.2",
14336         "1.2.3.3",
14337         "1.2.3.12",
14338         "::0",
14339         "::0"
14340 };
14341
14342 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14343         "1.2.3.1",
14344         "1.2.3.2",
14345         "1.2.3.3",
14346         "1.2.3.4",
14347         "1.2.3.5",
14348         "1.2.3.6",
14349         "1.2.3.7",
14350         "1.2.3.8",
14351         "1.2.3.9",
14352         "1.2.3.10",
14353         "1.2.3.11",
14354         "1.2.3.12",
14355         "1.2.3.13",
14356         "1001:1111:1111:1000:0:1111:1111:1111"
14357 };
14358
14359 static bool run_local_remove_duplicate_addrs2(int dummy)
14360 {
14361         struct samba_sockaddr test_vector[28];
14362         size_t count, i;
14363
14364         /* Construct the sockaddr_storage test vector. */
14365         for (i = 0; i < 28; i++) {
14366                 struct addrinfo hints;
14367                 struct addrinfo *res = NULL;
14368                 int ret;
14369
14370                 memset(&hints, '\0', sizeof(hints));
14371                 hints.ai_flags = AI_NUMERICHOST;
14372                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14373                                 NULL,
14374                                 &hints,
14375                                 &res);
14376                 if (ret) {
14377                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14378                                 remove_duplicate_addrs2_test_strings_vector[i]);
14379                         return false;
14380                 }
14381                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14382                 memcpy(&test_vector[i].u.ss,
14383                         res->ai_addr,
14384                         res->ai_addrlen);
14385                 freeaddrinfo(res);
14386         }
14387
14388         count = remove_duplicate_addrs2(test_vector, i);
14389
14390         if (count != 14) {
14391                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14392                         count);
14393                 return false;
14394         }
14395
14396         for (i = 0; i < count; i++) {
14397                 char addr[INET6_ADDRSTRLEN];
14398
14399                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14400
14401                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14402                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14403                                 i,
14404                                 addr,
14405                                 remove_duplicate_addrs2_test_strings_result[i]);
14406                         return false;
14407                 }
14408         }
14409
14410         printf("run_local_remove_duplicate_addrs2: success\n");
14411         return true;
14412 }
14413
14414 static bool run_local_tdb_opener(int dummy)
14415 {
14416         TDB_CONTEXT *t;
14417         unsigned v = 0;
14418
14419         while (1) {
14420                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14421                              O_RDWR|O_CREAT, 0755);
14422                 if (t == NULL) {
14423                         perror("tdb_open failed");
14424                         return false;
14425                 }
14426                 tdb_close(t);
14427
14428                 v += 1;
14429                 printf("\r%u", v);
14430         }
14431         return true;
14432 }
14433
14434 static bool run_local_tdb_writer(int dummy)
14435 {
14436         TDB_CONTEXT *t;
14437         unsigned v = 0;
14438         TDB_DATA val;
14439
14440         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14441         if (t == 0) {
14442                 perror("tdb_open failed");
14443                 return 1;
14444         }
14445
14446         val.dptr = (uint8_t *)&v;
14447         val.dsize = sizeof(v);
14448
14449         while (1) {
14450                 TDB_DATA data;
14451                 int ret;
14452
14453                 ret = tdb_store(t, val, val, 0);
14454                 if (ret != 0) {
14455                         printf("%s\n", tdb_errorstr(t));
14456                 }
14457                 v += 1;
14458                 printf("\r%u", v);
14459
14460                 data = tdb_fetch(t, val);
14461                 if (data.dptr != NULL) {
14462                         SAFE_FREE(data.dptr);
14463                 }
14464         }
14465         return true;
14466 }
14467
14468 static bool run_local_canonicalize_path(int dummy)
14469 {
14470         const char *src[] = {
14471                         "/foo/..",
14472                         "/..",
14473                         "/foo/bar/../baz",
14474                         "/foo/././",
14475                         "/../foo",
14476                         ".././././",
14477                         ".././././../../../boo",
14478                         "./..",
14479                         "/",
14480                         "/../../",
14481                         "/foo/../",
14482                         "/./././",
14483                         "/./././.",
14484                         "/.../././.",
14485                         "/./././.foo",
14486                         "/./././.foo.",
14487                         "/./././foo.",
14488                         "/foo/bar/..",
14489                         "/foo/bar/../baz/",
14490                         "////////////////",
14491                         "/////////./././././.",
14492                         "/./.././../.boo/../baz",
14493                         "/a/component/path",
14494                         "/a/component/path/",
14495                         "/a/component/path/..",
14496                         "/a/component/../path/",
14497                         "///a/./././///component/../////path/",
14498                         NULL
14499                         };
14500         const char *dst[] = {
14501                         "/",
14502                         "/",
14503                         "/foo/baz",
14504                         "/foo",
14505                         "/foo",
14506                         "/",
14507                         "/boo",
14508                         "/",
14509                         "/",
14510                         "/",
14511                         "/",
14512                         "/",
14513                         "/",
14514                         "/...",
14515                         "/.foo",
14516                         "/.foo.",
14517                         "/foo.",
14518                         "/foo",
14519                         "/foo/baz",
14520                         "/",
14521                         "/",
14522                         "/baz",
14523                         "/a/component/path",
14524                         "/a/component/path",
14525                         "/a/component",
14526                         "/a/path",
14527                         "/a/path",
14528                         NULL
14529                         };
14530         unsigned int i;
14531
14532         for (i = 0; src[i] != NULL; i++) {
14533                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14534                 if (d == NULL) {
14535                         perror("talloc fail\n");
14536                         return false;
14537                 }
14538                 if (strcmp(d, dst[i]) != 0) {
14539                         d_fprintf(stderr,
14540                                 "canonicalize mismatch %s -> %s != %s",
14541                                 src[i], d, dst[i]);
14542                         return false;
14543                 }
14544                 talloc_free(d);
14545         }
14546         return true;
14547 }
14548
14549 static bool run_ign_bad_negprot(int dummy)
14550 {
14551         struct tevent_context *ev;
14552         struct tevent_req *req;
14553         struct smbXcli_conn *conn;
14554         struct sockaddr_storage ss;
14555         NTSTATUS status;
14556         int fd;
14557         bool ok;
14558
14559         printf("starting ignore bad negprot\n");
14560
14561         ok = resolve_name(host, &ss, 0x20, true);
14562         if (!ok) {
14563                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14564                 return false;
14565         }
14566
14567         status = open_socket_out(&ss, 445, 10000, &fd);
14568         if (!NT_STATUS_IS_OK(status)) {
14569                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14570                           nt_errstr(status));
14571                 return false;
14572         }
14573
14574         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14575                                    NULL, 0, NULL);
14576         if (conn == NULL) {
14577                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14578                 return false;
14579         }
14580
14581         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14582         if (NT_STATUS_IS_OK(status)) {
14583                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14584                 return false;
14585         }
14586
14587         ev = samba_tevent_context_init(talloc_tos());
14588         if (ev == NULL) {
14589                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14590                 return false;
14591         }
14592
14593         req = smb1cli_session_setup_nt1_send(
14594                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14595                 data_blob_null, data_blob_null, 0x40,
14596                 "Windows 2000 2195", "Windows 2000 5.0");
14597         if (req == NULL) {
14598                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14599                 return false;
14600         }
14601
14602         ok = tevent_req_poll_ntstatus(req, ev, &status);
14603         if (!ok) {
14604                 d_fprintf(stderr, "tevent_req_poll failed\n");
14605                 return false;
14606         }
14607
14608         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14609                                                 NULL, NULL);
14610         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14611                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14612                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14613                           nt_errstr(status));
14614                 return false;
14615         }
14616
14617         TALLOC_FREE(conn);
14618
14619         printf("starting ignore bad negprot\n");
14620
14621         return true;
14622 }
14623
14624 static double create_procs(bool (*fn)(int), bool *result)
14625 {
14626         int i, status;
14627         volatile pid_t *child_status;
14628         volatile bool *child_status_out;
14629         int synccount;
14630         int tries = 8;
14631         struct timeval start;
14632
14633         synccount = 0;
14634
14635         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14636         if (!child_status) {
14637                 printf("Failed to setup shared memory\n");
14638                 return -1;
14639         }
14640
14641         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14642         if (!child_status_out) {
14643                 printf("Failed to setup result status shared memory\n");
14644                 return -1;
14645         }
14646
14647         for (i = 0; i < torture_nprocs; i++) {
14648                 child_status[i] = 0;
14649                 child_status_out[i] = True;
14650         }
14651
14652         start = timeval_current();
14653
14654         for (i=0;i<torture_nprocs;i++) {
14655                 procnum = i;
14656                 if (fork() == 0) {
14657                         pid_t mypid = getpid();
14658                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14659
14660                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14661
14662                         while (1) {
14663                                 if (torture_open_connection(&current_cli, i)) break;
14664                                 if (tries-- == 0) {
14665                                         printf("pid %d failed to start\n", (int)getpid());
14666                                         _exit(1);
14667                                 }
14668                                 smb_msleep(10); 
14669                         }
14670
14671                         child_status[i] = getpid();
14672
14673                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14674
14675                         child_status_out[i] = fn(i);
14676                         _exit(0);
14677                 }
14678         }
14679
14680         do {
14681                 synccount = 0;
14682                 for (i=0;i<torture_nprocs;i++) {
14683                         if (child_status[i]) synccount++;
14684                 }
14685                 if (synccount == torture_nprocs) break;
14686                 smb_msleep(10);
14687         } while (timeval_elapsed(&start) < 30);
14688
14689         if (synccount != torture_nprocs) {
14690                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14691                 *result = False;
14692                 return timeval_elapsed(&start);
14693         }
14694
14695         /* start the client load */
14696         start = timeval_current();
14697
14698         for (i=0;i<torture_nprocs;i++) {
14699                 child_status[i] = 0;
14700         }
14701
14702         printf("%d clients started\n", torture_nprocs);
14703
14704         for (i=0;i<torture_nprocs;i++) {
14705                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14706         }
14707
14708         printf("\n");
14709
14710         for (i=0;i<torture_nprocs;i++) {
14711                 if (!child_status_out[i]) {
14712                         *result = False;
14713                 }
14714         }
14715         return timeval_elapsed(&start);
14716 }
14717
14718 #define FLAG_MULTIPROC 1
14719
14720 static struct {
14721         const char *name;
14722         bool (*fn)(int);
14723         unsigned flags;
14724 } torture_ops[] = {
14725         {
14726                 .name = "FDPASS",
14727                 .fn   = run_fdpasstest,
14728         },
14729         {
14730                 .name = "LOCK1",
14731                 .fn   = run_locktest1,
14732         },
14733         {
14734                 .name = "LOCK2",
14735                 .fn   =  run_locktest2,
14736         },
14737         {
14738                 .name = "LOCK3",
14739                 .fn   =  run_locktest3,
14740         },
14741         {
14742                 .name = "LOCK4",
14743                 .fn   =  run_locktest4,
14744         },
14745         {
14746                 .name = "LOCK5",
14747                 .fn   =  run_locktest5,
14748         },
14749         {
14750                 .name = "LOCK6",
14751                 .fn   =  run_locktest6,
14752         },
14753         {
14754                 .name = "LOCK7",
14755                 .fn   =  run_locktest7,
14756         },
14757         {
14758                 .name = "LOCK8",
14759                 .fn   =  run_locktest8,
14760         },
14761         {
14762                 .name = "LOCK9A",
14763                 .fn   =  run_locktest9a,
14764         },
14765         {
14766                 .name = "LOCK9B",
14767                 .fn   =  run_locktest9b,
14768         },
14769         {
14770                 .name = "LOCK10",
14771                 .fn   =  run_locktest10,
14772         },
14773         {
14774                 .name = "LOCK11",
14775                 .fn   =  run_locktest11,
14776         },
14777         {
14778                 .name = "LOCK12",
14779                 .fn   =  run_locktest12,
14780         },
14781         {
14782                 .name = "LOCK13",
14783                 .fn   =  run_locktest13,
14784         },
14785         {
14786                 .name = "UNLINK",
14787                 .fn   = run_unlinktest,
14788         },
14789         {
14790                 .name = "BROWSE",
14791                 .fn   = run_browsetest,
14792         },
14793         {
14794                 .name = "ATTR",
14795                 .fn   =   run_attrtest,
14796         },
14797         {
14798                 .name = "TRANS2",
14799                 .fn   = run_trans2test,
14800         },
14801         {
14802                 .name  = "MAXFID",
14803                 .fn    = run_maxfidtest,
14804                 .flags = FLAG_MULTIPROC,
14805         },
14806         {
14807                 .name  = "TORTURE",
14808                 .fn    = run_torture,
14809                 .flags = FLAG_MULTIPROC,
14810         },
14811         {
14812                 .name  = "RANDOMIPC",
14813                 .fn    = run_randomipc,
14814         },
14815         {
14816                 .name  = "NEGNOWAIT",
14817                 .fn    = run_negprot_nowait,
14818         },
14819         {
14820                 .name  = "NBENCH",
14821                 .fn    =  run_nbench,
14822         },
14823         {
14824                 .name  = "NBENCH2",
14825                 .fn    = run_nbench2,
14826         },
14827         {
14828                 .name  = "OPLOCK1",
14829                 .fn    =  run_oplock1,
14830         },
14831         {
14832                 .name  = "OPLOCK2",
14833                 .fn    =  run_oplock2,
14834         },
14835         {
14836                 .name  = "OPLOCK4",
14837                 .fn    =  run_oplock4,
14838         },
14839 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14840         {
14841                 .name  = "OPLOCK5",
14842                 .fn    =  run_oplock5,
14843         },
14844 #endif
14845         {
14846                 .name  = "DIR",
14847                 .fn    =  run_dirtest,
14848         },
14849         {
14850                 .name  = "DIR1",
14851                 .fn    =  run_dirtest1,
14852         },
14853         {
14854                 .name  = "DIR-CREATETIME",
14855                 .fn    =  run_dir_createtime,
14856         },
14857         {
14858                 .name  = "DENY1",
14859                 .fn    =  torture_denytest1,
14860         },
14861         {
14862                 .name  = "DENY2",
14863                 .fn    =  torture_denytest2,
14864         },
14865         {
14866                 .name  = "TCON",
14867                 .fn    =  run_tcon_test,
14868         },
14869         {
14870                 .name  = "TCONDEV",
14871                 .fn    =  run_tcon_devtype_test,
14872         },
14873         {
14874                 .name  = "RW1",
14875                 .fn    =  run_readwritetest,
14876         },
14877         {
14878                 .name  = "RW2",
14879                 .fn    =  run_readwritemulti,
14880                 .flags = FLAG_MULTIPROC
14881         },
14882         {
14883                 .name  = "RW3",
14884                 .fn    =  run_readwritelarge,
14885         },
14886         {
14887                 .name  = "RW-SIGNING",
14888                 .fn    =  run_readwritelarge_signtest,
14889         },
14890         {
14891                 .name  = "OPEN",
14892                 .fn    = run_opentest,
14893         },
14894         {
14895                 .name  = "POSIX",
14896                 .fn    = run_simple_posix_open_test,
14897         },
14898         {
14899                 .name  = "POSIX-APPEND",
14900                 .fn    = run_posix_append,
14901         },
14902         {
14903                 .name  = "POSIX-SYMLINK-ACL",
14904                 .fn    = run_acl_symlink_test,
14905         },
14906         {
14907                 .name  = "POSIX-SYMLINK-EA",
14908                 .fn    = run_ea_symlink_test,
14909         },
14910         {
14911                 .name  = "POSIX-STREAM-DELETE",
14912                 .fn    = run_posix_stream_delete,
14913         },
14914         {
14915                 .name  = "POSIX-OFD-LOCK",
14916                 .fn    = run_posix_ofd_lock_test,
14917         },
14918         {
14919                 .name  = "POSIX-BLOCKING-LOCK",
14920                 .fn    = run_posix_blocking_lock,
14921         },
14922         {
14923                 .name  = "POSIX-MKDIR",
14924                 .fn    = run_posix_mkdir_test,
14925         },
14926         {
14927                 .name  = "POSIX-ACL-OPLOCK",
14928                 .fn    = run_posix_acl_oplock_test,
14929         },
14930         {
14931                 .name  = "POSIX-ACL-SHAREROOT",
14932                 .fn    = run_posix_acl_shareroot_test,
14933         },
14934         {
14935                 .name  = "POSIX-LS-WILDCARD",
14936                 .fn    = run_posix_ls_wildcard_test,
14937         },
14938         {
14939                 .name  = "POSIX-LS-SINGLE",
14940                 .fn    = run_posix_ls_single_test,
14941         },
14942         {
14943                 .name  = "POSIX-READLINK",
14944                 .fn    = run_posix_readlink_test,
14945         },
14946         {
14947                 .name  = "POSIX-STAT",
14948                 .fn    = run_posix_stat_test,
14949         },
14950         {
14951                 .name  = "POSIX-SYMLINK-PARENT",
14952                 .fn    = run_posix_symlink_parent_test,
14953         },
14954         {
14955                 .name  = "POSIX-SYMLINK-CHMOD",
14956                 .fn    = run_posix_symlink_chmod_test,
14957         },
14958         {
14959                 .name  = "POSIX-DIR-DEFAULT-ACL",
14960                 .fn    = run_posix_dir_default_acl_test,
14961         },
14962         {
14963                 .name  = "WINDOWS-BAD-SYMLINK",
14964                 .fn    = run_symlink_open_test,
14965         },
14966         {
14967                 .name  = "SMB1-WILD-MANGLE-UNLINK",
14968                 .fn    = run_smb1_wild_mangle_unlink_test,
14969         },
14970         {
14971                 .name  = "SMB1-WILD-MANGLE-RENAME",
14972                 .fn    = run_smb1_wild_mangle_rename_test,
14973         },
14974         {
14975                 .name  = "CASE-INSENSITIVE-CREATE",
14976                 .fn    = run_case_insensitive_create,
14977         },
14978         {
14979                 .name  = "ASYNC-ECHO",
14980                 .fn    = run_async_echo,
14981         },
14982         {
14983                 .name  = "UID-REGRESSION-TEST",
14984                 .fn    = run_uid_regression_test,
14985         },
14986         {
14987                 .name  = "SHORTNAME-TEST",
14988                 .fn    = run_shortname_test,
14989         },
14990         {
14991                 .name  = "ADDRCHANGE",
14992                 .fn    = run_addrchange,
14993         },
14994 #if 1
14995         {
14996                 .name  = "OPENATTR",
14997                 .fn    = run_openattrtest,
14998         },
14999 #endif
15000         {
15001                 .name  = "XCOPY",
15002                 .fn    = run_xcopy,
15003         },
15004         {
15005                 .name  = "RENAME",
15006                 .fn    = run_rename,
15007         },
15008         {
15009                 .name  = "RENAME-ACCESS",
15010                 .fn    = run_rename_access,
15011         },
15012         {
15013                 .name  = "OWNER-RIGHTS",
15014                 .fn    = run_owner_rights,
15015         },
15016         {
15017                 .name  = "DELETE",
15018                 .fn    = run_deletetest,
15019         },
15020         {
15021                 .name  = "DELETE-STREAM",
15022                 .fn    = run_delete_stream,
15023         },
15024         {
15025                 .name  = "DELETE-PRINT",
15026                 .fn    = run_delete_print_test,
15027         },
15028         {
15029                 .name  = "WILDDELETE",
15030                 .fn    = run_wild_deletetest,
15031         },
15032         {
15033                 .name  = "DELETE-LN",
15034                 .fn    = run_deletetest_ln,
15035         },
15036         {
15037                 .name  = "PROPERTIES",
15038                 .fn    = run_properties,
15039         },
15040         {
15041                 .name  = "MANGLE",
15042                 .fn    = torture_mangle,
15043         },
15044         {
15045                 .name  = "MANGLE1",
15046                 .fn    = run_mangle1,
15047         },
15048         {
15049                 .name  = "MANGLE-ILLEGAL",
15050                 .fn    = run_mangle_illegal,
15051         },
15052         {
15053                 .name  = "W2K",
15054                 .fn    = run_w2ktest,
15055         },
15056         {
15057                 .name  = "TRANS2SCAN",
15058                 .fn    = torture_trans2_scan,
15059         },
15060         {
15061                 .name  = "NTTRANSSCAN",
15062                 .fn    = torture_nttrans_scan,
15063         },
15064         {
15065                 .name  = "UTABLE",
15066                 .fn    = torture_utable,
15067         },
15068         {
15069                 .name  = "CASETABLE",
15070                 .fn    = torture_casetable,
15071         },
15072         {
15073                 .name  = "ERRMAPEXTRACT",
15074                 .fn    = run_error_map_extract,
15075         },
15076         {
15077                 .name  = "PIPE_NUMBER",
15078                 .fn    = run_pipe_number,
15079         },
15080         {
15081                 .name  = "TCON2",
15082                 .fn    =  run_tcon2_test,
15083         },
15084         {
15085                 .name  = "IOCTL",
15086                 .fn    =  torture_ioctl_test,
15087         },
15088         {
15089                 .name  = "CHKPATH",
15090                 .fn    =  torture_chkpath_test,
15091         },
15092         {
15093                 .name  = "FDSESS",
15094                 .fn    = run_fdsesstest,
15095         },
15096         {
15097                 .name  = "EATEST",
15098                 .fn    = run_eatest,
15099         },
15100         {
15101                 .name  = "SESSSETUP_BENCH",
15102                 .fn    = run_sesssetup_bench,
15103         },
15104         {
15105                 .name  = "CHAIN1",
15106                 .fn    = run_chain1,
15107         },
15108         {
15109                 .name  = "CHAIN2",
15110                 .fn    = run_chain2,
15111         },
15112         {
15113                 .name  = "CHAIN3",
15114                 .fn    = run_chain3,
15115         },
15116         {
15117                 .name  = "WINDOWS-WRITE",
15118                 .fn    = run_windows_write,
15119         },
15120         {
15121                 .name  = "LARGE_READX",
15122                 .fn    = run_large_readx,
15123         },
15124         {
15125                 .name  = "MSDFS-ATTRIBUTE",
15126                 .fn    = run_msdfs_attribute,
15127         },
15128         {
15129                 .name  = "NTTRANS-CREATE",
15130                 .fn    = run_nttrans_create,
15131         },
15132         {
15133                 .name  = "NTTRANS-FSCTL",
15134                 .fn    = run_nttrans_fsctl,
15135         },
15136         {
15137                 .name  = "CLI_ECHO",
15138                 .fn    = run_cli_echo,
15139         },
15140         {
15141                 .name  = "CLI_SPLICE",
15142                 .fn    = run_cli_splice,
15143         },
15144         {
15145                 .name  = "TLDAP",
15146                 .fn    = run_tldap,
15147         },
15148         {
15149                 .name  = "STREAMERROR",
15150                 .fn    = run_streamerror,
15151         },
15152         {
15153                 .name  = "NOTIFY-BENCH",
15154                 .fn    = run_notify_bench,
15155         },
15156         {
15157                 .name  = "NOTIFY-BENCH2",
15158                 .fn    = run_notify_bench2,
15159         },
15160         {
15161                 .name  = "NOTIFY-BENCH3",
15162                 .fn    = run_notify_bench3,
15163         },
15164         {
15165                 .name  = "BAD-NBT-SESSION",
15166                 .fn    = run_bad_nbt_session,
15167         },
15168         {
15169                 .name  = "IGN-BAD-NEGPROT",
15170                 .fn    = run_ign_bad_negprot,
15171         },
15172         {
15173                 .name  = "SMB-ANY-CONNECT",
15174                 .fn    = run_smb_any_connect,
15175         },
15176         {
15177                 .name  = "NOTIFY-ONLINE",
15178                 .fn    = run_notify_online,
15179         },
15180         {
15181                 .name  = "SMB2-BASIC",
15182                 .fn    = run_smb2_basic,
15183         },
15184         {
15185                 .name  = "SMB2-NEGPROT",
15186                 .fn    = run_smb2_negprot,
15187         },
15188         {
15189                 .name  = "SMB2-ANONYMOUS",
15190                 .fn    = run_smb2_anonymous,
15191         },
15192         {
15193                 .name  = "SMB2-SESSION-RECONNECT",
15194                 .fn    = run_smb2_session_reconnect,
15195         },
15196         {
15197                 .name  = "SMB2-TCON-DEPENDENCE",
15198                 .fn    = run_smb2_tcon_dependence,
15199         },
15200         {
15201                 .name  = "SMB2-MULTI-CHANNEL",
15202                 .fn    = run_smb2_multi_channel,
15203         },
15204         {
15205                 .name  = "SMB2-SESSION-REAUTH",
15206                 .fn    = run_smb2_session_reauth,
15207         },
15208         {
15209                 .name  = "SMB2-FTRUNCATE",
15210                 .fn    = run_smb2_ftruncate,
15211         },
15212         {
15213                 .name  = "SMB2-DIR-FSYNC",
15214                 .fn    = run_smb2_dir_fsync,
15215         },
15216         {
15217                 .name  = "SMB2-PATH-SLASH",
15218                 .fn    = run_smb2_path_slash,
15219         },
15220         {
15221                 .name  = "SMB1-SYSTEM-SECURITY",
15222                 .fn    = run_smb1_system_security,
15223         },
15224         {
15225                 .name  = "SMB2-SACL",
15226                 .fn    = run_smb2_sacl,
15227         },
15228         {
15229                 .name  = "SMB2-QUOTA1",
15230                 .fn    = run_smb2_quota1,
15231         },
15232         {
15233                 .name  = "SMB2-STREAM-ACL",
15234                 .fn    = run_smb2_stream_acl,
15235         },
15236         {
15237                 .name  = "CLEANUP1",
15238                 .fn    = run_cleanup1,
15239         },
15240         {
15241                 .name  = "CLEANUP2",
15242                 .fn    = run_cleanup2,
15243         },
15244         {
15245                 .name  = "CLEANUP4",
15246                 .fn    = run_cleanup4,
15247         },
15248         {
15249                 .name  = "OPLOCK-CANCEL",
15250                 .fn    = run_oplock_cancel,
15251         },
15252         {
15253                 .name  = "PIDHIGH",
15254                 .fn    = run_pidhigh,
15255         },
15256         {
15257                 .name  = "LOCAL-SUBSTITUTE",
15258                 .fn    = run_local_substitute,
15259         },
15260         {
15261                 .name  = "LOCAL-GENCACHE",
15262                 .fn    = run_local_gencache,
15263         },
15264         {
15265                 .name  = "LOCAL-DBWRAP-WATCH1",
15266                 .fn    = run_dbwrap_watch1,
15267         },
15268         {
15269                 .name  = "LOCAL-DBWRAP-WATCH2",
15270                 .fn    = run_dbwrap_watch2,
15271         },
15272         {
15273                 .name  = "LOCAL-DBWRAP-WATCH3",
15274                 .fn    = run_dbwrap_watch3,
15275         },
15276         {
15277                 .name  = "LOCAL-DBWRAP-WATCH4",
15278                 .fn    = run_dbwrap_watch4,
15279         },
15280         {
15281                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
15282                 .fn    = run_dbwrap_do_locked1,
15283         },
15284         {
15285                 .name  = "LOCAL-MESSAGING-READ1",
15286                 .fn    = run_messaging_read1,
15287         },
15288         {
15289                 .name  = "LOCAL-MESSAGING-READ2",
15290                 .fn    = run_messaging_read2,
15291         },
15292         {
15293                 .name  = "LOCAL-MESSAGING-READ3",
15294                 .fn    = run_messaging_read3,
15295         },
15296         {
15297                 .name  = "LOCAL-MESSAGING-READ4",
15298                 .fn    = run_messaging_read4,
15299         },
15300         {
15301                 .name  = "LOCAL-MESSAGING-FDPASS1",
15302                 .fn    = run_messaging_fdpass1,
15303         },
15304         {
15305                 .name  = "LOCAL-MESSAGING-FDPASS2",
15306                 .fn    = run_messaging_fdpass2,
15307         },
15308         {
15309                 .name  = "LOCAL-MESSAGING-FDPASS2a",
15310                 .fn    = run_messaging_fdpass2a,
15311         },
15312         {
15313                 .name  = "LOCAL-MESSAGING-FDPASS2b",
15314                 .fn    = run_messaging_fdpass2b,
15315         },
15316         {
15317                 .name  = "LOCAL-MESSAGING-SEND-ALL",
15318                 .fn    = run_messaging_send_all,
15319         },
15320         {
15321                 .name  = "LOCAL-BASE64",
15322                 .fn    = run_local_base64,
15323         },
15324         {
15325                 .name  = "LOCAL-RBTREE",
15326                 .fn    = run_local_rbtree,
15327         },
15328         {
15329                 .name  = "LOCAL-MEMCACHE",
15330                 .fn    = run_local_memcache,
15331         },
15332         {
15333                 .name  = "LOCAL-STREAM-NAME",
15334                 .fn    = run_local_stream_name,
15335         },
15336         {
15337                 .name  = "WBCLIENT-MULTI-PING",
15338                 .fn    = run_wbclient_multi_ping,
15339         },
15340         {
15341                 .name  = "LOCAL-string_to_sid",
15342                 .fn    = run_local_string_to_sid,
15343         },
15344         {
15345                 .name  = "LOCAL-sid_to_string",
15346                 .fn    = run_local_sid_to_string,
15347         },
15348         {
15349                 .name  = "LOCAL-binary_to_sid",
15350                 .fn    = run_local_binary_to_sid,
15351         },
15352         {
15353                 .name  = "LOCAL-DBTRANS",
15354                 .fn    = run_local_dbtrans,
15355         },
15356         {
15357                 .name  = "LOCAL-TEVENT-POLL",
15358                 .fn    = run_local_tevent_poll,
15359         },
15360         {
15361                 .name  = "LOCAL-CONVERT-STRING",
15362                 .fn    = run_local_convert_string,
15363         },
15364         {
15365                 .name  = "LOCAL-CONV-AUTH-INFO",
15366                 .fn    = run_local_conv_auth_info,
15367         },
15368         {
15369                 .name  = "LOCAL-hex_encode_buf",
15370                 .fn    = run_local_hex_encode_buf,
15371         },
15372         {
15373                 .name  = "LOCAL-IDMAP-TDB-COMMON",
15374                 .fn    = run_idmap_tdb_common_test,
15375         },
15376         {
15377                 .name  = "LOCAL-remove_duplicate_addrs2",
15378                 .fn    = run_local_remove_duplicate_addrs2,
15379         },
15380         {
15381                 .name  = "local-tdb-opener",
15382                 .fn    = run_local_tdb_opener,
15383         },
15384         {
15385                 .name  = "local-tdb-writer",
15386                 .fn    = run_local_tdb_writer,
15387         },
15388         {
15389                 .name  = "LOCAL-DBWRAP-CTDB1",
15390                 .fn    = run_local_dbwrap_ctdb1,
15391         },
15392         {
15393                 .name  = "LOCAL-BENCH-PTHREADPOOL",
15394                 .fn    = run_bench_pthreadpool,
15395         },
15396         {
15397                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
15398                 .fn    = run_pthreadpool_tevent,
15399         },
15400         {
15401                 .name  = "LOCAL-G-LOCK1",
15402                 .fn    = run_g_lock1,
15403         },
15404         {
15405                 .name  = "LOCAL-G-LOCK2",
15406                 .fn    = run_g_lock2,
15407         },
15408         {
15409                 .name  = "LOCAL-G-LOCK3",
15410                 .fn    = run_g_lock3,
15411         },
15412         {
15413                 .name  = "LOCAL-G-LOCK4",
15414                 .fn    = run_g_lock4,
15415         },
15416         {
15417                 .name  = "LOCAL-G-LOCK4A",
15418                 .fn    = run_g_lock4a,
15419         },
15420         {
15421                 .name  = "LOCAL-G-LOCK5",
15422                 .fn    = run_g_lock5,
15423         },
15424         {
15425                 .name  = "LOCAL-G-LOCK6",
15426                 .fn    = run_g_lock6,
15427         },
15428         {
15429                 .name  = "LOCAL-G-LOCK7",
15430                 .fn    = run_g_lock7,
15431         },
15432         {
15433                 .name  = "LOCAL-G-LOCK8",
15434                 .fn    = run_g_lock8,
15435         },
15436         {
15437                 .name  = "LOCAL-G-LOCK-PING-PONG",
15438                 .fn    = run_g_lock_ping_pong,
15439         },
15440         {
15441                 .name  = "LOCAL-CANONICALIZE-PATH",
15442                 .fn    = run_local_canonicalize_path,
15443         },
15444         {
15445                 .name  = "LOCAL-NAMEMAP-CACHE1",
15446                 .fn    = run_local_namemap_cache1,
15447         },
15448         {
15449                 .name  = "LOCAL-IDMAP-CACHE1",
15450                 .fn    = run_local_idmap_cache1,
15451         },
15452         {
15453                 .name  = "qpathinfo-bufsize",
15454                 .fn    = run_qpathinfo_bufsize,
15455         },
15456         {
15457                 .name  = "hide-new-files-timeout",
15458                 .fn    = run_hidenewfiles,
15459         },
15460 #ifdef CLUSTER_SUPPORT
15461         {
15462                 .name  = "ctdbd-conn1",
15463                 .fn    = run_ctdbd_conn1,
15464         },
15465 #endif
15466         {
15467                 .name  = "readdir-timestamp",
15468                 .fn    = run_readdir_timestamp,
15469         },
15470         {
15471                 .name = NULL,
15472         },
15473 };
15474
15475 /****************************************************************************
15476 run a specified test or "ALL"
15477 ****************************************************************************/
15478 static bool run_test(const char *name)
15479 {
15480         bool ret = True;
15481         bool result = True;
15482         bool found = False;
15483         int i;
15484         double t;
15485         if (strequal(name,"ALL")) {
15486                 for (i=0;torture_ops[i].name;i++) {
15487                         run_test(torture_ops[i].name);
15488                 }
15489                 found = True;
15490         }
15491
15492         for (i=0;torture_ops[i].name;i++) {
15493                 fstr_sprintf(randomfname, "\\XX%x", 
15494                          (unsigned)random());
15495
15496                 if (strequal(name, torture_ops[i].name)) {
15497                         found = True;
15498                         printf("Running %s\n", name);
15499                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
15500                                 t = create_procs(torture_ops[i].fn, &result);
15501                                 if (!result) { 
15502                                         ret = False;
15503                                         printf("TEST %s FAILED!\n", name);
15504                                 }
15505                         } else {
15506                                 struct timeval start;
15507                                 start = timeval_current();
15508                                 if (!torture_ops[i].fn(0)) {
15509                                         ret = False;
15510                                         printf("TEST %s FAILED!\n", name);
15511                                 }
15512                                 t = timeval_elapsed(&start);
15513                         }
15514                         printf("%s took %g secs\n\n", name, t);
15515                 }
15516         }
15517
15518         if (!found) {
15519                 printf("Did not find a test named %s\n", name);
15520                 ret = False;
15521         }
15522
15523         return ret;
15524 }
15525
15526
15527 static void usage(void)
15528 {
15529         int i;
15530
15531         printf("WARNING samba4 test suite is much more complete nowadays.\n");
15532         printf("Please use samba4 torture.\n\n");
15533
15534         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15535
15536         printf("\t-d debuglevel\n");
15537         printf("\t-U user%%pass\n");
15538         printf("\t-k                    use kerberos\n");
15539         printf("\t-N numprocs\n");
15540         printf("\t-n my_netbios_name\n");
15541         printf("\t-W workgroup\n");
15542         printf("\t-o num_operations\n");
15543         printf("\t-O socket_options\n");
15544         printf("\t-m maximum protocol\n");
15545         printf("\t-L use oplocks\n");
15546         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
15547         printf("\t-A showall\n");
15548         printf("\t-p port\n");
15549         printf("\t-s seed\n");
15550         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
15551         printf("\t-f filename           filename to test\n");
15552         printf("\t-e                    encrypt\n");
15553         printf("\n\n");
15554
15555         printf("tests are:");
15556         for (i=0;torture_ops[i].name;i++) {
15557                 printf(" %s", torture_ops[i].name);
15558         }
15559         printf("\n");
15560
15561         printf("default test is ALL\n");
15562
15563         exit(1);
15564 }
15565
15566 /****************************************************************************
15567   main program
15568 ****************************************************************************/
15569  int main(int argc,char *argv[])
15570 {
15571         int opt, i;
15572         char *p;
15573         int gotuser = 0;
15574         int gotpass = 0;
15575         bool correct = True;
15576         TALLOC_CTX *frame = talloc_stackframe();
15577         int seed = time(NULL);
15578
15579 #ifdef HAVE_SETBUFFER
15580         setbuffer(stdout, NULL, 0);
15581 #endif
15582
15583         setup_logging("smbtorture", DEBUG_STDOUT);
15584
15585         smb_init_locale();
15586         fault_setup();
15587
15588         if (is_default_dyn_CONFIGFILE()) {
15589                 if(getenv("SMB_CONF_PATH")) {
15590                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15591                 }
15592         }
15593         lp_load_global(get_dyn_CONFIGFILE());
15594         load_interfaces();
15595
15596         if (argc < 2) {
15597                 usage();
15598         }
15599
15600         for(p = argv[1]; *p; p++)
15601           if(*p == '\\')
15602             *p = '/';
15603
15604         if (strncmp(argv[1], "//", 2)) {
15605                 usage();
15606         }
15607
15608         fstrcpy(host, &argv[1][2]);
15609         p = strchr_m(&host[2],'/');
15610         if (!p) {
15611                 usage();
15612         }
15613         *p = 0;
15614         fstrcpy(share, p+1);
15615
15616         fstrcpy(myname, get_myname(talloc_tos()));
15617         if (!*myname) {
15618                 fprintf(stderr, "Failed to get my hostname.\n");
15619                 return 1;
15620         }
15621
15622         if (*username == 0 && getenv("LOGNAME")) {
15623           fstrcpy(username,getenv("LOGNAME"));
15624         }
15625
15626         argc--;
15627         argv++;
15628
15629         fstrcpy(workgroup, lp_workgroup());
15630
15631         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15632                != EOF) {
15633                 switch (opt) {
15634                 case 'p':
15635                         port_to_use = atoi(optarg);
15636                         break;
15637                 case 's':
15638                         seed = atoi(optarg);
15639                         break;
15640                 case 'W':
15641                         fstrcpy(workgroup,optarg);
15642                         break;
15643                 case 'm':
15644                         lp_set_cmdline("client max protocol", optarg);
15645                         break;
15646                 case 'N':
15647                         torture_nprocs = atoi(optarg);
15648                         break;
15649                 case 'o':
15650                         torture_numops = atoi(optarg);
15651                         break;
15652                 case 'd':
15653                         lp_set_cmdline("log level", optarg);
15654                         break;
15655                 case 'O':
15656                         sockops = optarg;
15657                         break;
15658                 case 'L':
15659                         use_oplocks = True;
15660                         break;
15661                 case 'l':
15662                         local_path = optarg;
15663                         break;
15664                 case 'A':
15665                         torture_showall = True;
15666                         break;
15667                 case 'n':
15668                         fstrcpy(myname, optarg);
15669                         break;
15670                 case 'c':
15671                         client_txt = optarg;
15672                         break;
15673                 case 'e':
15674                         do_encrypt = true;
15675                         break;
15676                 case 'k':
15677 #ifdef HAVE_KRB5
15678                         use_kerberos = True;
15679 #else
15680                         d_printf("No kerberos support compiled in\n");
15681                         exit(1);
15682 #endif
15683                         break;
15684                 case 'U':
15685                         gotuser = 1;
15686                         fstrcpy(username,optarg);
15687                         p = strchr_m(username,'%');
15688                         if (p) {
15689                                 *p = 0;
15690                                 fstrcpy(password, p+1);
15691                                 gotpass = 1;
15692                         }
15693                         break;
15694                 case 'b':
15695                         fstrcpy(multishare_conn_fname, optarg);
15696                         use_multishare_conn = True;
15697                         break;
15698                 case 'B':
15699                         torture_blocksize = atoi(optarg);
15700                         break;
15701                 case 'f':
15702                         test_filename = SMB_STRDUP(optarg);
15703                         break;
15704                 default:
15705                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15706                         usage();
15707                 }
15708         }
15709
15710         d_printf("using seed %d\n", seed);
15711
15712         srandom(seed);
15713
15714         if(use_kerberos && !gotuser) gotpass = True;
15715
15716         while (!gotpass) {
15717                 char pwd[256] = {0};
15718                 int rc;
15719
15720                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15721                 if (rc == 0) {
15722                         fstrcpy(password, pwd);
15723                         gotpass = 1;
15724                 }
15725         }
15726
15727         printf("host=%s share=%s user=%s myname=%s\n", 
15728                host, share, username, myname);
15729
15730         torture_creds = cli_session_creds_init(frame,
15731                                                username,
15732                                                workgroup,
15733                                                NULL, /* realm */
15734                                                password,
15735                                                use_kerberos,
15736                                                false, /* fallback_after_kerberos */
15737                                                false, /* use_ccache */
15738                                                false); /* password_is_nt_hash */
15739         if (torture_creds == NULL) {
15740                 d_printf("cli_session_creds_init() failed.\n");
15741                 exit(1);
15742         }
15743
15744         if (argc == optind) {
15745                 correct = run_test("ALL");
15746         } else {
15747                 for (i=optind;i<argc;i++) {
15748                         if (!run_test(argv[i])) {
15749                                 correct = False;
15750                         }
15751                 }
15752         }
15753
15754         TALLOC_FREE(frame);
15755
15756         if (correct) {
15757                 return(0);
15758         } else {
15759                 return(1);
15760         }
15761 }